PHP Security Question

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

User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Re: PHP Security Question

Post by John Cartwright »

This is a business site, not some stupid forum or the like.
If you are truly concerned about security, which it seems you are not, then you will not use your home brewed functions. I'm not suggesting you don't try to invent something better, but if you do not understand certain fundamentals about security then I would suggest you leave it to the more experienced.
And to Jcart, What is wrong with simply removing things I don't want? What if they accidently brush the single quote while typing in their password? Removing it mean's the can't find a way to unexcape it, because it's not there, and I provide options to make sure it will allow other characters when I need them.
If I enter my password as jc@rt (no my password(s) is not this so dont try ;)) I will certainly expect it to be exactly as I input. As others have mentioned, you have not even considered different languages/encodings. I simply do not understand why some people do not want to use mysql_real_escape_string().

Btw.. your script is still vulnerable to SQL injection.

...and I thought this was a business site. :twisted:
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Re: PHP Security Question

Post by John Cartwright »

Concept:

$id= '1\' UNION ALL SELECT creditCardNumber,1,1 FROM CreditCarTable WHERE 1 AS \'1';

Code: Select all

 
$id = sanitize($id, true, true);
$sql = 'SELECT Name, Phone, Address FROM Users WHERE Id=\''. $id .'\''; 
echo $sql;
You also had a bug in your code, where it would ignore spaces if you had both $allow_special and $allow_spaces set, since your logic was flawed.

Patch:

Code: Select all

 
            if ($allow_space && $char == ' ') {
                break;
            } else if ($allow_special) {
                if ($char == '@' || $char == '-' || $char == '_' || $char == '.' || $char == ',' || $char == "'") {
                    if ($char == '"') {
                        $string = substr_replace($string, '\\'.$char, $i, 1);
                        $i++;
                    }
                    break;
                } else {
                    $string = substr_replace($string, '', $i, 1);
                    $i--;
                    break;
                }
            }

Note: The forum bbcode parser seems to be killing the escape slashes in my post. Incase you are wondering why I left out the SQL from the code block
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: PHP Security Question

Post by Eran »

As Jcart has said, removing characters from input is not the right course - in some languages quotes and the like are part of characters you can type with a localized keyboard. Removing them will alter the input in the way the user will not expect.

mysql_real_escape_string() and similar escaping functions do not just escape data -
- Its aware of the database connection encoding (which your methods do not)
- It can escape binary data
- It is a compiled language feature and this inherently much more performant than solutions written in PHP
- It escapes characters you didn't bring into account

You should this past thread which discussed the same dilemma - viewtopic.php?f=34&t=90448
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Re: PHP Security Question

Post by matthijs »

Code: Select all

<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
PHP_SELF can contain user suplied input as well, so should not be used or measures have to be taken to prevent misuse.
http://en.wikipedia.org/wiki/Cross-site_scripting
cavemaneca
Forum Commoner
Posts: 59
Joined: Sat Dec 13, 2008 2:16 am

Re: PHP Security Question

Post by cavemaneca »

are you trying to say all I need to use to prevent injection is mysql_real_escape_string?
and matthijs, that link says nothing about the vulnerabilities of using php_self. Could you explain why it makes it vulnerable?
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: PHP Security Question

Post by Eran »

No, but it's much stronger than the solution you came up with. Read the link I posted for more information on SQL injections.
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: PHP Security Question

Post by kaisellgren »

cavemaneca wrote:are you trying to say all I need to use to prevent injection is mysql_real_escape_string?
and matthijs, that link says nothing about the vulnerabilities of using php_self. Could you explain why it makes it vulnerable?
mysql_real_escape_string() solves many SQL related security issues, however, not everything. It's still far better then the workarounds you have made.

Anyone can alter the data on PHP_SELF and since you output it directly to your site, an attacker can pass dangerous XSS into it which can again lead to unmetered amount of problems, cookie theft, redirections, etc etc...
cavemaneca
Forum Commoner
Posts: 59
Joined: Sat Dec 13, 2008 2:16 am

Re: PHP Security Question

Post by cavemaneca »

So I should always use an absolute url for the action field in forms?
Also, What about this?

Code: Select all

function input($in,$error=0) {
 
    $in = trim($in);
 
    if (strlen($in))
    {
        $in = htmlspecialchars($in);
        $in = preg_replace('/&(\#[0-9]+;)/','&$1',$in);
    }
    elseif ($error)
    {
        error($error);
    }
 
    if (!ini_get('magic_quotes_gpc'))
    {
        if (!is_array($in))
            $in = mysql_real_escape_string($in);
        else
            $in = slashArray($in);
    }
    else {
         $in = mysql_real_escape_string($in);
    }
 
    return $in;
 
}
 
