Skip to content

Instantly share code, notes, and snippets.

@nmcv
Created August 18, 2013 16:00
Show Gist options
  • Save nmcv/6262374 to your computer and use it in GitHub Desktop.
Save nmcv/6262374 to your computer and use it in GitHub Desktop.
Dynamic FORM parameters against SQLMap et al.
<?php
/*
Sample script to illustrate the problem described here:
http://security.stackexchange.com/q/40811/20422
**/
// Based on UNIX timestamp in seconds hash
$timehash = sha1(time());
/*
@DEBUG
print($timehash);
print "<br>";
print substr($timehash, 0, strlen($timehash) / 2);
print "<br>";
print substr($timehash, -strlen($timehash) / 2);
@@
*/
// Generate one-time tokens
$username_nonce = ''; // substr($timehash, 0, strlen($timehash) / 2);
$password_nonce = ''; // substr($timehash, -strlen($timehash) / 2);
$db = mysqli_connect('localhost', 'root', 'root', 'demo_db', '8889');
if (!$db)
{
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
// Looking for anything that may look like
// our username and password field names
$keys = array_keys($_POST);
$usernameMatch = preg_grep('/^username(.*)$/', $keys);
$passwordMatch = preg_grep('/^password(.*)$/', $keys);
if (sizeof($usernameMatch) === 1 && sizeof($passwordMatch) === 1)
{
$usernameFieldName = array_values($usernameMatch);
$passwordFieldName = array_values($passwordMatch);
$username = $_POST[$usernameFieldName[0]];
$password = $_POST[$passwordFieldName[0]];
// Get the both parts of the hash back
$lHash = substr($usernameFieldName[0], strlen('username'));
$rHash = substr($passwordFieldName[0], strlen('password'));
//@DEBUG
//printf("Time hash:<br>%s<br>Reconstructed hash from client:<br>%s:%s",
// $timehash, $lHash, $rHash);
//@@
$found = false;
// If the request has been received within 3
// seconds of token generation...
for ($i=0;$i<=3;$i++)
{
if ( $lHash . $rHash === sha1(time()-$i) )
{
printf("<br>%s", "You nailed it!");
auth($db, $username, $password);
$found = true;
break;
}
}
// Too late submitting the form
if (!$found)
printf("<br>%s", "You are too slow...");
}
function auth($mysqli_link, $username, $password)
{
//@DEBUG
// printf("Username: %s, password: %s", $username, $password);
// printf("<br>%s", "SELECT * FROM settings WHERE user='${username}' AND password='${password}'");
//@@
if (isset($username) && isset($password))
{
// SQLi here ofc.
$result = mysqli_query($mysqli_link, "SELECT id, user, password FROM settings WHERE user='${username}' AND password='${password}'")
or die("<br/><br/>" ."Couldn't execute the query. " . mysqli_error($mysqli_link));
$row = mysqli_fetch_assoc($result);
if ($row)
{
// Dumps out on successful retrieval from DB
print("<br>Result dump:<br>");
var_dump($row);
}
}
}
?>
<doctype html>
<head>
<title>SQLMap dynamic parameters workaround</title>
</head>
<body>
<form id="sqliForm" action="<?=$_SERVER['SCRIPT_NAME']?>" method="POST">
<input id="username" type="text" name="username<?=$username_nonce?>">
<input id="password" type="password" name="password<?=$password_nonce?>">
<input type="submit" value="Submit">
</form>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha1.js"></script>
<script>
document.addEventListener
?
document.addEventListener('DOMContentLoaded', init, false )
:
document.attachEvent('onreadystatechange', init)
function init()
{
var form = document.getElementById('sqliForm');
form.addEventListener
?
form.addEventListener('submit', submitForm, false)
:
form.attachEvent('submit', submitForm);
}
function submitForm()
{
var u = document.getElementById('username');
var p = document.getElementById('password');
var ts = (new Date()).getTime().toString().substr(0, 10);
var hash = CryptoJS.SHA1(ts).toString();
u.name = 'username' + hash.substr(0, 20);
p.name = 'password' + hash.substr(20);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment