DVWA靶场实战(七)——SQL Injection
DVWA靶场实战(七)
七、SQL Injection:
1.漏洞原理:
SQL Inject中文叫做SQL注入,是发生在web端的安全漏洞,主要是实现非法操作,例如欺骗服务器执行非法查询,他的危害在于黑客会有恶意获取,甚至篡改数据库信息,绕过登录验证,原理是针对程序员编写数据库程序的疏忽,通过执行SQL语句,实现目的性攻击,他的流程可以分为判断数据库类型、判断数据库版本、判断注入点、判断注入类型、判断数据字段数、判断显示位、获取数据库中的信息。
简单来说就是通过web表单把SQL命令提交到数据库,由于管理员没有细致的过滤用户输入的数据,造成字符串拼接,进而恶意的SQL语句被执行,造成数据库信息泄露、网页篡改、数据库被恶意操作等后果。
2.SQL Injection分类:
从注入参数类型分类:数字型注入、字符型注入、搜索型注入
从注入方法分:报错注入、布尔盲注、时间盲注、联合查询注入、堆叠注入、内联查询注入、宽字节注入
从提交方式分:GET注入、POST注入、COOKIE注入、HTTP头注入
3.SQL注入漏洞的利用思路:
(1)第一步:
寻找可能的漏洞站点,也就是目标站点。
(2)第二步:
通过站点的后缀名来判断网站的使用的是哪一种数据库,简单的判断可以观察脚本后缀,如果是“.asp”为后缀,则数据库可能是access,如果是“.aspx”为后缀可能是MsSql,如果是“.php”为后缀的可能是mysql数据库,如果是“.jsp”,可能是orcale数据库。
(3)第三步:
是寻找站点存在的注入点,可以再URL中进行尝试输入参数后在拼接上引号,通过回显可以判断该站点传输方式,为GET或POST方式POST需要查看表单数据,POST注入在表单中提交引号,而cookie注入可以通过burpsuite工具来判断注入点。
(4)第四步:
判断注入点的类型,如果加减法运算按照是否是数字型注入,如果单引号和页面报错信息来进一步判断是哪一种的字符型注入。
(5)第五步:
闭合我们输入的SQL语句,通过注释的方式来获取数据,有以下几种情况:
①当页面有回显但是没有显示位的时候,可以选择报错注入,常见的报错注入利用函数有那么几个:floor()、exp()、updatexml()、exteractvalue()等函数。
②当页面没有明确的回显信息的时候,但是输入正确和输入错误的时候页面不相同的情况下,可以考虑报错注入,报错注入常见的函数有:ascii()、substr()、length()、concat()等函数。
③当页面没有会回显也没有报错信息的时候,可以使用时间盲注去获取数据库中的数据,时间盲注常见的函数有:sleep()。
其他:当然还有很多其他的注入方式,比如:宽字节注入、base64注入、cookie注入、http头部注入、二次注入、堆叠注入等。
4.漏洞危害:
(1)获取企业内部、个人未授权的隐私信息,或一些机密数据。
(2)页面内容伪造篡改。
(3)数据库、服务器、网络(内网、局域网)受到攻击,严重时可导致服务器瘫痪,无法正常运行。
5.防御以及修复措施:
(1)对数据库进行严格的监控。
(2)对用户提交的数据进行严格的把关,多次筛选过滤。
(3)对用户内数据内容进行加密。
(4)代码层面最佳防御sql漏洞方案:采用sql语句预编译和绑定变量,是防御sql注入的最佳方式。
6.注意事项:
我们在进行查询的时候可能会遇到union联合查询我们利用Navicat Premium 15链接我们的dvwa的MySQL数据库,然后我们找到dvwa然后右键右键点击选择“设计表”。接下来我们将“first_name”、“last_name”、“user”等全部将默认排序的“utf8_unicode_ci”修改为“utf8_general_ci”。修改完成然后保存,完成修改。就可以正常使用union联合查询语句了。
7.实战:
(1)Low:
代码分析:
<?php if( isset( $_REQUEST[ 'Submit' ] ) ) {
// Get input
$id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) {
case MYSQL:
// 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 name: {$first}<br />Surname: {$last}</pre>";
} mysqli_close($GLOBALS["___mysqli_ston"]);
break;
case SQLITE:
global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']);
#$sqlite_db_connection->enableExceptions(true); $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
#print $query;
try {
$results = $sqlite_db_connection->query($query);
} catch (Exception $e) {
echo 'Caught exception: ' . $e->getMessage();
exit();
} if ($results) {
while ($row = $results->fetchArray()) {
// 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>";
}
} else {
echo "Error in fetch ".$sqlite_db->lastErrorMsg();
}
break;
}
} ?>
可以看出来基本上没有防护,所以我们直接开始攻击了。
首先利用语句“1’and’1’=’1”和“1’and’1’=’2”来判断是否有注入点。以下为两种语句的不同回显,可以判断出是有注入点的。
判断完注入点我们尝试获取他的判断他的列数,利用“1’order by 1#”语句替换“1”来判断行数,这里我们“#”或者“--+”的作用是注释掉原本语句后面的内容,让我们能够自如的进行查询。然后我们最后查询到“1’order by 3#”就弹出报错,就说明列数应该为两列。
判断完列数后,我们开始利用联合查询语句,这里使用“-1’union select 1,2#”,来判断显示位。我们这里可以看见回显了另外一个语句,就说明显示位为2,一般靶场中比如sqli-labs那种就会需要将前面的“1”改为“-1”,也就是“-1’union select 1,2#”才会正常回显我们查询的内容。这里我们也可以,之后的演示排除干扰就将第一行结果屏蔽了。
这里我们收集数据库名称利用database()函数,它的作用是返回数据库名,我们在后续查询中是需要数据库才能进行的所以利用语句“-1’union select 1,database()#”接下来进行查询,得到结果数据库名称为“dvwa”。
我们收集完以上的数据库信息后,我们再查询一下数据库的版本,因为mysql数据库注入大概是以5.0版本为分界线,5.0以下没有information表,5.0以上则都有information表。这里的MySQL版本为5.7.26,那么我们就可以查询information表来找到数据库的表名。
接下来,我们查询dvwa数据库有哪些表名,利用联合查询语句“-1'union select 1,table_name from information_schema.tables where table_schema='dvwa'#”来进行对表名的查询。得到两个表名“guestbook”和“users”。
我们查询好表名后,我们查询列名,利用语句“-1'union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users')#”得到“user_id,first_name,last_name,user,password,avatar,last_login,failed_login
”的结果,这个时候我们就可以知道我们应该查询“user”和“password”。
然后我们查询好表名为“users”和列名“user”、列名“password”后,我们利用查询语句“-1’union select user,password from users”,然后查询得到账号和密码,密码是MD5加密需要自己解密查询。
(2)Medium:
代码分析:
<?php if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ]; $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id); switch ($_DVWA['SQLI_DB']) {
case MYSQL:
$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 name: {$first}<br />Surname: {$last}</pre>";
}
break;
case SQLITE:
global $sqlite_db_connection; $query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
#print $query;
try {
$results = $sqlite_db_connection->query($query);
} catch (Exception $e) {
echo 'Caught exception: ' . $e->getMessage();
exit();
} if ($results) {
while ($row = $results->fetchArray()) {
// 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>";
}
} else {
echo "Error in fetch ".$sqlite_db->lastErrorMsg();
}
break;
}
} // 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"]);
?>
使用POST提交方式,还使用了转义预防SQL注入。
我们开始攻击,首先我们打开BP进行截包,得到如下的数据包。并将其发送到“Repeater”,方便接下来的注入回显操作。
我们同样利用“1 and 1=1”和“1 and 1=2”来判断,是否这里为注入点,观察两者的有差异且页面未报错,就说明这里是注入点。
这里我们可以看到,同样是在“3”的时候,我们这里用“order by 3”查询返回报错,所以我们这里判断前面只查询两列。利用语句“1 union select 1,2#”来进行验证,返回正确,验证成功。
此时同样判断完列数后,我们同时对版本和数据库名称进行查询,利用语句“1 union select database(),version()#”。此时观察回显,发现同时回显了数据库名称和数据库版本dvwa和5.7.26。
在查询完数据库后,我们先查询表名,然后查询列名,利用语句“1 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=’dvwa’)#”,但发现报错,没有任何反应,将“dvwa”改为“database()”后查询得到“users”表名后。后来发现是对单引号进行了转义。所以我们将单引号连同users一起写为16进制表示为“0x75736572”。
查询列名“1 union select (select group_concat(column_name) from information_schema.columns where table_name=0x75736572),(select group_concat(table_name) from information_schema.tables where table_schema=database())”,得到关键列名“user”和“password”。
最后我们利用,“1 union select user,password from users#”语句,得到最后的结果。
(3)High:
代码分析:
<?php if( isset( $_SESSION [ 'id' ] ) ) {
// Get input
$id = $_SESSION[ 'id' ]; switch ($_DVWA['SQLI_DB']) {
case MYSQL:
// 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);
break;
case SQLITE:
global $sqlite_db_connection; $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
#print $query;
try {
$results = $sqlite_db_connection->query($query);
} catch (Exception $e) {
echo 'Caught exception: ' . $e->getMessage();
exit();
} if ($results) {
while ($row = $results->fetchArray()) {
// 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>";
}
} else {
echo "Error in fetch ".$sqlite_db->lastErrorMsg();
}
break;
}
} ?>
使用了session 获取id 值,闭合方式单引号闭合。
虽然用了session来获取id值,但是同样也是数字型注入,利用同样的方法,然后最后用“-1’union select user,password from users #”,即可得到答案。
(4)Impossible:
代码分析:
<?php if( isset( $_GET[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); // Get input
$id = $_GET[ 'id' ]; // Was a number entered?
if(is_numeric( $id )) {
$id = intval ($id);
switch ($_DVWA['SQLI_DB']) {
case MYSQL:
// Check the database
$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();
$row = $data->fetch(); // Make sure only 1 result is returned
if( $data->rowCount() == 1 ) {
// 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>";
}
break;
case SQLITE:
global $sqlite_db_connection; $stmt = $sqlite_db_connection->prepare('SELECT first_name, last_name FROM users WHERE user_id = :id LIMIT 1;' );
$stmt->bindValue(':id',$id,SQLITE3_INTEGER);
$result = $stmt->execute();
$result->finalize();
if ($result !== false) {
// There is no way to get the number of rows returned
// This checks the number of columns (not rows) just
// as a precaution, but it won't stop someone dumping
// multiple rows and viewing them one at a time. $num_columns = $result->numColumns();
if ($num_columns == 2) {
$row = $result->fetchArray(); // 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>";
}
} break;
}
}
} // Generate Anti-CSRF token
generateSessionToken(); ?>
此为防御模板,CSRF、检测 id 是否是数字,prepare 预编译语句的优势在于归纳为:一次编译、多次运行,省去了解析优化等过程;此外预编译语句能防止 SQL 注入。
DVWA靶场实战(七)——SQL Injection的更多相关文章
- DVWA全级别之SQL Injection(SQL注入)
DVWA全级别之SQL Injection(注入) DVWA简介 DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web ...
- [靶场实战]:SQL注入-显错注入
SQL注入的本质:就是将用户输入的数据当作代码带入执行. 注入条件: 1.用户能控制输入 2.能够将程序原本执行的代码,拼接上用户输入的数据进行执行 首先检查是否存在注入点 Rank1: 构造语句 ? ...
- 使用sqlmap注入DVWA的SQL Injection菜单
1 使用sqlmap注入DVWA的SQL Injection菜单 本教程中的登陆地址:http://192.168.0.112/dvwa/login.php 1.1 获取cookie信息 1) 使用a ...
- sqlmap dvwa SQL Injection使用小记
刚刚开始学习sql injection,初步使用sqlmap,使用 GET http://www.dvssc.com/dvwa/vulnerabilities/sqli/?id=1&Submi ...
- DVWA SQL Injection 通关教程
SQL Injection,即SQL注入,SQLi,是指攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的.SQL注入漏洞的危害巨大,常常会导致整个数据库被“脱 ...
- DVWA SQL Injection(Blind) 通关教程
SQL Injection(Blind),即SQL盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是 ...
- 【DVWA】SQL Injection(SQL 注入)通关教程
日期:2019-07-28 20:43:48 更新: 作者:Bay0net 介绍: 0x00.基本信息 关于 mysql 相关的注入,传送门. SQL 注入漏洞之 mysql - Bay0net - ...
- (十二)DVWA全等级SQL Injection(Blind)盲注--SQLMap测试过程解析
一.测试前分析 前文<DVWA全等级SQL Injection(Blind)盲注-手工测试过程解析> 通过手工测试的方式详细分析了SQL Injection(Blind)盲注漏洞的利用过程 ...
- (十一)DVWA全等级SQL Injection(Blind)盲注--手工测试过程解析
一.DVWA-SQL Injection(Blind)测试分析 SQL盲注 VS 普通SQL注入: 普通SQL注入 SQL盲注 1.执行SQL注入攻击时,服务器会响应来自数据库服务器的错误信息,信息提 ...
- DVWA之 SQL Injection(Blind)
SQL Injection(Blind) SQL Injection(Blind),即SQL盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法 ...
随机推荐
- 如何规范App广告的隐私获取,让用户拥有更多知情权?
随着互联网的不断普及,越来越多老百姓使用智能设备触达互联网.但用户经常发现自己无意间提到的东西,打开App就收到相关产品的广告推送,甚至有人怀疑手机App是通过麦克风来窃取自己平时聊天信息中的关键词进 ...
- 知识图谱-生物信息学-医学顶刊论文(Bioinformatics-2022)-SGCL-DTI:用于DTI预测的监督图协同对比学习
14.(2022.5.21)Bioinformatics-SGCL-DTI:用于DTI预测的监督图协同对比学习 论文标题: Supervised graph co-contrastive learni ...
- NLP之基于Transformer的句子翻译
Transformer 目录 Transformer 1.理论 1.1 Model Structure 1.2 Multi-Head Attention & Scaled Dot-Produc ...
- virtualenv +virtualenvwrapper
一.虚拟环境virtualenv 1.安装:pip3 install virtualenv 2.创建虚拟环境:virtualenv venv #venv为虚拟环境目录名,目录名自定义 #virtual ...
- wpf 手指触摸图片放大缩小 设置放大缩小值
xaml代码: <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/w ...
- Codeforces Round #828 (Div. 3) A-F
比赛链接 A 题解 知识点:贪心,模拟. 遇到没用过的数字就给个字母,遇到用过的数字就对照字母是否一致. 时间复杂度 \(O(n)\) 空间复杂度 \(O(n)\) 代码 #include <b ...
- SpringCloud微服务实战——搭建企业级开发框架(四十八):【移动开发】整合uni-app搭建移动端快速开发框架-使用第三方UI框架
uni-app默认使用uni-ui全端兼容的.高性能UI框架,在我们开发过程中可以满足大部分的需求了,并且如果是为了兼容性,还是强烈建议使用uni-ui作为UI框架使用. 如果作为初创公司,自 ...
- Unity——第一人称控制器的实现
Unity--第一人称控制器的实现 一.功能描述 在一个场景中实现人物的前后左右移动和跳跃功能:其中前后左右移动通过W.A.S.D方向键实现,跳跃功能通过空格键实现,并且考虑到重力作用,来调节跳跃功能 ...
- html页面跳转方式
js里的方法 第一种: window.location.href = XXXX; 第二种: window.setTimeout("javascript:location.href='xxxx ...
- 九、kubernetes命令行工具kubectl
为了方便在命令行下对集群.节点.pod进行管理,kubernetes官方提供了一个管理命令:kubectl kubectl作为客户端CLI工具,可以让用户通过命令行对Kubernetes集群进行操作. ...