From: Operating system: PHP version: Irrelevant Package: MySQL related Bug Type: Feature/Change Request Bug description:Untrusted input variables tagging to detect and prevent SQL injection
Description: ------------ I propose that PHP tag bytes in variables that come from untrusted sources such as user input (eg. $_GET $_POST $_COOKIE $_REQUEST etc..) or read from the database. For each php variable, there would be a piece of metadata that defines the byte ranges in that variable containing bytes from untrusted sources. This metadata would be updated whenever any php code or function changed the contents of a variable. This is a very simple concept in theory, but I am not sure how difficult it would be to implement in php. The mysql functions such as mysql_query() can then use the metadata to differentiate between bytes that come from untrusted sources from the part of the query that the programmer wrote. eg. in my test script below, mysql_query() would know that the $username and $password parts in the $query variable are untrusted and must be escaped. The php mysql functions can then alter the query to automatically add escaping before passing it on to mysql database thus making all SQL injection exploits obsolete without needing to rewrite any php code. This would work similar to magic quotes, without the problem of double escaping or display errors when the variables are displayed on a webpage instead of used in a database. A color diagram should make my idea more clear. http://img690.imageshack.us/img690/3313/mysqlinjection.png Test script: --------------- <?php // username and password variables vulnerable to SQL injection // Example exploit http://server/test.php?username=john&password=' OR 1=1 -- $username = $_GET['username']; $password = $_GET['password']; $query = "SELECT * FROM `users` WHERE `username` = '$username' AND `password` = '$password' "; $result = mysql_query ( $query ); ?> Expected result: ---------------- mysql_query() would change the query to SELECT * FROM `users` WHERE `username` = 'john' AND `password` = '\' OR 1=1 --' Actual result: -------------- The query that gets executed SELECT * FROM `users` WHERE `username` = 'john' AND `password` = '' OR 1=1 --' -- Edit bug report at https://bugs.php.net/bug.php?id=61708&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=61708&r=trysnapshot54 Try a snapshot (PHP 5.3): https://bugs.php.net/fix.php?id=61708&r=trysnapshot53 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=61708&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=61708&r=fixed Fixed in SVN and need be documented: https://bugs.php.net/fix.php?id=61708&r=needdocs Fixed in release: https://bugs.php.net/fix.php?id=61708&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=61708&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=61708&r=needscript Try newer version: https://bugs.php.net/fix.php?id=61708&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=61708&r=support Expected behavior: https://bugs.php.net/fix.php?id=61708&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=61708&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=61708&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=61708&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=61708&r=php4 Daylight Savings: https://bugs.php.net/fix.php?id=61708&r=dst IIS Stability: https://bugs.php.net/fix.php?id=61708&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=61708&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=61708&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=61708&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=61708&r=mysqlcfg