代码调试

Java 版本

远程调试

本文以 Tomcat + IntelliJ 为例,介绍如何通过 JPDA - Java Platform Debugger Architecture 协议调试 OpenRASP 源代码。整个流程涉及如下两个步骤:

  1. 修改 Tomcat 启动参数,开启远程调试
  2. 配置IDE,连接Tomcat远程调试

1. 配置 tomcat 服务器

可通过设置 JAVA_OPTS 开启远程调试,具体操作如下:

Linux,在 catalina.sh 中 OpenRASP 相关配置相中增加一行,如下,共有两处该配置,都需修改:

JAVA_OPTS="-javaagent:\"${CATALINA_HOME}/rasp/rasp.jar\" ${JAVA_OPTS}"
JAVA_OPTS="-agentlib:jdwp=transport=dt_socket,address=1043,server=y,suspend=y ${JAVA_OPTS}"

Windows,在 catalina.bat 中 OpenRASP 相关配置相中增加一行,如下:

if "%ACTION%" == "start" set JAVA_OPTS="-javaagent:%CATALINA_HOME%\rasp\rasp.jar" %JAVA_OPTS%
if "%ACTION%" == "start" set JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,address=1043,server=y,suspend=y %JAVA_OPTS%

JDWP 配置参数说明

  1. transport=dt_socket 指定通信协议
  2. address=1043 指定调试端口
  3. server=y 指是否支持在server模式的VM中
  4. suspend=y 指是否在调试客户端建立起来后,再执行JVM(调试premain() 需要设置suspend=y)

P.S 在 tomcat 下面直接使用 bin/catalina.sh jpda start 也能达到类似的效果,这样的端口默认是 8000

2. 配置 IDE

用Intellij导入OpenRASP源代码;点击 Run -> Edit Configuration

编辑配置

点击左上角加号,选择 Remote

新增tomcat server

Configuration 标签页中,配置 HostPort以及 源码路径,并点击确认保存。

server标签配置

下好断点后,点击 Run -> Debug 继续执行。如果调试信息窗口出现 Connected to target VM 说明成功连接,如下图:

connect success

之后大概等待 3s 左右,如果下了断点,就可以看到堆栈信息了。下面两张图分别为 premaincheckXXE 两个断点调试的截图。

断点调试

断点调试

已知问题

1. IntelliJ 断点不生效

在远程调试时,我们发现有些类的断点一直断不上问题,该问题可能出在 IntelliJ 的 Settings -> Debugger -> Stepping 配置上。若勾选了 Do not step into the classes,则会让这些断点失效:

断点调试

2. 在 Intellij 里看不到 OpenRASP 启动信息?

由于是远程调试,OpenRASP 启动日志还是要在 tomcat 日志里看,比如 logs/catalina.out

3. 如何定位 OpenRASP 问题?

某支付客户反馈,在 jetty 下面安装 OpenRASP 之后,产生了一些奇怪的问题。经过调试,我们发现是对方使用了非标准SESSION导致的,目前已经解决。如果你也遇到了奇怪的问题,可通过如下方式定位问题:

  1. 首先在 openrasp.yml 配置中配置 hooks.ignore: all 来禁用所有 hook 点,然后验证问题是否还存在。如果存在说明问题基本和 OpenRASP 无关。
  2. 如果上一步之后问题不存在了,那么就是用上一步中的 hooks.ignore 配置,来一一禁用每个 hook 点,来过滤问题所在的 hook 点。
  3. 当找到有问题 hook 点,删除 hooks.ignore 配置,然后使用上文中的 OpenRASP 调试方法,在有问题的 hook 点处设置断点,进行单步调试来进一步锁定问题原因。

性能调试

方法1: 检查 JavaScript 检测插件是否性能不足

删除 <app_home>/rasp/plugin/official.js,检查性能是否提升?如果提升很明显,可逐步禁用各个检测算法,找出最消耗性能的算法。

方法2: 检查 hook 点是否存在性能瓶颈

修改配置,设置 hooks.ignore: all 并重启服务器。如果性能提升明显,可根据 其他配置选项 里的值,逐步禁用各个 hook 点,找出最消耗性能的 hook 点。

方法3: 开启 hook 点调试日志

修改 debug_level 选项,设置为 1 并重启服务器。之后每当服务器收到请求,我们就会在 rasp/logs/rasp/rasp.log 里打印这样的日志,

2018-01-18 20:06:37,075 INFO  [http-bio-8080-exec-1][com.baidu.openrasp.HookHandler] request_id=27d98d7827f04892b31bb6fe7a0fa4f0 type=request time=0
2018-01-18 20:06:37,079 INFO  [http-bio-8080-exec-1][com.baidu.openrasp.HookHandler] request_id=27d98d7827f04892b31bb6fe7a0fa4f0 type=readFile time=3
2018-01-18 20:06:37,553 INFO  [http-bio-8080-exec-1][com.baidu.openrasp.HookHandler] request_id=754515705fd942708efafe7c66d955be type=request time=0
2018-01-18 20:06:38,843 INFO  [http-bio-8080-exec-1][com.baidu.openrasp.HookHandler] request_id=2cc0377881cd42a09868d017a276c405 type=request time=0

日志里会记录hook点进入的次数、检测逻辑消耗的时间 - 毫秒。若 request_id相同,则表示这些日志是同一个请求产生的。如果你需要调试性能,可以通过这种方式采集日志,并发给我们来分析。

当然,这种日志只需要你访问一次接口即可,不需要压测。

方法4: 开启插件调试日志

下载 999-event-logger.js 并安装到插件目录,然后访问一次你要测试的接口。这个插件会将所有收到的参数打印出来,比如:

2018-07-25T16:28:14+08:00 [event-logger] 999-event-logger: 初始化成功
2018-07-25T16:28:19+08:00 [event-logger] 读取文件: /etc/hosts

这个日志也只需要你访问一次接口,无需压测。

PHP 版本

与常规的PHP扩展调试方法一致,使用 gdb 启动 PHP 命令行服务器,下断点调试即可,e.g

gdb php -ex "run -S 0.0.0.0:8123"

其他内容不再赘述