Forum Moderators: coopster

Message Too Old, No Replies

Site Search sql injection attack

how to stop sql injection attack on site search

         

ski442

2:18 pm on Dec 12, 2009 (gmt 0)

10+ Year Member



Hi Guys,
A bit of help needed with protection. I found this script and have been playing with and works well, just need two points of help.

1- Is preg_match the same as sql injection attack prevention or do i need both? if so how to implement on this script.

<?php
if(isset($_POST['submit'])){
if(isset($_GET['go'])){
if(preg_match("/^[ a-zA-Z0-9]+/", $_POST['name'])){
$name=$_POST['name'];
//connect to the database
virtual('/include.php');

//-query the database table
$sql="SELECT id, stockcode, title, price FROM products WHERE stockcode LIKE '%" . $name . "%' OR title LIKE '%" . $name ."%' OR discription LIKE '%" . $name . "%' ";
//-run the query against the mysql query function
$result=mysql_query($sql);
//-create while loop and loop through result set
while($row=mysql_fetch_array($result)){
$stockcode =$row['stockcode'];
$title=$row['title'];
$price =$row['price'];

//-display the result of the array
echo "<ul>\n";
echo "<li>" . "<a href=\"tvlisting.php?id=$stockcode\">" . $stockcode . " " . $title . " " . $price . "</a></li>\n";
echo "</ul>";
}
}
else{
echo "<p>Please enter a search query</p>";
}
}
}
?>

2- I would like to add in this segment of script
<img src=\"pictures\$stockcode_nail.jpg\">
to this line
echo "<li>" . "<a href=\"tvlisting.php?id=$stockcode\">" . $stockcode . " " . $title . " " . $price . "</a></li>\n";

I have tried a number of veriations but I don't know where I am going wrong.
echo "<li>" . "<a href=\"tvlisting.php?id=$stockcode\"><img src=\"pictures\"$stockcode"_nail.jpg\">" . $stockcode . " " . $title . " " . $price . "</a></li>\n";

even tried these
\?id=$stockcode_nail.jpg
\" . $stockcode . "_nail.jpg
Thanks in advance
Ski442

ski442

8:33 pm on Dec 14, 2009 (gmt 0)

10+ Year Member



I have now sorted problem number 2 with this

echo "<li>" . "<a href=\"tvlisting.php?id=$stockcode\"><img src=\"/pictures/" . $stockcode . "_nail.jpg\"/>" . $stockcode . " " . $title . " " . $price . "</a></li>\n";

So just need advice on sql_injection attack please.
Thanks
Ski442

CyBerAliEn

9:09 pm on Dec 15, 2009 (gmt 0)

10+ Year Member



Concerning number one...

Your idea is solid. Use regular expressions to check or cleanse your user input, always. However, your code checks the input against a pattern, then if it is an intended match, you then use the raw user input later on. They're the same thing, but I just don't like this lol...

I'll have to check my coding library later when I get on my laptop to see the specific function/pattern to use... but the idea is that you want to do something ~like:

$name = regExpFunc('the pattern',$_POST['name']);

And then the wherever you want to use the "name value", you just straight up use it. I use this methodology to clean every user input before I use it (even if it isn't for a database). For example, most form fields are sufficient with just raw alpha characters... you could apply a pattern/filter to strip out all non-alpha characters; and more.

Even AFTER doing the above to user input, I always like to run database input through this function just to be extra safe:

$useThisInDatabaseQueries = mysql_real_escape_string($userInputHere);

Best of luck! Sorry I can't be more specific at this moment, but I have to run off to take a final.

CyBerAliEn

4:09 pm on Dec 16, 2009 (gmt 0)

10+ Year Member



To follow up...

On most of the sites I work on, I include "modules" of useful/relevant functions that I employ on the site... everything from common time/string manipulation to file handling. A common function I use is a "clean" function which I use to cleanse user input before it is even handled.

For example, suppose I have a form field that asks for a user's first name. Or maybe a field asking for an age. On the side where it is processed/used, I would simply access it as:


<?php
$firstname = clean($_REQUEST['firstname'],'standard');
$age = clean($_REQUEST['age'],'numeric');
?>

The above insures that 'firstname' and 'age' only contain what's expected; because anything not specified in the filter/pattern is stripped out and removed. So if I know I want/get numeric values from the user, I'll just have it strip out any non-numeric character. In most cases, this is easy and straightforward to employ. On different sites, I use different incarnations of this function: some will employ trimming, some will cap the length, etc. And you can specify as many patterns/filters as you want by just adding another array entry into the function.

Understand that this specific function is a "cleaning" function --- it strips out anything you don't want in the string. If you're looking for matching (ie: is this string a real/valid SS#, etc)... then you want to use appropriate regular expressions and functions for matching. You could easily modify this function or create a new one that performs easy matching requests, ie: match($string,'socialsecuritynumber'); [etc].

If I were to use user input in a query, I would also still use PHP's mySQL real escape function just to be extra safe.

Should you use this code? It is up to you. It's just one tidbit example of what you can do. You can modify the function to fit your needs, optimize it, etc... but it might give you an insight into options available to you. I like this approach because I use a lot of user input all over the place... and it is a lot easier for me to simply "clean" the input with an identifier filter (basic, alpha, etc) instead of continuously referencing the replace function and regular expression over-and-over (my preference).


<?php
function clean($str,$type="standard",$replace="blank",$strip="true")
{
//...Purpose...
//Strips code, adds slashes, etc.
//...Variables...
$output = "";
$input = $str;
$patterns = array();
$patterns['standard'] = "/[^a-zA-Z0-9 \.\,\:\;\(\)]/";
$patterns['basic'] = "/[^a-zA-Z0-9]/";
$patterns['alphanumeric'] = "/[^a-zA-Z0-9]/";
$patterns['numeric'] = "/[^0-9]/";
$patterns['alpha'] = "/[^a-zA-z]/";
$patterns['alphanumericplus'] = "/[^a-zA-Z0-9 \\n\.\-\_\(\)\,\:\?\/\;\'\"\#\&\@\!]/";
$patterns['file'] = "/[^a-zA-Z0-9\.\_\-]/";
$patterns['filepath'] = "/[^a-zA-Z0-9\.\_\-\/]/";
$replaces = array();
$replaces['blank'] = "";
$replaces['debug'] = "<b>X</b>";
$pattern = $patterns[$type];
if ($pattern=="") { $pattern = $patterns['standard']; }
$replace = $replaces[$replace];
//...Process...
if ($str!="")
{
$now = $str;
if ($strip=="true") { $now = strip_tags($now); }
$now = preg_replace($pattern,$replace,$now);
if ($strip=="true") { $now = str_replace("\"","&quot;",$now); }
if ($strip=="true") { $now = addslashes($now); }
$output = $now;
}
//...Output...
return $output;
}
?>

Note... my code is tabbed but this forum doesn't seem to like tabs --- but the idea/code is still the same.

ski442

4:10 pm on Dec 28, 2009 (gmt 0)

10+ Year Member



Hi CyBerAliEn
Thanks very much for your time to explain and to publish your function.
My user input field is just for a site search.
So your Clean function, I think will be great, along with mysql_real_escape as sugest.
Thanks very much.
Ski442

FourDegreez

7:39 pm on Dec 29, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If I may make one general suggestion, it would be to make the switch-over to PDO [php.net] instead of the mysql_ functions. PDO should be available on most PHP5 installations. I made the switch awhile ago and never looked back.