note 126029 added to function.extract

From: Date: Thu, 22 Apr 2021 07:38:09 +0000
Subject: note 126029 added to function.extract
Groups: php.notes 
Request: Send a blank email to php-notes+get-216311@lists.php.net to get a copy of this message
In response to Dan O'Donnell's note: "Presumably one easy way of dealing with this security issue is to use the EXTR_IF_EXISTS flag and make sure" Not necessarily - even using the EXTR_IF_EXISTS flag could be extremely dangerous - imagine this code running... <?php global $sql ; function runSql () { $result = $conn->query($sql); $conn-> close(); return $result; } function extractGet () { $name = '' ; $address = '' ; foreach ( $_GET as $key => $value ) $_GET[$key] = urldecode ( $value ) ; extract($_GET,EXTR_IF_EXISTS); $sql = str_replace ( '{NAME}', $name, $sql ) ; $sql = str_replace ( '{ADDRESS}', $address, $sql ) ; } function outputResult ( $res ) { echo '<pre>'.print_r ( $res->fetch_array(MYSQLI_NUM) ).'</pre>' ; } $sql = 'SELECT postcode FROM Customers WHERE name={NAME} AND address={ADDRESS}'; extractGet () ; $res = runSql () ; outputResult ( $res ) ; ?> Now can you see a massive security issue here... seems all well and good if we had a url like mycode.php?name=joe%20bloggs&address=20%20Any%20Street as that would specifically find joe bloggs of 20 any street. however what if someone typed in mycode.php?sql=SELECT%20password%20FROM%20Customers or even worse mycode.php?sql=DELETE%20from%20Customers The problem here is that even though as far as you're aware you defined both name and address as the only two empty variables within that function - you may have forgotten about global variables, and these global variables could cause major security issues In the example above $sql is defined as "SELECT postcode FROM Customers WHERE name={NAME} AND address={ADDRESS}" which seems all well and good, and safe, and then later on str_replace in the extractGet function replaces {NAME} and {ADDRESS} with the name and address variables from $_GET - but if GET contains an SQL variable then that would overwrite the global $sql variable before the str_replace function - and if the str_replace function finds no matches it just returns the original string - in the above two examples the SQL string would be "SELECT password FROM Customers" which in the example outputResult just prints the data retrieved from the database and so in this stage it could print all the customers passwords (hopefully encrypted!) to the screen (oops!) or in the second example the SQL string would be "DELETE from Customers" - with no WHERE clause that would delete all the data from the Customers table and of course a combination of SELECT table_name FROM information_schema.tables and DROP TABLE <table_name> could be a real disaster! Of course, this is only a basic example, but it could be quite easy to forget about global variables and these global variables could quite easily be used with extract to cause serious security risks if GET, REQUEST or POST is sent to extract! ---- Server IP: 45.112.84.4 Probable Submitter: 45.112.85.242 (proxied: 185.130.159.112) ---- Manual Page -- https://php.net/manual/en/function.extract.php Edit -- https://main.php.net/note/edit/126029 Del: integrated -- https://main.php.net/note/delete/126029/integrated Del: useless -- https://main.php.net/note/delete/126029/useless Del: bad code -- https://main.php.net/note/delete/126029/bad+code Del: spam -- https://main.php.net/note/delete/126029/spam Del: non-english -- https://main.php.net/note/delete/126029/non-english Del: in docs -- https://main.php.net/note/delete/126029/in+docs Del: other reasons-- https://main.php.net/note/delete/126029 Reject -- https://main.php.net/note/reject/126029 Search -- https://main.php.net/manage/user-notes.php

« previous php.notes (#216311) next »