This topic is locked
[SOLVED]

 security XMLHttpRequest

11/4/2011 5:04:17 AM
PHPRunner General questions
M
mickna author

Hi there,
in some importPage events I use an additional drop down to get some necessary data.

The values are submitted to the server via Ajax (XMLHttpRequest) The result of this request ends obviously in a variable, send as:

..../myTable_import.php?q=DropDownValue



I use the variable "q" in "importPage Before Insert Record" in a SQL WHERE clause:

SELECT ... FROM ... WHERE ... AND 'select'='$q'


Now I ask myself, if it is recommend to filter somehow the send variable "q" before processing (Cross-Site-Scripting)?

And if so, how should I do this? I have no idea if there are some native php functions, or if I need some lines of code to "clean" the variable.
Hints, Tips and Tricks are welcome.

Thanks

mickna

C
cgphp 11/4/2011

Use post instead of get for posting data. Filter the q value using a conditional statement like this:

if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' && isset($_POST['q']) && !empty($_POST['q']))

{

$query = "SELECT ... FROM ... WHERE ... AND select='".$q."'";

}
M
mickna author 11/4/2011

Hi Christian,
thank you.

I'll guess I have to change more. If I just insert "POST" instead of "GET" I do not receive my selection....
My custom PHP code:
Somewhere I build up the drop down and call (only the call routine here) my script:

$output = '<select name="colTarget" size="1" onChange="slectedCol(this.value)">';


and my script looks like this:

echo '<script type="text/javascript">

function slectedCol(str)

{

if (str=="")

{return;}

if (window.XMLHttpRequest)

{// code for IE7+, Firefox, Chrome, Opera, Safari

xmlhttp=new XMLHttpRequest();

}

else

{// code for IE6, IE5

xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

}

xmlhttp.open("GET","'.$strTableName.'_import.php?q="+str,true);

xmlhttp.send();

}

</script>';
if ($_GET["q"]) {

$_SESSION["select"]=$_GET["q"];}

echo $output;


At before Insert I use then $_SESSION["select"]
I changed all three GET to POST, but this seams to be false...

C
cgphp 11/4/2011
echo "<script type='text/javascript'>

function slectedCol(str)

{

if (str=="")

{return;}

$.ajax({

url: '".$strTableName."_import.php',

type: 'POST',

data: 'q='+str

});
}

</script>';
if($_POST["q"]) {

$_SESSION["select"]=$_POST["q"];}

echo $output;
M
mickna author 11/4/2011

I am sorry Christian.

No Data for $_SESSION["select"]
With GET I'll receive the values in $_SESSION["select"].....

C
cgphp 11/4/2011

In the "After Application initialized" event enter this code:

if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest')

{

if(basename($_SERVER['PHP_SELF']) == 'yourimportpagename_import.php')

{

if(isset($_POST["q"]) && !empty($_POST["q"]))

{

$_SESSION["select"]=$_POST["q"];

}

}

}


Update your script to the following:

echo "<script type='text/javascript'>

function slectedCol(str)

{

if (str=="")

{return;}

$.ajax({

url: '".$strTableName."_import.php',

type: 'POST',

data: 'q='+str

});
}

</script>';
echo $output;
M
mickna author 11/4/2011

Again thank you.

I have not tried yet. But may be you can do me a favor:

Why should I switch do Post? Is Get more insecure than post?
Your filter from your first answer should also work with get - or?
Thank you so much for your time!

mickna

M
mickna author 11/4/2011

Ok!
Found the answer in general:
"Sending user input (which can contain unknown characters), POST is more robust and secure than GET"
Thx!

Sergey Kornilov admin 11/4/2011

Sending data via POST is more robust but doesn't provide any additional security.
In both POST/GET cases you need to sanitize your input. Use mysql_real_escape_string() function for this purpose:

http://php.net/manual/en/function.mysql-real-escape-string.php

M
mickna author 11/4/2011

Thank you Sergey,
my solution was so fare to use preg_replace to filter and after this I cut the string, as the field in my Database is only set to 20 Characters and so there is no need for a longer string / code



$search = array('/<\?((?!\?>).)*\?>/s');

$new = strip_tags(preg_replace($search, '', $_GET["q"]));

$new = substr($new, 0, 20); //cut the name after 20 characters as this matches with the mySQL table

$_SESSION["select"]=$new;


@Cristian:

Unfortunately I have several customized import pages. So I can not tell in "After Application initialized" which table ('yourimportpagename_import.php') will be used....

Sergey Kornilov admin 11/4/2011

You doing it wrong way. Here is the example of URL that will destroy data in your database.
...list.php?q=a';delete from users;'

C
cgphp 11/4/2011



Thank you Sergey,
my solution was so fare to use preg_replace to filter and after this I cut the string, as the field in my Database is only set to 20 Characters and so there is no need for a longer string / code



$search = array('/<\?((?!\?>).)*\?>/s');

$new = strip_tags(preg_replace($search, '', $_GET["q"]));

$new = substr($new, 0, 20); //cut the name after 20 characters as this matches with the mySQL table

$_SESSION["select"]=$new;


@Cristian:

Unfortunately I have several customized import pages. So I can not tell in "After Application initialized" which table ('yourimportpagename_import.php') will be used....


You can create an array with import page names as values and looping through it to find the current import page.

$import_pages = array('page_name_import_1.php','page_name_import_2.php','page_name_import_3.php','','',.......);
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest')

{

foreach($import_pages as $page)

{

if(basename($_SERVER['PHP_SELF']) == $page)

{

if(isset($_POST["q"]) && !empty($_POST["q"]))

{

$_SESSION["select"]=$_POST["q"];

}

break;

}

}

}
M
mickna author 11/4/2011

Nice! Thank you.
I would like to say: "You rock!" <img src='https://asprunner.com/forums/file.php?topicimage=1&fieldname=reply&id=62020&image=1&table=forumreplies' class='bbc_emoticon' alt=':)' />

M
mickna author 11/4/2011

ShitShitShit!
So if I use mysql_real_escape_string I am (more or less) save? :

$new = mysql_real_escape_string($_GET["q"]); //clean the input to prevent XXS

$new = substr($new, 0, 20); //cut the name after 20 characters as this matches with the mySQL table. Also to prevent some XSS

$_SESSION["select"]=$new;




You doing it wrong way. Here is the example of URL that will destroy data in your database.
...list.php?q=a';delete from users;'

Sergey Kornilov admin 11/4/2011

Yes, that would do it. Just in case truncate it first and then apply mysql_real_escape_string().

M
mickna author 11/6/2011



Yes, that would do it. Just in case truncate it first and then apply mysql_real_escape_string().


Again thanks to you both!