众测案例分享,全加密站点从无从下手到抽丝剥茧,本文将将你代入我的视角,做一次沉浸式渗透测试。(本文首发博客:https://sanshiok.com/archive/9.html,点击阅读原文跳转)
目标网站资产,有注册页面,但是需要内部手机账号才能注册,如图所示:
通过信息收集找到了内部手机账号,但是又提示,账号已经注册:
后端的功能漏洞肯定会比前端多,至此若要想注册账号,可以通过以下三种方式:
通过抓取数据包发现站点数据存在全局加密:
那就需要通过js逆向,梳理加解密规则,这里通过一款由f0ng
师傅开发的Burpsuite
插件autoDecoder
(项目地址),能够实现明文发,明文接收的效果:
autoDecoder
插件工作原理如图所示,意思就是我们需要编写一个python脚本,通过插件把流量转发给脚本处理:
通过F12全局搜索data
参数,接口等信息,找到关键加密逻辑如下:
getRandStringLenEight
——>获取8位随机数
JSON.stringify(e.data)
——>将JavaScript对象转换为JSON字符串
Object(m.a)(r + "" + c).slice(0, 32)
——>对拼接的参数做SHA-256算法并取32位
p(s)
——>将上述的s
参数做AES加密
最后编写出来的flask
脚本如下(已脱敏):
import hashlib
import random
from Crypto.Util.Padding import pad,unpad
import json
from flask import Flask,request
import base64#接口加解密 请求响应不同加解密
def get_rand_string_len_eight():
...
return t
def sha256(message):
return hashlib.sha256(message.encode()).hexdigest()[:32]
def aes_encrypt(plaintext):
...
return ciphertext
def aes_decrypt(ciphertext):
...
return plaintext
def sign(param):
newparam = param.replace('"', '\\"')
r = get_rand_string_len_eight()
s = '"'+newparam + "" + sha256(r + "" + param) + r+'"';
c = "2"+aes_encrypt(s) #随机添加一位
return c
app = Flask(__name__)
@app.route('/encode',methods=["POST"])
def encrypt():#加密请求会请求这里
requestorresponse = request.form.get('requestorresponse') # 获取 post 参数
param = request.form.get('dataBody').strip("\n") # 获取 post 参数
if requestorresponse == 'request'and param != '':#请求加密
param = '{"data":"'+sign(param)+'"}'
print(param)
elif param == '': #请求为GET 请求体为空 直接返回
return param
else:#响应加密
param = '{"data":"1' + aes_encrypt(param) + '"}'
return param
return param
@app.route('/decode',methods=["POST"])
def decrypt():#解密请求会请求这里
requestorresponse = request.form.get('requestorresponse') # 获取 post 参数
param = request.form.get('dataBody').strip("\n") # 获取 post 参数
print(param)
if param == '':
return "error"
data = aes_decrypt(json.loads(param)['data'])
if requestorresponse == 'request': # 请求解密
param = data.rsplit('}')[0].replace("\\", "")[1:] + '}' # 先解密获取到原来的json数据格式
else: # 响应解密
param = data # 先解密获取到原来的json数据格式
return param
if __name__ == '__main__':
app.debug = True # 设置调试模式,生产模式的时候要关掉debug
app.run(host="0.0.0.0",port="8888")
最后按照需求,在autoDecoder
插件处设置即可:
推荐的使用方法如下,先在接口加解密处获取数据包的明文:
再在repeater
处使用,即可做到明文发送,明文返回:
将全站解密后,通过上述的替换返回包的方法即可,绕过第一步内部账号的校验,成功注册账号:
经验证通过审查js代码,构造注册接口,也是能够成功注册账号的
成功注册账号后,后续漏洞挖掘就和平时的渗透无异了,在忘记密码处,可通过A手机账号接受验证码重置B手机账号(这里通过F12,直接修改手机号参数也可以做到):
通过在前台的文章发布界面,成功发现管理员手机号,但在测试注意事项中,重置管理员密码不允许,遂停止测试🚫
最后在后台测试到了XSS,文件上传等漏洞,测试方法比较基础,属于有手就行就不再一一赘述了。