baidu/openrasp

rasp截获的http body 疑似冗余

xl1605368195 opened this issue · 1 comments

复现环境

  • jdk 1.8
  • springboot(2.7.4)+内嵌jetty(9.4.49.v20220914)
  • open-rasp 1.3.7

问题描述:

有一个接口通过http请求可以触发命令执行:

    @PostMapping(value = "/json/unixProcess.do", consumes = APPLICATION_JSON_VALUE)
    public Map<String, Object> jsonUnixProcess(@RequestBody Map<String, Object> map) throws Exception {
        return unixProcess((String) map.get("cmd")); // 调用命令执行方法
    }

通过postman 发送请求:
image

http 请求的 body 参数为 {"cmd": "cat /etc/passwd"}

debug open-rasp 1.3.7 ,发现截获的body与输入不同

image

com.baidu.openrasp.request.AbstractRequest#getStringBody

rasp 截获的body参数:{{"cmd": "cat /etc/passwd"} 与输入对比多了第一个字节

初步原因

open-rasp hook 了org.eclipse.jetty.server.HttpInput中的2个方法:

1.public int read() throws IOException
2.public int read(byte[] b, int off, int len) throws IOException
JettyHttpInputHook源码位置

image

org.eclipse.jetty.server.HttpInput 中2个方法调用关系:read() 最终会调用 read(byte[] b, int off, int len)
image

open-rasp 中2个方法都会读取的 http body 字节并存储,而 read() 读取body 的第一个字节,open-rasp 将body的第一个字节存储:
image

read(byte[] b, int off, int len) 读取全部字节,导致http body 第一个字节读取了2次。
image

初步优化

由于第一个hook点read()调用read(byte[] b, int off, int len) ,因此可以去掉read() 仅保留 read(byte[] b, int off, int len)

优化前后代码:

    @Override
    protected void hookMethod(CtClass ctClass) throws IOException, CannotCompileException, NotFoundException {
        //String srcRead1 = getInvokeStaticSrc(ServerInputHook.class, "onInputStreamRead",
        //        "$_,$0", int.class, Object.class);
        //insertAfter(ctClass, "read", "()I", srcRead1);
        String src2Read2 = getInvokeStaticSrc(ServerInputHook.class, "onInputStreamRead",
                "$_,$0,$1,$2", int.class, Object.class, byte[].class, int.class);
        insertAfter(ctClass, "read", "([BII)I", src2Read2);
    }

优化方案经过验证,http body读取正常。

如有错误,欢迎指正~~

你好,可以提交个PR吗