function slashArray ($a)
{
    while (list($k,$v) = each($a))
    {
        if (!is_array($v))
            $a[$k] = mysql_real_escape_string($v);
        else
            $a[$k] = slashArray($v);
    }
 
    reset ($a);
    return ($a);
}
 
$string = /*input*/;
$string = input($string);
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Re: PHP Security Question

Post by matthijs »

cavemaneca wrote: and matthijs, that link says nothing about the vulnerabilities of using php_self. Could you explain why it makes it vulnerable?
kaisellgren already gave the answer, but a quick google search will give you more info on that question. You do know what XSS is?
cavemaneca
Forum Commoner
Posts: 59
Joined: Sat Dec 13, 2008 2:16 am

Re: PHP Security Question

Post by cavemaneca »

I do know what xss is, but there was nothing on that page telling why php_self was vulnerable to it. So I did some separate research(google) and found out why, and it seems that i should be using an actual file name instead of self. And, that doesn't answer my question about the last code I posted. I am not using it yet because I don't know if it is good enough, but for now I am just using mysql_real_escape_string(). I decided I was being stupid and that my function really did just over-complicate things. But I also realized how to use preg_match, and a few other things.
Now I'm am just trying to set up SSL and also add a little more security to the input. I put a function in the above post that uses mysql_real_escape_string and htmlspecialchars as well as preg_replace. Does this work with actually helping stop sql injection?

Also, this is kind of a different note, but I use a pop3/smtp/imap mail server running off of the same address that this site I am building uses. This will be used for work related accounts, and I've had no problems until recently. Apparently while I was out of town from yesterday afternoon to this afternoon, and using the program, they were able to start sending spam from my server to whoever. I was quickly able to stop this, but only by blocking access to every port except about 20 or so used by the server software in place(http/https/ftp/etc.). Also, I realized that one of my firewalls, was blocking the one built in to this program, and I fixed that. The main problem is that i keep on receiving packets telling the mail server to send messages, and they are still getting passed the router firewall(but not the server firewall). I still have not published anything, and I'm working making everything as secure as possible before anything is, and I though that they wouldn't find my server behind two routers with built-in firewall and the software firewall on the server. Where is the best place to look up info on how that end works.

(And if you want to call me stupid because I make mistakes, go ahead. Just because I haven't written a book about it doesn't mean I'm an idiot. I still haven't been stupid enough to put important data on the server, and I have backups of everything I work on offline)
matthijs
DevNet Master
Posts: 3360
Joined: Thu Oct 06, 2005 3:57 pm

Re: PHP Security Question

Post by matthijs »

About the function you posted: I let others (better programmers) scrutinize that one.

In general terms though: I think it's always best to go for the simplest, already existing solutions. The use of mysql_real_escape_string() is a good example. It's a basic function, build for one specific purpose. very safe, if you know what it does (and does not). So if you write your own functions, I would try to write each one in such a way that it does only one, very specific thing. The more complicated a function gets, the higher the chance there's something you do wrong or forget. But you already found out you wanted to simplify a few things.

(and nobody is calling you stupid, don't worry. It's a friendly bunch of people here. If anything, the fact that you keep asking questions shows you are smart enough to keep on digging to learn more. a good thing, as security related topics are difficult enough)
cavemaneca
Forum Commoner
Posts: 59
Joined: Sat Dec 13, 2008 2:16 am

Re: PHP Security Question

Post by cavemaneca »

Thanks. Also, I just found my own problem's answer with something. The mail server has a simple setting to block all messages from external accounts to external accounts.
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: PHP Security Question

Post by kaisellgren »

cavemaneca wrote:So I should always use an absolute url for the action field in forms?
Also, What about this?

Code: Select all

function input($in,$error=0) {
 
    $in = trim($in);
 
    if (strlen($in))
    {
        $in = htmlspecialchars($in);
        $in = preg_replace('/&(\#[0-9]+;)/','&$1',$in);
    }
    elseif ($error)
    {
        error($error);
    }
 
    if (!ini_get('magic_quotes_gpc'))
    {
        if (!is_array($in))
            $in = mysql_real_escape_string($in);
        else
            $in = slashArray($in);
    }
    else {
         $in = mysql_real_escape_string($in);
    }
 
    return $in;
 
}
 
function slashArray ($a)
{
    while (list($k,$v) = each($a))
    {
        if (!is_array($v))
            $a[$k] = mysql_real_escape_string($v);
        else
            $a[$k] = slashArray($v);
    }
 
    reset ($a);
    return ($a);
}
 
$string = /*input*/;
$string = input($string);
It does not matter whether the URL is absolute or relative. The only thing that really matters is that whether it's vulnerable to XSS or not. You may use REGEX to remove everything after .php (or whatever filetypes you are using).
Post Reply