note 126029 added to function.extract
| From: | darrenforster99 at gmail dot com | 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