IT技术博客大学习 共学习 共进步

Burpsuite插件开发之RSA加解密

绿盟科技博客 2016-02-11 22:37:04 浏览 1,802 次

   burpsuite是一款非常好用的抓包工具,我自己也是重度用户,所以就上手了burpsuite的插件接口开发,本文主要记录了一个解密请求包,插入payload,再加密的插件开发过程,插件应用场景主要是用于通过分析apk的实现。这里做探讨的目的只是方便安全测试人员的个人学习,或大家渗透测试使用。

   详细的代码见github代码,在文档中数据首先是以rsa方式加密des的key得到encryptKey,然后使用des的key加密数据包得到data,再组装成一个JSON格式串,这是加密过程,当然解密过程就是逆向的。插件应用场景主要是用于通过分析apk的实现,或者泄露的密钥,获取其加解密算法,在解密后的数据包中插入payload,发现注入问题等。

   如下则是加密后的数据包:

   c={

    "data":"21BhviedgtbwK6rdlK7vzltqxOLxUmU2g5qaO5LWPYTha5fXslmL6jrMkFnJBwpZPZMNl5foxTUHw2Mae++zkWwtzWkKXI9WJ/CJqxO9uORT5I6iUmIG7bBcgnHpmlSNKfFwBvnr9vj3v5ByvW2s2/pL9rSaeD+/8XsX01NA96mC4g5pVBeU5IY9F4tdxH9yobXfN6GzEVhLeiEd30xzMA\u003d\u003d",

    "encryptKey":"bjWZgigAW/ZaAA55v7Yi9AGt2qsP7BfZZISu70qc/xVUVfh5L/Mw/mMbzxkcZ6uXb1vvgXvF7hHYwjsVzvEkRK0rIfIwkcYzn160fvQ/8+F8YBMDLzTEhf8r0KjOLlJV+HgOsS4QG/G9lOU5mnupfrVA9sf54b3OvXHU0TQVG7U\u003d"

    }

   从数据库包能看到大的数据是一个json格式,里面有data,和encryptKey值,encryptKey就是使用RSA加密des 的key得到的,RSA的工作方式和pem文件可通过界面设置,再接着用这个key采用des方式解密data中的内容。操作界面如下:

burp_rsa

burp_rsa

2,InsertPoint 接口

   InsertPoint顾名思义就是注入点,就是payload插入的地方,比如request中的cookie,参数等位置。为了对一些burpsuite不支持的参数格式进行支持就必须实现该接口,可以用在Active Scanner和Intruder中.

2.1 基础开发知识

   最好的方式就是在原有插件的基础上修改,这样能省很多精力,当然如果要一步一步来的话,步骤如下:

   (1)包含burp的接口文件

   (2)创建一个包名为burp,在里面创建BurpExtender类,实现IBurpExtender接口,这个BurpExtender类是所有接口的心脏,注意这里涉及到名字都不能改动,burp插件就这么规定的。

   (3)实现唯一的接口函数

   public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) {

           this. callbacks = callbacks ;

          }

   通过callbacks获取核心基础库能力,像日志,请求,返回值修改等。

   (4)日志接口

   PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true);

   PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true);

   //输出到插件的output

   stdout.println("Hello output");

   // 输出到alerts tab

   callbacks.issueAlert("Hello alerts");

   //打印调用栈

   e.printStackTrace(stderr)

   有了这些日志接口就能比较好的调试代码了,如果要很好的跟踪请求的,可以在BApp Store中添加”Custom Logger”这个插件,能够记录所有的请求和返回信息。

2.2 getInsertionPoints

   下面我们就来讲讲如何实现一个InsertionPoints接口。第一步继承IScannerInsertionPointProvider接口,实现getInsertionPoints()方法,同时通过callbacks.registerScannerInsertionPointProvider(this)方法注册成为insertion point provider。下面我们就来看看getInsertionPoints()的实现。

@Override 
 public List<IScannerInsertionPoint> getInsertionPoints (IHttpRequestResponse baseRequestResponse) { // 生成insertPoints数组  
 List<IScannerInsertionPoint> insertionPoints = new ArrayList<IScannerInsertionPoint>(); // 获取请求参数 
 IRequestInfo requestInfo = helpers.analyzeRequest(baseRequestResponse.getRequest());  
 List<IParameter> requestParams = requestInfo.getParameters();

    for (IParameter parameter : requestParams) {
        String value = parameter.getValue();
        value = helpers.urlDecode(value).trim();
        EncryptBean encryptBean = new EncryptBean();
        if (parameter.getName().trim().equals("c")){//参数中含有c参数表示要加密的内容
            encryptBean = JSON.parseObject(value, EncryptBean.class);
            stdout.println("private key: " + key.privateKey + " public key " + key.publicKey);
            try {
                value = decryptRSAAndDES(key, encryptBean);
                stdout.println("after decrypted:Will scan  data at parameter " + parameter + " with value decrypted " + value);
            } catch (Exception e) {
                e.printStackTrace(stderr);
            }
            if (value.isEmpty()) continue;

            try {
                String basename = parameter.getName();
                //insertionPoints.add(new InsertionPoint(this, baseRequestResponse.getRequest(), basename, value));
                JSONObject jsonObj = JSON.parseObject(value);
                String basevalue = "";
                for(Map.Entry<String, Object> entry: jsonObj.entrySet()){
                    basename = entry.getKey();
                    basevalue = entry.getValue().toString();                    
                    //在这里传入总的value值以便在InsertionPoint进行分解,构造加密后的request请求,构造InsertionPoint时传入的value为总的value值
                    insertionPoints.add(0,new InsertionPoint(this, baseRequestResponse.getRequest(), basename, value));
                    stdout.println("in for:Will scan AES encrypted data at parameter " + basename + " with value " + value);
                }
            } catch(Exception e) {
            }
        }
    }
    return insertionPoints;
}

   这一段代码的大体意思就是通过helper.analyzeRequest方法获取所有请求信息,遍历其中的参数信息,当发现参数名等于”c”时就会调用解密过程,这块的代码需要根据参数格式自定义解析参数过程。调用解密的过程大体就是先解析JSON格式,然后解密,得到解密数据的内容后调用

