Implementing a quick administrative function

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Implementing a quick administrative function

Post by Ambush Commander »

I need to implement some administrative functions, and fast. So there's no time to go off with login pages and user tables and the whole kaboodle. It's a mostly anonymous user application, no registration at all, so there never was a need for user tables. But we've been receiving a huge spam attack (ineffectual, since it's only plaintext messages) which is not very convenient.

I'm thinking there should be an admin password in the config file, and if you want to do admin functions like banning ips and keywords, you need to produce it. How secure is this?
Corvin
Forum Commoner
Posts: 49
Joined: Sun Dec 03, 2006 1:04 pm

Post by Corvin »

If the config file is outside of the document root it's secure, but imo the most secure and fastest way to protect some files is to put them into an own directory and protect them via .htaccess and .htpasswd.
Last edited by Corvin on Sat Apr 05, 2008 3:02 am, edited 1 time in total.
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Post by Mordred »

I agree with Corvin on htaccess, with some added notes:
1. You can restrict files even if they are in the same directory.
2. .htpasswd belongs outside of the htdocs tree, but if you can't put it there, you must protect it.

Here's an example:

Code: Select all

<FilesMatch admin.php>
AuthName "What have you eaten today?"
AuthType Basic
AuthUserFile /home/..../www/www/..../..../htpasswd
Require valid-user
</FilesMatch>

<FilesMatch htpasswd>
Deny from all
</FilesMatch>
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

I'm using a front controller, so htaccess really isn't workable (Besides, it's not portable across webservers).
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

In cases like this I usually mock a Gateway class with a simple finder interface -- then I can add a database later if I want. It can be pretty trivial. Something like:

Code: Select all

class UserGateway {

	function findUser($username, $password) {
		$rows = array(
			'admin1' => array(
				'userid' => 'admin1',
				'password' => 'yohohoanda',
				'permissions' => 'whatever',
				),
			'admin2' => array(
				'userid' => 'admin2',
				'password' => 'barrelofrum',
				'permissions' => 'whatever',
				),
			);
		$username = pref_replace('/[^a-zA-Z0-9]/', '', $username);
		$password= pref_replace('/[^a-zA-Z0-9]/', '', $password);
		if (isset($rows[$username]) && ($rows[$username]['password'] == $password)) {
			return $rows[$username];
		} 
	}
		
}
Just make the interface match what you normally use.

PS -I believe that HTTP authentication can be defeated by brute force techniques on many server configs so I might shy away from those unless you know what you are doing.
(#10850)
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

Hmm... that's an interesting idea, if I'm working on refactoring code that's something I could easily do. Although, I wonder why you also put the password in the finder.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

arborint, you always have such cool ideas... I love it.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Ambush Commander wrote:Hmm... that's an interesting idea, if I'm working on refactoring code that's something I could easily do. Although, I wonder why you also put the password in the finder.
As I said, you can change the interface to match your log-in logic. For really simple sites I just have it check in the Model if there is a record where both match. You could just as well do $row = $user->findByKey($username) and check the password in the returned row.
(#10850)
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

The interface I'm using is:

Code: Select all

$this->Plugin->verifyAdmin($post['colocus_password'])
Where $this->Plugin is a sort of configuration object. Obviously doesn't lend very well to the method, but refactoring would be needed anyway if you wanted to extend the functionality.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Code: Select all

class UserGatewayPlugin {

        function verifyAdmin($password) {
                $rows = array(
                        'admin1' => 1,
                        'admin2' => 1,
                        );
                $password= pref_replace('/[^a-zA-Z0-9]/', '', $password);
                if (isset($rows[$username])) {
                        return true;
                }
        }
               
}
(#10850)
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

But the rest of the plugin is all settings like database login parameters, configuration on view timers, path to web root, etc. It makes no sense to put that sort of logic there. Don't worry about it though, I've got a good idea from your original idea on how to go about doing it.

By the way, what's pref_replace. ;-)
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Ambush Commander wrote:By the way, what's pref_replace. ;-)
Regular expressions with a lisp I guess?!?
(#10850)
Post Reply