Page 1 of 1

Protecting against client attack without MySQL present?

Posted: Sun Jul 05, 2009 9:01 pm
by JAB Creations
I've been redoing my site's PHP preference class and since it doesn't directly interact with MySQL PHP doesn't seem to allow me to use mysql_real_escape_string. I'm trying to avoid an elongated attack like...having $_POST set to $_SESSION, and since I can't set mysql_real_escape_string in one place it would later open up a security hole if I continued to not use mysql_real_escape_string on $_SESSION. Right now I don't have anything live susceptible to this and I've been tracking down $_SESSION on the version of my site I'm working on right now for the just-in-case scenario. However as far as the forum thread is concerned I'm wondering how to protect against this kind of scenario up front (in the PHP class) versus only relying on when I have PHP execute a MySQL query?

Here is what I've coded today which will eventually morph in to the new version of the PHP preferences class...

Code: Select all

<?php
 
$default = array(
'audio'=>'0',
'broadbandimages'=>'0',
'checkbox'=>'0',
'columns'=>'1',
'connection'=>'0',
'css3'=>'0',
'csspatch'=>'1',
'cursors'=>'0',
'dhtmleffects'=>'0',
'dtd'=>'1',
'initialfocus'=>'search_query',
'keyboardlayout'=>'developer',
'mediatype'=>'ns',
'pagination'=>'form',
'personality'=>'0',
'powerkeys'=>'0',
'sidebar'=>'20',
'sounds'=>'0',
'theme'=>'classic'
);
 
 
$c = count($default);
$i = 0;
foreach($default as $type=>$default)
{
 $$type = client($type, $default);
 
 $i++;
 if (isset($cookie_value)) {$cookie_value .= $type.'.'.$$type; if ($c!=$i) {$cookie_value .='_';}}
 else {$cookie_value = $type.'.'.$$type.'_';}
}
 
function client($type, $default)
{
 if (isset($_GET[$type])) {/*echo '<div>'.$type.' = <b>GET</b> = '.$_GET[$type].'</div>'."\n"; */return mysql_real_escape_string($_GET[$type]);}
 else if (isset($_POST[$type])) {/*echo '<div>'.$type.' = <b>POST</b> = '.$_POST[$type].'</div>'."\n"; */return mysql_real_escape_string($_POST[$type]);}
 else if (isset($_SESSION[$type])) {/*echo '<div><b>'.$type.' = <b>$_SESSION</b> = '.$_SESSION[$type].'</div>'."\n"; */return $_SESSION[$type];}
 else if (isset($_COOKIE['settings']))
 {
  $pieces = explode('_', $_COOKIE['settings']);
  $c = count($pieces);
  $i = 0;
  foreach($pieces as $value)
  {
   $value = explode('.', $value);
   $i++;
   if ($value[0]==$type && $value[1] != '') {/*echo '<div>'.$type.' = <b>$COOKIE</b> = '.$value[1].'</div>'."\n"; */return mysql_real_escape_string($value[1]);}
   else if ($c==$i) {/*echo '<div>'.$type.' = <b>Default</b> = '.$default.'</div>'."\n"; */return $default;}
  }
 }
 else {/*echo '<div>'.$type.' = <b>Default</b> = '.$default.'</div>'."\n"; */return $default;}
}
 
if (!headers_sent()) {setcookie('settings',$cookie_value,time()+2592000,'/'); echo '<p>ok now echo stuff!</p>';}
 
 
echo '<br /><br />'."\n".'<div>$audio = '.$audio.'</div>'."\n";
echo '<div>$broadbandimages = '.$broadbandimages.'</div>'."\n";
echo '<div>$checkbox = '.$checkbox.'</div>'."\n";
echo '<div>$columns = '.$columns.'</div>'."\n";
echo '<div>$connection = '.$connection.'</div>'."\n";
echo '<div>$css3 = '.$css3.'</div>'."\n";
echo '<div>$csspatch = '.$csspatch.'</div>'."\n";
echo '<div>$cursors = '.$cursors.'</div>'."\n";
echo '<div>$dhtmleffects = '.$dhtmleffects.'</div>'."\n";
echo '<div>$dtd = '.$dtd.'</div>'."\n";
echo '<div>$initialfocus = '.$initialfocus.'</div>'."\n";
echo '<div>$keyboardlayout = '.$keyboardlayout.'</div>'."\n";
echo '<div>$mediatype = '.$mediatype.'</div>'."\n";
echo '<div>$pagination = '.$pagination.'</div>'."\n";
echo '<div>$personality = '.$personality.'</div>'."\n";
echo '<div>$powerkeys = '.$powerkeys.'</div>'."\n";
echo '<div>$sidebar = '.$sidebar.'</div>'."\n";
echo '<div>$sounds = '.$sounds.'</div>'."\n";
echo '<div>$theme = '.$theme.'</div>'."\n";
echo '<br /><br />'.$cookie_value;
?>
*EDIT* - After doing a thorough I found search all $_SESSION variables use mysql_real_escape_string before being used before data was put in to a MySQL query. :)