`new InsertionPoint(this, baseRequestResponse.getRequest(), basename, value)`

   实例化一个注入点。一般情况下basename和value是一一对应的,如param1=phoneNum,但是这里我们basename传入param1,value值则是解密后的值如

`{"userid":"51ba27cb-514d-3d86-0000-2f7515a40613","task_id":"1450147269","param1":"000000000000000","m":"https"}`,

   这么传递是为了方便实例化插入点。接着我们看下InsertionPoint的参数构造。

2.3 InsertionPoint

InsertionPoint(BurpExtender newParent, byte[] baseRequest, String basename, 
                String basevalue) { 
    this.parent = newParent; this.baseRequest = baseRequest; this.baseName = basename;  
    //this.baseValue = basevalue; 
     this.value = basevalue; this.baseValue = JSON.parseObject(basevalue).getString(basename);
}

   在InsertionPoint的代码中有一个很重要的接口就是buildRequest,这个函数就是用来添加payload。

@Override
public byte[] buildRequest(byte[] payload)
{
    String payloadPlain = parent.helpers.bytesToString(payload);
    String payloadEncrypted = "";
    String tmpAESKey = "0123456789abcdef";
    parent.stdout.println("payloadPlain:" + payloadPlain);
    parent.callbacks.issueAlert("payloadPlain:" + payloadPlain);
    try {
        Map<String,String> map = JSON.parseObject(this.value, new TypeReference<Map<String, String>>(){}.getType());
        map.put(this.baseName, getBaseValue() + payloadPlain );
        String allPayloadPlain = JSON.toJSONString(map);
        payloadEncrypted = parent.encryptRSAAndDES(allPayloadPlain, tmpAESKey, parent.key);
    } catch(Exception e) {
        parent.callbacks.issueAlert(e.toString());
    }
    parent.stdout.println("Inserting " + payloadPlain + " [" + payloadEncrypted + "] in parameter " + baseName);
    // TODO: Only URL parameters, must change to support POST parameters, cookies, etc.
    //"c" 解密数据格式包一致
    return parent.helpers.updateParameter(baseRequest, parent.helpers.buildParameter("c", payloadEncrypted, IParameter.PARAM_BODY));
}

   这段代码就是获取payload,然后嵌入到解密后的请求包,然后将请求加密,最后调用updateParameter更新参数信息。在这里要注意parent.helpers.buildParameter("c", payloadEncrypted, IParameter.PARAM_BODY) c是body中的请求参数,和我们的数据格式对应,IParameter.PARAM_BODY这个参数则表明是Body中的请求参数,如果是URl中的则是PARAM_URL

2.4 接口关系

   知道了上述接口的作用,感觉还糊里糊涂的。那就是这些接口是怎么串起来的,数据包是如何流动的,下面我们来看下active scanning的流程。

burp-active-scan

burp-active-scan

   ActiveScanner引擎从InsertionPoints Provider获取Insertion Points,然后调用BuildRequest发送Request,Requst再经过HttpListener的处理到达webServer。

   参考文献:

   http://drops.wooyun.org/papers/3962

   http://2015.zeronights.ru/assets/files/42-Elkin-Bulatenko.pdf

   https://github.com/lgrangeia/aesburp

建议继续学习

  1. 代理的加密部分 (阅读 8,244)
  2. 网址加密(URL加密)(RC4、PHP、密钥长度可变) (阅读 8,001)
  3. 使用bcompiler对PHP文件进行加密 (阅读 5,382)
  4. 在浏览器中加密Cookie (阅读 5,383)
  5. 使用系统命令实现文件的压缩与加密 (阅读 5,184)
  6. 公钥私钥加密解密数字证书数字签名详解 (阅读 5,123)
  7. 加密你的shell (阅读 4,845)
  8. 可逆的加密方法(Mcrypt Encryption Functions) (阅读 4,724)
  9. 跨越千年的RSA算法 (阅读 4,183)
  10. 如何“加密”你的email地址 (阅读 4,163)