0

One of the sites that I manage includes a listing of press releases, each Press Release title acts a link to a detail page.

The title and the details are pulled from a mysql db.

The url link to the detail page is ../pr.php?ID=457

How can I prevent someone from adding sql injection code into the parameter?

The public site has no user input forms.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
david
  • 3
  • 1

3 Answers3

4

You can't. People who can make a network connection to the server can send whatever data they want.

You have to render the injection attempts harmless instead (and make sure you handle the cases where you get 0 rows back from the data in a sensible way, e.g. by sending a 404 Not Found response).

Community
  • 1
  • 1
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
1

In your example, I'm assuming that you need the ID parameter to be a nonzero positive integer, and nothing else. The answer from @Czarek is sufficient for that.

$id = (int) $_GET["ID"];

Or with th builtin function intval():

$id = intval($_GET["ID"]);

But both of these methods return 0 if the input has no integer value (e.g. "abc"), so you should be careful that an id of 0 isn't itself going to reveal something you don't intend users to have access to. It's likely that your id values start at 1, and if so that's safe.

You can also use PHP's builtin filter extension for more flexibility.

if (filter_has_var(INPUT_GET, "ID") && 
    filter_input(INPUT_GET, "ID", FILTER_VALIDATE_INT, array("min_range"=>1))
{
    $id = filter_input(INPUT_GET, "ID", FILTER_SANITIZE_NUMBER_INT);
    // then show data for $id
} else {
    // show default page
}

You may also be interested in:

Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
-1

Find a line of code that gets the ID from the url, it will be like this:

$ID = $_GET["ID"];

Change it to:

$ID = (int) $_GET["ID"];

Or even better and safer, at the top of the script add this:

$_GET["ID"] = (int) $_GET["ID"];

When you cast to INT there is no way anyone will be able to inject any sql into that variable. You should also check whether that variable from the url is used through $_GET variable, and not by $_REQUEST, or even worse by parsing the $_SERVER["QUERY_STRING"] manually.

Make sure that ID is the only variable passed in the url to that script, if there are more, then you need to secure all of them.

Securing variables that accept only Integer values is easy, you just need to make this conversion. It will be harder when variable can be of any string, then you need to use mysql_real_escape_string() on that string or similar, depending what type of database and driver you use.

If you need a full blown universal solution to sql injections, take a look to my another recent answer, that explains how to use PDO extension along with automatic data binding to prevent injections, link below:

stackoverflow.com/questions/8105508/does-this-work-to-stop-sql-injections/8105598#8105598

Community
  • 1
  • 1
Czarek Tomczak
  • 20,079
  • 5
  • 49
  • 56
  • Let's just hope you don't have a record with `id` of `0`. – PeeHaa Nov 13 '11 at 17:32
  • And what would be the difference with `0` ? Besides, no one keeps records with id of `0`. – Czarek Tomczak Nov 13 '11 at 17:38
  • casting to int on the string `test3` will return `0` in stead of the 'expected' `3`. http://codepad.org/Nrb5Wufb – PeeHaa Nov 13 '11 at 17:39
  • `Besides, no one keeps records with id of 0`. I wouldn't say no one. – PeeHaa Nov 13 '11 at 17:40
  • He provided the URL on the details page: `../pr.php?ID=457` => Products have integer values, they are not strings. So solution to this is as easy, as it is. – Czarek Tomczak Nov 13 '11 at 17:41
  • 1
    You must be kidding me, what is this -1? – Czarek Tomczak Nov 13 '11 at 17:47
  • I didn't give the downvote, but FWIW I don't agree that bound parameters are a "universal" solution. Parameters aren't a solution if you want you queries to include dynamic table names, column names, SQL keywords, expressions, etc. Parameterized queries are quite useful, but they're not the whole story of SQL injection defense. – Bill Karwin Nov 13 '11 at 21:47
  • 1
    Yeah, they are not the whole story, but let's say 99%(?) of the whole story. It all depends, for basic applications that's almost always all you need. In other cases, you just have to know what you're doing. – Czarek Tomczak Nov 13 '11 at 22:58