Re: Protecting against client attack without MySQL present?

Posted: Sun Jul 05, 2009 10:59 pm
by jackpf
You mean addslashes is run on it? As in, you have magic quotes turned on?

If so, you really shouldn't rely on them...they're stupid and irritating, deprecated in newer versions of php, and might not be turned on on other servers.

And I'm not really sure I understand...why would you want to use mysql_real_escape_string() if you're not executing any queries?

Re: Protecting against client attack without MySQL present?

Posted: Sun Jul 05, 2009 11:32 pm
by JAB Creations
I'm trying to avoid indirectly trusting clientside data...

Client-->$_POST-->$_SESSION['variable']-->$mysql_query

We know we're supposed to check $_POST, $_GET, etc. Thankfully I didn't have have $_SESSION variables being used without mysql_real_escape_string, however I still like the idea of protecting against an attack at the front door...rather then at an inner door (to a room, closet, bathroom, etc sort of analogy).

Re: Protecting against client attack without MySQL present?

Posted: Mon Jul 06, 2009 5:59 am
by kaisellgren
If you have data that goes to the database, escape it, if not, don't escape it.

If I understood correctly, you are passing $_SESSION data into the database at some point?
JAB Creations wrote:PHP doesn't seem to allow me to use mysql_real_escape_string. I'm trying to avoid an elongated attack like...having $_POST set to $_SESSION, and since I can't set mysql_real_escape_string in one place it would later open up a security hole if I continued to not use mysql_real_escape_string on $_SESSION.
The reason why you cannot use the function without a database connection is simply due to the fact that the function is not aware of the encoding used in the MySQL server. It needs to have the connection. What you should do is to just place the $_POST data on $_SESSION, and whenever you pass $_SESSION data into your SQL queries, then escape them. The escaping process should always be the very last thing to do before passing something into queries.
JAB Creations wrote:Client-->$_POST-->$_SESSION['variable']-->(escape)-->$mysql_query
I still like the idea of protecting against an attack at the front door...rather then at an inner door (to a room, closet, bathroom, etc sort of analogy).
The escaping should be done just before passing anything to the database. Having escaping done at an inner door is no less secure than doing it at the front door, because you have had the control over the data from the very beginning (when it entered your house). That's exactly what prepared statements do, they escape when data is about to enter the database.

Escaping data, which is later processed, is actually less secure. For example, escaping some $_POST data and then processing them (e.g. copying the data to $_SESSION) is just less secure, because this creates a trust. You would be blindly trusting the $_SESSION to contain only escaped data. There are three ways to have your sessions altered by an intruder: session storage attacks, session poisoning attacks and session transportation attacks. Even though these kinds of attacks are rare and may be protected against, it will always be questionable whether you can trust $_SESSION at all.

Just escape the data before passing it on the database. This will also simplify your code.

Edit: You have a couple of lines in your code like this:

Code: Select all

mysql_real_escape_string($_GET[$type]);
That does not change anything.. It would need to be:

Code: Select all

$_GET[$type]= mysql_real_escape_string($_GET[$type]);
and now the $_GET[$type] would be escaped. Isn't that what the code was supposed to do?

Re: Protecting against client attack without MySQL present?

Posted: Mon Jul 06, 2009 8:30 am
by jackpf
Plus, what if you're not running your session data in a query?

Then it's got slashes added to it...which is jst a pain.

addslashes is removed in version 6 I think, so I really wouldn't use it if I were you.

Re: Protecting against client attack without MySQL present?

Posted: Mon Jul 06, 2009 6:33 pm
by JAB Creations
Ok, looks like I really don't have to change anything...and I removed the escapes from the PHP settings (to yet be a) class I posted above. I just wanted to make sure I had my bases covered, thanks guys. :)