SQL Injection Filter Bypassing v0.4


Note: This application does not require any database.

Code:

<!DOCTYPE html>
<html>
<head>
<title>SQL Injection Filter Bypassing v0.4</title>
<style>
hr {margin:24px 0;}
</style>
</head>
<body>
<h1>SQL Injection Filter Bypassing v0.4</h1>
<?php
$filter = array(
'syntax' => array(
'union' => array('caption' => 'UNION','filter' => 'union'),
'select' => array('caption' => 'SELECT','filter' => 'select'),
'from' => array('caption' => 'FROM','filter' => 'from'),
'where' => array('caption' => 'WHERE','filter' => 'where'),
'limit' => array('caption' => 'LIMIT','filter' => 'limit'),
'wait_for' => array('caption' => 'WAIT FOR','filter' => 'wait for'),
'group_by' => array('caption' => 'GROUP BY','filter' => 'group by'),
'order_by' => array('caption' => 'ORDER BY','filter' => 'order by'),
'into' => array('caption' => 'INTO', 'filter' => 'into'),
'file' => array('caption' => 'FILE', 'filter' => 'file'),
'outfile' => array('caption' => 'OUTFILE', 'filter' => 'outfile'),
'infile' => array('caption' => 'INFILE', 'filter' => 'infile'),
'having' => array('caption' => 'HAVING', 'filter' => 'having'),
'truncate' => array('caption' => 'TRUNCATE', 'filter' => 'truncate'),
'insert' => array('caption' => 'INSERT','filter' => 'insert'),
'update' => array('caption' => 'UPDATE','filter' => 'update'),
'delete' => array('caption' => 'DELETE','filter' => 'delete'),
'droptable' => array('caption' => 'DROPTABLE','filter' => 'droptable'),
'case' => array('caption' => 'CASE', 'filter' => 'case'),
),
'operators' => array(
'and' => array('caption' => 'AND','filter' => 'and'),
'&&' => array('caption' => '&&','filter' => '&&'),
'or' => array('caption' => 'OR','filter' => 'or'),
'||' => array('caption' => '||','filter' => '\|\|'),
'=' => array('caption' => '=', 'filter' => '='),
'<>' => array('caption' => '<>', 'filter' => '<>'),
'like' => array('caption' => 'LIKE','filter' => 'like'),
'is' => array('caption' => 'IS','filter' => 'is'),
'not' => array('caption' => 'NOT','filter' => 'not'),
'if' => array('caption' => 'IF','filter' => 'if'),
'null' => array('caption' => 'NULL','filter' => 'null')
),
'functions' => array(
'benchmark' => array('caption' => 'BENCHMARK','filter' => 'benchmark'),
'hex' => array('caption' => 'HEX','filter' => 'hex'),
'unhex' => array('caption' => 'UNHEX','filter' => 'unhex'),
'substr' => array('caption' => 'SUBSTR','filter' => 'substr'),
'mid' => array('caption' => 'MID','filter' => 'mid'),
'extractvalue' => array('caption' => 'ExtractValue','filter' => 'extractvalue'),
'concat' => array('caption' => 'CONCAT', 'filter' => 'concat'),
'concat_ws' => array('caption' => 'CONCAT_WS','filter' => 'concat_ws'),
'group_concat' => array('caption' => 'GROUP_CONCAT','filter' => 'group_concat'),
'mod' => array('caption' => 'MOD','filter' => 'mod'),
'load_file' => array('caption' => 'LOAD_FILE','filter' => 'load_file'),
'cast' => array('caption' => 'CAST', 'fitler' => 'cast'),
),
'misc' => array(
'--' => array('caption' => '--','filter' => '--'),
'#' => array('caption' => '#','filter' => '#'),
'/*' => array('caption' => '/*','filter' => '\/\*'),
)
);
if (!empty($_POST)) {
$case = (isset($_POST['case'])) ? $_POST['case'] : 'lower';
$method = (isset($_POST['method'])) ? $_POST['method'] : 'string';
$injection = $_POST['injection'];
$mods = '';
if ($case == 'both') { $mods .= 'i'; }
$parts = array();
if (isset($_POST['filter'])) {
foreach ($_POST['filter'] as $type => $keyword) {
foreach ($keyword as $k => $state) {
$key = $filter[$type][$k]['filter'];
if ($case == 'upper') {
$used[$k] = strtoupper($key);
$parts[] = strtoupper($key);
} elseif ($case == 'lower') {
$used[$k] = strtolower($key);
$parts[] = strtolower($key);
} else {
$used[$k] = $key;
$parts[] = $key;
}
}
}

$filters = implode('|',$parts);

#if ($method == 'integer') { $used['\''] = '\\\''; $used['\"'] = '\\\"'; $filters .= '|\'|\"'; }
if ($method == 'integer') { $used['\''] = '\\\''; $user['\"'] = '\\\"'; $filters .= '|\'|\"'; }

if (preg_match_all("/{$filters}/{$mods}", $injection, $matches)) {
$matched = array();
for ($i = 0;$i <= (sizeof($matches[0])-1);$i++) {
$matched[] = $used[strtolower($matches[0][$i])];
}
$matched = implode('|', $matched);
$injection = preg_replace("/({$matched})/{$mods}", '<span style="color:red;">\1</span>', $injection);
$triggers = array_unique($matches[0]);
$triggers = implode(', ', $triggers);
if ($method == 'string') {
$query = "SELECT * FROM table WHERE column = '{$injection}'";
} else {
$query = "SELECT * FROM table WHERE column = {$injection}";
}
echo "<hr><h2>Result: Filtered</h2><strong>Triggers:</strong> {$triggers}<br /><br />{$query}<hr>";
} else {
if ($method == 'string') {
$query = "SELECT * FROM table WHERE column = '{$injection}'";
} else {
$query = "SELECT * FROM table WHERE column = {$injection}";
}
echo "<hr><h2>Result: Passed</h3>{$query}<hr>";
}
} else {
if ($method == 'integer') {
if (!isset($filters)) { $used['\''] = '\\\''; $user['\"'] = '\\\"'; $filters = '|\'|\"'; }
if (preg_match_all("/{$filters}/{$mods}", $injection, $matches)) {
$matched = array();
for ($i = 0;$i <= (sizeof($matches[0])-1);$i++) {
if (isset($used[strtolower($matches[0][$i])])) {
$matched[] = $used[strtolower($matches[0][$i])];
}
}
$matched = implode('|', $matched);
$triggers = array_unique($matches[0]);
$triggers = implode(', ', $triggers);
$injection = preg_replace("/({$matched})/{$mods}", '<span style="color:red;">\1</span>', $injection);
if ($method == 'string') {
$query = "SELECT * FROM table WHERE column = '{$injection}'";
} else {
$query = "SELECT * FROM table WHERE column = {$injection}";
}
echo "<hr><h2>Result: Filtered</h2><strong>Triggers:</strong> {$triggers}<br /><br />{$query}<hr>";
}
} else {
if ($method == 'string') {
$query = "SELECT * FROM table WHERE column = '{$injection}'";
} else {
$query = "SELECT * FROM table WHERE column = {$injection}";
}
echo "<hr><h2>Result: Passed</h2>{$query}<hr>";
}
}
}
?>
<form name="keywords" method="post" action="">
<input type="text" name="injection" style="width:500px;" autofocus="true" value="<?php echo (isset($_POST['injection'])) ? $_POST['injection'] : ''; ?>">
<input type="submit" value="Execute"><br />
<?php $case = (isset($_POST['case'])) ? $_POST['case'] : 'both'; ?>
<?php $method = (isset($_POST['method'])) ? $_POST['method'] : 'string'; ?>
Case: <input type="radio" name="case" value="both"<?php echo ($case == 'both') ? ' checked' : ''; ?>> Any
<input type="radio" name="case" value="lower"<?php echo ($case == 'lower') ? ' checked' : ''; ?>> Lowecase
<input type="radio" name="case" value="upper"<?php echo ($case == 'upper') ? ' checked' : ''; ?>> Uppercase<br />
Method: <input type="radio" name="method" value="string"<?php echo ($method == 'string') ? ' checked' : ''; ?>> String
<input type="radio" name="method" value="integer"<?php echo ($method == 'integer') ? ' checked' : ''; ?>> Integer<br />
Predefined filters: <select onchange="setPredefined()" id="predefined">
<option>Predefined</option>
<option value="1">AND, OR, NULL, WHERE, WHILE</option>
<option value="2">UNION, SELECT, FROM, HAVING</option>
<option value="5">UNION, SELECT, FROM, WHERE</option>
<option value="3">INTO, FILE, CASE</option>
<option value="4">GROUP BY, ORDER BY, HAVING, LIMIT</option>
</select>
<table border="1" cellpadding="4" cellspacing="0" style="border:1px solid #000000;border-collapse:collapse;width:600px;">
<thead>
<th style="width:25%;">SYNTAX</th>
<th style="width:20%;">OPERATORS</th>
<th style="width:30%;">FUNCTIONS</th>
<th style="width:25%;">MISC</th>
</thead>
<tbody>
<tr>
<td valign="top">
<?php
foreach($filter['syntax'] as $key => $keyword) {
$checked = (isset($_POST['filter']['syntax'][$key])) ? ' checked' : '';
$id = "syntax_{$key}";
echo "<input type=\"checkbox\" id=\"{$id}\" name=\"filter[syntax][{$key}]\"{$checked}> {$keyword['caption']}<br />\n";
}
?>
</td>
<td valign="top">
<?php
foreach($filter['operators'] as $key => $keyword) {
$checked = (isset($_POST['filter']['operators'][$key])) ? ' checked' : '';
$id = "operators_{$key}";
echo "<input type=\"checkbox\" id=\"{$id}\" name=\"filter[operators][{$key}]\"{$checked}> {$keyword['caption']}<br />\n";
}
?>
</td>
<td valign="top">
<?php
foreach($filter['functions'] as $key => $keyword) {
$checked = (isset($_POST['filter']['functions'][$key])) ? ' checked' : '';
$id = "functions_{$key}";
echo "<input type=\"checkbox\" id=\"{$id}\" name=\"filter[functions][{$key}]\"{$checked}> {$keyword['caption']}<br />\n";
}
?>
</td>
<td valign="top">
<?php
foreach($filter['misc'] as $key => $keyword) {
$checked = (isset($_POST['filter']['misc'][$key])) ? ' checked' : '';
$id = "misc_{$key}";
echo "<input type=\"checkbox\" id=\"{$id}\" name=\"filter[misc][{$key}]\"{$checked}> {$keyword['caption']}<br />\n";
}
?>
</td>
</tr>
</tbody>
</table>
</form>
<script language="javascript">
var setPredefined = function() {
e = document.getElementById('predefined')
selected = e.value

uncheckAll();
check = new Array();
switch (e.value) {
case '1':
check = ['syntax_where', 'syntax_limit', 'operators_and', 'operators_or', 'operators_null'];
break;
case '2':
check = ['syntax_union', 'syntax_select', 'syntax_from', 'syntax_having'];
break;
case '3':
check = ['syntax_into', 'syntax_file', 'syntax_case']
break;
case '4':
check = ['syntax_group_by', 'syntax_order_by', 'syntax_having', 'syntax_limit']
break;
case '5':
check = ['syntax_union', 'syntax_select', 'syntax_from', 'syntax_where'];
break;
}

for (var i=0; i < check.length; i++) {
el = document.getElementById(check[i]);
el.checked = true;
}
}

var uncheckAll = function() {
var inputs = new Array();
inputs = document['keywords'].getElementsByTagName('input');

for (var i=0; i < inputs.length; i++) {
if (inputs[i].type == 'checkbox') {
inputs[i].checked = false;
}
}
}
</script>
</body>
</html>



Changelog

v0.4
- Modified the design
- Bug fixes
- Added new filter keywords:
- INTO, FILE, OUTFILE, INFILE, HAVING, NULL, CAST, CASE, TRUNCATE, INSERT, UPDATE, DELETE, DROPTABLE
- Added predefined filters:
- AND, OR, NULL, WHERE, WHILE
- UNION, SELECT, FROM, HAVING
- UNION, SELECT, FROM, WHERE
- INTO, FILE, CASE
- GROUP BY, ORDER BY, HAVING, LIMIT

v0.3
- Added new filter keywords: MOD
- Added separation on string and integer
- Minor bugfix

v0.2
- Cleaned up the design
- Added new filter keywords: <>, IS, NOT, WAIT FOR

v0.1
- Quick draft just to get something working

Enjoy
- Happy Hacking!


Σχόλια