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.
Example 27.2. Splitting the result set into pages ... and making superusers (PostgreSQL)
<?php
$offset = $argv[0]; // beware, no input validation!
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);
?>
Normal users click on the 'next', 'prev' links where the $offset is encoded into the URL. The script expects that the incoming $offset is a decimal number. However, what if someone tries to break in by appending a urlencode()'d form of the following to the URL
0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
select 'crack', usesysid, 't','t','crack'
from pg_shadow where usename='postgres';
--
If it happened, then the script would present a superuser access to him. Note that 0; is to supply a valid offset to the original query and to terminate it.
What does urlencode here?May someone explain more about this attack?
urlencode() will allow this long string with newlines etc. to be correctly copy/pasted in a browser address bar.
If you use HTML forms instead, the browser does urlencode() automatically.
0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,pass wd)
select 'crack', usesysid, 't','t','crack'
from pg_shadow where usename='postgres';
--
<?php
$str = "abcdef?%!@#$%^&*(";
echo urlencode($str);
// This will display: abcdef%3F%25%21%40%23%24%25%5E%26%2A%28
?>
In your example, since the $offset variable is numeric, you don't need to use urlencode. Instead, you can cast the variable to an integer, which prevents any injections.
If someone tries to use an injection, the offset variable will automatically become "0".
<?php
$offset = (int)$argv[0]; // Cast to an integer. If the argument is not a number, it will become 0
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);
?>