Only this pageAll pages
Powered by GitBook
1 of 67

OpenRASP Documents (Old)

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

兼容性说明

Java Agent

操作系统

  • MacOS 10.10+

  • Windows x64

  • Linux

    • RHEL/CentOS 6 以及更高版本

    • Ubuntu 14 以及更高版本

    • Debian 6 以及更高版本

    • 其他 glibc >= 2.12 的发行版

Web 服务器 - 支持 docker 部署

  • Tomcat 5 ~ 10

  • Jetty 7 ~ 9

  • JBoss 4 ~ 8

  • Wildfly 8 ~ 16

JDK 版本

  • Oracle JDK 6~15

  • OpenJDK 6~11

数据库

  • MySQL

  • SQLServer

  • SQLite3

  • Oracle

PHP Agent

SAPI 支持范围(同时支持TS/非TS版本)

  • PHP-FPM

  • Apache PHP 模块

操作系统

Linux

  • PHP 5.3 ~ 5.6,7.0 ~ 7.3

    • Ubuntu 14.04 以及更高版本

    • RHELL/CentOS 6 以及更高版本

    • 其他 glibc >= 2.12 的发行版

Mac OS

  • Homebrew PHP 5.6,7.0 ~ 7.3 (没有深入测试)

数据库

  • MySQL (mysql/mysqli/PDO 等连接方式)

  • PostgreSQL

  • SQLite3

管理后台

操作系统

  • Linux

    • CentOS 6 以及更高版本

    • Ubuntu 14.04 以及更高版本

    • 后台基于Golang开发,只要不是太老的系统一般都支持

Resin 3 ~ 4
  • SpringBoot 1 ~ 2 (内置 tomcat/jetty/undertow)

  • WebSphere 7.X 及以上版本

    • 部分版本由于 IBM JDK 自身限制,无法启用文件读写删改相关检测(可自行更换 Oracle JDK)

    • 商业版不受影响,可正常检测漏洞

  • WebLogic 10.3.6 / 12.2

  • 宝兰德BES 9.5.X

  • 中创InforSuiteAS 10.0.X

  • PostgreSQL
  • DB2

  • HSQLDB (WebGoat 使用的嵌入数据库)

  • Mac OS X

    快速接入

    快速接入

    OpenRASP 支持私有化部署,包含客户端与服务端两个组件。在接入之前,请先阅读 兼容性说明 文档,检查客户端是否支持你的应用服务。

    第一步: 下载最新版本的安装包

    常用镜像

    • 国内镜像: packages.baidu.com

    文件说明

    文件名
    说明

    第二步: 安装管理后台 (可选)

    OpenRASP 支持单机防护,也支持远程管理。若要开启远程管理,请先参考 安装管理后台。

    第三步: 安装客户端

    取决于你的服务器类型,请参考不同的子章节进行安装。比如 Tomcat 可以查看 进行操作。

    第四步: 安装测试用例(可选){#step4}

    如果你需要测试漏洞检测效果,请参考 安装漏洞环境。

    第五步: 安装IAST扫描工具(可选){#step5}

    如果你需要安装扫描工具,请参考 页面进行安装和配置。

    其他常用链接

    开发相关

    常见问题

    常见问题

    1. 常见自动安装失败原因

    Java 版本

    错误码
    说明

    关于 java 不重启安装,卸载:由于不支持不重启升级,所以在不重启安装然后不重启卸载之后,想要再次安装需要重启服务器安装。

    PHP 版本

    错误码
    分类说明

    2. OpenRASP 无法拦截攻击

    Java 服务器

    1. 首先,使用浏览器访问网站,检查服务器是否启动成功

      • 若服务器没有启动,可检查启动日志,寻找堆栈信息。对于 tomcat 通常是 catalina.out

    2. 根据子章节的文档,检查 OpenRASP 是否安装成功

    PHP 服务器

    1. 首先,使用浏览器访问网站,检查服务器是否启动成功

      • 若服务器没有启动,可检查 PHP/Apache/Nginx 错误日志

    2. 根据子章节的文章,检查 OpenRASP 扩展是否安装成功

    3. jnotify 无法释放

    有的公司会定制应用启动脚本,比如 catalina.sh,当以root启动tomcat,他会自动切换到低权限用户,再继续启动

    通常,你会看到如下的堆栈错误

    这说明 OpenRASP 在释放 jnotify 动态链接库时出错(用来监控插件目录变更),错误原因是 Permission denied

    所以,你可能需要调整下RASP目录权限,e.g chmod 777 -R rasp,然后再次启动 tomcat

    4. Could not find or load main class com.baidu.rasp.App 错误

    QQ群用户反馈,执行 RaspInstall 时报错,

    经过排查,这是因为当前目录本身没有读取权限导致的,执行 chmod 777 $PWD 后解决。

    5. APM 兼容性说明

    如果你同时使用 OpenRASP 和 APM 产品,比如 ,那你需要增大 -XX:MaxPermSize 参数。否则运行一段时间后可能会出现 java.lang.OutOfMemoryError: PermGen space 错误,产生大量GC,最终导致服务器假死。

    如果原先没有配置过此参数,我们建议你设置为 1024m;如果配置过,我们建议在原先基础上增加至少 512m。

    另外,为了避免APM回滚钩子,请将我们的 -javaagent 参数放在前面。

    6. JDK9 以上安装问题

    由于JDK9以上版本的 Modularity System 属性,需要在手动安装后为服务器添加以下 Java 启动参数:

    7. 常见 v8 加载失败原因

    7.1 java.io.IOException: Permission denied 异常

    如果 /tmp 目录没有写权限,Java 会抛出 java.io.IOException: Permission denied 异常,e.g

    此时请检查 /tmp 是否有写权限,以及是否有安全防护软件对 /tmp 目录增加了写保护。

    7.2 libopenrasp_v8_java.so: failed to map segment from shared object: Permission denied

    对于以下两种场景,

    1. 机器开启了SELinux,不允许Tomcat加载不符合策略的动态链接库

    2. so释放目录没有执行权限,比如使用了 noexec 参数挂载

    Java可能会出现无法加载so的情况,并提示无法创建区段映射:

    解决方法是关闭SELinux(如果开启),并去掉释放目录的noexec挂载(如果有)。如果不是上述两种情况,请加入QQ群联系我们排查。

    7.3 java.io.IOException: Couldn't load library openrasp_v8_java

    如果你在不支持的系统架构上运行OpenRASP(比如aarch64),可能会看到 Couldn't find resource 错误:

    目前我们仅支持x64/x86_64两类架构,其他架构会逐步支持

    7.4 java.lang.UnsatisfiedLinkError 错误

    如果释放的 libopenrasp_v8_java.so 无法加载,Java 会抛出如下异常:

    目前已知的情况有:

    1. JDK是32位的,没有安装32位的glibc运行库。在CentOS系统下可以安装 glibc.i686 软件包。

    2. JDK是64位的,且在 docker alpine 环境里无法启动。这个因为你没有装 libcurl libstdc++ 两个软件包。

    如果是其他情况,请加入联系我们。

    8. libzip.so 崩溃问题

    Java 在运行时可能会产生这个错误:

    OpenRASP会定期读取jar包里的pom信息,获取应用所使用的类库和版本。这个是JDK自身的BUG,与OpenRASP无关。你可以通过如下几种方式解决问题:

    方案1: 升级JDK版本

    根据用户反馈,JDK 1.8 Update 261 没有这个问题。

    方案2: 关掉jar包的内存映射

    这可能因为Java在读取jar包时,对应的文件已经被修改,导致JVM崩溃,具体可以参考。

    通过增加如下JVM启动参数可以解决问题,但可能带来额外的性能损耗:

    方案3: 关闭依赖库采集功能

    参考 文档,将 dependency_check.enable 设置为 false 即可。 另外,也可以在执行RaspInstall安装的时候增加 -nodep 参数,程序会自动将 dependency_check.enable 改为 false。

    方案4: 避免多个Java进程使用相同的业务jar包

    有用户反馈,他们的业务存在多个容器共用jar的问题,将jar打包到容器内部就没有这个错误了。

    APM 兼容性说明
  • JDK9 以上安装问题

  • 常见 v8 加载失败原因

  • libzip.so 崩溃问题

  • 方法一: 访问网站,检查响应头里是否有
    X-Protected-By: OpenRASP
    字样?
  • 方法二: 检查启动日志里是否有 OpenRASP Engine Initialized 字样

  • 检测测试用例是否支持

    • 对于官方测试用例,若无法拦截,则说明存在绕过或者bug

    • 对于其他测试用例,请联系QQ群群主,我们会检查

  • 方法一: 访问网站,检查响应头里是否有
    X-Protected-By: OpenRASP
    字样?
  • 方法二: 创建内容为 <?php phpinfo(); ?> 的PHP文件并访问,检查页面中是否包含 openrasp 扩展信息?

  • 检测测试用例是否支持

    • 对于官方测试用例,若无法拦截,则说明存在绕过或者bug

    • 对于其他测试用例,请联系QQ群群主,我们会检查

  • rasp-cloud.tar.gz

    管理后台,Linux 版本

    rasp-cloud-mac.tar.gz

    管理后台,Mac 版本

    rasp-java.tar.gz

    JavaAgent,Linux 版本

    rasp-java.zip

    JavaAgent,Windows 版本

    rasp-php-linux.tar.bz2

    PHP Agent,Linux NTS 版本

    rasp-php-linux-ts.tar.bz2

    PHP Agent,Linux TS 版本

    10001

    未找到插入 JAVA_OPTIONS 的标志

    10002

    未找到服务器根目录,e.g 使用了不存在的目录

    10003

    未找到启动脚本,e.g bin/catalina.sh

    10004

    无法识别应用服务器类型

    10005

    命令行参数错误

    10006

    不重启安装,attach 进程失败

    20001

    fswatch 类库初始化失败,比如 rasp 安装目录没有写权限

    20002

    日志记录发生异常,比如日志文件没有写权限

    20003

    申请共享内存失败

    20004

    php.ini 配置不正确,比如缺少 openrasp.root_dir 配置

    20005

    JavaScript 插件加载错误

    国外镜像: github.com
    安装管理后台
    Tomcat 服务器安装
    安装测试用例
    安装灰盒扫描工具
    发版纪要
    项目里程碑
    beta 版本文档
    常见自动安装失败原因
    OpenRASP 无法拦截攻击
    jnotify 无法释放
    Could not find or load main class com.baidu.rasp.App 错误
    pinpoint
    QQ技术讨论群
    Oracle 官方博客 - Crashes in ZIP_GetEntry
    其他配置
    Unable to extract jnotify library (rasp/libjnotify_64bit.so):
    java.io.FileNotFoundException: /data/w/tomcat/rasp/libjnotify_64bit.so (Permission denied)
    	at java.io.FileOutputStream.open0(Native Method)
    	at java.io.FileOutputStream.open(FileOutputStream.java:270)
    	at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
    	at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
    $ java -jar RaspInstall.jar -install /usr/local/tomcat/
    Error: Could not find or load main class com.baidu.rasp.App
    --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED
    --add-opens=java.base/java.net=ALL-UNNAMED
    java.lang.ExceptionInInitializerError
        at org.scijava.nativelib.NativeLoader.<clinit>(NativeLoader.java:107)
        at com.baidu.openrasp.v8.V8.Load(V8.java:25)
        at com.baidu.openrasp.plugin.js.JS.Initialize(JS.java:44)
        at com.baidu.openrasp.EngineBoot.start(EngineBoot.java:56)
        at com.baidu.openrasp.ModuleContainer.start(ModuleContainer.java:78)
        at com.baidu.openrasp.ModuleLoader.<init>(ModuleLoader.java:74)
        at com.baidu.openrasp.ModuleLoader.load(ModuleLoader.java:103)
        at com.baidu.openrasp.Agent.init(Agent.java:93)
        at com.baidu.openrasp.Agent.premain(Agent.java:70)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:382)
        at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:397)
    Caused by: java.io.IOException: Permission denied
        at java.io.UnixFileSystem.createFileExclusively(Native Method)
        at java.io.File.createTempFile(File.java:2001)
        at java.io.File.createTempFile(File.java:2047)
        at org.scijava.nativelib.BaseJniExtractor.getTempDir(BaseJniExtractor.java:123)
        at org.scijava.nativelib.WebappJniExtractor.<init>(WebappJniExtractor.java:69)
        at org.scijava.nativelib.NativeLoader.<clinit>(NativeLoader.java:103)
        ... 14 more
    java.lang.UnsatisfiedLinkError: /var/cache/tomcat/temp/nativelib-loader_4485267645656510327/Classloader.1658314629304.0/libopenrasp_v8_java.so: /var/cache/tomcat/temp/nativelib-loader_4485267645656510327/Classloader.1658314629304.0/libopenrasp_v8_java.so: failed to map segment from shared object: Permission denied
       at java.lang.ClassLoader$NativeLibrary.load(Native Method)
       at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1934)
       at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1817)
       at java.lang.Runtime.load0(Runtime.java:810)
       at java.lang.System.load(System.java:1088)
       at com.baidu.openrasp.nativelib.NativeLibraryUtil.loadNativeLibrary(NativeLibraryUtil.java:340)
       at com.baidu.openrasp.nativelib.NativeLoader.loadLibrary(NativeLoader.java:136)
       at com.baidu.openrasp.v8.Loader.load(Loader.java:12)
       at com.baidu.openrasp.EngineBoot.start(EngineBoot.java:57)
       at com.baidu.openrasp.ModuleContainer.start(ModuleContainer.java:78)
       at com.baidu.openrasp.ModuleLoader.<init>(ModuleLoader.java:89)
       at com.baidu.openrasp.ModuleLoader.load(ModuleLoader.java:117)
       at com.baidu.openrasp.Agent.init(Agent.java:94)
       at com.baidu.openrasp.Agent.premain(Agent.java:71)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
       at java.lang.reflect.Method.invoke(Method.java:498)
       at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:386)
       at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401)
    INFO: Couldn't find resource META-INF/lib/linux_arm64/libopenrasp_v8_java.so
    [OpenRASP] Failed to load native library, please refer to https://rasp.baidu.com/doc/install/software.html#faq-v8-load for possible solutions.
    java.io.IOException: Couldn't load library openrasp_v8_java
            at com.baidu.openrasp.nativelib.NativeLoader.loadLibrary(NativeLoader.java:138)
            at com.baidu.openrasp.v8.Loader.load(Loader.java:12)
            at com.baidu.openrasp.EngineBoot.start(EngineBoot.java:57)
            at com.baidu.openrasp.ModuleContainer.start(ModuleContainer.java:78)
            at com.baidu.openrasp.ModuleLoader.<init>(ModuleLoader.java:89)
            at com.baidu.openrasp.ModuleLoader.load(ModuleLoader.java:118)
    ava.io.IOException: Couldn't load library library openrasp_v8_java
        at org.scijava.nativelib.NativeLoader.loadLibrary(NativeLoader.java:141)
        at com.baidu.openrasp.v8.V8.Load(V8.java:25)
        at com.baidu.openrasp.plugin.js.JS.Initialize(JS.java:44)
        at com.baidu.openrasp.EngineBoot.start(EngineBoot.java:56)
        at com.baidu.openrasp.ModuleContainer.start(ModuleContainer.java:78)
        at com.baidu.openrasp.ModuleLoader.<init>(ModuleLoader.java:74)
        at com.baidu.openrasp.ModuleLoader.load(ModuleLoader.java:103)
        at com.baidu.openrasp.Agent.init(Agent.java:93)
        at com.baidu.openrasp.Agent.premain(Agent.java:70)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:382)
        at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:397)
    Caused by: java.lang.UnsatisfiedLinkError: no openrasp_v8_java in java.library.path
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
        at java.lang.Runtime.loadLibrary0(Runtime.java:849)
        at java.lang.System.loadLibrary(System.java:1088)
        at org.scijava.nativelib.NativeLoader.loadLibrary(NativeLoader.java:136)
        ... 14 more
    Stack: [0x00007f3951edb000,0x00007f3951fdc000],  sp=0x00007f3951fda2d8,  free space=1020k
    Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
    C  [libc.so.6+0x15a00b]  __memmove_ssse3_back+0x6cb
    C  [libzip.so+0x12b33]  ZIP_GetNextEntry+0x53
    J 5497  java.util.zip.ZipFile.getNextEntry(JI)J (0 bytes) @ 0x00007f3a15da3c76 [0x00007f3a15da3bc0+0xb6]
    J 5495 C1 java.util.zip.ZipFile$ZipEntryIterator.next()Ljava/util/zip/ZipEntry; (212 bytes) @ 0x00007f3a15daebec [0x00007f3a15dae940+0x2ac]
    -Dsun.zip.disableMemoryMapping=true

    安装管理后台

    快速开始

    在开始之前,请先根据 里的说明,下载 rasp-cloud.tar.gz,并解压缩到本地。

    安装数据库

    目前,我们使用了 ElasticSearch 和 MongoDB 两种数据库。前者用来存储报警和统计信息,后者用来存储应用、账号密码等信息。

    目前我们对数据库的要求是,

    • MongoDB 版本大于等于 3.6

    • ElasticSearch 版本大于等于 5.6,小于 7.0 (ES 7.X 变化较大,暂无计划支持)

    具体如何安装数据库,这里不在赘述。

    启动管理后台

    首先,编辑 conf/app.conf 文件,修正 ElasticSearch 和 MongoDB 两个服务器的地址。如果这两个数据库都安装在了本机,且使用默认端口,请跳过此步骤:

    关于 MongoDB 认证配置,可参考 mongoDB Linux 认证配置、重置密码、远程登录配置详解 文章操作;如果 MongoDB 有主从,只需要填写主地址。

    然后,在终端里执行如下命令,启动后台服务器:

    最后,在浏览器里打开 http://your-ip:8086,登录管理后台。其中用户名固定为 openrasp,初始密码为 admin@123。如果不能访问,请检查防火墙设置,或者检查 logs/api/agent-cloud.log 下面的错误信息。

    登录成功后,请根据 管理后台 - 添加主机 文档,了解如何添加第一台主机。

    高级配置

    后台负载均衡

    在实际场景中,我们需要部署多个服务器,才能处理来自数十万主机的连接。因此,我们将管理后台拆分为 Agent 接口服务器 (AgentServer) 和 前端服务器 (PanelServer)。前者用于跟agent通信,比如心跳、日志上传,可以部署多个;后者用于展示数据、定时报警、修改配置,用户可访问这个后台来查看报警。后者用于发送报警邮件,部署多个会有重复报警的问题,所以目前只能部署一个。

    在百度,我们会启动一个前端服务器,

    然后在不同的机房,分别启动一个 agent 服务器(使用同一份 conf/app.conf 配置文件即可)

    服务器部署完成后,请根据 管理后台 - 设置后台信息 文档,将所有的Agent服务器填入。之后就可以在 添加主机 界面上,生成自动安装命令了。

    容量说明: 目前,在2核4GB的主机上,按照3分钟一个心跳计算,大概单台机器可容纳 1000个 客户端。

    ElasticSearch 负载均衡

    在使用ES集群时,EsAddr 填写一个服务器的地址即可。我们自动会调用 /_nodes/ 接口获取全部服务器信息并轮询,以避免单点问题。

    配置项详细说明

    以下配置均为在 conf/app.conf 中配置

    Beego 相关

    常用 beego 配置项如下,更多设置请参考 beego官网 文档,

    参数
    说明
    默认值

    appname

    应用名称

    无

    httpaddr

    http 监听IP

    0.0.0.0

    httpport

    http 监听端口

    8086

    runmode

    运行模式,dev 为开发模式,prod 为线上模式

    prod

    OpenRASP 相关

    OpenRASP 可用配置项目如下,

    参数
    说明
    默认值

    EsAddr

    Elasticsearch 服务器地址,多个地址用逗号隔开

    http://127.0.0.1:9200

    EsUser

    Elasticsearch 用户名 (X-Pack)

    空

    EsPwd

    Elasticsearch 密码 (X-Pack)

    空

    EsTTL

    Elasticsearch 数据过期时间,单位/天

    365

    开启 HTTPS

    在 conf/app.conf 中加入以下配置即可,修改后重启后台生效:

    后台运维

    升级后台

    请登录到每一台部署了 rasp-cloud 的主机,并按照如下步骤进行升级:

    如果是 v1.3.0 之前的后台

    1. 备份原来的配置文件,conf/app.conf

    2. 下载新的安装包,解压缩到相同目录

    3. 检查是否需要更新配置文件

    4. 执行命令 ps aux | grep rasp-cloud 找到后台进程 PID

    5. 对上述进程发出 HUP 信号,e.g kill -HUP $PID

    6. 检查后台是否可以正常访问

    如果是 v1.3.0 甚至更高版本的后台

    1. 备份原来的配置文件,conf/app.conf

    2. 下载新的安装包,解压缩到相同目录

    3. 检查是否需要更新配置文件

    4. 执行 /path/to/rasp-cloud -s restart

    5. 检查后台是否可以正常访问

    找回密码

    请登录到后台所在的主机,执行如下命令,根据提示重置密码。目前密码强度要求是 8-50 位,必须包含数字和字母。

    检查后台状态

    请登录到后台所在的主机,执行如下命令即可:

    查看后台版本

    请登录到后台所在的主机,执行如下命令即可:

    定期备份

    在百度,我们以小时级别对 MongoDB 和 ElasticSearch 数据库进行备份。其中,MongoDB 需要备份 openrasp 数据库,可以使用 mongodump + mongorestore 实现;ElasticSearch 需要备份如下索引,可以用 snapshot 方式备份:

    当然,如果公司有DBA团队,可以考虑托管给他们。

    其他说明

    Logstash 配置

    当 AlarmLogMode 设置为 file 时,可使用 Logstash 采集文件日志。Logstash 样例配置如下,使用前请先修正日志路径

    FAQ

    1. 常见启动失败原因

    日志会打印到 logs/api/agent-cloud.log 里。如果启动时没有增加 -d 参数,我们将同时在前台打印错误消息,e.g

    目前定义的错误如下,

    错误码 | 说明 :---- | :--- | :--- 30001 | 日志初始化失败,如文件权限问题 30002 | MongoDB 初始化失败,如 MongoDB 地址无法连接、MongoDB 认证失败等等 30003 | ES 初始化失败,如 ES 地址无法连接 30004 | 配置错误 ,如未配置 Domain 30005 | 启动模式错误,启动使用了 agent, panel 之外的,不支持模式 30006 | 管理员密码初始化失败 30007 | geoip 初始化失败,如 geoip 数据库文件权限问题 30008 | 后台管理员用户名密码重置失败 30009 | 创建默认 app 失败 30010 | -d 参数启动后台失败

    具体错误信息请查看 nohup 控制台输出

    2. 管理后台打开后空白、按钮点不动等问题

    我们目前只兼容 Google Chrome 浏览器。如果页面出现任何问题,请按下 F12 调出开发工具,并检查控制台是否有错误输出。如下图中的红色字样:

    console

    如果发现这种问题,请加入QQ群联系我们处理。

    3. ElasticSearch "Result window is too large" 错误

    如果你搜索的时间范围太大,ES 可能会爆出如下错误:

    Result window is too large, from + size must be less than or equal to: [10000] but was [281280]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.

    这是因为你搜索的时间范围很大,导致ES需要对大量的数据进行排序。解决方法是打开 config/elasticsearch.yml,修改或者增加 index.max_result_window 配置,将它调整为一个较大的值。当然,修改这个值会消耗更多的内存。

    4. 我的主机名显示为 "im-not-resolvable"

    在 Java 版本里,我们使用了 InetAddress 来获取主机名称,如果这个主机名在 /etc/hosts 下面没有对应的记录,Java 将抛出 Unknown host 异常。在这种情况下,我们会将主机名设置为 im-not-resolvable,并让程序继续运行。

    解决方法是,在 /etc/hosts 下面为你的主机名添加一条记录:

    添加后,重启 Java 服务器生效。再次启动时,我们会注册一个新的agent到后台。

    5. 管理后台打不开,Chrome 浏览器提示 ERR_CONNECTION_REFUSED

    默认情况下,后台监听地址为 0.0.0.0:8086。如果你无法访问服务器,请检查防火墙是否开启对应端口。对于基于 netfilter 的防火墙,你可以执行如下命令开放 8086 端口:

    6. 无法发送邮件报警,提示 5XX 错误

    大部分国内邮箱都不支持密码登录,需要申请授权码进行登录。如果你在使用下列邮箱,请参考他们的 FAQ 文档进行配置:

    • 网易邮箱: 126/163/yeah.net

    • QQ 邮箱: qq.com/vip.qq.com

    • Coremail - 请联系销售

    7. ElasticSearch X-Pack 使用说明

    目前,后台使用的索引名称前缀为:

    • real-openrasp-X (alias)

    • openrasp-X

    如果你在使用 X-Pack,且需要按照索引名称前缀进行授权,可以根据上述规则添加认证。若要查看当前 ES 的索引和别名列表,可访问如下URL:

    8. 自己编译的后台,访问前端服务器 8086 端口提示 404 错误

    前端文件在 dist 目录下,如果前端服务器返回 404 则说明这个目录不存在,或者 dist/index.html 不存在。

    9. 误删ES索引,如何处理?{#es-index-reset}

    ES索引里只保存报警信息,误删索引不会导致agent信息丢失。若要完全重置ES,请先删除所有以 real-openrasp-、openrasp- 开头的索引,并重新启动 rasp-cloud 即可。rasp-cloud 会在启动时检查并重新创建索引。

    10. 报警上传成功,后台看不到报警而且 ES 健康状态为 yello

    为了避免阻塞,管理后台是异步将报警日志写入 ElasticSearch,因此 API 接口成功不代表报警保存成功。当 ES 服务器磁盘空间占用超过 95%,ES 会拒绝接受日志并抛出 cluster_block_exception 异常:

    修复方式请参考 Elasticsearch磁盘占用大于95%时将所有索引置为只读 文章解决。

    11. 我使用 nginx 作为管理后台的反向代理,iast 扫描器无法连接,总是提示400错误

    iast 扫描器使用 websocket upgrade 协议连接管理后台,nginx 需要同时传递 Upgrade 头才能工作:

    否则会在管理后台 api/agent-cloud.log 看到如下错误

    12. 管理后台假死,日志里出现大量 too many open files

    参考 linux 打开文件数 too many open files 解决方法 修正 limits.conf 里的配置即可,修正后需要重新登录生效。

    最后通过 ulimits -n 命令确认即可。

    13. 离线主机排查

    如果后台出现离线主机,请按照如下步骤排查:

    1. 检查客户端与后台是否连通。使用 curl 命令访问管理后台,检查是否能访问。

    2. 重启 Tomcat/PHP 服务器,检查主机是否上线。

    3. 检查客户端主机名、网卡信息是否有变化。如果有,后台信息会跟着变更,并产生一台新的主机。这个问题会在后续版本修正,即固定 rasp_id 到配置目录。

    4. 检查管理后台系统时间是否正确。

    14. rasp-cloud 启动卡住

    目前已知的情况有

    1. beego自身存在BUG,如果日志目录被链接到 /dev/null,将会卡住。e.g log/access 目录

    软件下载

    简介

    OpenRASP 抛弃了传统防火墙依赖请求特征检测攻击的模式,创造性的使用RASP技术(应用运行时自我保护),直接注入到被保护应用的服务中提供函数级别的实时防护,可以在不更新策略以及不升级被保护应用代码的情况下检测/防护未知漏洞,尤其适合大量使用开源组件的互联网应用以及使用第三方集成商开发的金融类应用。

    另外,OpenRASP 提供的IAST解决方案,相比于与传统的DAST方案有着革命性提升。漏洞检测无需动态爬虫或者旁路代理,扫描更全面;结合应用探针准确的识别漏洞类型,通过针对性扫描大幅度提升检测效率;商业版新增的动态污点追踪能力,还可以在不扫描的情况下,预判接口是否存在漏洞。

    OpenRASP 是经过开源社区大规模验证过的产品,目前客户数量已经过百,QQ群人数超过1800人。如果你在使用过程中遇到任何问题,请加入,联系我们处理。

    常用链接

    安装部署

    安装部署

    目前,OpenRASP 支持 Java 和 PHP 两种开发语言。更多语言支持计划,请查看 。具体开发排期和版本内容,请关注我们置顶的 页面。

    [prod]
    EsAddr = http://127.0.0.1:9200
    EsUser =
    EsPwd =
    MongoDBAddr = 127.0.0.1:27017
    MongoDBUser =
    MongoDBPwd =
    ./rasp-cloud -d
    ./rasp-cloud -type=panel -d
    ./rasp-cloud -type=agent -d
    EnableHTTPS = true
    EnableHttpTLS = true
    HttpsPort = 443
    HTTPSCertFile = "cert.pem"
    HTTPSKeyFile  = "cert.key"
    ./rasp-cloud -type=reset
    %> ./rasp-cloud -s status
    /rasp-cloud/
    2020/02/11 18:13:39 The rasp-cloud is running!
    %> ./rasp-cloud -version
    /rasp-cloud/
    Version:       1.3
    Build Time:    2020-02-11 17:56:52
    Git Commit ID: d6902d60f8874e7255562544041edbd340e6b676
    real-openrasp-report-data-{appid}
    real-openrasp-attack-alarm-{appid}
    real-openrasp-policy-alarm-{appid}
    real-openrasp-error-alarm-{appid}
    real-openrasp-dependency-data-{appid}
    input{
        file{
            path=>[
                ## 1. 修改该处,将 $cloud-agent-home 替换为部署的 agent 模式后台的根目录
                "$cloud-agent-home/openrasp-logs/attack-alarm/attack.log"
            ]
            start_position => "beginning"
            type => "attack-alarm"
            codec => "json"
        }
      
        file{
            path=>[
                ## 2. 修改该处,将 $cloud-agent-home 替换为部署的 agent 模式后台的根目录
                "$cloud-agent-home/openrasp-logs/policy-alarm/policy.log"
            ]
            start_position => "beginning"
            type => "policy-alarm"
            codec => "json"
       }
    }
    
    output {
    
        if [type] == "attack-alarm" {
            elasticsearch {
                ## 3. 修改 ES 地址
                hosts  => "0.0.0.0:9200"
                index =>  'real-openrasp-%{type}-%{[app_id]}'
                timeout => 30
                document_type => '%{type}'
            }
        }
    
        if [type] == "policy-alarm"{
            elasticsearch {
                ## 4. 修改 ES 地址
                hosts  => "0.0.0.0:8200"
                index =>  'real-openrasp-%{type}-%{[app_id]}'
                timeout => 30
                document_type => '%{type}'
                action => 'update'
                document_id => '%{[upsert_id]}'
                doc_as_upsert => true
            }
        }
    
    }
    2018/12/14 09:55:11.393 [I] [environment.go:62]  ===== start type: default =====
    2018/12/14 09:55:11.408 [E] [mongo.go:54]  [30002] init mongodb failed: no reachable servers
    127.0.0.1 myhostname
    iptables -I INPUT -p tcp --dport 8086 -j ACCEPT
    http://elasticsearch_hostname:port/_cat/indices?v
    http://elasticsearch_hostname:port/_cat/alias?v
    blocked by: [FORBIDDEN/12/index read-only / allow delete (api)]
    server {
        listen 84;
        location / {
            proxy_set_header Host $http_host;
            proxy_pass http://172.17.0.4;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }
    2020/02/07 11:37:47.784 [E] [iast.go:147]  upgrade err: websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header

    快速接入

  • 性能测试

  • 检测能力

    • 检测能力,覆盖场景,以及零规则算法介绍

    • CVE 漏洞覆盖列表

    我们的技术讨论QQ群
    baidu/openrasp - 里程碑
    baidu/openrasp - ISSUE

    MongoDBAddr

    MongoDB 连接地址,多个地址用逗号隔开

    127.0.0.1:27017

    MongoDBName

    使用的 MongoDB 的数据库名称

    openrasp

    MongoPoolLimit

    MongoDB 连接池最大限制

    2048

    MongoDBUser

    MongoDB 认证用户名,该用户需要有操作 openrasp 数据库的权限,有认证才需要配置

    空

    MongoDBPwd

    MongoDB 认证密码

    空

    LogMaxSize

    单个日志文件最大大小,超过就rotate当天日志

    104857600

    LogMaxDays

    最多保留多少天的日志

    7

    MaxPlugins

    每个App最多保留多少插件,超过删除最老的

    30

    CookieLifeTime

    登录 cookie 有效期,单位/小时

    168

    AlarmLogMode

    报警日志采集模式,file 模式将日志落地到文件,可配合 logstash 上传到 es;es 模式将日志直接写入到 ES

    es

    AlarmBufferSize

    es 模式下日志缓冲区大小,当日志量过大,缓冲区满的情况下,将会出现日志丢失

    300

    AlarmCheckInterval

    报警检查间隔时间,单位秒 v1.3 开始改为前端配置

    120

    RequestBodyEnable

    access.log中是否包含请求体信息

    false

    DebugModeEnable

    是否开启Debug开关,打印调试信息

    false

    ErrorLogEnable

    是否将错误日志记录到es

    false

    LogMaxSize

    rasp每个日志文件大小(单位:字节)

    104857600

    LogMaxDays

    rasp日志最长保留天数

    10

    LogPath

    rasp日志文件根路径

    /home/openrasp/logs

    OfflineInterval

    rasp主机离线时间判定超时阈值,允许范围为30~31622400(单位:秒)

    180

    RegisterCallbackUrl

    rasp主机注册回调地址,如果失败将不会注册

    空

    Tomcat 服务器

    自动化安装

    下载 rasp-java.tar.gz 或者 rasp-java.zip 并解压缩。之后进入到解压后的目录中,e.g rasp-20181221

    如果你要开启远程管理,请先参考 管理后台 - 添加主机 文档,找到 app_id/app_secret/backend_url 三个关键参数,然后执行如下命令,

    如果你只是运行单机版,只需要指定 -install 参数,

    这里的 <tomcat_root> 不是 webapps 目录,而是 tomcat 的根目录。没有错误表示安装成功,其他配置请参考 文档。安装后,需要重启 Tomcat 服务器生效。

    不重启安装(仅支持 JDK 6-8)

    以上方式安装成功之后需要重启服务器,如果在服务器启动的情况下,不重启安装 OpenRASP,需要在以上命令后面增加 -pid 参数指定运行的服务器进程ID:

    在 Windows 下面请替换 $JAVA_HOME 为 %JAVA_HOME%

    RASP 升级方法

    在 Linux 下面,可以使用 bin/catalina.sh stop 来执行 graceful stop

    你会在日志里看到类似下面的输出,这表明 Tomcat 将在处理完当前的HTTP后退出

    之后参考我们的自动或者手动安装文档,重新安装即可

    手动安装 - Linux

    1. 安装软件

    进入到 tomcat 安装目录(绝对路径包含空格将导致启动失败),e.g /opt/apache-tomcat-8.5.6,将 rasp 目录复制过来

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以还需要修改 rasp 目录的权限,e.g

    否则你可能在 catalina.out 里看到类似这样的错误,

    2. 修改 Tomcat 启动脚本

    打开 bin/catalina.sh, 找到如下内容:

    修改为如下(增加 -javaagent 项)

    对于使用 yum 安装的 tomcat,你需要创建 /etc/tomcat/conf.d/rasp.conf,并写入以下内容

    对于JDK9以上版本,还需要增加额外的JDK启动参数,e.g

    3. 开启远程管理

    如果你不需要远程管理功能,请跳过这个步骤。

    首先,请先参考 文档,找到 openrasp.yml 配置文件内容。然后打开 <tomcat_home>/rasp/conf/openrasp.yml,添加或者修改如下内容:

    4. 验证安装是否成功

    首先重启tomcat服务器。如果安装了管理后台,在管理后台检查主机是否上线即可;如果是单机版,可以按照如下流程检查:

    检查响应的请求头是否包含 X-Protected-By 字样,出现则表示安装成功:

    如果使用了反向代理,可能不会看到上面的请求头。此时可以检查 rasp/logs/rasp/rasp.log 中是否出现 OpenRASP Engine Initialized 字样,出现也表示安装成功:

    如果服务器无法启动,请检查 tomcat 启动日志,看Java是否抛出异常,e.g catalina.out。如果你无法解决问题,请。

    手动安装 - Windows

    1. 安装软件

    进入到 tomcat 安装目录,e.g D:\apache-tomcat-8.5.6,将 rasp 目录复制过来

    2. 修改 tomcat 配置

    2.1 如果是下载的 "32-bit/64-bit Windows Service Installer" 安装包,

    请参考,打开 bin/tomcatXw.exe

    切换到 Java 标签页,

    在 Java Options 下面增加启动参数,注意替换下绝对路径,e.g

    对于JDK9以上版本,还需要额外增加如下内容

    2.2 如果是下载的 "Windows zip" 安装包

    打开 bin\catalina.bat, 找到 :setArgs 处:

    在 :setArgs 下增加新的 JAVA_OPTS,e.g

    对于JDK9以上版本,还需要额外增加两个JDK启动参数,e.g

    3. 开启远程管理

    方法同 Linux 版本,在 openrasp.yml 里增加相关配置即可。

    4. 验证安装是否成功

    重启 tomcat 服务器,然后检查日志文件,一般是 rasp/logs/rasp/rasp.log,如果出现 OpenRASP Engine Initialized 字样,出现则说明安装成功;或者访问一下服务器,检查是否存在 X-Protected-By: OpenRASP 响应头,存在即表示安装成功。

    常见问题

    1. Tomcat Windows Service Installer 版本,无法自动安装

    服务版本的安装包,没有提供 catalina.sh,只提供了 tomcatX.exe 作为启动工具

    请参考,打开 bin/tomcatXw.exe 进行配置

    PHP 服务器

    OpenRASP 依赖于如下几个扩展。如果你在使用发行版自带的 PHP 环境,可以使用 yum、apt-get 等工具安装下这些扩展;如果是自己编译的 PHP 环境,则需要在编译阶段开启这些功能。

    • pdo

    • pcre

    • json

    java -jar RaspInstall.jar -install <tomcat_root> -backendurl http://XXX -appsecret XXX -appid XXX
    java -jar RaspInstall.jar -install <tomcat_root>
    其他配置
    管理后台 - 添加主机
    请联系我们
    这篇文章
    安装中出现任何问题,请联系我们
    Windows 手动安装文档
    tomcatw
    # <server_pid> 为 tomcat 进程 id
    # $JAVA_HOME 为 jdk 根目录环境变量,如果未指定该环境变量,替换为 jdk 的完整根目录
    java -Xbootclasspath/a:$JAVA_HOME/lib/tools.jar -jar RaspInstall.jar -install <tomcat_root> -pid <server_pid>
    Jan 12, 2018 6:11:55 PM org.apache.catalina.core.StandardWrapper unload
    INFO: Waiting for 1 instance(s) to be deallocated for Servlet [jsp]
    Jan 12, 2018 6:11:56 PM org.apache.catalina.core.StandardWrapper unload
    INFO: Waiting for 1 instance(s) to be deallocated for Servlet [jsp]
    Jan 12, 2018 6:11:57 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
    cp -R ~/Downloads/rasp-20170721/rasp .
    chmod 777 -R rasp
    com.baidu.openrasp.exception.ConfigLoadException: Fail to extract rasp-log4j.xml, because of: /usr/share/tomcat8/rasp/conf/rasp-log4j.xml (Permission denied)
    	at com.baidu.openrasp.messaging.LogConfig.extractLogConfigFile(LogConfig.java:153)
    	at com.baidu.openrasp.messaging.LogConfig.completeLogConfig(LogConfig.java:72)
    	at com.baidu.openrasp.Agent.loadConfig(Agent.java:91)
    	at com.baidu.openrasp.Agent.premain(Agent.java:66)
    elif [ "$1" = "start" ] ; then
    	if [ ! -z "$CATALINA_PID" ]; then
    elif [ "$1" = "start" ]; then
    	JAVA_OPTS="-javaagent:${CATALINA_HOME}/rasp/rasp.jar ${JAVA_OPTS}"
    	if [ ! -z "$CATALINA_PID" ]; then
    JAVA_OPTS="-javaagent:${CATALINA_HOME}/rasp/rasp.jar ${JAVA_OPTS}"
    JAVA_OPTS="--add-opens=java.base/jdk.internal.loader=ALL-UNNAMED ${JAVA_OPTS}"
    JAVA_OPTS="--add-opens=java.base/java.net=ALL-UNNAMED ${JAVA_OPTS}"
    JAVA_OPTS="-javaagent:${CATALINA_HOME}/rasp/rasp.jar ${JAVA_OPTS}"
    # 云控配置
    cloud.enable: true
    cloud.backend_url: xxx
    cloud.app_id: xxx
    cloud.app_secret: xxx
    cloud.heartbeat_interval: 180
    %> curl -v 127.0.0.1:8080
    
    ...
    X-Protected-By: OpenRASP
    X-Request-ID: eb3b8e287de8406bb4bdb9d86bd31f99
    ...
    %> grep OpenRASP -ir rasp/logs/
    rasp/logs/rasp/rasp.log:2018-05-22 16:13:25,842 INFO  [main][com.baidu.openrasp.Agent] OpenRASP Engine Initialized [1.0-SNAPSHOT (build: GitCommit=3da661734e3ad7641cd98e83f32950deaefcacac date=2017-08-14T03:34:41Z)]
    -javaagent:C:\Program Files\Apache Software Foundation\Tomcat 7.0\rasp\rasp.jar
    --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED
    --add-opens=java.base/java.net=ALL-UNNAMED
    :setArgs
    if ""%1""=="""" goto doneSetArgs
    set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
    :setArgs
    if "%ACTION%" == "start" set JAVA_OPTS=-javaagent:%CATALINA_HOME%\rasp\rasp.jar %JAVA_OPTS%
    if ""%1""=="""" goto doneSetArgs
    set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
    :setArgs
    if "%ACTION%" == "start" set JAVA_OPTS=-javaagent:%CATALINA_HOME%\rasp\rasp.jar --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED %JAVA_OPTS%
    if ""%1""=="""" goto doneSetArgs
    set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
    对于服务器环境和操作系统的支持情况,可查看兼容性说明 - PHP Agent,目前 5.3 - 7.3 都是支持的。

    自动化安装

    下载 rasp-php-linux.tar.bz2 或者 rasp-php-linux-ts.tar.bz2(线程安全版本) 并解压缩。之后进入到解压后的目录中,e.g rasp-php-20180320

    如果你要开启远程管理,请先参考 管理后台 - 添加主机 文档,找到 app_id/app_secret/backend_url 三个关键参数,然后执行如下命令,

    如果你只是运行单机版,只需要指定 -d 参数,

    其中 /opt/rasp 为 OpenRASP 安装目录,用于存储检测插件、报警日志等等,可根据实际情况调整。在某些情况下,php cli 和 php-fpm 使用的 ini 不同,自动安装程序可能会失败。

    升级 PHP Agent

    首先,备份老的扩展,e.g

    然后,安装新的扩展,e.g

    最后,通过 graceful reload 方式重新加载服务。

    针对不同的服务器类型,你需要执行不同的命令,e.g

    需要注意的是,请不要直接覆盖 openrasp.so,否则会产生意想不到的内存错误。我们建议使用 重命名方式 来安装新版,以避免出现问题。

    手动安装 - Linux

    1. 确认基本信息

    在 web 目录下面,我们建立一个 info.php,并填写如下内容

    在浏览器里打开这个页面,使用搜索功能,

    1. 定位到 extension_dir 字样,确认PHP扩展安装目录

      • e.g /usr/lib/php/20151012

    2. 搜索 Additional .ini files parsed 字样,

      • 如果找到了,我们就在这个目录下面创建一个新的 ini 文件,e.g /etc/php.d/z-openrasp.ini

    3. 如果找不到,就定位到 Loaded Configuration File 字样,确认 ini 配置文件路径

      • e.g /etc/php.ini

    2. 安装软件

    首先,根据你的 PHP 版本号,复制正确的 openrasp.so 到扩展目录,e.g

    然后,确定 OpenRASP 安装目录,在这里我们使用 /opt/rasp

    这个目录将会用于存储检测插件、报警日志、插件日志等内容,需要手动创建,并保证 PHP 进程可以写入,e.g

    由于报警日志存储在 /opt/rasp/logs,我们建议挑选一个空间较大的分区,以避免将根分区打满

    最后,修改 php.ini,或者创建 z-openrasp.ini 文件,添加如下内容:

    其中,openrasp.root_dir 表示刚才选择的 OpenRASP 安装目录,不填写则无法加载。对于其他配置参数,可参考其他配置文档进行调整。

    3. 安装检测插件

    点击这里下载官方插件 plugins/official/plugin.js,并放置到 <openrasp.root_dir>/plugins/ 目录,下载后自动加载并生效。

    4. 验证安装是否成功

    访问刚才创建的 info.php,检查 openrasp 模块是否加载成功即可,e.g

    img

    如果你没有看到类似的信息,则说明扩展加载失败。常见原因有

    1. PHP版本和扩展版本不一致,比如 PHP 是 5.3 版本,但你安装了 PHP 5.6 版本的 openrasp.so

    2. INI 配置不正确,请参考 php error.log 里的错误消息

      • 所有的错误消息都以 [OpenRASP] 错误码 开头,方便和其他日志进行区分

      • 对于 apache/nginx,可以查看类似 /var/log/nginx/error.log 的路径

    确认安装成功后,请删除 info.php 这个文件,以避免泄露敏感信息。

    手动安装 - MacOS

    我们只支持 Homebrew PHP 5.6 版本,安装过程同 Linux 系统,aka

    1. 复制 dylib 文件到 PHP 扩展目录

    2. 修改 INI 配置文件

    3. 重启 php-fpm 生效

    另外,MacOS 版本不支持远程管理。

    FAQ

    1. include/require hook 点未生效

    OpenRASP 扩展跟 xdebug 模块存在冲突,若同时开启了 xdebug 模块,请先禁用它

    2. 单机版 php-fpm 模式下,插件目录的文件监控功能,有时会失效

    在 openrasp 扩展初始化时,我们创建了文件监控线程,用于插件目录的监控。当我们发现插件目录发生变化,就会通过发送 USR2 信号的方式,通知 php-fpm master process 去重新加载子进程,即 gracefully reload。

    然而,如果你在启动 php-fpm 的时候,没有使用 -F 参数,则意味着 php-fpm 会主动 fork() 到后台。此时,我们创建的文件监控线程就会失效,也就无法监控插件目录了。

    解决方法就是使用 php-fpm -F 这样的方式启动PHP服务器。当然,如果你使用发行版自带的 php-fpm,通常都是这样启动的,无需担心。

    3. OpenRASP正常拦截攻击,但是alarm.log没有日志

    默认情况下,OpenRASP会被安装到/opt/rasp,以下用<openrasp.root_dir>代替。你需要检查<openrasp.root_dir>/rasp/logs目录是否存在,以及是否有写权限。

    常见没有权限的原因有:

    1. 使用了root账号安装OpenRASP,而应用使用低权限账号运行(比如nobody)。

      1. 可以执行chmod 777 -R <openrasp.root_dir>/logs增加权限

      2. 也可以使用chmod修改上述目录的属主(更加安全)

    2. 开启了LSM

    3. 对于CentOS/RHEL系统,请检查SELinux是否开启。如果开启,可执行setenforce 0关闭

    4. 对于Debian/Ubuntu系统,请检查AppArmor是否开启。如果开启,可以修改php-fpm、apache进程的加固配置

    5. 开启了open_basedir配置

      1. 我们使用PHP Stream方式写入日志,需要将日志目录加到open_basedir白名单里。如果没有加入,将会看到类似这样的错误

      2. 由于nginx/php-fpm/apache都可以修改php的配置,建议在网站根目录下放置phpinfo来检查该配置项,要比命令行准确

    6. 如果依然无法解决问题,请检查 php error_log 是否有 OpenRASP 相关的错误日志

      • 如果没有配置过,请在 php.ini 里开启,e.g error_log = /tmp/php_error.log

    4. CentOS 7.4 apache 使用 systemd 启动会崩溃的问题

    systemd 会限制应用栈的大小,导致 openrasp 无法启动。你通过修改 /usr/lib/systemd/system/httpd.service,并提高 LimitStack 的值来解决问题。经过测试,我们发现将栈大小限制改为 16MB 可以解决问题,对应的配置为:

    当然,直接使用命令行启动 apache 是没有这个问题的,因为他会继承系统默认的 limit 配置,即 unlimited。

    5. php_json_encode 未定义错误

    OpenRASP 依赖于多个PHP扩展,json、pdo、pcre 等等。由于 PHP 不会严格按照依赖顺序去加载扩展,所以当 openrasp 先于 json 加载,就会产生这个错误,e.g

    解决方法就是让 openrasp 扩展最后加载。常见的做法是调整配置文件的权重,比如将 openrasp 配置文件改为 /etc/php.d/z-openrasp.ini,这样 json 配置文件就会先于 openrasp 配置文件加载,就解决了扩展依赖的问题。

    6. 无法检测到 web 目录下的敏感文件?{#faq-webdir-scan}

    当PHP服务器处理过至少一次请求后,我们才能够检测到 webroot,之后才会启动敏感目录检测功能。为了保证性能,该检测点具有如下限制:

    1. 只会检测根目录,子目录不会处理

    2. 最多在内存里缓存 256 个不同的 webroot 路径,超过这个限制时,只保留已有的路径

    7. alphine 环境无法启动,提示找不到 ld-linux-x86-64.so.2

    根据QQ群用户反馈,增加软连接可以解决问题:

    8. 如何判断PHP是否为线程安全版本

    执行如下命令,如果返回 bool(true) 则是线程安全(TS)版本

    当然也可以编写PHP脚本来测试,如果页面返回 bool(true) 则是线程安全(TS)版本

    JBoss 服务器

    自动化安装

    解压缩后,首先进入到解压后的目录中,e.g rasp-20170721

    如果你要开启远程管理,请先参考 文档,找到 app_id/app_secret/backend_url 三个关键参数,然后执行如下命令,

    如果你只是运行单机版,只需要指定 -install 参数,

    安装成功后,需要重启 JBoss 服务器生效。

    不重启安装

    php install.php -d /opt/rasp --backend-url http://myserver:port --app-secret XXX --app-id XXXX
    php install.php -d /opt/rasp
    mv /usr/lib64/php/modules/openrasp.so /usr/lib64/php/modules/openrasp.so.bak
    cp openrasp.so /usr/lib64/php/modules/openrasp.so
    PHP-FPM 服务器
    killall -USR2 php-fpm
    
    Apache HTTPD 服务器
    apachectl -k reload
    <?php phpinfo();?> 
    cp php/linux-php5.4-x86_64/openrasp.so /usr/lib/php/20151012
    chmod 755 /usr/lib/php/20151012/openrasp.so
    mkdir -p /opt/rasp
    chmod 777 -R /opt/rasp
    ; BEGIN OPENRASP
    
    [openrasp]
    extension=openrasp.so
    openrasp.root_dir=/opt/rasp
    
    ; 远程管理配置,不需要不用配置
    ; openrasp.backend_url=
    ; openrasp.app_id=
    ; openrasp.app_secret=
    ; openrasp.remote_management_enable=1
    
    ; END OPENRASP
    LimitStack=163840
    PHP Warning:  PHP Startup: Unable to load dynamic library '/usr/lib64/php/modules/openrasp.so' - /usr/lib64/php/modules/openrasp.so: undefined symbol: php_json_encode in Unknown on line 0
    ln -s /lib64/ld-linux-x64-64.so.2 /lib/
    php -r "var_dump(ZEND_THREAD_SAFE);"
    <?php echo var_dump(ZEND_THREAD_SAFE); ?>
    以上方式安装成功之后需要重启服务器,如果在服务器启动的情况下,不重启安装 OpenRASP,需要在以上命令后面增加 -pid 参数指定运行的服务器进程 id,JDK6 - JDK8 样例命令如下,

    ** 由于无法在运行时增加 JbossEAP 对 OpenRASP 的运行时依赖,所以无法支持 JbossEAP 的不重启安装 **

    ** jdk9 ~ jdk11 不支持不重启安装 **

    手动安装 - Linux

    1. 安装软件

    进入到 jboss 安装目录(绝对路径包含空格将导致启动失败),e.g /opt/jboss

    复制安装包内的 rasp 目录到当前目录,

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以还需要修改 rasp 目录的权限,e.g

    2. 配置 JBoss

    如果是 JBoss 4-6 (非 EAP 版本),

    打开bin/run.sh, 找到任意以 JAVA_OPTS= 为起始的行,e.g

    在下面增加 JAVA_OPTS="-javaagent:${JBOSS_HOME}/rasp/rasp.jar ${JAVA_OPTS}",最终效果如下:

    如果是 JBoss EAP,

    standalone模式

    打开bin/standalone.sh,找到# Display our environment处,在下面添加:

    domain模式

    server-group方式配置rasp

    如果按照server-group配置rasp,那么此group下面所有的服务器都会安装rasp,打开domain/configuration/domain.xml文件,找到<server-groups>标签,在需要安装rasp的server-group中找到<jvm>标签添加如下配置:

    server方式配置rasp

    如果只对某个server-group的特定的server安装rasp,打开domain/configuration/host.xml文件,找到<servers>标签,在需要安装rasp的server中添加如下配置:

    3. 开启远程管理

    配置方法同 Tomcat 开启远程管理,不再赘述。

    4. 验证安装是否成功

    重启 JBoss 服务器,观察启动日志中是否出现 OpenRASP Engine Initialized字段,出现则说明安装成功

    手动安装 - Windows

    1. 安装软件

    进入到 jboss 安装目录,e.g D:\\jboss

    复制安装包内的 rasp 目录到当前目录

    2. 配置 JBoss

    如果使用Jboss 4~6 (非 EAP 版本),则打开 bin\run.bat;

    打开脚本后,找到任意以 set JAVA_OPTS 为起始的行,如:

    在下面增加 set JAVA_OPTS=-javaagent:%JBOSS_HOME%\rasp\rasp.jar %JAVA_OPTS%:

    如果使用Jboss EAP,

    standalone模式

    打开 bin\standalone.bat 找到第一次出现rem Setup JBoss specific properties处,在下面添加:

    domain模式

    方法同 Linux 版本

    3. 开启远程管理

    配置方法同 Tomcat 开启远程管理,不再赘述。

    4. 验证安装是否成功

    重启 JBoss 服务器,观察启动日志(默认输出到终端)中是否出现 OpenRASP Engine Initialized字段,出现则说明安装成功;或者访问一下服务器,检查是否存在 X-Protected-By: OpenRASP 响应头,存在即表示安装成功。

    已知问题

    1. java.io.ObjectInputStream 错误

    这个并不是 OpenRASP 的问题,请尝试更新JDK到最新版本

    参考资料

    • The type java.io.ObjectInputStream cannot be resolved. It is indirectly referenced from required .class files

    2. JDK 9 以上版本兼容性问题

    请参考 JDK9 以上安装问题 手动修改启动参数。我们会尽快修改 RaspInstall 程序,并自动添加这个配置。

    3. org.jboss.logmanager.PropertyConfigurator cannot be cast to org.jboss.as.logging.logmanager.ConfigurationPersistence 异常

    在JBoss EAP 6.1.0上安装OpenRASP后,JBoss可能会无法启动并打印如下错误:

    根据Redhat的描述,有两种解决方法:

    • 升级到 JBoss EAP 6.1.1

    • 手动修正 JBOSS_MODULES_SYSTEM_PKGS 配置,暴露相关的Jar给javaagent

    管理后台 - 添加主机
    PHP Warning:  scandir(): open_basedir restriction in effect. File(/www/rasp/logs/alarm/alarm.log.2018-07-26) is not within the allowed path(s)
    java -jar RaspInstall.jar -install <jboss_root> -backendurl http://XXX -appsecret XXX -appid XXX
    java -jar RaspInstall.jar -install <jboss_root>
    # <server_pid> 为 jboss 进程 id
    # $JAVA_HOME 为 jdk 根目录环境变量,如果未指定该环境变量,替换为 jdk 的完整根目录
    java -Xbootclasspath/a:$JAVA_HOME/lib/tools.jar -jar RaspInstall.jar -install <jboss_root> -pid <server_pid>
    cp -R ~/Downloads/rasp-20170721/rasp .
    chmod 777 -R rasp
    # Setup JBoss specific properties
    JAVA_OPTS="-Dprogram.name=$PROGNAME $JAVA_OPTS"
    # Setup JBoss specific properties
    JAVA_OPTS="-Dprogram.name=$PROGNAME $JAVA_OPTS"
    JAVA_OPTS="-javaagent:${JBOSS_HOME}/rasp/rasp.jar ${JAVA_OPTS}"
    JAVA_OPTS="${JAVA_OPTS} -javaagent:${JBOSS_HOME}/rasp/rasp.jar"
    <jvm-options>
       <option value="-javaagent:<jboss_root>/rasp/rasp.jar"/>
    </jvm-options>
    <jvm name="default">
        <jvm-options>
       		<option value="-javaagent:<jboss_root>/rasp/rasp.jar"/>
    	</jvm-options>
    </jvm>
    set JAVA_OPTS=%JAVA_OPTS% -Dprogram.name=%PROGNAME%
    set JAVA_OPTS=%JAVA_OPTS% -Dprogram.name=%PROGNAME%
    set JAVA_OPTS=-javaagent:%JBOSS_HOME%\rasp\rasp.jar %JAVA_OPTS%
    set "JAVA_OPTS=%JAVA_OPTS% -javaagent:%JBOSS_HOME%\rasp\rasp.jar"
    14:27:19,691 ERROR [org.jboss.as.controller.management-operation] (ServerService Thread Pool -- 11) JBAS014612: Operation ("add") failed - address: ([
        ("subsystem" => "logging"),
        ("console-handler" => "CONSOLE")
    ]): java.lang.ClassCastException: org.jboss.logmanager.PropertyConfigurator cannot be cast to org.jboss.as.logging.logmanager.ConfigurationPersistence
            at org.jboss.as.logging.logmanager.ConfigurationPersistence.getOrCreateConfigurationPersistence(ConfigurationPersistence.java:93)
            at org.jboss.as.logging.logmanager.ConfigurationPersistence.getOrCreateConfigurationPersistence(ConfigurationPersistence.java:81)
            at org.jboss.as.logging.LoggingOperations$LoggingOperationStepHandler.execute(LoggingOperations.java:154)
            at org.jboss.as.controller.AbstractOperationContext.executeStep(AbstractOperationContext.java:440) [jboss-as-controller-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
            at org.jboss.as.controller.AbstractOperationContext.doCompleteStep(AbstractOperationContext.java:322) [jboss-as-controller-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
            at org.jboss.as.controller.AbstractOperationContext.completeStepInternal(AbstractOperationContext.java:229) [jboss-as-controller-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
            at org.jboss.as.controller.AbstractOperationContext.executeOperation(AbstractOperationContext.java:224) [jboss-as-controller-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
            at org.jboss.as.controller.ParallelBootOperationStepHandler$ParallelBootTask.run(ParallelBootOperationStepHandler.java:334) [jboss-as-controller-7.2.0.Final-redhat-8.jar:7.2.0.Final-redhat-8]
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_79]
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_79]
            at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_79]
            at org.jboss.threads.JBossThread.run(JBossThread.java:122) [jboss-threads-2.1.0.Final-redhat-1.jar:2.1.0.Final-redhat-1]

    Jetty 服务器

    手动安装

    1. 安装软件

    进入到 jetty 安装目录,e.g /opt/jetty

    复制安装包内的 rasp 目录到当前目录,

    cp -R ~/Downloads/rasp-20170721/rasp .

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以还需要修改 rasp 目录的权限,e.g

    2. 配置 Jetty

    这里假设 rasp 目录释放到了 /opt/jetty/rasp/。

    修改 java 启动参数,增加 -javaagent 参数(注意将 -jar 放在命令最末尾):

    需要注意的是,对于Windows服务器,请修正 -javaagent 参数,比如

    3. 开启远程管理

    配置方法同 ,不再赘述。

    4. 检查 Jetty 是否安装成功

    重启 Jetty 服务器,然后检查日志文件,如果出现 OpenRASP Engine Initialized 字样,出现则说明安装成功;或者访问一下服务器,检查是否存在 X-Protected-By: OpenRASP 响应头,存在即表示安装成功。

    FAQ

    1. Jetty / JDK 兼容性问题

    Jetty 在 linux/windows 下存在很多问题,经常会看到以下几种错误

    • PWC6345: There is an error in invoking javac

    • PWC6199: The type java.io.ObjectStream cannot be resolved

    以上这些问题大多是JDK、Jetty自身的问题,可通过更换其他小版本来解决。即使没有安装OpenRASP,Jetty运行也是不正常的。在安装 OpenRASP 前,请先保证Jetty是正常运行的

    当然,如果安装OpenRASP后导致jetty出错,你可以

    Resin 服务器

    自动化安装

    解压缩后,首先关闭Resin服务器,然后进入到解压后的目录中,e.g rasp-20180522

    如果你要开启远程管理,请先参考 文档,找到 app_id/app_secret/backend_url 三个关键参数,然后执行如下命令,

    如果你只是运行单机版,只需要指定 -install 参数,

    安装成功后,需要重启 Resin 服务器生效。

    不重启安装

    chmod 777 -R rasp
    Tomcat 开启远程管理
    联系我们
    Resin 目前不支持。

    手动安装

    1. 安装软件

    进入到 resin 安装目录(绝对路径包含空格将导致启动失败),e.g /opt/resin

    复制安装包内的 rasp 目录到当前目录,

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以还需要修改 rasp 目录的权限,e.g

    2. 配置 Resin

    注意: 对于集群模式,可能不存在 <server-default> 标签。对于此类情况,请联系研发团队,并确认应该在哪里增加 JVM 启动参数。

    如果是 resin 3,

    打开conf/resin.conf, 找到 <server-default> 下面的 <jvm-arg> 起始行,e.g

    在下面增加:

    如果是 resin 4,

    打开 conf/cluster-default.xml, 找到 <server-default> 下面的 <jvm-arg-line> 起始行,e.g

    在下面增加:

    3. 开启远程管理

    配置方法同 Tomcat 开启远程管理,不再赘述。

    4. 验证安装是否成功

    重启 Resin 服务器,观察启动日志中是否出现 OpenRASP Engine Initialized 字样,出现则说明安装成功;或者访问一下服务器,检查是否存在 X-Protected-By: OpenRASP 响应头,存在即表示安装成功。

    管理后台 - 添加主机
    java -javaagent:/opt/jetty/rasp/rasp.jar -jar start.jar
    -javaagent:D:\jetty\rasp\rasp.jar
    java -jar RaspInstall.jar -install <resin_root> -backendurl http://XXX -appsecret XXX -appid XXX
    java -jar RaspInstall.jar -install <resin_root>
    cp -R ~/Downloads/rasp-20170721/rasp .
    chmod 777 -R rasp
    <jvm-arg>-Xmx256m</jvm-arg>
    <jvm-arg>-Xss1m</jvm-arg>
    <jvm-arg>-Xdebug</jvm-arg>
    <jvm-arg>-Dcom.sun.management.jmxremote</jvm-arg>
    <jvm-arg>-javaagent:/opt/resin/rasp/rasp.jar</jvm-arg>
    <jvm-arg-line>${jvm_args}</jvm-arg-line>
    <jvm-mode>${jvm_mode}</jvm-mode>
    <jvm-arg>-javaagent:/opt/resin/rasp/rasp.jar</jvm-arg>

    Spring Boot 框架

    我们支持 war 包、jar 包两种部署模式。如果是 war 包的形式,直接参考相应服务器文档即可;如果是内嵌服务器的 jar 包形式,请参考本文档安装。对于 WebGoat 项目,对应的 jar 包通常为 webgoat-XXX.jar。

    半自动安装

    从 v1.2.0 版本开始,我们加入了 SpringBoot 半自动安装支持。之前的版本请参考手动安装章节。

    1. 安装软件

    SpringBoot 没有提供通用的启动脚本,所以我们的半自动安装程序只会释放文件。在解压缩后,首先进入到解压后的目录中,e.g rasp-20181221

    如果你要开启远程管理,请先参考 管理后台 - 添加主机 文档,找到 app_id/app_secret/backend_url 三个关键参数,然后执行如下命令,

    如果你只是运行单机版,只需要指定 -install 参数,

    这里的 <spring_boot_folder> 通常是 XXX.jar 包所在的目录。具体 jar 的名字请咨询业务线。

    2. 配置启动参数

    假设 spring_boot_folder 目录为 /opt/spring-boot/。

    修改 SpringBoot 启动参数,增加 -javaagent 绝对路径参数(注意将 -jar 放到命令最末尾),e.g

    如果JDK版本为6-8,那么启动参数如下配置

    如果JDK版本为11,那么启动参数如下配置

    3. 检查安装是否成功

    访问服务器,检查是否存在 X-Protected-By: OpenRASP 响应头即可。

    手动安装

    1. 安装软件

    进入到 Spring Boot 所在目录,通常是 jar 所在的目录,e.g /opt/spring-boot

    复制安装包内的 rasp 目录到当前目录,

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以还需要修改 rasp 目录的权限,e.g

    2. 开启远程管理

    配置方法同 ,不再赘述。

    3. 配置启动参数

    假设 rasp 目录释放到了 /opt/spring-boot/rasp/。

    修改 SpringBoot 启动参数,增加 -javaagent 绝对路径参数(注意将 -jar 放到命令最末尾),e.g

    如果JDK版本为6-8,那么启动参数如下配置

    如果JDK版本为11,那么启动参数如下配置

    4. 检查安装是否成功

    访问服务器,检查是否存在 X-Protected-By: OpenRASP 响应头即可。

    Tomcat 开启远程管理
    java -jar RaspInstall.jar -nodetect -install <spring_boot_folder> -backendurl http://XXX -appsecret XXX -appid XXX
    java -jar RaspInstall.jar -nodetect -install <spring_boot_folder>
    java -javaagent:/opt/spring-boot/rasp/rasp.jar -jar XXX.jar
    java --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED -javaagent:/opt/spring-boot/rasp/rasp.jar -jar XXX.jar
    cp -R ~/Downloads/rasp-20170721/rasp .
    chmod 777 -R rasp
    java -javaagent:/opt/spring-boot/rasp/rasp.jar -jar XXX.jar
    java --add-opens java.base/jdk.internal.loader=ALL-UNNAMED -javaagent:/opt/spring-boot/rasp/rasp.jar -jar XXX.jar

    东方通TongWeb服务器

    手动安装

    1. 安装软件

    复制安装包内的 rasp 目录到 TongWeb 安装目录,比如

    • D:\tongweb安装目录\rasp

    • /opt/tongweb安装目录/rasp

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以在 Linux 下还需要修改 rasp 目录的权限,e.g

    2. 配置 TongWeb 服务器

    2.1 方法一: 手动配置 external.vmoptions 文件

    打开 Tongweb安装目录/bin/external.vmoptions,然后在其中添加javaagent的配置项:

    添加完成后的效果如下图所示(参考红线部分):

    配置完成后,重启TongWeb服务器即可生效。

    2.2 方法二: 通过TongWeb控制台进行配置

    登陆TongWeb的管理控制台,点击左侧 启动参数配置,然后找到 其他jvm参数,添加javagent配置项即可:

    添加完成后的效果如下图所示(参考红线部分):

    添加完成后点击保存按钮,然后重启TongWeb服务器即可生效。

    3. 开启远程管理

    配置方法同 ,不再赘述。

    4. 检查安装是否成功

    访问下服务器,检查响应头里是否存在 X-Protected-By: OpenRASP 字样,存在即表示安装成功。当然,如果安装 OpenRASP 后导致TongWeb出错,你可以

    Tomcat 开启远程管理
    联系我们
    console
    console
    chmod 777 -R /opt/tongweb安装目录/rasp
    -javaagent:${TongWeb_Home}/rasp/rasp.jar
    -javaagent:${TongWeb_Home}/rasp/rasp.jar

    Wildfly 服务器

    自动化安装

    解压缩后,首先进入到解压后的目录中,e.g rasp-20181221

    如果你要开启远程管理,请先参考 管理后台 - 添加主机 文档,找到 app_id/app_secret/backend_url 三个关键参数,然后执行如下命令,

    如果你只是运行单机版,只需要指定 -install 参数,

    这里的 <wildfly_root> 是 wildfly 的根目录。没有错误表示安装成功,其他配置请参考 其他配置 文档。安装后,需要重启 Wildfly 服务器生效。

    ** 由于无法在运行时增加 Wildfly 对 OpenRASP 的运行时依赖,所以无法支持 Wildfly 的不重启安装 **

    手动安装 - Linux

    1. 安装软件

    进入到 wildfly 安装目录(绝对路径包含空格将导致启动失败),e.g /opt/wildfly-9.0.1.Final,将 rasp 目录复制过来

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以还需要修改 rasp 目录的权限,e.g

    2. 修改 Wildfly 启动脚本

    如果是standalone模式

    打开 bin/standalone.sh, 找到如下内容:

    在其下面增加如下内容:

    如果是domain模式

    server-group

    如果按照server-group配置rasp,那么此group下面所有的服务器都会安装rasp,打开domain/configuration/domain.xml文件,找到<server-groups>标签,在需要安装rasp的server-group中找到<jvm>标签添加如下配置:

    server

    如果只对某个server-group的特定的server安装rasp,打开domain/configuration/host.xml文件,找到<servers>标签,在需要安装rasp的server中添加如下配置:

    3. 开启远程管理

    如果你不需要远程管理功能,请跳过这个步骤。

    首先在管理后台找到 app_id、app_secret 两个关键参数,然后打开 <wildfly_home>/rasp/conf/openrasp.yml,添加或者修改如下内容:

    4. 验证安装是否成功

    重启 wildfly 服务器,然后检查 rasp/logs/rasp/rasp.log 中是否出现 OpenRASP Engine Initialized 字样,e.g

    或者检查响应的 Header 是否包含 X-Protected-By 字样,e.g

    出现则表示安装成功

    手动安装 - Windows

    1. 安装软件

    进入到 wildfly 安装目录,e.g D:\wildfly-9.0.1.Final,将 rasp 目录复制过来

    2. 修改 wildfly 配置

    如果是standalone模式

    打开 bin\standalone.bat, 找到 rem Setup JBoss specific properties 处:

    在其下增加如下内容:

    如果是domain模式

    方法同 Linux 版本

    3. 开启远程管理

    方法同 Linux 版本,在 openrasp.yml 里增加相关配置即可。

    4. 验证安装是否成功

    重启 wildfly 服务器,然后检查日志文件,一般是 rasp/logs/rasp/rasp.log,如果出现 OpenRASP Engine Initialized 字样,出现则说明安装成功;或者访问一下服务器,检查是否存在 X-Protected-By: OpenRASP 响应头,存在即表示安装成功。

    java -jar RaspInstall.jar -install <wildfly_root> -backendurl http://XXX -appsecret XXX -appid XXX
    java -jar RaspInstall.jar -install <wildfly_root>
    安装中出现任何问题,请联系我们
    安装中出现任何问题,请联系我们
    cp -R ~/Downloads/rasp-20170721/rasp .
    chmod 777 -R rasp
    # Display our environment
    JAVA_OPTS="$JAVA_OPTS -javaagent:$JBOSS_HOME/rasp/rasp.jar"
    <jvm-options>
       <option value="-javaagent:<wildfly_root>/rasp/rasp.jar"/>
    </jvm-options>
    <jvm name="default">
        <jvm-options>
            <option value="-javaagent:<wildfly_root>/rasp/rasp.jar"/>
        </jvm-options>
    </jvm>
    # 云控配置
    cloud.enable=true
    cloud.backend_url=http://XXXX
    cloud.app_id=XXXX
    cloud.app_secret=XXXX
    %> grep OpenRASP -ir rasp/logs/
    rasp/logs/rasp/rasp.log:2018-05-22 16:13:25,842 INFO  [main][com.baidu.openrasp.Agent] OpenRASP Engine Initialized [1.0-SNAPSHOT (build: GitCommit=3da661734e3ad7641cd98e83f32950deaefcacac date=2017-08-14T03:34:41Z)]
    %> curl -v 127.0.0.1:8080
    
    ...
    X-Protected-By: OpenRASP
    X-Request-ID: eb3b8e287de8406bb4bdb9d86bd31f99
    ...
    set JAVA_OPTS=%JAVA_OPTS% -javaagent:%JBOSS_HOME%/rasp/rasp.jar

    WebSphere 服务器

    手动安装

    1. 安装软件

    复制安装包内的 rasp 目录到 WebSphere 安装目录,比如

    • D:\IBM

    • /opt/IBM/WebSphere/AppServer

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以在 Linux 下还需要修改 rasp 目录的权限,e.g

    2. 配置 WebSphere 服务器

    以 WAS 8.5 为例,在控制台左侧的导航栏里,选择 Servers -> Server Types -> WebSphere Application Server,进入应用列表界面:

    选择你要开启 RASP 的应用(这里是 server1),点击进入管理页面。在新页面向下翻,找到 Server Infrastructure -> Process definition,并点击进入:

    之后在右侧,点击 Additional Properties -> Java Virtual Machine 进入JVM启动参数编辑界面

    最后找到 Generic JVM arguments,开始编辑

    如果是 Windows 系统,请填写:

    如果是 Linux 系统,请填写:

    保存后重启应用生效。

    3. 开启远程管理

    配置方法同 ,不再赘述。

    4. 检查安装是否成功

    • 方法1,检查日志中是否出现 OpenRASP Engine Initialized 字样,出现则说明安装成功。比如 /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/logs/server1

    • 方法2,访问下服务器,检查响应头里是否存在 X-Protected-By: OpenRASP 字样,存在即表示安装成功。

    当然,如果安装 OpenRASP 后导致 WebSphere 出错,你可以

    常见问题

    1. 远程管理无法开启,且日志中出现 java.security.AccessControlException 异常

    在 WebSphpere Windows 某些小版本下,比如 8.5.5.0,可能会出现 java 安全异常错误。此时会在 ${WAS_INSTALL_ROOT}/profiles/AppSrv01/logs/native_stderr.log 里看到如下内容:

    解决方案是增加相关权限,打开 ${WAS_INSTALL_ROOT}/java/jre/lib/security/java.policy,增加如下内容:

    修改后,需要重启 WebSphere 服务器生效。

    Tomcat 开启远程管理
    联系我们
    console
    server1
    server1
    server1
    chmod 777 -R /opt/IBM/WebSphere/AppServer/rasp
    -javaagent:${WAS_INSTALL_ROOT}\rasp\rasp.jar
    -javaagent:${WAS_INSTALL_ROOT}/rasp/rasp.jar
    ************ Start Display Current Environment ************
    Log file started at: [18-11-13 20:10:08:993 CST]
    ************* End Display Current Environment *************
    Exception in thread "Thread-8" java.security.AccessControlException: Access denied (java.lang.RuntimePermission accessDeclaredMembers)
    	at java.security.AccessController.checkPermission(AccessController.java:132)
    	at java.lang.SecurityManager.checkPermission(SecurityManager.java:544)
    	at java.lang.SecurityManager.checkMemberAccess(SecurityManager.java:1689)
    	at java.lang.Class.checkMemberAccess(Class.java:117)
    	at java.lang.Class.getDeclaredConstructor(Class.java:465)
    	at com.baidu.openrasp.gson.internal.ConstructorConstructor.newDefaultConstructor(ConstructorConstructor.java:82)
    	at com.baidu.openrasp.gson.internal.ConstructorConstructor.get(ConstructorConstructor.java:66)
    	at com.baidu.openrasp.gson.internal.bind.MapTypeAdapterFactory.create(MapTypeAdapterFactory.java:128)
    	at com.baidu.openrasp.gson.Gson.getAdapter(Gson.java:349)
    	at com.baidu.openrasp.gson.Gson.toJson(Gson.java:574)
    	at com.baidu.openrasp.gson.Gson.toJson(Gson.java:561)
    	at com.baidu.openrasp.gson.Gson.toJson(Gson.java:516)
    	at com.baidu.openrasp.gson.Gson.toJson(Gson.java:496)
    	at com.baidu.openrasp.cloud.Register$RegisterThread.run(Register.java:50)
    	at java.lang.Thread.run(Thread.java:773)
    grant codeBase "file:${was.install.root}/rasp/*" {
        permission java.security.AllPermission;
    };

    宝兰德BES服务器

    手动安装

    1. 安装软件

    复制安装包内的 rasp 目录到 BES 安装目录,比如

    • D:\bes\rasp

    • /opt/bes/rasp

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以在 Linux 下还需要修改 rasp 目录的权限,e.g

    2. 配置 BES 服务器

    2.1 方法一: 通过BES控制台进行配置

    以 BES 9.5 为例,在控制台左侧的导航栏里,选择 实例信息 -> JVM配置,进入JVM配置页面:

    在JVM配置页面向下翻,找到JVM选项,并开始编辑

    如果是 Windows 系统,请填写:

    如果是 Linux 系统,请填写:

    保存后重启应用生效。

    2.2 方法二: 手动修改BES的server.config文件

    编辑 <bes-home>/conf/server.config 文件,并在 <server>/<java-config>/<jvm-options> 标签下,增加新的 JVM 配置,e.g

    保存后重启应用生效。

    3. 开启远程管理

    配置方法同 ,不再赘述。

    4. 检查安装是否成功

    访问下服务器,检查响应头里是否存在 X-Protected-By: OpenRASP 字样,存在即表示安装成功。当然,如果安装 OpenRASP 后导致 BES 出错,你可以

    Tomcat 开启远程管理
    联系我们
    console
    server1
    chmod 777 -R /opt/bes/rasp
    -javaagent:${BES_HOME}\rasp\rasp.jar
    -javaagent:${BES_HOME}/rasp/rasp.jar
    <jvm-options>-javaagent:/opt/bes/rasp/rasp.jar</jvm-options>

    WebLogic 服务器

    自动化安装

    解压缩后,进入到解压后的目录中(如rasp-20170721),在终端中执行以下命令,

    如果你要开启远程管理,请先参考 管理后台 - 添加主机 文档,找到 app_id/app_secret/backend_url 三个关键参数,然后执行如下命令,

    如果你只是运行单机版,只需要指定 -install 参数,

    安装后,需要重启 WebLogic 服务器生效。

    不重启安装

    以上方式安装成功之后需要重启服务器,如果在服务器启动的情况下,不重启安装 OpenRASP,需要在以上命令后面增加 -pid 参数指定运行的服务器进程 id,JDK6 - JDK8 样例命令如下,

    ** jdk9 ~ jdk11 不支持不重启安装 **

    手动安装(Linux)

    1. 安装软件

    进入到需要安装插件的domain目录下,如 e.g /opt/wls122212/base_domain

    复制安装包下面的 rasp 目录到当前目录

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以还需要修改 rasp 目录的权限,e.g

    2. 配置 WebLogic

    非集群方式

    打开 bin/startWebLogic.sh, 找到 JAVA_OPTIONS="${SAVE_JAVA_OPTIONS}" 这一行,在该行下增加:

    集群方式

    方式一:通过weblogic的console

    • 访问weblogic的console,例如:http://10.115.184.54:8001/console/console.portal

    • 环境->服务器,找到要安装的server(本例为Server-0)

    • 点击进入Server-0,选择服务器启动,在参数框中,添加如下配置,保存退出

    • 重启Server-0之后,服务器生效

    方式二:通过配置weblogic的config.xml文件

    找到<weblogic-home>/user_projects/domains/base_domain/config目录,打开config.xml文件,定位到需要安装rasp的<server>/<server-start>/<arguments>标签,在<arguments>标签内添加javaagent参数。

    如果没有相应的标签可以手动添加,e.g

    重启安装rasp的server,服务器生效

    3. 验证安装是否成功

    访问 WebLogic 服务器,检查HTTP响应里是否包含 X-Protected-By: OpenRASP 字样,若出现则表示安装成功。若没有安装成功,请检查 WebLogic 是否有异常日志:

    手动安装(Windows){#manual-window}

    1. 安装软件

    进入 WebLogic Domain 目录,e.g C:\wls12212\user_projects\domains\base_domain,并将压缩包内的 rasp 目录复制过来

    2. 配置 WebLogic

    非集群模式

    打开 bin/startWebLogic.cmd, 找到 set JAVA_OPTIONS=%SAVE_JAVA_OPTIONS%"这一行,在下面增加:

    集群模式

    同Linux的集群模式

    3. 验证安装是否成功

    访问 WebLogic 服务器,检查HTTP响应里是否包含 X-Protected-By: OpenRASP 字样,若出现则表示安装成功。若没有安装成功,请检查 WebLogic 是否有异常日志:

    FAQ

    1. Weblogic 10.36 无法加载的问题

    Weblogic 10.36版本使用32位的JRockit JDK,若系统缺少32位的glibc,可能无法加载 openrasp.so。解决方法就是安装32位glibc,并再次尝试启动。

    对于 CentOS 系统,你需要安装 libgcc.i686,否则会提示找不到 libgcc_s.so.1 错误:

    若安装过程中出现 libgcc multilib 版本保护问题,e.g

    可尝试先升级 libgcc 到最新版本,再安装32位的 libgcc,e.g

    之后尝试启动即可。

    java -jar RaspInstall.jar -install <weblogic_domain_home> -backendurl http://XXX -appsecret XXX -appid XXX
    java -jar RaspInstall.jar -install <weblogic_domain_home>
    img
    # <server_pid> 为 weblogic 进程 id
    # $JAVA_HOME 为 jdk 根目录环境变量,如果未指定该环境变量,替换为 jdk 的完整根目录
    java -Xbootclasspath/a:$JAVA_HOME/lib/tools.jar -jar RaspInstall.jar -install <weblogic_domain_home> -pid <server_pid>
    cp -R ~/Downloads/rasp-20170721/rasp .
    chmod 777 -R rasp
    JAVA_OPTIONS="-javaagent:${DOMAIN_HOME}/rasp/rasp.jar ${JAVA_OPTIONS}"
    -javaagent:<agent_directory_full_path>/rasp/rasp.jar
    <server>
    	<server-start>
    		<arguments>-javaagent:/PATH/TO/DOMAIN_HOME/rasp/rasp.jar</arguments>
    	</server-start>
    </server>
    ${DOMAIN_HOME}/servers/<安装rasp的server名字>/logs
    set JAVA_OPTIONS=-javaagent:%DOMAIN_HOME%\rasp\rasp.jar %JAVA_OPTIONS%
    ${DOMAIN_HOME}/servers/<安装rasp的server名字>/logs
    yum install -y ligbcc.i686
    Error: Multilib version problems found. This often means that the root
           cause is something else and multilib version checking is just
           pointing out that there is a problem. Eg.:
    
    Protected multilib versions: libgcc-4.8.2-8.el6.x86_64 != libgcc-4.4.7-11.el6.i686
    yum install -y libgcc
    yum install -y ligbcc.i686
    img
    img

    Splunk

    本文介绍如何通过 Syslog TCP 方式,将日志采集到 Splunk 平台。

    添加日志类型

    在开始之前,我们需要先添加 openrasp 日志类型,否则 Splunk 无法组装超过1KB的日志。

    方法1 - 手动添加

    创建或者编辑 ,添加如下内容,并重启 Splunk 服务器以生效:

    上述配置添加了一个名为 openrasp 的日志类型,格式为 JSON,单行最大长度 320000 字符,足够使用了。

    方法2 - 安装插件

    首先在这里下载控制台插件,安装此插件会自动创建 openrasp 日志类型:

    然后在 Splunk 首页左上角,点击 App -> Manage Apps -> Install app from file,点击浏览文件,选中刚才下载的插件,然后勾选 Upgrade app. Checking this will overwrite the app if it already exists 选项,点击上传:

    安装成功后,会在首页看到 RASP 应用,

    应用界面如图

    配置 Splunk 端口监听

    在 Splunk 首页,点击右上角的 Settings -> DATA -> Data Inputs,然后选择 TCP 类型,并点击 NEW 进入配置界面。在这里,我们输入监听端口,即 514。

    选择日志类型时,依然是 openrasp。接着点击 Review,然后点击 Submit 保存即可。

    当服务器收到日志,就可以在界面上查看了

    其他端口也是可以的,但协议只能是 TCP 类型。

    配置 OpenRASP

    如果是单机版,请根据 的说明,配置至少如下两项:

    • syslog.enable=true

    • syslog.url=tcp://X.X.X.X:514

    修改后应用重启服务器生效。

    如果开启了管理后台,定位到 系统设置 -> 报警设置 -> Syslog 报警设置,在界面上配置即可。

    开启邮件报警

    首先点击右上角 设置 -> 系统 -> 服务器设置 -> 电子邮件设置,输入邮件服务器和账号信息,

    设置好上面邮箱信息后,可定期搜索报警,并通过邮件方式通知。

    打开 Splunk -> 搜索 -> 设置搜索语句 -> 另存为 -> 告警

    已知问题

    1. Syslog UDP 方式日志截断问题

    如果你使用 Syslog UDP 方式采集日志,那么单条日志长度将被限制为 1KB。由于我们的报警日志通常在 2~3 KB,所以会导致报警日志截断

    2. 界面上看不到日志

    请按照如下步骤进行排查

    1. OpenRASP 是否产生报警日志?

      • 检查 <app_home>/rasp/logs/alarm.log 是否有报警?

    2. OpenRASP 是否将日志发给 Syslog 服务器?

    使用 wireshark/tcpdump 抓包分析
  • Splunk 是否能收到数据?

    • 在应用服务器上,检查 Splunk 端口是否可连接?

    • 使用 linux logger 命令,模拟发送一条日志到 splunk,splunk 是否能收到?

      • e.g logger -n X.X.X.X -T -P 514 '{"hello":"world123"}'

  • Splunk 有日志,但是 OpenRASP app 看不到数据

    • 使用默认的搜索应用,看是否能搜到数据?

    • 检查搜索时间范围是否正确?

  • $SPLUNK_HOME/etc/system/local/props.conf
    splunk-app-1.1.zip
    其他配置 - syslog 日志
    Alt text
    Alt text
    Alt text
    log type
    log type
    log type
    Alt text
    Alt text
    [openrasp]
    BREAK_ONLY_BEFORE = \d\d?:\d\d:\d\d
    SEDCMD-StripHeader = s/^[^{]+//
    KV_MODE = json
    pulldown_type = true
    
    # Change the default maximum line length (in bytes)
    TRUNCATE = 320000

    中创InforSuiteAS服务器

    手动安装

    1. 安装软件

    复制安装包内的 rasp 目录到 InforSuiteAS 安装目录,比如

    • D:\inforsuiteas\rasp

    • /opt/inforsuiteas/rasp

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以在 Linux 下还需要修改 rasp 目录的权限,e.g

    2. 配置 InforSuiteAS 服务器

    2.1 方法一: 通过 InforSuiteAS 控制台进行配置

    以 InforSuiteAS 10.0 为例,在控制台左侧的导航栏里,选择 配置 -> server-config-> JVM设置,进入JVM选项页面:

    在JVM选项页面向下翻,找到JVM选项,并开始编辑:

    如果是 Windows 系统,请填写:

    如果是 Linux 系统,请填写:

    保存后重启应用服务生效。

    2.2 方法二: 手动修改InforSuiteAS的domain.xml文件

    编辑 <com.cvicse.loong.las.installRoot>/as/domains/domain1/config/domain.xml 文件,并在 <domain>/<configs>/<config name="server-config">/<java-config>/<jvm-options> 标签下,增加新的 JVM 配置,e.g

    保存后重启应用服务生效。

    3. 开启远程管理

    配置方法同 ,不再赘述。

    4. 检查安装是否成功

    访问下服务器,检查响应头里是否存在 X-Protected-By: OpenRASP 字样,存在即表示安装成功。当然,如果安装 OpenRASP 后导致 InforSuiteAS 出错,你可以

    Tomcat 开启远程管理
    联系我们
    jvm
    param
    chmod 777 -R /opt/inforsuiteas/rasp
    -javaagent:${com.cvicse.loong.las.installRoot}\rasp\rasp.jar
    -javaagent:${com.cvicse.loong.las.installRoot}/rasp/rasp.jar
    <jvm-options>-javaagent:${com.cvicse.loong.las.installRoot}/rasp/rasp.jar</jvm-options>

    IAST 高级配置选项

    启动参数

    指定其他配置文件

    在配置阶段,可以使用 -o 参数将配置文件生成到其他路径,e.g

    在启动阶段,可以使用 -c 加载你指定的配置文件,e.g

    若启动阶段没有指定配置文件,openrasp-iast 会从如下几个路径寻找,找不到无法启动:

    • ~/openrasp-iast/config.yaml

    • /etc/openrasp/config.yaml

    • ./config.yaml

    配置文件

    目前支持的配置内容如下,修改后需要重启 openrasp-iast 进程生效:

    预处理模块

    参数名
    说明
    默认值

    监控模块

    参数名
    说明
    默认值

    扫描模块

    参数名
    说明
    默认值

    云控配置

    参数名
    说明
    默认值

    CPU核心绑定

    参数名
    说明
    默认值

    日志配置

    参数名
    说明
    默认值

    数据库配置

    参数名
    说明
    默认值
    openrasp-iast config -o /path/to/config.yaml -a X -b Y -c Z -m mysql://xxx

    preprocessor.max_buffer_size

    http服务器接受请求的缓冲区大小, 单位Bytes

    104857600

    preprocessor.plugin_name

    使用的去重插件名

    default

    scanner.retry_times

    扫描请求失败重试次数

    3

    scanner.max_module_instance

    最大并发扫描任务数量

    16

    database.db_name

    数据库名

    openrasp

    preprocessor.http_port

    与rasp agent通信的http服务监听端口

    25931

    preprocessor.process_num

    http服务进程数

    2

    preprocessor.request_lru_size

    每个http服务进程的每个扫描目标对应一个LRU,用于存储32byte hash,总大小: 进程数 * 扫描目标数 * lru_size

    1000

    preprocessor.api_path

    rasp agent发送数据的目标 url的path

    /openrasp-result

    monitor.schedule_interval

    扫描速率自动调整策略执行间隔(s)

    1.000

    monitor.max_cpu

    cpu使用率上限,超过限制会降低并发扫描速率

    98

    monitor.min_cpu

    cpu使用率上限下限,低于该值会增加并发扫描速率

    85

    monitor.console_port

    web管理后台使用的端口

    18664

    scanner.max_concurrent_request

    单个扫描任务最大扫描并发线程数

    20

    scanner.min_request_interval

    每个扫描线程最小扫描请求间隔(ms)

    0

    scanner.max_request_interval

    每个线程最大扫描请求间隔(ms)

    1000

    scanner.request_timeout

    扫描请求超时时间(s)

    5

    cloud_api.enable

    是否上传结果到云控

    True

    cloud_api.backend_url

    云控地址

    http://127.0.0.1

    cloud_api.app_secret

    云控的secret_key

    无

    cloud_api.app_id

    云控的app_id

    无

    affinity.enable

    是否以绑定CPU核心的方式运行

    False

    affinity.core_num

    绑定的核心数量

    1

    log.level

    日志级别,可选: DEBUG INFO WARNING ERROR

    INFO

    log.path

    log文件路径, 为空时使用 /home/user/openrasp-iast/log

    空

    log.rotate_size

    单个日志文件触发rotate的日志大小,单位MB

    5

    log.rotate_num

    rotate文件最多保存份数,不包括当前日志文件

    2

    database.host

    mysql数据库地址

    localhost

    database.port

    mysql端口

    3306

    database.username

    用户名

    root

    database.password

    连接密码

    空

    openrasp-iast start -f -c /path/to/config.yaml

    普元PAS服务器

    手动安装

    1. 安装软件

    复制安装包内的 rasp 目录到 PAS 安装目录,比如

    • D:\PAS安装目录\rasp

    • /opt/PAS安装目录/rasp

    OpenRASP 需要在 rasp 目录下释放一些动态链接库,所以在 Linux 下还需要修改 rasp 目录的权限,e.g

    2. 配置 PAS 服务器

    2.1 方法一: 手动配置 domain.xml 文件

    打开 PAS安装目录/pas6/pas/domains/domain1/config/domain.xml,然后在其中添加javaagent的配置项:

    添加完成后的效果如下图所示(参考红线部分):

    配置完成后,重启PAS服务器即可生效。

    2.2 方法二: 通过PAS控制台进行配置

    登陆PAS的管理控制台,点击左侧配置中的server-config,然后找到jvm选项,添加javagent配置项即可:

    添加完成后的效果如下图所示(参考红色箭头部分):

    添加完成后点击保存按钮,然后重启PAS服务器即可生效。

    3. 开启远程管理

    配置方法同 ,不再赘述。

    4. 检查安装是否成功

    访问下服务器,检查响应头里是否存在 X-Protected-By: OpenRASP 字样,存在即表示安装成功。当然,如果安装 OpenRASP 后导致PAS出错,你可以

    日志说明

    存储路径

    OpenRASP 默认会开启文件日志,存储路径如下:

    • Java 版本: <app_home>/rasp/logs/alarm/*.log*

    Tomcat 开启远程管理
    联系我们
    image.png
    image.png
    chmod 777 -R /opt/PAS安装目录/rasp 
    -javaagent:${PAS_Home}/rasp/rasp.jar 
    -javaagent:${PAS_Home}/rasp/rasp.jar 
    PHP 版本: <openrasp_rootdir>/logs/alarm/*.log

    值得注意的是,Java 版本当前的报警没有日期,只有日志滚动之后才会有日期,e.g

    对于 PHP 版本,报警日志总是会带有日期,e.g

    不过,由于 PHP 本身的限制,有些日志还是会打印到 PHP 错误日志里,比如 INI 配置错误。

    日志类型

    OpenRASP 包含四类日志,

    文件名
    文件内容

    plugin/plugin-DATE.log

    检测插件的日志,e.g 插件异常、插件调试输出

    rasp/rasp-DATE.log

    rasp agent 调试日志

    alarm/alarm-DATE.log

    攻击报警日志,JSON 格式,一行一个

    policy_alarm/policy_alarm-DATE.log

    安全基线检查报警日志,JSON 格式,一行一个

    日志格式

    1. 攻击日志格式

    当发生攻击事件时,OpenRASP 将会记录以下信息,

    字段
    说明

    rasp_id

    RASP agent id

    app_id

    应用ID

    app_name

    应用名称

    event_type

    日志类型,固定为 attack 字样

    event_time

    事件发生时间

    event_level

    漏洞级别,范围是 critical/high/medium/low

    一个完整的 JSON 日志样例如下:

    2. 安全基线检查日志

    当检测到不符合安全规范的配置时,OpenRASP 将会记录以下信息:

    字段
    说明

    event_type

    日志类型,固定为 security_policy 字样

    event_time

    事件发生时间

    server_hostname

    服务器主机名

    server_nic

    服务器IP

    server_type

    应用服务器类型

    server_version

    应用服务器版本

    一个完整的 JSON 日志样例如下:

    3. 应用行为日志

    当你在管理后台 -> 防护设置里,开启 打印「行为日志」,仅用于调试,请勿在线上开启 后,我们会在 plugin.log 里打印应用的行为日志,样例如下:

    管理后台

    如果你还没有安装管理后台,请先参考 进行安装和配置。

    设置后台信息

    若要使用负载均衡模式,请在 系统设置 -> 后台设置 下面,编辑Agent服务器列表:

    修改后,在 添加主机 -> 基础信息 里会显示所有的 Agent 服务器地址,即 BackendURL 参数。

    单机版本

    OpenRASP 支持单机模式运行,只不过大部分操作都需要登录服务器进行。

    修改配置

    请参考 文档,手动编辑配置文件。部分配置需要重启服务生效。

    查看日志

    /tomcat/rasp/logs/alarm/alarm.log
    /tomcat/rasp/logs/alarm/alarm.log.2018-12-04
    ...
    /opt/rasp/logs/alarm/alarm.log.2018-12-16
    {
      "@timestamp": 1618894722217,
      "app_id": "88cce00aa5a5207f2d13250f892bdcb96c46f080",
      "app_name": "Demo App",
      "attack_count": 2,
      "attack_location": {
        "latitude": 0,
        "location_en": "-",
        "location_zh_cn": "-",
        "longitude": 0
      },
      "attack_params": {
        "command": "cmd /c calc",
        "env": [],
        "stack": [
          "java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java)",
          "java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)",
          "java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1109)",
          "java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)",
          "java.base/java.lang.Runtime.exec(Runtime.java:590)",
          "java.base/java.lang.Runtime.exec(Runtime.java:414)",
          "java.base/java.lang.Runtime.exec(Runtime.java:311)",
          "org.apache.jsp._004_002dcommand_002d1_jsp._jspService(_004_002dcommand_002d1_jsp.java:136)",
          "org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)",
          "javax.servlet.http.HttpServlet.service(HttpServlet.java:741)",
          "org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:476)",
          "org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386)",
          "org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330)",
          "javax.servlet.http.HttpServlet.service(HttpServlet.java:741)",
          "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)",
          "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)",
          "org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)",
          "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)",
          "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)",
          "org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)",
          "org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)",
          "org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)",
          "org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)",
          "org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)",
          "org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)",
          "org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)",
          "org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)",
          "org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)",
          "org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)",
          "org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)",
          "org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)",
          "org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)",
          "java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)",
          "java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)",
          "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)",
          "java.base/java.lang.Thread.run(Thread.java:831)"
        ]
      },
      "attack_source": "127.0.0.1",
      "attack_type": "command",
      "body": "",
      "client_ip": "",
      "event_level": "critical",
      "event_time": "2021-04-20T12:58:42+0800",
      "event_type": "attack",
      "header": {
        "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
        "accept-encoding": "gzip, deflate, br",
        "accept-language": "en,zh-CN;q=0.9,zh;q=0.8,la;q=0.7",
        "connection": "keep-alive",
        "cookie": "JSESSIONID=FA7196A1FDE61D1795DCEB3280890E14",
        "dnt": "1",
        "host": "127.0.0.1:8080",
        "referer": "http://127.0.0.1:8080/vulns/004-command-1.jsp",
        "upgrade-insecure-requests": "1",
        "user-agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0"
      },
      "id": "5f425ea2234ca4d4bcd991108affff8c",
      "intercept_state": "log",
      "parameter": {
        "form": "{\"cmd\":[\"cmd /c calc\"]}",
        "json": "{}",
        "multipart": "[]"
      },
      "path": "/vulns/004-command-1.jsp",
      "plugin_algorithm": "command_other",
      "plugin_confidence": 90,
      "plugin_message": "Command execution - Logging all command execution by default, command is cmd /c calc",
      "plugin_name": "official",
      "rasp_id": "520d19c523509c53025d66e67e394ab2",
      "rasp_version": "1.3.6",
      "request_id": "c7229f3f91e34e95902c7ada3b17865d",
      "request_method": "get",
      "server_hostname": "YOUR_COMPUTER",
      "server_ip": "127.0.0.1",
      "server_nic": [
        {
          "ip": "192.168.154.1",
          "name": "vmnet8"
        },
        {
          "ip": "172.16.177.1",
          "name": "vmnet1"
        },
        {
          "ip": "172.24.172.41",
          "name": "en0"
        }
      ],
      "server_type": "tomcat",
      "server_version": "9.0.14.0",
      "source_code": "",
      "stack_md5": "c0eccc0d41f14fcef3f0a6d7521d0875",
      "target": "127.0.0.1",
      "upsert_id": "5f425ea2234ca4d4bcd991108affff8c",
      "url": "http://127.0.0.1:8080/vulns/004-command-1.jsp?cmd=cmd+/c+calc"
    }
    {
       "event_type":      "security_policy",
       "event_time" :     "2017-04-01T08:00:00Z",
       "policy_id":       "3002",
       "server_hostname": "my-bloodly-hostname",
       "server_nic": {
          {
             "name": "eth0",
             "ip":   "10.10.1.131"
          },
          {
             "name": "eth0",
             "ip":   "192.168.1.150"
          }
       },
       "server_type":    "Tomcat",
       "stack_trace":    "org.apache.catalina.startup.Catalina.start(Catalina.java)\nsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\nsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\nsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\njava.lang.reflect.Method.invoke(Method.java:606)\norg.apache.catalina.startup.Bootstrap.start(Bootstrap.java:294)\norg.apache.catalina.startup.Bootstrap.main(Bootstrap.java:428)\n"
       "server_version": "7.0.15",   
       "message":        "Tomcat 不应该以root权限启动",
       "policy_params":  {
          "pid": 1023
       }
    }
    2021-01-04 10:11:39,627 INFO  [http-bio-8080-exec-2][com.baidu.openrasp.plugin.js.log] http://127.0.0.1:8080/vulns/004-command-1.jsp [official] Read file: /usr/local/apache-tomcat-7.0.78/webapps/vulns/004-command-1.jsp
    2021-01-04 10:11:40,882 INFO  [http-bio-8080-exec-1][com.baidu.openrasp.plugin.js.log] http://127.0.0.1:8080/vulns/004-command-1.jsp [official] Execute command: cp /etc/passwd /tmp/ [ 'java.lang.UNIXProcess.<init>',
      'java.lang.ProcessImpl.start',
      'java.lang.ProcessBuilder.start',
      'java.lang.Runtime.exec',
      'java.lang.Runtime.exec',
      'java.lang.Runtime.exec',
      'org.apache.jsp._004_002dcommand_002d1_jsp._jspService',
      'org.apache.jasper.runtime.HttpJspBase.service',
      'javax.servlet.http.HttpServlet.service',
      'org.apache.jasper.servlet.JspServletWrapper.service',
      'org.apache.jasper.servlet.JspServlet.serviceJspFile',
      'org.apache.jasper.servlet.JspServlet.service',
      'javax.servlet.http.HttpServlet.service',
      'org.apache.catalina.core.ApplicationFilterChain.internalDoFilter',
      'org.apache.catalina.core.ApplicationFilterChain.doFilter',
      'org.apache.tomcat.websocket.server.WsFilter.doFilter',
      'org.apache.catalina.core.ApplicationFilterChain.internalDoFilter',
      'org.apache.catalina.core.ApplicationFilterChain.doFilter',
      'org.apache.catalina.core.StandardWrapperValve.invoke',
      'org.apache.catalina.core.StandardContextValve.invoke',
      'org.apache.catalina.authenticator.AuthenticatorBase.invoke',
      'org.apache.catalina.core.StandardHostValve.invoke',
      'org.apache.catalina.valves.ErrorReportValve.invoke',
      'org.apache.catalina.valves.AccessLogValve.invoke',
      'org.apache.catalina.core.StandardEngineValve.invoke',
      'org.apache.catalina.connector.CoyoteAdapter.service',
      'org.apache.coyote.http11.AbstractHttp11Processor.process',
      'org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process',
      'org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run',
      'java.util.concurrent.ThreadPoolExecutor.runWorker',
      'java.util.concurrent.ThreadPoolExecutor$Worker.run',
      'org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run',
      'java.lang.Thread.run' ]

    request_id

    当前请求ID

    request_method

    请求方法

    intercept_state

    拦截状态

    attack_source

    攻击来源 IP

    target

    被攻击目标域名

    server_hostname

    被攻击的服务器主机名

    server_ip

    被攻击目标 IP

    server_type

    应用服务器类型

    server_version

    应用服务器版本

    path

    当前URL,不包含参数

    url

    当前URL,包含完整GET参数

    attack_type

    攻击类型

    attack_params

    攻击参数,包含hook点参数、堆栈等等

    attack_source

    请求来源

    client_ip

    客户端真实IP地址,请参考 其他配置选项 进行配置

    plugin_name

    报告攻击插件名称

    plugin_confidence

    检测结果可靠性,插件返回

    plugin_message

    检测结果信息

    plugin_algorithm

    插件检测算法

    header

    请求header信息

    stack_md5

    当前堆栈MD5

    body

    当前请求的body,如果有

    policy_id

    匹配的策略编号

    policy_params

    基线报警额外参数,比如 PID

    message

    不符合规范的配置说明

    stack_trace

    当前调用堆栈,某些情况可能为空

    请参考 日志说明 文档,了解我们的日志格式和存储路径。也可以参考 SIEM系统集成 文档了解如何将日志发往SIEM平台。

    设置白名单

    编辑配置文件,

    • PHP 版本一般为: /opt/rasp/conf/openrasp.yml

    • Java 版本路径为: $APP_HOME/rasp/conf/openrasp.yml

    假设我们白名单的需求是这样的:

    • 针对所有URL,关闭 SSRF 检测点

    • 针对 www.baidu.com,关闭所有检测点

    • 针对 pma.baidu.com/phpmyadmin/,关闭 SQL 检测点

    我们定位到 hook.white(如果没有可以手动添加)并增加如下内容:

    具体检测点的名字(如 ssrf/sql)可以从 alarm.log 报警日志里获取,也可以从 参数说明 里查看:

    其中 all 表示关闭所有检测点。

    检测插件

    注意: 对于单机版本,Java 版本默认监控了插件目录,当目录里有任何插件发生变化,将会立即重新加载所有插件;PHP 版本默认没有开启 fswatch,所以需要重启 httpd/php-fpm 生效。远程管理版本不受影响,支持插件热加载。

    插件安装目录如下,其中 official.js 为官方插件:

    • Java 版本是 <app_home>/rasp/plugins/

    • PHP 版本是 <openrasp_rootdir>/rasp/plugins/

    开启拦截

    打开官方插件,首先定位到如下内容,将 all_log 改为 false。修改后,大部分检测算法都会变成拦截模式:

    对于其他算法,如XSS检测,还需要手动调整拦截策略,即修改 action 字段为 block:

    之后根据 检测插件 的说明决定是否重启应用服务器。

    开启行为日志

    打开官方插件,首先定位到如下内容,将log_event改为true

    开启后,JS插件会把应用的所有行为和堆栈都打印到<rasp_home>/logs/plugin/plugin.log,比如

    安装插件

    打开插件目录,将文件复制过来即可。之后根据 检测插件 的说明决定是否重启应用服务器。

    状态检查

    你可以在插件末尾,打印一条日志,e.g

    当插件成功加载后就会执行,并在 plugin.log 里打印这条消息:

    若插件有语法错误会打印日志,e.g

    卸载插件

    打开插件目录,删除指定的文件即可。之后根据 检测插件 的说明决定是否重启应用服务器。

    应用加固

    在配置文件里,找到 inject.custom_headers 内容,并修改配置即可。

    若要去掉所有响应头信息,可以设置为空数组:

    FAQ

    1. 我修改了检测插件,总要重启服务器才会生效

    如果你是在 VMWare 虚拟机里测试 OpenRASP,然后插件是放在 VMWare 共享 里的,这个时候 inotify 不会生效,也就无法实时更新插件

    这可能是因为 vmhgfs 跟 inotify 本身存在兼容性问题,解决方法就是将整个服务器软件都复制到虚拟机的磁盘上,比如 /root/tomcat/

    其他配置
    hook.white:
        "*":
            - "ssrf"
        "www.baidu.com":
            - "all"
        "pma.baidu.com/phpmyadmin/":
            - "sql"
    {
        ...
        "attack_type": "readFile",
        ...
    }
    var algorithmConfig = {
        // 快速设置
        meta: {
            // 若 all_log 开启,表示为观察模式,会将所有的 block 都改为 log
            all_log: true,
    
            // 若 is_dev 开启,表示为线下环境,将开启更多消耗性能的检测算法
            is_dev:  false,
    
            // schema 版本
            schema_version: 1
        },
    
        ...
    var algorithmConfig = {
        ...
    
        xss_userinput: {
            name:   '算法2 - 拦截输出在响应里的反射 XSS',
            action: 'block',
    
            filter_regex: "<![\\-\\[A-Za-z]|<([A-Za-z]{1,12})[\\/ >]",
            min_length:   15,
        },
    
        ...
    }
    var algorithmConfig = {
        // 快速设置
        meta: {
            // 若 all_log 开启,表示为观察模式,会将所有的 block 都改为 log
            all_log: true,
    
            // 若 is_dev 开启,表示为线下环境,将开启更多消耗性能的检测算法
            is_dev:  false,
    
            // 若 log_event 开启,将打印应用行为信息到 plugin.log
            log_event: false,
    
            // schema 版本
            schema_version: 1
        },
    
        ...
    2022-03-07 15:05:56,658 INFO  [http-nio-8080-exec-1][com.baidu.openrasp.plugin.js.log] http://127.0.0.1:8080/ [official] JNDI lookup: ldap://127.0.0.1:1389/a [ 'com.sun.jndi.toolkit.url.GenericURLContext.lookup',
      'com.sun.jndi.url.ldap.ldapURLContext.lookup',
      'javax.naming.InitialContext.lookup',
      'org.apache.logging.log4j.core.net.JndiManager.lookup',
      'org.apache.logging.log4j.core.lookup.JndiLookup.lookup',
      'org.apache.logging.log4j.core.lookup.Interpolator.lookup',    
      ...]
    plugin.log('初始化成功')
    2017-10-18 17:30:34,781 INFO  [main][com.baidu.openrasp.plugin.log] [offical] 初始化成功
    2017-10-18 17:40:01,402 INFO  [main][com.baidu.openrasp.plugin.log] org.mozilla.javascript.EvaluatorException: unterminated string literal (plugin.js#335)
    inject.custom_headers:
      X-Protected-By: OpenRASP
    #   X-Content-Type-Options: nosniff
    #   X-Frame-Options: deny
    #   X-XSS-Protection: 1; mode=block
    #   X-Download-Options: noopen
    inject.custom_headers:
    #   X-Protected-By: OpenRASP
    #   X-Content-Type-Options: nosniff
    #   X-Frame-Options: deny
    #   X-XSS-Protection: 1; mode=block
    #   X-Download-Options: noopen
    添加主机

    点击后台右上角的 添加主机 -> 基础信息,可获取安装 openrasp.yml 配置文件内容:

    text

    如果你有大规模部署的需求,请参考 大规模部署 文档

    添加白名单

    在 系统设置 -> 黑白名单 -> 添加 下面,可以增加检测点白名单。以 phpMyAdmin 应用为例,如果我们不想对 rasp.baidu.com/phpMyAdmin/ 这个URL进行SQL注入检测,可以参考下图配置,点击保存后生效。

    text

    修改登录密码

    在 系统设置 -> 登录认证 -> 修改登录密码 下面,可以设置新的后台登录密码。目前我们不支持多用户模式,未来会逐步完善。对于新密码,我们的要求是 8-50 位,且同时包含数字和字符,不符合规范的密码会被拒绝。

    text

    配置邮件报警

    在界面配置即可。一般情况下,端口写 25 即可,如果服务器支持 STARTTLS,会自动开启加密。如果你使用 465 端口,才需要勾选强制TLS。

    常见错误

    判定为垃圾邮件:

    554 DT:SPM 126 smtp4,jdKowACnCjHT2iVcPGzDAA--.262S3 1545984724,please see http://mail.163.com/help/help_spam_16.htm?ip=xxxxx&hostid=smtp4&time=1545984724

    需要授权码:

    535 Error: 请使用授权码登录。详情请看: http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256

    配置钉钉报警

    请先参考 创建应用 创建企业应用。

    然后点击应用,查看应用详情:

    text

    配置中的 Agent ID 就在下图位置:

    text

    之后获取配置中的 Corp ID 和 Corp Secret:

    打开链接 https://open-dev.dingtalk.com/#/corpAuthInfo ,如下所示为 Corp ID 和 Corp Secret,

    text

    推送用户列表 和 推送部门列表 在 钉钉通讯录 中获取,填写用户和部门的 id:

    用户 id 点击用户即可获取,如下图所示:

    text

    部门 id 点击编辑部门即可获取,如下图所示:

    text

    反向代理支持

    在使用反向代理的情况下,比如 nginx + php-fpm,后端应用看到的请求来源通常是nginx的IP地址。为了解决这个问题,我们一般会在 nginx 配置里增加如下内容,即将客户端真实IP,通过 X-Client-IP 这个请求头传递过来:

    因此,当发生攻击时,我们获取这个 ClientIP 的内容,就是攻击者真实IP了。若要从指定的header里获取真实IP地址,请打开 管理后台 -> 系统设置 -> 通用设置,将 真实 IP header 填写为 ClientIP 即可,e.g

    text

    之后发生攻击时,我们就可以看到真实IP了:

    text

    开启代码反汇编功能

    若要在检测到漏洞时,同时展示应用的源代码,可以在 通用设置 -> 开启反汇编功能 里开启这个功能。当频繁发生攻击时,本功能会有一定的性能损耗,建议只在测试环境开启。

    开启后,在获取到应用堆栈的同时,我们还会在 报警详情 -> 漏洞详情 上展示应用源代码,e.g

    text

    获取 API KEY

    若要使用我们的 API 接口,请先在 登录认证 -> TOKEN 管理 -> 创建 里创建一个 API KEY,输入备注信息后点击确定保存。

    text

    之后请参考我们的 后台接口文档 来了解如何调用接口。

    安装管理后台
    text

    安装灰盒扫描工具

    openrasp-iast 是一款灰盒扫描工具,能够结合应用内部hook点信息精确的检测漏洞。传统黑盒扫描器依赖于页面响应检测漏洞,不但需要发送大量的请求,还有误报的可能。对于SSRF、文件上传等漏洞,在页面没有回显、主机没有外网权限的情况下,还可能会漏报。openrasp-iast 很好的解决了上述问题,下面我们来看下如何安装它。

    另外,IAST 污点追踪功能已经在开发中,将会跟随商业版本发布。若要了解当前的系统架构,请参考 文档。

    快速体验

    我们提供了一整套的测试环境,包含 IAST 扫描器、OpenRASP 管理后台 以及 漏洞测试用例。如果你已经安装了docker-compose, 首先修改 vm.max_map_count

    Logstash

    本文讲解如何使用 Logstash 采集报警日志,并发送到 ElasticSearch 保存。

    开始之前

    在开始之前,你需要知道如下信息:

    • ElasticSearch 相关信息

    proxy_set_header ClientIP $remote_addr;

    服务配置

    从 1.0.0 RC1 开始,大部分配置都可以从云端下发,插件也可以远程升级。不过,由于服务器本身的限制,有些配置还是得在本地设置。具体有哪些配置项目,请参考 其他配置 文档。

    服务器地址和端口,这里是 192.168.154.200:9200

  • 要创建的索引名称,这里是 rasp-%{+YYYY.MM.dd}

  • 要使用的数据类型,这里是 attack

  • 报警日志的绝对路径,请参考 日志说明 - 存储路径 文档

  • 配置示例

    以某 tomcat 服务器为例,一个完整的 Logstash 配置示例如下:

    更多信息请求参考如下文档:

    • input file plugin 参数说明

    • output elasticsearch 参数说明

    FAQ

    1. Kibana 里看不到数据

    首先,确认 Elasticsearch 里是否有数据

    在命令行里,执行以下命令,

    如果返回 count 字段,则说明 Elasticsearch 存在数据。请检查 Kibana 是否配置了错误的 Elasticsearch 地址?

    其他情况,比如返回 error 字段,e.g IndexMissingException,则说明 Elasticsearch 里没有数据,需要进一步查看原因。

    然后,检查 OpenRASP 是否工作正常

    检查 <app_home>/rasp/logs/alarm/*.log* 是否有报警日志?如果没有,可以通过攻击测试用例,来产生一些报警日志。

    最后,检查 Logstach 是否正常

    如果要采集的路径存在日志,但是 Elasticsearch 里却没有数据,则说明 Logstash 工作不正常。

    1. input 配置的日志路径是否正确?

    2. <logstash_root>/logs 下面是否有 [ERROR] 类型的日志?

    input {
        file {
            path => ["/home/tomcat/rasp/logs/alarm/*.log*"]
            start_position => "beginning"
        }
    }
    filter {
        json {
             source => "message"
        }
    }
    output {
        stdout {
            codec => rubydebug
        }
    }
    output {
        elasticsearch {
            hosts => ["192.168.154.200:9200"]
            index => "rasp-%{+YYYY.MM.dd}"
        }
    }
    curl '192.168.154.200:9200/rasp-*/_count'
    {"count":420,"_shards":{"total":5,"successful":5,"failed":0}}
    {"error":"IndexMissingException[[attack] missing]","status":404}
    (参考[这篇文档]](https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html))

    然后执行如下命令,即可启动环境:

    之后,请按照顺序分别:

    • 访问 http://127.0.0.1:18662/vulns/ 触发PHP测试用例

    • 访问 http://127.0.0.1:18661/ IAST控制台启动扫描 (1.3版本后IAST后台合并到云控后台,此端口的后台删除)

    • 访问 http://127.0.0.1:18660/ 云控后台(账号openrasp/admin@123),左上角选择IAST应用查看扫描结果

    安装或升级扫描器

    本工具仅支持Linux平台,在开始之前,请先确保安装:

    1. OpenRASP 管理后台 版本 >= 1.2.0,并至少有一台在线主机

    2. Python 3.6 或者更高版本

    3. MySQL 5.5.3, 或者更高版本

    使用 pip3 安装 openrasp-iast,以及依赖的库:

    也可以直接下载 PyInstaller 打包的二进制版本,我们每隔2小时自动更新一次:

    配置 MySQL 数据库,建立名为 openrasp 的数据库,并为 rasp@% 授权,密码为 rasp123(建议使用强度更高的密码,这里只是举例)。请用 root 账号连接 mysql 并执行如下语句:

    注意: 如果管理后台是 v1.3.0 之前的版本,你可以使用这个命令安装老版本的 openrasp-iast:

    配置管理后台

    打开云控管理后台,左上角选择一个IAST扫描器使用的应用,若没有可以在应用管理创建一个。扫描器检出的报警都可以在这里查看。

    然后在 插件管理 里,上传并下发 IAST 插件。若在插件列表里无法看到名为 iast: 2019-XXXX-YYYY 的插件,可以手动从 baidu/openrasp 下载并上传。

    接着在 系统设置 -> 防护设置 -> Fuzz 服务器地址 里填入 openrasp-iast 所监听的URL,e.g

    这里需要保证你的WebServer(安装agent的机器) 可以访问IAST服务器地址,否则请自行配置代理或调整网络架构

    最后在 系统设置 -> 通用设置中,修改检测配置:

    • [插件] 单个hook点最大执行时间 设置为 5000

    • 开启文件过滤器: 当文件不存在时不调用检测插件 设置为 关闭

    • LRU 大小 设置为 0

    如果使用1.2.2以上版本,还需在 系统设置 -> 应用加固中,修改检测配置:

    • 自定义 X-Protected-By 头 设置为非空

    点击保存后,以上配置需要等待一个心跳周期后生效(默认90秒)。如果想要立即生效,请手动重启下 Tomcat/PHP 等服务器。

    配置并启动扫描器

    在云控后台右上角 添加主机 -> Fuzz 工具安装 找到 fuzz 工具安装命令。执行后会自动创建配置文件,并修正云控相关字段:

    若要在前台启动,请使用如下命令:

    若要在后台启动,请去掉 -f 参数:

    IAST 控制台

    openrasp-iast 是被动扫描模式,不会使用爬虫技术去获取URL信息。当 iast.js 下发成功,Java/PHP 内部的探针会自动在请求结束时,将本次请求的参数、hook点信息提交给 openrasp-iast 服务器进行分析,并选择性的 Fuzz 目标。

    通常,我们会将 OpenRASP 部署至测试环境,并长期运行。在QA、RD做单元测试、功能测试时自动的进行漏洞检测。检测的目标按照 IP:PORT 或者 HOST 进行分组,每个目标可以有不同的配置。若勾选 自动启动扫描 选项,则会在发现新目标时自动启动扫描任务:

    web_console

    在任何状态下,都可点击 设置 按钮对某个任务进行配置,设置会立即生效。

    URL 白名单

    若要避免扫描某些URL,比如注销页面 /logout.php,可以在 IAST 控制台设置一个正则表达式,e.g

    控制台会在保存时自动校验正则表达式是否合法。

    扫描并发速率控制

    openrasp-iast 会自动调节扫描速率,默认最大并发是 20,扫描间隔是 0 ~ 1000ms。若扫描速率过快可能会造成拒绝服务,请谨慎修改。

    FAQ

    1. 目前支持哪些漏洞的检测?

    目前支持的漏洞触发条件均为用户输入的参数直接拼接产生的漏洞,尚不支持非HTTP参数、参数编解码方式触发的漏洞,包含以下类型:

    • 命令注入

    • 目录遍历

    • PHP eval代码执行

    • 文件上传

    • 文件包含

    • 任意文件读取

    • 任意文件写入

    • SQL注入

    • SSRF

    • Java XXE

    2. 调试日志说明

    openrasp-iast 包含如下几类日志,默认存储路径为 ~/openrasp-iast/logs:

    文件名
    文件内容

    error.log

    所有模块的错误日志,ERROR级的日志会打印到这个文件

    MainProcess.log

    主进程日志

    Preprocessor.log

    预处理模块日志,包含对rasp agent传入信息的处理日志

    Monitor.log

    监控模块日志,包含web后台操作、扫描任务启停等日志

    Scanner_*

    扫描任务日志目录,每个任务对应一个目录,包含主线程日志Scanner.log,和所有插件的日志 plugin_插件名.log

    3. 常见错误说明

    启动失败:

    • OSError: [Errno 48] Address already in use

      指定的http服务端口被占用,检查openrasp-iast是否已在运行,或是其他应用占用了配置项中preprocessor.http_port和monitor.console_port指定的端口

    • OSError: [Errno 24] Too many open files

      文件描述符超过限制,使用 ulimit -n 10240 命令修改当前文件描述符数量限制后再启动

    4. 找不到 openrasp-iast 命令

    如果是 pip3 安装后没有 openrasp-iast 命令,那么它可能是被安装到了 python3 所在的目录,如 /usr/local/lib/python3.7/bin。

    解决方法有:

    1. 添加软链接,比如以 root 执行 ln -s /usr/local/lib/python3.7/bin/openrasp-iast /usr/bin 命令

    2. 将该目录加入 $PATH,比如在当前shell下执行 export PATH=$PATH:/usr/local/lib/python3.7/bin

    5. 在 IAST 控制台清空或删除任务之后,原先的漏洞无法再次检出

    1. 请先确认漏洞是否已经修复

    2. 如果漏洞未修复,请检查 云控后台 -> 系统设置 -> 通用设置->LRU 大小 的设置是否为 0。

    6. IAST 控制台看不到任务

    1. 尝试在目标系统进行一些操作,触发一些API接口调用

    2. 检查 logs/preprocessor.log 中是否有收到请求信息的日志,如果收到请求依然没有任务,请将 ~/openrasp-iast/logs 打包提交给我们

    3. 检查agent端/rasp/logs/plugin/plugin.log 是否有报错,一般插件timeout可能意味着Fuzz 服务器地址配置错误,请参考上文进行配置

    7. IAST 启动任务后扫描不到任何漏洞

    1. 如果使用的是官方测试环境,检查agent版本是否 > 1.2

    2. 如果是自建靶场,查看~/openrasp-iast/logs/preprocessor.log中的请求日志,检查是否正确获取了hook_info

    3. 检查 openrasp-iast 服务器是否能够访问目标地址

      • 扫描器默认会使用 服务器 IP + HTTP头host字段的PORT 方式发起请求

      • 如果扫描器无法直接连接目标地址,你可以改为 HOST 方式扫描

      • 在后台 防护设置 -> 使用 HOST 直接访问的服务 里填入 .* 或者 匹配对应 host 的正则即可,被正则命中的HOST将作为扫描目标地址

    8. IAST 扫描一直没有完成

    iast是被动模式的扫描,在启动扫描后会保持运行状态,对新获取的url进行实时扫描,扫描器无法预知是否还会有新请求被获取,当 总任务=已扫描+已失败 时,所有当前获取到的url已扫描完毕,如果没有继续扫描的需求,手动停止扫描即可

    9. MySQL 出现 Too many connections 错误

    MySQL 默认的最大连接数为 100,启动的扫描进程过多会导致MySQL连接数超过100并报错,只需在 my.ini 文件中添加或修改以下条目增加最大连接数即可

    max_connections = 10000

    10. 阿里云RDS兼容性问题

    开源版本的IAST使用MySQL来存储扫描任务,并需要开启 lower-case-table-names 配置。由于云上的RDS通常为托管状态,无法修改此选项,所以请单独部署MySQL服务器。

    值得注意的是,这个仅影响IAST本身。如果你要扫描的业务使用了云上的RDS,是完全不受影响的。

    11. IAST 启动后报错400

    IAST启动后,持续抛出 ConnectionError: Connection failed, status code:400 异常

    检查iast连接的云控是否配置了代理,如nginx等,导致http无法upgrade为websocket;如果配置了http代理,那么需要给websocket也配置相应代理

    二次开发 - 架构说明 - 灰盒扫描器

    SIEM 系统集成

    无论是自研的,开源的还是商业SIEM产品,OpenRASP 都可以无缝集成。

    Kafka 日志推送

    从 v1.3 开始,管理后台支持直接将报警日志写入 Kafka。为了方便你测试,我们还支持推送测试报警。

    管理后台推送

    当管理后台收到报警日志,我们可以立即将日志推送到指定的 HTTP/HTTPS 地址,直接在界面上配置即可。为了方便你测试,我们还支持推送测试报警。

    文件日志

    默认情况下,我们会打印 JSON 格式的报警日志、基线日志。你可以通过部署主机agent,来采集日志。目前开源的日志采集工具有 Logstash, Flume, Filebeat 等等。如果你想要使用这种方案,请参考 章节进行配置,其他软件大同小异。

    Syslog TCP 方式

    由于单条报警日志大小超过了1KB,所以我们只支持以 Syslog TCP 方式,直接将日志发送到指定的服务器。若要采用这种方式采集日志,请参考 章节进行配置。

    值得注意的是,在PHP版本里,syslog 是阻塞发送的。如果因为网络问题,导致syslog远程服务器不可用,发生攻击时会阻塞当前请求。

    攻击检测能力说明

    本表格参考 进行分类,如果你有任何疑惑,或者发现无法拦截的攻击,请;具体每种攻击覆盖哪些场景,可翻到最下面查看详细说明

    sudo sysctl -w vm.max_map_count=262144
    git clone https://github.com/baidu-security/openrasp-iast.git
    cd openrasp-iast/docker/iast-cloud
    docker-compose up
    pip3 install --upgrade git+https://github.com/baidu-security/openrasp-iast
    wget https://packages.baidu.com/app/openrasp/openrasp-iast-latest -O /usr/local/bin/openrasp-iast
    # 如果是 MySQL 8.X 以及更高版本
    DROP DATABASE IF EXISTS openrasp;
    CREATE DATABASE openrasp default charset utf8mb4 COLLATE utf8mb4_general_ci;
    CREATE user 'rasp'@'%' identified with mysql_native_password by 'rasp123';
    grant all privileges on openrasp.* to 'rasp'@'%' with grant option;
    grant all privileges on openrasp.* to 'rasp'@'localhost' with grant option;
    
    # 如果是低版本 MySQL
    DROP DATABASE IF EXISTS openrasp;
    CREATE DATABASE openrasp default charset utf8mb4 COLLATE utf8mb4_general_ci;
    grant all privileges on openrasp.* to 'rasp'@'%' identified by 'rasp123';
    grant all privileges on openrasp.* to 'rasp'@'localhost' identified by 'rasp123';
    pip3 install --upgrade git+https://github.com/baidu-security/openrasp-iast@v1.2
    http://IAST服务器地址:25931/openrasp-result
    openrasp-iast config -a APP_ID -b APP_SECRET -c BACKEND_URL -m mysql://rasp:rasp123@127.0.0.1/openrasp
    openrasp-iast start -f
    openrasp-iast start
    ^/logout\.php.*
    Logstash
    Splunk

    功能说明

    本章节介绍 OpenRASP 的主要功能

    OWASP TOP 10 覆盖说明
    编号
    分类说明
    攻击类型
    危害
    说明

    A1

    注入

    SQL注入

    高危

    命令注入

    高危

    OpenRASP 零规则检测算法介绍

    具体请查看以下几篇公众号文章

    • ​OpenRASP v1.3.0 正式发布 | 数据泄露检测、类库版本查询、检测能力加强

    • OpenRASP v1.2.0 正式发布 | 发布DevSecOps轻量级解决方案,Java内存占用减少一半

    • 那些年我们堵住的洞 – OpenRASP纪实

    • OpenRASP v1.0 正式版发布 | 数据库异常监控与WebLogic支持如约而至

    覆盖场景说明

    1. 数据库: SQL注入

    覆盖场景:

    • 来自 GET、POST、Header、JSON、Multipart 等参数的SQL注入

    • 其他类型的SQL注入,如二次注入、RPC接口SQL注入

    覆盖类型:

    • 盲注、UNION 注入、时间差注入、错误注入、多语句注入

    • SQL 异常监控: 如语法错误、密码错误

    2. 数据库: 慢查询(已废弃)

    说明: 在SQL获取数据时,同时获取SQL语句较为困难,目前这个检测点已经废弃;另外,我们无法区分网络耗时和SQL执行时间,难以确认慢查询是不是真的慢查询

    期望覆盖场景

    • SELECT 语句执行时间超过 N 秒

    • SELECT 语句一次读取数据超过 N 条(容易误报,如数据导出)

    3. 任意文件上传

    覆盖场景

    • HTTP PUT 方式上传脚本文件,比如 CVE-2017-12615

    • HTTP PUT + MOVE 方式,先上传普通文件,再重命名为脚本文件

    • 使用标准的 multipart 方式上传脚本文件

      • 支持 Java struts、spring、common.io 等框架

      • 支持 PHP $_FILES 方式

    4. 敏感文件下载、任意文件读取

    覆盖场景

    • 利用任意文件下载漏洞,尝试跳出web目录下载系统文件,e.g /download.jsp?path=/../././//./.././/../../etc/hosts

    • PHP webroot 下存在 .tar/.sql/.log/... 等敏感文件(仅做基线检测,不拦截)

    5. 文件目录列出

    覆盖场景

    • 使用 PHP WebShell 查看服务器的文件目录

    • 开启了 directory index,使得用户可以直接看到某个目录下的文件(此检查默认不开启)

    • 使用 ../ 获其他变形跳出前目录,查看其它目录内容

    6. 扫描器探测行为 [官方插件不支持]

    说明: 大部分情况下,发现扫描器行为不代表存在漏洞。这个功能不符合RASP的初衷,所以我们默认关闭了这个功能。若要开启,请下载 002-detect-scanner.js,并参考 检测插件配置 - 安装插件 文档,安装这个插件即可。

    覆盖场景

    • 使用知名扫描器探测网站漏洞,e.g SQLMap、WVS 等等

    7. CSRF [暂无计划支持]

    说明

    此类漏洞应该由开发框架来完成。RASP可以通过插入JS的方式来实现,即在JS里面监控form创建,插入csrf token,并在服务端进行token验证

    覆盖场景

    • 使用 img/video/frame/.. 等方式,触发GET类型CSRF

    • Form 表单自动提交的方式

    • XHR 方式提交表单

    8. Cookie 篡改

    覆盖场景

    • 修改cookie获取管理员权限

    9. CRLF [暂无计划支持]

    说明: HTTP header CRLF 注入漏洞大多已经在API层面被修复,我们没有支持的计划;然而在一些非HTTP协议里依然存在,比如最近爆出的 Java FTP 协议CRLF注入。由于我们没有足够的案例,所以暂时不打算支持。

    覆盖场景

    • 在设置 HTTP header,或者处理其他TCP流时(比如FTP协议),插入换行符

    10. XXE

    说明: PHP无法挂钩xml检测点,暂不支持

    覆盖场景

    • 通过 org.apache.xerces 引用外部实体

      • 访问 ftp/dict/gopher/expect/.. 等不常见协议,实现OOB攻击

      • 使用 file 协议读取敏感文件

    11. 反序列化漏洞

    覆盖场景

    • Java

      • fastjson

      • transformer

      • xstream(如 S2-052)

      • ... (其他未知类型,具体看检测插件 command_reflect 算法)

    • PHP

      • 待整理

    12. Struts OGNL 代码执行

    覆盖场景

    • Struts OGNL 系列所有代码执行漏洞

    • OGNL 语句注入攻击

    13. WebShell 行为

    覆盖场景

    • 使用SQL管理器访问数据库

    • 使用文件管理器下载敏感文件

    • 使用中国菜刀执行命令

    • ...

    14. 远程命令执行

    覆盖场景

    • 使用 Runtime.exec() 类执行命令

    • 使用 system/passthru/shell_exec/proc_open/pcntl_exec/.. 等函数执行命令

    • 通过反序列化等方式执行命令

    15. 命令注入

    覆盖场景

    • 使用 &、|、; 等符号截断、拼接命令

    • 使用 $(xxx)、反引号等方式注入命令

    • 在命令注入攻击时,产生了语法错误

    16. XSS: 反射形式

    覆盖场景

    • 使用 PHP echo 函数直接输出 GPC

    • 用户输入含有HTML标签的内容,且直接输出到页面中

    17. XSS: 存储型(尚未发布)

    覆盖场景

    • 后台盲打

    18. LDAP 注入 [仅IAST商业版支持]

    覆盖场景

    • 通过注入修改LDAP查询逻辑

    19. DOS: Regex Group 攻击 [仅IAST商业版支持]

    覆盖场景

    • 常见 Regex DOS 攻击,e.g (a+)+、(a|aa)+

    20. 打印敏感日志信息

    覆盖场景

    • 使用 log4j、java.util.logging 打印身份证、银行卡、信用卡等敏感信息

    • HTTP响应(html/json/xml/等等)返回了未打码的敏感信息

    21. 文件包含

    覆盖场景

    • PHP 使用 include|include_once|require|require_once 等方式,包含日志、图片、文本文件等等

    • Java 使用 jstl 等方式包含文件

    22. NTLM 信息泄露攻击

    覆盖场景(仅限 Windows)

    • MySQL DNS 方式脱裤

    • 使用 302重定向到file/smb/scp协议 方式,泄露NTLM key

    • ...

    23. SSRF

    覆盖场景

    • 绕过

      • 使用 10.10.10.10.xip.io / *.vcap.me 等已知域名访问内网资源

      • 使用 302 重定向方式访问 file:// 域的资源

      • 尝试混淆访问的目标地址,且是内网IP,e.g http://0x7f001、http://0x7f.0x0.0x0.0x1

      • 访问保留地址,e.g http://0/

    • 常见场景

      • 尝试访问 aws metadata,e.g http://169.254.169.254/latest/meta-data/

      • 尝试访问已知的回显服务,e.g *.burpcollaborator.net、requestb.in

    24. 资产弱点识别 [开源版本仅采集信息,商业版支持漏洞识别]

    覆盖场景

    • 采集 composer/pom 信息

    • 使用存在已知漏洞的类库

    25. 后台爆破识别

    覆盖场景

    • 无验证码的后台爆破

    OWASP TOP 10 2017
    联系我们
    OWASP TOP 10 覆盖说明
    零规则检测算法介绍
    覆盖场景说明

    安全基线检查

    在应用服务器启动时,进行安全配置规范检查。如果 security.enforce_policy 设置为 true,发现不安全配置时,将抛出 com.baidu.openrasp.exception.SecurityException 异常并拒绝应用服务启动

    报警只会打印一次,具体格式参考 安全配置检查报警日志 相关文档

    3001 - 关键 cookie 是否开启 httpOnly

    ** 支持的服务器 **

    tomcat

    ** 策略说明 **

    在 tomcat 服务器下,检查是否在 JSESSIONID 是否开启 httpOnly 开关

    开启后,将对XSS攻击有一定的防范能力,可避免一些问题

    ** 修复方法 **

    若是 tomcat 7 以下版本,打开 CATALINA_HOME/conf/context.xml,将 useHttpOnly 改为 true,重启应用服务器即可

    3002 - 进程启动账号检查

    ** 支持的服务器 **

    tomcat, jetty, jboss, resin, springboot 等所有的 java 服务器

    ** 策略说明 **

    检查应用服务器的启动账号,当以如下账号启动则认为不符合安全规范:

    • Linux 系统的 root 账号

    • Windows 系统的 Administrator 或者 system 账号

    当应用服务器存在安全漏洞,以高权限账号启动会带来更大的安全风险,e.g 上传 webshell 即可获取最高权限、利用 struts 漏洞直接获取 root 权限

    ** 修复方法 **

    使用低权限用户启动应用服务器

    3003 - 后台弱口令检查

    ** 支持的服务器 **

    tomcat

    ** 策略说明 **

    在 tomcat 下,检查 $CATALINA_HOME/conf/tomcat-users.xml 下面配置的用户,如果具有 admin,manager,admin-gui,manager-gui 权限之一,即认为是管理员。然后针对所有管理员用户,检查密码的健壮性。

    目前策略非常简单,当用户名和密码均是以下内容之一,才认为是弱口令

    ** 修复方法 **

    使用高强度密码,e.g 使用10位以上的密码,并包含数字、字母、特殊符号

    3004 - 不安全的默认应用检查

    ** 支持的服务器 **

    tomcat

    ** 策略说明 **

    在 tomcat 下,检查 ROOT、manager、host-manager、docs 四个 webapps 是否删除

    默认应用或多或少会泄露敏感信息,或者造成管理后台对外暴露的风险

    ** 修复方法 **

    全部删除

    3005 - Directory Listing 检查

    ** 支持的服务器 **

    tomcat

    ** 策略说明 **

    在 tomcat 下检测 $CATALINA_HOME/conf/web.xml 是否为全局开启了 default servlet 的 Directory Listing功能

    开启 Directory Listing 功能,会泄露项目的目录结构,并泄露服务器的版本信息,危险配置如下:

    ** 修复方法 **

    打开 $CATALINA_HOME/conf/web.xml 把如上 xml 配置中的名字为 listing 的 init-param 删除,或者把 param-value 改为 false 即可

    3006 - 数据库连接账号审计

    ** 支持的服务器 **

    所有使用 JDBC 的服务器、PHP 服务器

    ** 策略说明 **

    检查是否使用 root (mysql)、sa (mssql)、sys (oracle) 等高权限账号连接数据库

    当存在SQL注入漏洞,使用高权限账号连接数据库会带来更大风险,泄露更多的数据;当服务器被黑客入侵,使用高权限账号,还可能同时导致数据库服务器沦陷

    如果 security.enforce_policy 选项设置为 true,那么无论数据库连接成功与否,我们都会拦截并产生报警;如果设置为 false(默认值),则只有成功的连接才会报警,且对于每个JDBC URL,相同的报警每天只会打印一次

    ** 修复方法 **

    创建新账号,授予最小的权限;不同的服务器集群使用不同的数据库账号连接

    3007 - JBoss HTMLAdaptor 认证检查

    ** 支持的服务器 **

    JBoss 4-6

    ** 策略说明 **

    检查 /jmx-console/HTMLAdaptor 是否开启认证

    ** 修复方法 **

    1. 编辑 $JBOSS_HOME/server/default/deploy/jmx-console.war/WEB-INF/web.xml,开启 security-constraint 相关配置

    2. 编辑 $JBOSS_HOME/server/default/deploy/jmx-console.war/WEB-INF/jboss-web.xml,开启 security-domain 相关配置

    3009 - Web 根目录下存在敏感文件

    ** 支持的服务器 **

    PHP

    ** 策略说明 **

    定期扫描 webroot,检查是否存在后缀为 sql、tar、rar、... 的文件

    ** 修复方法 **

    1. 删除这些文件

    2. 从 nginx、apache 层面过滤掉这些扩展名,防止被外界下载

    4001 - allow_url_include 配置审计

    ** 支持的服务器 **

    PHP 服务器

    ** 策略说明 **

    检查 allow_url_include 是否开启。开启后,将允许包含远程文件,e.g

    当应用存在文件包含、任意文件读取等漏洞,开启这个配置会让应用更加容易被入侵。

    ** 修复方法 **

    修改 ini 配置,将 allow_url_include 设置为 Off

    4002 - expose_php 配置审计

    ** 支持的服务器 **

    PHP 服务器

    ** 策略说明 **

    检查 expose_php 是否开启。若开启,在请求响应里可看到PHP的完整版本号,e.g

    ** 修复方法 **

    修改 ini 配置,将 expose_php 设置为 Off

    4003 - display_errors 配置审计

    ** 支持的服务器 **

    PHP 服务器

    ** 策略说明 **

    检查 display_errors 是否开启。当这个选项被开启,用户可在前端看到PHP程序内部的错误消息,e.g

    Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in C:\wamp\www\post\includes\pm_send.php on line 12

    当应用存在漏洞,结合这些错误消息,攻击者可以获取应用运行的路径、进行SQL报错注入攻击等等

    ** 修复方法 **

    修改 ini 配置,将 display_errors 设置为 Off

    4004 - yaml.decode_php 配置审计

    ** 支持的服务器 **

    PHP 服务器

    ** 策略说明 **

    检查 yaml.decode_php 是否开启。当这个选项被开启,在加载 yaml 文件的时候,将允许反序列化PHP对象,可能执行任意代码。另外,如果没有安装 yaml 扩展,即使配置了 yaml.decode_php=On 也不会报警。

    ** 修复方法 **

    修改 ini 配置,将 yaml.decode_php 设置为 Off

    大规模部署

    物理机部署

    百度内部主要是 Java/PHP 两种语言,其中Java服务器主要是 tomcat。目前,我们只提供了 Java + Tomcat 环境的批量安装脚本,可在源代码仓库里找到:

    批量安装脚本会执行如步骤:

    尝试使用 gopher://、dict 等不常见协议
  • (Java)使用JSTL import方式访问内网资源

  • LDAP 注入

    高危

    仅IAST商业版支持

    NOSQL 注入

    高危

    仅IAST商业版支持

    XPATH 注入

    高危

    仅IAST商业版支持

    A2

    失效的身份认证和会话管理

    Cookie 篡改

    低危

    仅IAST商业版支持

    后台爆破

    中危

    仅IAST商业版支持

    A3

    敏感数据泄露

    敏感文件下载

    高危

    任意文件读取

    高危

    数据库慢查询

    高危

    文件目录列出

    低危

    A4

    XML 外部实体(XXE)

    XXE

    中危

    A5

    失效的访问控制

    任意文件上传

    高危

    CSRF

    中危

    仅IAST商业版支持

    SSRF

    高危

    文件包含

    高危

    A6

    安全配置错误

    打印敏感日志信息

    低危

    Struts OGNL 代码执行

    高危

    远程命令执行

    高危

    A7

    跨站脚本(XSS)

    反射型 XSS

    低危

    存储型 XSS

    高危

    仅IAST商业版支持

    A8

    不安全的反序列化

    反序列化用户输入

    高危

    A9

    使用含有已知漏洞的组件

    资产弱点识别

    低危

    A10

    不足的日志记录和监控

    WebShell 行为

    高危

    OpenRASP v0.40 发布 | 正式支持 PHP 7
    OpenRASP v0.30 发布 | PHP 支持,堆栈异常和用户输入识别
    OpenRASP v0.23 发布 | 性能提升与SSRF检测
    OpenRASP v0.21 发布 | 拖库检测与数据安全
    OpenRASP v0.20 发布 | 性能提升与零规则漏洞检测

    类库信息查询

    从 v1.3 版本开始,我们加入了类库信息采集功能。Java 版本会采集 POM 信息,PHP 版本会采集 composer.json。值得注意的是,Java 版本在使用了相关的类之后才能获取到,PHP 是在发现新的 webroot 后才会采集。

    我们默认每隔6小时采集一次,为了保证时效性,Java 版本会在启动2分钟后提交一次。

    遍历所有名字为 "java" 的进程

  • 获取进程相关信息

    • 进程检查: 获取启动参数、环境变量信息,检查是否为 tomcat 进程,如果不是,跳过

    • 端口检查: 尝试获取 tomcat 一个可用的 HTTP 端口,如果找不到跳过当前进程

    • 权限检查: 如果用户为root,使用su进行安装;否则检查进程UID是否和当前用户一致,不一致跳过

    • 用户检查: 检查是否能否获取到当前用户名,获取不到就跳过

    • 版本检查: 检查 tomcat/jdk 是否为支持的范围,不支持就跳过

    • 冲突检查: 检查是否有其他的 javaagent 参数,如果发现且不为 openrasp,就跳过

  • 安装流程

    • 首先执行 RaspInstall.jar 进行安装,如果出错进入回滚流程

    • 然后尝试关闭 tomcat 服务器,最多等待30s

    • 之后尝试启动 tomcat 服务器,并不断尝试访问之前找到的 URL 地址,最多尝试60次

      • 如果失败,进入回滚流程

  • 回滚流程

    • 执行卸载操作,然后启动 tomcat 服务器

    • 如果无法启动,打印错误

  • 最后上传完整的脚本日志,包括安装和回滚(如果有)

  • 当然,在实际上线的过程中,我们还编写了一个打包脚本,用来生成单文件的安装包。有兴趣可以参考 baidu/openrasp - rasp-install/packer 相关脚本。

    容器化部署

    容器部署通常都需要定制。在百度内部,我们一般是修改 Dockerfile,并在发布镜像时集成 OpenRASP。在执行下面的命令之前,请先在管理后台获取 app_id/app_secret/backendurl 等参数的值。

    对于 alpine 容器,需要增加如下内容

    如果不能运行,请尝试增加软连接

    Java 版本

    Tomcat 示例

    假设 tomcat 安装路径为 /tomcat/,在服务器启动之前增加 ADD + RUN 命令即可:

    更多内容可参考 baidu-security/app-env-docker - src/openrasp/tomcat7.0/Dockerfile

    SpringBoot 示例

    假设 springboot 打包后的jar为 /springboot.jar,请先解压缩 rasp 相关文件,然后修改 JVM 启动参数:

    PHP 版本

    请在 apache/php-fpm 启动前增加如下命令

    更多内容可参考 baidu-security/app-env-docker - src/openrasp/php5.4/Dockerfile

    baidu/openrasp - rasp-install/remote/linux/batch-installer.sh
    both
    tomcat
    admin
    123456
    <servlet>
            <servlet-name>default</servlet-name>
            <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
            <init-param>
                <param-name>debug</param-name>
                <param-value>0</param-value>
            </init-param>
            <init-param>
                <!-- 如下就开启了 default sevelet 的 Directory Listing 功能-->
                <param-name>listings</param-name>
                <param-value>true</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    include("http://xxxxx")
    X-Powered-By: PHP/5.1.2-1
    RUN apk add --no-cache gcompat libcurl libstdc++
    ln -s /lib64/ld-linux-x86-64.so.2 /lib/ld-linux-x86-64.so.2
    ADD https://packages.baidu.com/app/openrasp/release/latest/rasp-java.tar.gz /tmp
    RUN cd /tmp \
        && tar -xf rasp-java.tar.* \
        && /jdk/bin/java -jar rasp-*/RaspInstall.jar -install /tomcat/ -appid XXX -appsecret XXX -backendurl XXX \
        && rm -rf rasp-*
    ADD https://packages.baidu.com/app/openrasp/release/latest/rasp-java.tar.gz /tmp
    RUN cd /tmp \
        && tar -xf rasp-java.tar.* \
        && mv rasp-*/rasp/ /rasp/ \
        && rm -f rasp-java.tar.gz
    
    RUN echo "cloud.enable: true" >> /rasp/conf/openrasp.yml \
        && echo "cloud.backend_url: XXX" >> /rasp/conf/openrasp.yml \
        && echo "cloud.app_id: XXX" >> /rasp/conf/openrasp.yml \
        && echo "cloud.app_secret: XXX" >> /rasp/conf/openrasp.yml
    
    RUN java -javaagent:"/rasp/rasp.jar" -jar /springboot.jar
    ADD https://packages.baidu.com/app/openrasp/release/latest/rasp-php-linux.tar.bz2 /tmp/
    RUN cd /tmp \
        && tar -xf rasp-php-linux.tar.bz2 \
        && php rasp-php-*/install.php -d /opt/rasp/ --backend-url XXX --app-id XXX --app-secret XXX \
        && rm -rf rasp-php*

    应用加固支持

    点击劫持防护

    ** 实现方式 **

    输出 X-Frame-Options 响应头

    ** 可选配置 **

    配置
    说明

    不开启

    MIME 嗅探防护

    ** 实现方式 **

    输出 X-Content-Type-Options 响应头

    ** 可选配置 **

    配置
    说明

    XSS Auditor 防护

    ** 实现方式 **

    输出 X-XSS-Protection 响应头

    ** 可选配置 **

    配置
    说明

    文件自动运行防护

    ** 实现方式 **

    输出 X-Download-Options 响应头

    ** 可选配置 **

    配置
    说明

    X-Protected-By 头

    这个 Header 用于检查服务器是否安装了 OpenRASP,可以关闭

    卸载软件

    自动卸载方法

    如果你安装时使用了自动安装程序,那么卸载的时候你也应该使用自动卸载程序。

    Java 服务器

    仅适用于 tomcat/jboss/resin/weblogic/wildfly 服务器。

    进入 rasp 安装包解压目录,e.g rasp-2018-12-20,并执行如下命令

    不重启卸载:

    不重启卸载 OpenRASP,需要在以上命令后面增加 -pid 参数指定运行的服务器进程 id,JDK6 - JDK8 样例命令如下,

    jdk9 ~ jdk11 样例命令如下,

    注意:不重启卸载之后,若想再次安装不能使用不重启安装,只能使用需要重启的安装方式

    PHP 服务器

    进入 rasp 安装包解压目录,e.g rasp-2018-12-20,并执行如下命令

    手动卸载方法

    Tomcat 服务器

    假设Tomcat根目录为${CATALINA_HOME}

    1. 删除目录${CATALINA_HOME}/rasp

    2. 找到启动配置文件

      • Linux环境下打开${CATALINA_HOME}/bin/catalina.sh

    JBoss 服务器

    假设 JBoss 根目录为 ${JBOSS_HOME}

    1. 删除插件安装目录 ${JBOSS_HOME}/rasp

    2. 如果是 JBoss4 ~ Jboss6:

      • Linux下打开 ${JBOSS_HOME}/bin/run.sh

    Resin 服务器

    假设Resin根目录为${RESIN_HOME}

    1. 删除插件安装目录 ${resin_HOME}/rasp

    2. 如果是 resin3:

      • Linux下打开 ${RESIN_HOME}/conf/resin.conf

    Wildfly 服务器

    假设 Wildfly 根目录为 ${JBOSS_HOME}

    1. 删除插件安装目录 ${JBOSS_HOME}/rasp

    2. 找到启动配置文件:

      • Linux下打开 ${JBOSS_HOME}/bin/standalone.sh

    Jetty 服务器

    假设Jetty根目录为${JETTY_HOME}

    1. 删除插件安装目录 ${JETTY_HOME}/rasp

    2. 修改服务器启动参数,删除 javaagent、Dlog4j.rasp.configuration 参数

    3. 重启 Jetty 服务器

    Websphere 服务器

    假设Websphere的根目录为 ${WEBSPHERE_HOME}。首先删除 OpenRASP 相关文件 ${WEBSPHERE_HOME}/rasp,然后参考下面的步骤删除 JVM 启动参数。

    打开 WebSphere 控制台,

    在左边的导航栏选择,服务器 > 服务器类型 > WebSphere Application Server

    点击 server1 服务器进入服务器的管理界面(或者你的服务器)

    找到,服务器基础架构 >java和进程管理 > 进程定义,点击进入

    点击右侧 Java虚拟机 选项

    找到 通用JVM参数,将其删除,保存修改

    最后重启 WebSphere 服务器生效

    Spring Boot 服务器

    假设Spring Boot根目录为${SPRING_BOOT_HOME}

    1. 删除插件安装目录 ${SPRING_BOOT_HOME}/rasp

    2. 修改服务器启动参数,删除 javaagent、Dlog4j.rasp.configuration 参数

    3. 重启 Spring Boot 服务器

    PHP 服务器

    找到 php.ini 配置文件,删除 extension=openrasp.so,以及所有 openrasp. 开头的配置选项,e.g

    然后重新加载PHP服务器生效,e.g

    1. 对于PHP-FPM服务器,可尝试 service php5.6-fpm reload

    2. 对于Apache PHP模块,可尝试 service apache2 reload

    最后在 phpinfo() 里确认,如果看不到 openrasp 模块信息,则表示卸载成功

    HTML 响应修改

    功能说明

    为了防御/检测某些漏洞,CSRF、后台盲打等等,OpenRASP 允许你在 页面末尾 上注入代码,e.g

    要注意的是,只有在当满足如下条件时,OpenRASP 才会插入HTML

    • 页面响应的 Content-Type 为 text/html

    -

    deny

    禁止网站被 frame/iframe 嵌套

    sameorigin

    允许网站被 frame/iframe 嵌套,但父页面只能是当前域

    不开启

    -

    nosniff

    如果从script或stylesheet读入的文件的MIME类型与指定MIME类型不匹配,不要读取该文件。可用于防止XSS等跨站脚本攻击。

    不开启

    -

    1; mode=block

    开启浏览器的 XssAuditor 功能

    不开启

    -

    noopen

    IE 8以上版本的用户,不打开文件而直接保存文件。在下载对话框中不显示 "打开" 选项。

    接口说明

    本章节讲解 OpenRASP 提供的一系列接口

    若有新的接口需求,你可以去 Github 提交 Issue

    Windows下打开
    ${CATALINA_HOME}/bin/catalina.bat
  • 搜索关键词 javaagent 与 Dlog4j.rasp.configuration,删除或注释掉相应行

  • 重启 tomcat 服务器

  • Windows下打开
    ${JBOSS_HOME}/bin/run.bat
  • 如果是 JBoss7:

    • Linux下打开 ${JBOSS_HOME}/bin/standalone.sh

    • Windows下打开 ${JBOSS_HOME}/bin/standalone.bat

  • 把如上文件按照手动安装文档恢复原样

  • 重启 JBoss 服务器

  • Windows下打开
    ${RESIN_HOME}/conf/resin.conf
  • 如果是 resin4:

    • Linux下打开 ${RESIN_HOME}/conf/cluster-default.xml

    • Windows下打开 ${RESIN_HOME}/conf/cluster-default.xml

  • 把如上文件按照手动安装文档恢复原样

  • 重启服务器

  • Windows下打开
    ${JBOSS_HOME}/bin/standalone.bat
  • 把如上文件按照手动安装文档恢复原样

  • 重启 Wildfly 服务器

  • 控制台
    two
    three
    four
    five
    six
    ,且状态码为
    200
  • 响应是动态生成的,比如 JSP 文件或者 Servlet

  • inject.urlprefix 配置选项不为空

  • 要注入的内容,aka <app_home>/rasp/assets/inject.html 存在且内容不为空

  • 另外,如果你使用的是自动化安装包,我们在默认生成的 openrasp.yml 配置文件里,禁用了这个功能

    你需要手动注释掉 hooks.ignore 这一行,才能开启这个功能

    自定义插入的 HTML

    1. 你需要配置 inject.urlprefix 选项,设置要匹配的URL前缀,e.g http://www.baidu.com/admin/

    2. 编辑 <app_home>/rasp/assets/inject.html 文件,输入你要插入的内容,e.g

    OpenRASP 会监控这个文件,保存后立刻生效

    关闭响应修改功能

    删除 <app_home>/rasp/assets/inject.html 文件,删除后立即生效

    状态检查

    访问一个 JSP 或者 Servlet 页面,检查注入的内容是否存在即可。

    注意: 浏览器可能有缓存,建议清掉缓存测试

    FAQ

    1. 我修改了 inject.html,总要重启服务器才会生效

    如果你是在 VMWare 虚拟机里测试 OpenRASP,然后插件是放在 VMWare 共享 里的,这个时候 inotify 可能不会生效,也就无法实时更新 js 脚本。

    这可能是因为 vmhgfs 跟 inotify 本身存在兼容性问题。最快的解决方法,就是将整个服务器软件都复制到虚拟机的磁盘上,比如 /root/tomcat/

    java -jar RaspInstall.jar -uninstall <app_home>
    # <server_pid> 为服务器进程 id
    # $JAVA_HOME 为 jdk 根目录环境变量,如果未指定该环境变量,替换为 jdk 的完整根目录
    java -Xbootclasspath/a:$JAVA_HOME/lib/tools.jar -jar RaspInstall.jar -uninstall <app_home> -pid <server_pid>
    # <server_pid> 为服务器进程 id
    java -jar RaspInstall.jar -uninstall <app_home> -pid <server_pid>
    php uninstall.php -d <openrasp_rootdir>
    extension=openrasp.so
    openrasp.root_dir=/opt/rasp
    ...
    <!-- Added by OpenRASP -->
    <script type="text/javascript">
    	alert('Hello from OpenRASP - https://rasp.baidu.com');
    </script>
    <!-- End added by OpenRASP -->
    hooks.ignore: http_output
    <!-- Added by OpenRASP -->
    <script type="text/javascript">
    	alert('Hello from OpenRASP - https://rasp.baidu.com');
    </script>
    <!-- End added by OpenRASP -->

    RASP 类接口

    所有插件需要实例化一个 RASP 对象,并在此对象上注册各检测点对应的检测程序

    创建实例

    创建 RASP 实例需传入插件名,e.g demo

    获取agent版本号 (v1.2.0 加入)

    获取JS引擎名称

    发送HTTP请求 (v1.2.0 加入)

    支持发送 GET/POST 请求,其中 data 字段可以是字符串、对象或者 Buffer

    注册检测程序到对应检测点

    检测函数接受两个参数

    • params 对应检测点的参数信息

    • context 请求上下文信息

    具体有哪些检测点可以注册,以及 params 的样例,请参考检

    注意: 对于同一个检测点,如果你注册了多个检测函数,这些函数会按照注册顺序,依次调用

    将SQL语句解析为 Token(BETA)

    函数接受两个参数

    • query 表示要解析的查询语句

    • server 表示SQL服务器类型

    目前本功能还在试验阶段,且暂时不区分SQL服务器类型。

    将 Bash/CMD 语句解析为 Token(BETA)

    函数接受一个参数

    • command 表示要解析的命令

    目前本功能还在试验阶段,且暂时不区分操作系统

    打印调试日志

    使用方法与 console.log 一致,只是会同时输出插件的名字,方便你区分不同插件的日志

    获取插件名

    手动调用检测方法

    在编写单元测试时,可手动调用此方法

    这个方法会按照注册顺序,依次调用所有的检测函数,并返回一个检测结果数组

    e.g 模拟一个SQL注入请求,请调用插件获取检测结果

    单元测试

    参数说明

    我们的插件开发工具 提供了插件测试命令,可以对插件进行功能和性能测试。命令行参数如下,

    创建测试用例

    我们在 上提供了一些样例。测试用例以 JSON 格式保存,示例如下:

    其他配置

    通用配置

    以下配置支持云端下发,也支持单机修改。若开启远程管理,单机配置不会加载;如果没有开启,Java 版本单机配置修改后立即生效,PHP 大部分情况下会立即生效。

    目前配置路径如下:

    • PHP 版本: <openrasp_rootdir>/conf/openrasp.yml

    var plugin = new RASP('demo')
    参数说明
    其中,action 表示期望的结果,是拦截、日志还是放行;id 是测试用例编号。其他字段主要是对请求上下文的模拟。

    运行测试用例

    运行单元测试,需要两个关键参数

    • 测试用例目录

    • 检测插件路径

    比如,若要测试官方插件,可以执行如下命令:

    当测试结果中出现 failing 和详细错误信息时,表示测试用例没有通过。

    插件耗时测试

    每一个测试用例所消耗的时间出现在测试结果行的最末端。

    若时间被标注为黄色,表示该测试用例消耗时间过长,若时间被标注为红色,表示该测试用例消耗时间超过最大限制。默认超时时间为 20ms

    openraspjs
    baidu/openrasp
    var name = plugin.get_version()
    // 返回 1.2.0
    var name = plugin.get_jsengine()
    // 返回 rhino / v8
    var body = {
        "name": "openrasp"
    }
    
    var req  = {
        "method":       "post",
        "url":          "http://127.0.0.1/test",
        "data":         data,
        "maxRedirects": 0,
        "timeout":      30,
        "headers": { 
            "content-type": "application/json"
        },    
    }
        
    RASP.request(req)
    plugin.register('sql', function(params, context) {
      // 在这里实现检测逻辑
      // 并返回结果
      return {
         action: 'ignore',
         message: '无风险'
      }
    })
    RASP.sql_tokenize('SELECT * FROM users WHERE id = -1 union/*!50000select*/1,2,3', 'mysql')
    // [
    // 	  { text: 'SELECT', start: 0, stop: 5 },
    // 	  { text: '*',      start: 7, stop: 7 },
    // 	  ...
    // ]
    RASP.cmd_tokenize('/bin/bash -c ls')
    // [ 
    //    { text: '/bin/bash', stop: 8,  start: 0  },
    //    { text: '-c',        stop: 11, start: 10 },
    //    { text: 'ls',        stop: 14, start: 13 } 
    // ]
    plugin.log('hello', 'openrasp')
    // 将会在日志里输出 [demo] hellp openrasp
    var name = plugin.name
    // => 'demo'
    var params = {
      'query': 'select * from users',
      'server': 'mysql'
    }
    var checkContext = new Context()
    RASP.check('sql', params, context)
    // => [{
    //    'action': 'block',
    //    'message': 'attack',
    //    'name': 'demo'
    // }]
    $ rasp check
    
    OpenRASP plugin devtool - https://rasp.baidu.com
    Usage: rasp-check
    
    Options:
      -d, --case-dir <dir>        specify a testcases directory
      -p, --plugin-file <plugin>  specify a javascript plugin file
      -h, --help                  output usage information 
    [{
        "id": "ssrf_userinput_intranet",
        "name": "ssrf",
        "action": "block",
        "params": {
            "hostname": "172.16.177.120",
            "ip": ["172.16.177.120"],
            "url": "http://172.16.177.120/hello.action?redirect=123"
        },
        "context": {
            "parameter": {
                "url": ["http://172.16.177.120/hello.action?redirect=123"]
            }
        },
        "description": "SSRF userinput match test"
    }]
    $ rasp check -d ~/openrasp/agent/java/engine/src/test/resources/pluginUnitTest/unitCases/ -p ~/openrasp/plugins/official/plugin.js
    
    [offical] OpenRASP official plugin: Initialized, version 2018-1010-1600
     
      ✓ sql.json Simple userinput match test: 9ms
      ✓ sql.json SQL injection with hex values: 1ms
      ✓ sql.json SQL injection with datetime methods: 2ms
      ✓ ssrf.json SSRF userinput match test: 2ms
      ✓ ssrf.json SSRF false positive test: 1ms
     
      5 passing (26ms)

    Java 版本: <app_home>/rasp/conf/openrasp.yml

    若配置修改后没有生效,请检查日志里是否有 yaml语法错误异常

    • PHP日志: rasp.log 以及error_log ini配置的文件名

    • Java日志: rasp.log

    插件相关

    参数值
    说明
    默认值

    plugin.timeout.millis

    对于单个检测算法, JS 插件超时时间 (毫秒)

    100

    plugin.maxstack

    插件获取堆栈的最大深度

    100

    plugin.filter

    针对文件访问hook点,是否开启过滤机制。 若开启,当目标文件不存在,将不进入检测插件。 支持 directory, readFile, rename, include 四个 hook 点

    true

    body.maxbytes

    最多读取 POST body 的前多少字节

    4096

    文件日志相关

    参数值
    说明
    默认值

    log.maxstack

    报警日志记录的最大堆栈深度(v1.2开始废弃)

    50

    log.maxburst

    每个进程/线程每分钟最大日志条数

    100

    log.maxbackup

    日志最大备份天数

    30

    syslog 日志相关

    syslog.facility 的值请参考 What are Syslog Facilities and Levels,比如 7 表示 news 类型。另外,由于报警日志大小超过 1KB,所以我们仅支持 TCP 方式推送报警。

    参数值
    说明
    默认值

    syslog.enable

    是否开启 syslog

    false

    syslog.url

    服务器地址,如 tcp://ip:port

    (空)

    syslog.tag

    tag 值

    OpenRASP

    syslog.facility

    facility 值

    1

    拦截相关

    参数值
    说明
    默认值

    block.status_code

    拦截攻击后,将状态码设置为这个值

    302

    block.redirect_url

    拦截攻击后,跳转到这个URL,并根据模板设置 request_id 参数

    https://rasp.baidu.com/blocked/?request_id=%request_id%

    block.content_json

    拦截攻击后,若期望响应类型为JSON,则根据此模板显示内容

    {"error":true, "reason": "Request blocked by OpenRASP", "request_id": "%request_id%"}

    block.content_xml

    拦截攻击后,若期望响应类型为XML,则根据此模板显示内容

    <?xml version="1.0"?> <doc> <error>true</error> <reason>Request blocked by OpenRASP</reason><request_id>%request_id%</request_id> </doc>

    熔断配置

    注意: 目前仅 Java 服务器支持熔断,PHP 暂不支持

    参数值
    说明
    默认值

    cpu.usage.enable

    是否开启熔断支持

    false

    cpu.usage.interval

    每隔多少秒采集一次CPU占用率 配置范围是 1-1800

    5

    cpu.usage.percent

    当单核CPU占用率超过这个数值,关闭所有防护。 配置范围是 30-90

    90

    其他配置

    参数值
    说明
    默认值

    dependency_check.enable

    是否采集依赖库

    true

    request.param_encoding

    仅Java支持,设置 Form 参数的编码格式。设置后,可在用户解析参数之前按照该编码提前获取用户输入,如 UTF-8

    (空)

    clientip.header

    从指定的 HTTP header 里获取客户端真实IP,并记录到报警日志的 client_ip 字段里。注意: 本配置区分大小写。

    ClientIP

    inject.urlprefix

    对于以下URL,修改响应并注入HTML

    (空)

    PHP 版本独立配置

    以下配置无法云端下发,需要放在 php.ini 里,修改后重启PHP服务器生效。

    参数值
    说明
    默认值

    openrasp.root_dir

    openrasp 根目录,存放插件、日志

    (空)

    openrasp.locale

    配置的语言类型

    (空)

    openrasp.heartbeat_interval

    心跳间隔,单位秒

    180

    openrasp.backend_url

    云控后台 URL 地址

    (空)

    Java 版本独立配置

    单机版文件监控相关设置,监控范围是配置文件以及插件目录 (要求客户端版本 >= 1.3.6)

    参数值
    说明
    默认值

    file_monitor.mode

    单机版文件目录监控机制,重启生效。 jnotify: 使用 jnotify 监控目录变更 scan: 定期扫描目录变更 disable: 关闭插件更新机制

    scan

    file_monitor.interval

    在定期扫描模式下,多久扫描一次目录(秒)

    3

    以下配置虽然还是在 openrasp.yml 里,但是无法云端下发,且修改后需要重启服务器生效。

    参数值
    说明
    默认值

    cloud.backend_url

    云控后台 URL 地址

    (空)

    cloud.app_id

    云控通信使用的 app_id 值

    (空)

    cloud.app_secret

    云控通信使用的 app_secret 值

    (空)

    cloud.enable

    是否开启远程管理功能

    false

    hooks.ignore 全部可选值

    其中 http_output 为HTML注入功能,其他的都比较好理解。修改后需要重启 Java 应用服务器。

    hooks.ignore=sql,sqlPrepared,directory,request,readFile,writeFile,fileUpload,command,xxe,ognl,deserialization,include,ssrf,http_output,webdav,sqlSlowQuery,rename,dubboRequest

    若要禁用所有 hook 点,可直接使用 hooks.ignore=all 配置。

    V8 通用

    提高内存 (1.2.2 之后无需修改)

    当在标准输出或者插件日志里看到如下内容时候,可以考虑提高内存占用:

    1. [libopenrasp_v8_java.so+0xb4f142] v8::base::OS::Abort()+0x12

    2. Allocation failed - JavaScript heap out of memory

    e.g 将老生代内存设置为20MB,新生代2MB:

    对于 Tomcat 这样具有启动脚本的服务器,在启动脚本最前面加上即可

    对于 SpringBoot 这样直接使用 java 命令启动的服务器,在启动之前设置下环境变量即可

    注意: 设置后需要重启 Java、PHP 进程生效。

    Context 类接口

    Context 类包含当前请求信息和服务器信息

    获取请求路径

    绝对路径,不包含 Query String

    获取 Query String

    返回URL参数

    获取请求方法

    字母为小写

    获取请求协议

    获取请求头

    获取当前请求的 headers,其中key的名字均为小写。这个值可能为空,使用前需要判断,e.g if (context.header != null)

    获取请求体

    仅返回请求体原始数据的前4KB,类型为

    因受到服务器限制,插件系统不保证一定能够获取到请求体原始数据。在Java应用下面,只有应用读取了body,插件才能获取到。因此在 request hook 点是拿不到 body 的。

    获取请求 JSON

    获取当前请求的 POST JSON 参数

    获取请求参数

    对于 java 服务器,当用户已经获取过请求参数的情况下, 我们会返回 ServletRequest.getParameterMap() 的结果,也就是 Map<String, String[]>

    当用户还没有获取过任何参数, 我们会返回空对象, 这样做既可以保证用户在获取参数的时候不会产生乱码, 同时在插件中做用户参数匹配检测过程中也可以降低误报率。若要在 request hook 点获取到用户输入,请参考 文档,设置 request.param_encoding 参数。

    获取请求来源地址

    这个参数只是应用服务器看到的请求来源IP。如果是反向代理部署方式,你可能需要获取 X-Forwarded-For、X-Client-IP 等HTTP响应头数据

    获取服务器信息

    当前服务器的属性,包括服务器类型、开发语言等等

    若要判定是否为 Windows 系统,可使用 context.server.os.indexOf('Windows') == 0

    获取Web根目录

    对于java服务器,返回 webapps 目录;对于php服务器,返回 webroot

    自定义实例

    在编写单元测试时,若要同时模拟请求信息,可以通过自定义 Context 实例的方式来实现,e.g

    当然,除了请求方法以外,你可还可以自定义其他参数,

    如果没有定义某个方法,这个方法将返回 undefined

    export OPENRASP_V8_OPTIONS="--max-old-space-size=20 --max-semi-space-size=2"
    #!/bin/sh
    
    export OPENRASP_V8_OPTIONS="--max-old-space-size=20 --max-semi-space-size=2"
    
    # Licensed to the Apache Software Foundation (ASF) under one or more
    # contributor license agreements.  See the NOTICE file distributed with
    # this work for additional information regarding copyright ownership.
    export OPENRASP_V8_OPTIONS="--max-old-space-size=20 --max-semi-space-size=2"
    java -jar XXX.jar [其他参数]
    context.path
    // => '/my/article.jsp'

    lru.maxsize

    插件检测结果为ignore时,我们会缓存检测结果。 再次遇到相同的行为参数,将不会进行检测。 LRU只对数据库、文件操作生效,所有检测点共享一个LRU。

    1024

    ognl.expression.minlength

    为了减少OGNL检测的性能损耗, 当OGNL语句达到这个长度才调用插件

    30

    syslog.connection_timeout

    连接超时时间 (毫秒)

    50

    syslog.read_timeout

    读超时时间 (毫秒)

    10

    syslog.reconnect_interval

    重连时间间隔 (秒)

    300

    block.content.html

    拦截攻击后,若期望响应类型为其他情况,则根据此模板显示内容

    </script><script> location.href= "https://rasp.baidu.com/blocked2/?request_id=%request_id%" </script>

    debug.level

    debug 等级,0为关闭 debug 模式

    0

    decompile.enable

    是否开启反汇编功能。 开启后可获取源代码,但是会非常消耗性能

    0

    offline_hosts.cleanup.interval

    清理离线时间间隔超过几天以上的主机。1以上的值表示开启

    0

    openrasp.app_id

    云控通信使用的 app_id 值

    (空)

    openrasp.rasp_id

    自定义的 RASP ID,如果空就计算一个

    (空)

    openrasp.app_secret

    云控通信使用的 app_secret 值

    (空)

    openrasp.remote_management_enable

    是否开启远程管理功能

    false

    cloud.heartbeat_interval

    心跳间隔,单位秒

    180

    hooks.ignore

    默认开启全部 hook 点,有不需要的可在这里关闭,逗号分隔

    (空)

    rasp.id

    自定义的 RASP ID,如果空就计算一个

    (空)

    ArrayBuffer
    其他配置
    context.querystring
    // => 'offset=10&size=10'
    context.method
    // => 'get'
    context.protocol
    // => 'https'
    context.header
    // => {
    //   'user-agent': 'Chrome',
    //   'content-type': 'application/json'
    //   ...
    // }
    context.body
    // => ArrayBuffer
    context.json
    // => {
    //   'field': 'Value',
    //   ...
    // }
    // context.querystring = 'offset=10&size=10'
    // context.body = 'filter=odd'
    context.parameter
    // => {
    //   'offset': ['10'],
    //   'size':   ['10'],
    //   'filter': ['odd']
    // }
    context.remoteAddr
    // => '2.3.3.3'
    context.server
    // {
    //    'name': 'Tomcat / JBoss / Jetty',
    //    'version': '8',
    //    'os': 'Linux',
    //    'language': 'java / php' 
    // }
    context.appBasePath
    // => '/home/tomcat/webapps'
    var context = new Context()
    
    // 自定义 method 参数信息
    var context = new Context({
      getMethod: function() {
        return 'get'
      }
    })
    var context = new Context({
      getPath: function(){},
      getQuerystring: function(){},
      getMethod: function(){},
      getProtocol: function(){},
      getHeader: function(){},
      getParameter: function(){},
      getBody: function(){},
      getRemoteAddr: function(){},
      getServer: function(){}
    })

    应用异常监控

    数据库异常监控

    在SQL注入的探测阶段,或者报错注入的攻击阶段,通常会在数据库产生大量的异常。因此,通过监控异常可以有效的发现的SQL注入攻击。目前我们所有支持的数据库均可以监控SQL异常,且异常代码可以在插件里配置。

    插件里默认监控的SQL异常如下,具体请参考官方插件的 sql_exception 检测算法。

    MySQL

    错误编号
    报警样例

    PostgreSQL

    错误编号
    报警样例

    SQLite

    错误编号
    报警样例

    Oracle

    错误编号
    报警样例

    HSQL

    错误编号
    报警样例

    SQLServer

    错误编号
    报警样例

    DB2

    错误编号
    报警样例

    FAQ

    1. Unable to derive error code from SQL exceptions 错误

    当MySQL服务器与JDBC驱动不兼容,我们将无法从异常消息里提取SQL错误代码,并打印这个错误。比如 JDBC 5.1.46 + MySQL 5.5 就会出现这个问题,可以考虑升级JDBC驱动到对应的版本来解决。

    这个错误会让数据库异常监控失效。

    CVE 漏洞覆盖说明

    本列表还在不断更新中,如果你有任何疑问,请联系我们。

    大部分漏洞环境都可以在 baidu-security/app-env-docker - 基于 Docker 的真实应用测试环境 找到,如果你需要进行测试,参考上面的文档操作即可。

    Java 漏洞

    Struts OGNL 系列

    • CVE-2013-2251 - Apache Struts2 S2-016 OGNL 代码执行漏洞

    Spring 系列

    反序列化系列

    任意文件下载

    任意代码执行

    未分类

    PHP 漏洞

    任意文件上传

    SQLi

    任意文件写入 - 需要开启 writeFile_script 算法

    任意文件包含

    任意文件下载

    目录遍历漏洞

    代码执行

    反序列化

    SSRF

    NodeJS 漏洞

    待添加

    Python 漏洞

    待添加

    Ruby 漏洞

    待添加

    架构说明

    背景介绍

    RASP 是一种新型应用安全防护技术。这种技术直接将防护引擎嵌入到应用内部,能够感知应用上下文。传统的防护设备,WAF、IDS等等,均是对HTTP请求进行分析和处理,并结合请求特征库进行匹配,能做的事情比较有限。

    举个例子,当发生SQL注入攻击时,WAF和IDS只能看到HTTP请求。而RASP技术不但能看到完整的SQL语句,还可以和当前的HTTP请求进行关联,并结合语义引擎、用户输入识别等能力,实现对SQL注入的检测。

    如果你还想了解更多,可以参考下面的内容

    官方链接

    在线调试

    当你编写的插件,在线上运行不正常时,你可以参考这个文档,以解决问题

    检查运行时错误

    当插件存在运行时错误,错误日志和堆栈会打印到 <app_home>/rasp/logs/plugin/plugin-DATE.log,e.g

    官方插件定制

    官方插件定制

    不同的研发人员,编码的习惯可能会不同;不同的业务,应用场景也不同。根据QQ群里用户的反馈,我们进行了整理。如果还有没覆盖的情况,请联系QQ群主,我们会给出方案,并更新文档。

    案例研究

    我如何审计应用执行的命令?{#case-cmd-other}

    1060

    Duplicate column name '5.5.60-0ubuntu0.14.04.1'

    1062

    Duplicate entry '::root@localhost::1' for key 'group_key'

    1064

    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') from mysql.user' at line 1

    1105

    XPATH syntax error: 'root@localhost'

    1367

    Illegal non geometric 'user()' value found during parsing

    42601

    normal syntax error

    22P02

    ERROR: invalid input syntax for type double precision: "DATABASE: test1"

    1

    generic error, like syntax error、malformed MATCH expression: ["3.6.23.1] and other

    ORA-01740

    missing double quote in identifier

    ORA-01756

    quoted string not properly terminated

    ORA-00907

    missing right parenthesis

    -5583

    malformed quoted identifier

    -5590

    unexpected end of statement

    105

    Unclosed quotation mark after the character string '%.*ls'.

    245

    Conversion failed when converting the %ls value '%.*ls' to data type %ls.

    42603

    The string constant beginning with "'xxx" does not have an ending string

    SemCms 2.3 多个SQL注入漏洞
  • ECShop 3.0.0 SQL注入漏洞

  • ZentaoPMS SQL注入漏洞

  • CVE-2018-5211 - PHPMelody 2.7.1 SQL注入漏洞

  • CVE-2017-15081 - PHPMelody 2.6.1 SQL注入漏洞

  • HDWiki 6.0 referer注入漏洞

  • PHPMyWind <= 5.3 SQL 注入漏洞

  • CVE-2016-4010 - Magento代码执行漏洞
    CVE-2017-5638 - Apache Struts2 S2-045 OGNL 代码执行漏洞
    CVE-2018-1273 - RCE with Spring Data Commons 分析报告
    CVE-2017-4971 - Spring Web Flow 远程代码执行漏洞
    CVE-2018-1260 - RCE with spring-security-oauth2
    Spring Boot < 1.2.8 SSTI 代码执行漏洞
    CVE-2017-12149 - JBOSSAS 5.x/6.x 反序列化命令执行漏洞
    CVE-2017-9805 - Apache Struts S2-052
    CVE-2016-0792 - Jenkins XStream 反序列化漏洞
    Fastjson 反序列化漏洞
    Confluence 5.8.10 任意文件读取漏洞
    CVE-2018-14667 - Unauthenticated Remote Code execution in WebApps using Richfaces 3.X all versions
    CVE-2018-16341 - Nuxeo 认证绕过和RCE漏洞
    CVE-2017-12615 - Tomcat PUT 任意文件上传漏洞
    CVE-2018-1000130 - Apache Jolokia JNDI 注入漏洞
    Monstra 3.0.4 任意文件上传漏洞(使用大写PHP扩展名绕过过滤)
    CVE-2018-9153 - Z-BlogPHP 1.5.1 后台文件上传
    CVE-2018-8893 - Z-BlogPHP 1.5.1 CSRF GetShell
    CVE-2018-8045 - Joomla! 3.5 - 3.8.5 SQLi 漏洞
    CVE-2017-8917 - Joomla! 3.7.0 Core SQL Injection
    Thinkphp框架 < 5.0.16 sql注入漏洞分析
    Thinkphp 3.2.3 最新版update注入漏洞
    帝国CMS CSRF GetShell
    TinyShop 缓存文件获取 webShell
    CmsEasy < 5.6 20161012 cut_image 代码执行漏洞
    CVE-2018-7422 - LFI vulnerability in WordPress Site Editor Plugin
    phpMyAdmin 4.8.x文件包含漏洞
    PHPCMS 9.6.2 文件读取漏洞
    PHPCMS 9.6.1 任意文件下载漏洞
    TinyShop 2.4 任意文件读取漏洞
    PHPMyWind 5.3 后台任意文件读取漏洞
    PHPMyWind 5.3 后台目录遍历漏洞
    CVE-2017-1000480 - Smarty <= 3.1.32 代码执行漏洞
    Discuz! 6.x/7.x 全局变量防御绕过导致命令执行
    海洋CMS SeaCMS <= 6.45 searchword 代码注入漏洞
    ThinkPHP 2.X dispatcher preg_replace 代码执行漏洞
    Typecho 反序列化漏洞导致前台getshell
    vBulletin MEDIA UPLOAD SSRF 漏洞
    PHP-Proxy 5.1.0 - Local File Inclusion (SSRF 导致的)

    插件开发

    OpenRASP 大部分的安全检测逻辑都是在插件中实现的,可以在多个平台复用。当引擎检测到敏感行为时,会依次调用插件进行检测,如果某个插件认为此操作存在风险,可返回 拦截,我们便会阻断这个操作,同时不再调用后续插件进行检测。

    目前,OpenRASP 支持对数据库、文件、网络等行为进行检测,本章节讲解如何编写一个插件。

  • OpenRASP 和 WAF的区别在哪里

  • OpenRASP 零规则检测算法介绍

  • 绿盟科技博客

    • 绿盟科技博客: RASP 技术分析

    • 绿盟科技博客: OpenRASP 技术分析

    Seebug

    • Java RASP浅析——以百度OpenRASP为例

    详细设计

    • Java 版本

    • PHP 版本

    • 管理后台

    • IAST 扫描器

    OpenRASP 最佳实践 - PDF下载
    开启详细插件参数日志

    下载 999-event-logger.js 这个插件并安装到插件目录。

    这个插件会把所有的参数打印出来,通常是 <app_home>/rasp/logs/plugin/plugin-DATE.log,e.g

    注意: 从 1.0 RC1 开始,我们默认开启了检测结果LRU。当插件检测结果为 ignore,在插件更新之前,相同的插件参数将不会再次检测。在这种情况下,event-logger 将不会打印调试日志。

    2017-10-13 17:10:05,254 INFO  [http-bio-8080-exec-3][com.baidu.openrasp.plugin.log]
    ReferenceError: "abc" is not defined.
    	at official.js:407 (test)
    	at official.js:412 (anonymous)
    2018-07-25T16:28:14+08:00 [event-logger] 999-event-logger: 初始化成功
    2018-07-25T16:28:19+08:00 [event-logger] 读取文件: /etc/hosts
    OpenRASP 可以记录应用所有执行的命令,并上传到管理后台。若要开启,请在管理后台定位到 系统设置 -> 防护设置 -> 命令执行,将 记录或者拦截所有命令执行操作 改为 记录日志 即可(默认关闭)

    通过文件函数写入 WebShell,OpenRASP 不会拦截?{#case-file-write}

    我们发现,有的业务需要能够写 PHP 脚本,e.g

    由于这类情况较多,官方插件已经默认不再拦截写 PHP/JSP 等脚本文件的操作。如果你没有这样的业务,可以在管理后台定位到 系统设置 -> 防护设置 -> 任意文件写入,并将 拦截所有 php/jsp 等脚本文件的写入操作 改为拦截攻击或者记录日志即可。

    我使用 WebShell 查看了一些系统目录,OpenRASP 不会拦截?{#case-dir}

    理论上,web 应用不应该访问 webroot 之外的文件。但在实际情况中,我们发现了很多例外:

    1. 某OA厂商反馈,他们的 tomcat 应用会读取 ../../../../license.dat,会造成误报

    2. PHP Larvael 框架,需要包含 webroot 同级目录的框架文件

    为了兼容这些情况,我们在 directory_outsideWebroot、include_outsideWebroot 等几个算法里都增加了判断,只有当请求参数里包含跨目录,且跳出了 webroot,我们才会判定为漏洞,比如:

    当然,如果你想快速解决这个问题,可以通过增加文件目录探针来解决。即定位到 forcefulBrowsing,修改探针列表:

    当应用访问了这些敏感文件或者目录,我们就会打印报警或者拦截请求。

    我的SQL语句里包含 chr(10) 调用,导致被拦截

    在SQL注入阶段,自动化利用工具通常会大量使用 chr 函数来实现盲注攻击。因此,OpenRASP对SQL语句进行了检查,默认情况下如果 chr 函数调用超过5次,就会判定为攻击。

    若要关闭这个检测算法,请打开官方插件,定位到如下内容:

    删除 chr 这一行后,重新在后台上传并下推插件即可。

    我在使用 phpMyAdmin 的时候,操作被 OpenRASP 拦截

    URL白名单是一个比较好的解决方式,目前可以通过修改检测插件的方式来实现。请参考 管理后台 - 添加白名单 进行配置。

    在某些情况下,你还需要重启PHP服务器生效。

    我在应用内部,使用 ../../ 读取web目录外面的文件,OpenRASP不会拦截?

    有一些OA厂商,在Windows下面会使用类似 ../../../license/license.dat 来读取文件,所以单纯看应用是否用 ../ 来读取其他目录的文件,是会产生误报的。所以我们默认关闭了 readFile_outsideWebroot 算法。

    如果你没有这样的需求,可以打开这个算法。

    支付回调接口,测试环境下SSRF误报?

    SSRF 常见的特征为,访问的URL来自用户输入,且域名指向内网地址。比如,

    按照这个思路,我们实现了 ssrf_intranet 检测算法。但是在某些测试环境下,这个算法会产生误报。

    1. 支付类的接口,当支付完成,通常会调用回调接口以通知支付是否成功。在测试环境,回调接口通常是内网地址,就造成了 ssrf_intranet 算法的误报。当然,线上的回调接口都是公网地址,不会有这个问题。

    OpenRASP 支持XSS检测吗?

    支持,是通过检查页面结构是否被用户输入所改变来实现的。

    其他参考

    官方插件无法拦截攻击,我应该如何调试

    有的时候,你会发现官方插件无法拦截攻击,你可以参考 999-event-logger.js 这个插件,将插件收到的内容打印出来,并观察官方插件的检测算法是不是不够完善?

    有问题请到QQ群里反馈,我们会尽快解决。

    wp_config.php    - wordpress 安装时需要写配置文件,如果是安装好的可忽略
    201704_cplog.php - discuz 错误日志,经常更新
    runtime/cache/   - thinkphp 框架页面缓存
    ...
    GET /download.php?file=./../..///././../../etc/resolv.conf
    var forcefulBrowsing = {
        ...
    
        // 目录探针 - webshell 查看频次最高的目录
        unwantedDirectory: [
    
        ],
    
        // 文件探针 - webshell 查看频次最高的文件
        absolutePaths: [
    
        ]
    
        ...
    }
            function_count: {
                chr:              5,
                char:             5
            }
    GET /ssrf.php?url=http://test.baidu.com

    IAST 扫描器

    背景

    IAST(交互式扫描)技术是一种实时动态交互的漏洞检测技术,通过在服务端部署agent程序,收集、监控Web应用程序运行时函数执行、数据传输,并与扫描器端进行实时交互,高效、准确的识别安全缺陷及漏洞。目前OpenRASP项目已实现相当于IAST agent端的OpenRASP agent,在此基础上引入一个扫描端,即可实现一个完整的IAST扫描工具。

    系统架构

    灰盒扫描工具采用Python3实现,数据库采用MySQL,通讯采用HTTP+JSON的方式。整体架构图如下: 工具分为扫描器端和agent端,Agent端用于收集web应用的运行信息,扫描器端用于处理插件产生的请求信息,并完成整个IAST扫描逻辑

    agent端{#iast-structure-agent}

    由一个单独的OpenRASP插件构成,用于提取http请求中hook点产生的信息,并通过HTTP协议以JSON形式发送至扫描器端。

    扫描器端{#iast-structure-scanner}

    该部分是一个独立运行的扫描工具,借助从OpenRASP插件部分获取的信息完成扫描任务。

    • 功能设计和模块划分

      扫描模块包括三个模块:预处理模块(Preprocessor)、扫描模块(Scanner)、监控模块(Monitor)

      预处理模块即图中HTTPServer部分,用于接收agent插件的http请求,处理、存储、分发http请求信息

      扫描模块用于运行扫描插件,执行漏洞扫描逻辑

      监控模块用于定期获取其他模块的运行时信息,调整参数,提供控制台的HTTP服务等

    • 运行流程示例

      一个典型扫描流程,以SQL注入的扫描过程为例:

    插件开发

    获取代码

    在安装了python3.7的环境中可以直接运行IAST

    运行参数与pip安装相同

    扫描插件

    所有扫描插件均位于plugin/scanner目录下,所有扩展名为.py的文件都会在启动扫描器时被加载,ScanPluginBase.py为插件基础类,提供编写插件所需的一系列接口,具体参考

    这里以编写一个简单的sql注入fuzz插件为例,介绍插件的编写方法:

    首先在plugin/scanner目录下新建一个new_plugin.py文件,粘贴以下内容:

    在plugin_info中填写插件基本信息:

    实现mutant函数,生成扫描向量

    每个被发送并获取结果的请求序列都会回调check函数,在check函数中来实现漏洞判定:

    如果自行实现检测函数,需要在检测到漏洞时,使用set_vuln_hook标记有漏洞的hook点信息:

    需要注意的是,扫描模块是基于asyncio实现的异步扫描,每个插件会以一个coroutine的形式运行,因此应避免在插件中使用同步的io操作以免影响扫描性能。在进行异常捕获时,如果要捕获全部异常,应单独处理asyncio.CancelledError异常,以免扫描任务无法被终止:

    去重插件

    所有扫描插件均位于plugin/deduplicate目录下,IAST启动时会加载core/config.py中指定的去重插件,去重插件是为了避免同一个请求被反复扫描,应当根据扫描目标的url结构、参数等特性来编写,DedupPluginBase.py为插件基础类,提供编写插件所需的一系列接口,具体参考

    • 编写一个去重插件

      在plugin/deduplicate目录下新建一个new_plugin.py文件,写入以下内容:

      去重插件只需要实现一个get_hash方法即可,该方法传入当前待去重请求对应的raspResult类的实例,返回一个hash字符串,返回hash相同的请求会被视为重复请求,这里直接调用了默认的get_hash_default方法,其具体实现如下:

      注意:如果插件运行中抛出异常,会自动调用get_hash_default函数生成默认的hash

    Java 版本

    简要说明

    java 版本使用 javaagent 机制来实现。在服务器启动时,可动态的修改Java字节码,对敏感操作的函数进行挂钩,比如:

    • 数据库操作

    • 文件读取、写入操作

    • 命令执行

    • ...

    当服务器发生攻击,就会触发这些Hook点,此时RASP agent就可以获取到函数的参数,比如要读取的文件名、要执行的命令等等。

    启动流程

    1. 启动时首先会进入 javaagent 的 premain 函数,该函数会在 main 函数之前预先执行,

    2. 当去 hook 像 java.io.File 这样由 BootstrapClassLoader 加载的类的时候,无法从该类调用非 BootstrapClassLoader 加载的类中的接口,所以 agent.jar 会先将自己添加到 BootstrapClassLoader 的ClassPath下,这样 hook 由 BootstrapClassLoader 加载的类的时候就能够成功调用到 agent.jar 中的检测入口

    Hook Class 流程

    1. 因为启动时候进行了插桩操作,当有类被 ClassLoader 加载时候,所以会把该类的字节码先交给自定义的 Transformer 处理

    2. 自定义 Transformer 会判断该类是否为需要 hook 的类,如果是会将该类交给 javassist 字节码处理框架进行处理,

    3. javassist 框架会将类的字节码依照事件驱动模型逐步解析每个方法,当触发了我们需要 hook 的方法,我们会在方法的开头或者结尾插入进入检测函数的字节码

    4. 把 hook 好的字节码返回给 transformer 从而载入虚拟机

    启动时架构如下图所示:

    请求处理流程

    我们以 tomcat + JDBC + MySQL 为例,简单说明下请求处理的流程

    1. 服务器收到一个请求,从而进入了服务器的请求 hook 点(该 hook 点每个服务器不一样,具体参照源码),该 hook 点标注当前线程为请求线程,开启当前线程的检测开关并把请求对象和响应对象进行缓存,以便后面使用

    2. 服务器发起SQL查询

    3. 进入 SQLStatementHook 点,我们挂钩了 execute、executeUpdate、executeQuery 等方法,从该方法进入检测流程如下:

      • 判断当前线程是否为请求线程(第一步标记的),如果是继续下面检测

    OpenRASP 中JS引擎执行架构如下图所示:

    基线检测

    我们以 tomcat 启动为例,说明基线检测流程

    1. 进入了基线检测关键函数(tomcat 启动函数)

    2. 进入本地基线检测插件(注:基线检测不进入js插件检测),检测当前环境的关键参数(http-only是否开启,是否为root启动等)

    3. 根据检测结果决定是否拦截,不拦截的情况下只打印日志到 logs/policy_alarm.log

    检测架构如下图所示:

    管理后台

    业务模型

    云控后台为了将 RASP Agent 分组,引入 APP 的概念,每个 APP 代表一个业务线,每个 APP 有独立的 Secret 用于提供认证,每个 APP 可以管理多个 RASP Agent 的配置和插件。

    技术架构

    目前,Agent 管理后台采用的是 Go 语言编写,数据库采用的是 MongoDB + Elasticsearch,通讯采用 HTTP/HTTPS + JSON 定时通讯的方式。 整体的架构图如下所示:

    PHP 版本

    简要说明

    关于PHP扩展开发,可参考 。

    以 cli SAPI 为例,其单个请求生命周期如下图所示:

    OpenRASP 核心原理为:在 MINIT 阶段,替换全局compiler_globals的function_table与class_table中特定 PHP_FUNCTION 对应的函数指针(封装原有handler,增加前置、后置处理),由此实现对敏感函数的挂钩。通过敏感函数参数结合请求信息判断是否存在攻击行为,进而采取拦截或者放行操作。

    从源代码编译

    本章节讲解如何编译 OpenRASP,具体内容请参考子章节。

    释放 log4j 日志配置文件,如果存在则跳过
  • 根据 openrasp.yml 文件初始化相应配置项

  • 初始化 JS 插件模块

    • JS 上下文类初始化

    • 插件文件初始化

  • 初始化字节码转换模块

    • 给 load class 操作进行插桩操作,当类加载的时候会先进入 agent 进行处理

    • 对于在初始化前已加载的类执行 retransform 处理,e.g FileInputStream

  • 输出启动成功日志,开启全局 Hook 开关(启动阶段为关闭状态)

    • 若启动过程中发生错误,记录错误日志

  • 给 openrasp.yml 配置文件和 js 插件目录以及 assets 目录增加文件监控,以便文件内容更改的时候不需要重启就能够实时生效

  • 采集 connection_id(这个字段仅JDBC支持)、SQL 语句以及数据库类型 等信息

  • 构建参数信息,调用本地插件和 JS 插件进行安全检测,JS 插件由 Rhino 引擎执行,Rhino 引擎执行是 mozilla 为 java 提供的 JavaScript引擎,该引擎会将 JS 代码编译为 java 的 class 字节码在 JVM 中运行,Rhino 引擎文档

  • 根据插件的执行结果决定是拦截请求、放行还是仅打印日志

  • 进入 SQLResultSetHook 点,我们挂钩了 resultSet.next 方法

    • 调用本地插件检查是否发生拖库行为,默认策略为一次查询结果超过500条就报警

  • 若决定拦截攻击

    • 输出报警日志到 logs/alarm.log

    • 如果header还没有发出,默认使用 302 跳转到拦截页面

    • 如果body还没有发出,则重置未发送的body

    • 输出自定义拦截页面跳转js脚本

      • </script><script>location.href='.../?request_id=xxx'</script>

  • javaagent参考文档
    javassist
    images/startup.png
    images/js.png
    images/check.png
    启动流程

    OpenRASP 采用模块化的结构,按照初始化顺序,启动流程如下:

    1. 初始化OpenRASP所需全局变量

    2. 注册INI配置条目,通过ini配置文件初始化全局配置

    3. 日志模块,记录报警、插件、基线等日志,支持FILE/TCP/UDP

    4. V8模块,JS运行环境,负责插件加载与结合运行时上下文的检测能力

    5. HOOK模块,敏感PHP_FUNCTION挂钩执行检测及检测结果处理

    6. INJECT模块,针对特定URL,修改响应内容,注入HTML

    7. 安全基线检查模块,检查敏感ini配置项

    8. 文件监控模块,监控插件目录,实现运行时检测逻辑修改

    下面针对几个主要的模块进行针对性说明:

    日志模块{#log-module}

    日志模块启动流程如下:

    1. 初始化日志模块所需全局变量

    2. 申请共享内存(针对特定SAPI),用于部分日志的进/线程间同步

    3. 获取本机网卡以及主机信息,用于基线日志记录

    V8模块

    我们将 V8 嵌入到 OpenRASP 中作为 JavaScript 插件的执行引擎

    • MINIT 阶段载入所有插件,生成一份 V8 Startup Snapshot

    • 请求处理线程第一次触发检测时,使用 V8 Startup Snapshot 还原此线程独享的 V8 Isolate

    • 每个请求线程在对应的 V8 Isolate 环境上执行检测逻辑

    • 执行检测逻辑前向 V8 Platform 添加超时监控后台任务,超时后中断检测

    • GSHUTDOWN 阶段销毁线程对应 V8 Isolate

    HOOK模块

    HOOK流程包含两类:compiler_globals的handler替换和用户自定义opcode_handler,启动流程如下

    1. 在全局compiler_globals对应的hashtable(function_table和class_table)中查找非禁用函数对应zend_function

    2. 封装原有handler,根据需求增加前置、后置处理

    3. 针对指定opcode(如ZEND_INCLUDE_OR_EVAL)通过zend_set_user_opcode_handler自定义处理逻辑

    文件监控模块

    我们使用经过我们优化增强的 libfswatch 实现了跨平台的文件监控

    • MINIT 阶段初始化 fswatch 实例,并开启后台线程进行目标文件目录监控

    • 目标文件目录发生变化时,根据类型,向支持重载的 SAPI 主线程发送重载信号

    • MSHUTDOWN 阶段停止目标文件目录监控,销毁 fswatch 实例和后台线程

    白名单实现

    经过对比,我们最终选择了 Double Array Trie 算法来匹配白名单,具体实现如下:

    1. 白名单存储。白名单放在共享内存里,当云端下发新的配置,通过读写锁更新

    2. 白名单匹配。使用 Double Array Trie 算法在白名单里寻找匹配的项目,并生成检测类型的 bitmask。当进入检测点,根据 bitmask 来决定是否直接放行。

    3. 内存消耗。每个检测类型最多允许10条白名单,URL长度最大200。最坏情况下,PHP 版本内存 400 KB。

    容器支持

    为了适配百度内部的ORP平台,我们特意实现了扩展进程管理模型,以避免再安装一个独立的agent。

    在扩展初始化阶段,我们会 fork 出三个进程,分别用于异步日志发送、远程管理、进程守护等功能;在 PHP-FPM 或者 apache 退出或者重启时,我们会杀死这些进程。具体请参考我们的代码实现。

    请求处理流程

    以PHP(mysqli) + MySQL为例,简要说明请求处理的流程,即 RINIT - RSHUTDOWN 阶段:

    1. 为新请求计算唯一的request-id,设置response header

    2. 初始化不同logger,收集日志相关请求信息

    3. 连接数据库,触发 mysqli_connect HOOK点:enforce_policy为1时,若用高权限用户连接数据库,记录基线日志,中断当前请求;enforce_policy为0时,仅当成功连接数据库后检查是否为高权限用户,若是记录日基线志,并将连接信息存入共享内存防止其他进/线程重复报警

    4. 数据库语句检测,即mysqli_query HOOK点pre检测,收集查询参数调用V8模块执行检测,具体流程如下:

      1. (待添加)

    5. 慢查询检测。即mysqli_query HOOK点post检测,通过 call_user_function 检测查询结果数目,超过 openrasp.slowquery_min_rows 配置项则报警

    6. RSHUTDOWN阶段:释放请求相关资源,根据 openrasp.inject_urlprefix 配置判断是否注入用户自定义HTML

    Extending and Embedding PHP
    ref: Extending and Embedding PHP
    1、运行扫描器端,初始化所有模块

    2、测试人员发送了一条HTTP请求到web server,产生请求及其对应的HOOK信息被OpenRASP插件获取,发送至http_server

    3、http_server发现请求不是扫描器发出的,对其进行去重后写入数据库

    4、扫描模块从数据库获取一条HOOK信息,下发到所有扫描插件

    5、sql注入扫描插件分析HOOK信息发现用户输入参数拼接进了sql查询,运行对应扫描逻辑

    6、扫描插件生成扫描请求,把原始请求进入query的输入参数替换为单引号

    7、扫描插件在请求头添加用于识别扫描请求的scan_request_id,发送扫描请求给web server

    10、web server处理请求并返回结果,扫描插件获得http response,同时OpenRASP插件获取到请求hook信息,发送至http_server

    11、http_server发现请求是扫描器发出的,将其写入rasp_result_queue队列

    12、扫描模块读取rasp_result_queue队列,将rasp_result传给对应的扫描插件

    13、扫描插件检查收到的hook信息,发现query逻辑被改变,认为存在SQL注入,将漏洞信息写入数据库

    接口文档
    接口文档
    iast-main
    Docker 自动化编译环境

    如果你对 docker、Makefile 很熟悉,也可以使用我们的自动化编译环境 - baidu-security/app-env-docker,编译所有的版本,e.g

    最终生成的文件在 /tmp/ 下面

    Java agent
    PHP agent
    管理后台
    # 使用 JDK6 + maven 3.2.3 编译 Java agent
    make -C src/openrasp-buildenv compile_java
    
    # 使用 CentOS 6 + gcc 4.9 编译 PHP agent 5.3~5.6, 7.0-7.2 等多个版本
    make -C src/openrasp-buildenv compile_php
    
    # 使用 CentOS 6 + go + nodejs 编译管理后台
    make -C src/openrasp-buildenv compile_panel
    
    # 执行上面所有步骤
    make -C src/openrasp-buildenv compile
    git clone https://github.com/baidu-security/openrasp-iast.git
    cd openrasp-iast
    python3 openrasp_iast/main.py start -f
    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    
    # 导入scanner插件基类
    class ScanPlugin(scan_plugin_base.ScanPluginBase):
    
        plugin_info = {
            "name": "name",
            "show_name": "plugin",
            "description": "des"
        }
    
        # 用于生成测试向量
        def mutant(self, rasp_result_ins):
            pass
    	
        # 用于检测测试结果
        def check(self, request_data_list):
            pass
    
    plugin_info = {
        "name": "sql_basic", # 插件文件名去除扩展名.py后的部分
        "show_name": "SQL注入检测插件", # 插件在后台显示的名称
        "description": "基础sql注入漏洞检测插件" # 插件功能描述
    }
    def mutant(self, rasp_result_ins):
        # 首先判断是否需要扫描
        if not rasp_result_ins.has_hook_type("sql"):
            return
    
        payload_list = [("1'openrasp", "1'openrasp"),
                        ("1\"openrasp", "1\"openrasp"),
                        ("`a openrasp", "`a openrasp")]
    
        # 获取所有待测试参数
        request_data_ins = self.new_request_data(rasp_result_ins)
        test_params = self.mutant_helper.get_params_list(request_data_ins, ["get", "post", "json", "headers", "cookies"])
    
        # 生成测试向量的逻辑,返回必须是一个iterable
        for param in test_params:
            # 只测试包含sql类型hook的请求
            if not request_data_ins.is_param_concat_in_hook("sql", param["value"]):
                continue
                # 每个测试点(参数)生成一个payload_seq,防止重复报警,含有相同payload_seq的测试请求仅保留产生的第一个报警
                payload_seq = self.gen_payload_seq()
                for payload in payload_list:
                    # 基于RaspResult类的实例生成测试请求RequestData类的实例
                    request_data_ins = self.new_request_data(rasp_result_ins, payload_seq, payload[1])
                    request_data_ins.set_param(param["type"], param["name"], payload[0])
                    request_data_list = [request_data_ins]
                    # 每次迭代返回的应该是一个由RequestData类的实例组成的list, 该list中的每个RequestData实例都会被作为测试请求依次发送
                    yield request_data_list
    def check(self, request_data_list):
        # 当前插件每个请求序列仅包含1个请求,取[0]
        request_data_ins = request_data_list[0]
        # 获取检测特征和请求结果
        feature = request_data_ins.get_payload_info()["feature"]
        rasp_result_ins = request_data_ins.get_rasp_result()
        # 检测是否触发sql注入,直接使用checker检测
        if self.checker.check_concat_in_hook(rasp_result_ins, "sql" , feature):
    
            # 存在漏洞,返回漏洞描述字符串
            return "sql语句逻辑可被用户输入控制"
        else:
            # 不存在漏洞,返回None
            return None
    for hook_item in rasp_result_ins.get_hook_info():
    	if has_vuln(hook_item):
    		rasp_result_ins.set_vuln_hook(hook_item)
    import asyncio
    
    try:
        # do something...
        except asyncio.CancelledError as e:
            raise e
    	except Exception as e:
            # do something...
    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    
    # 导入去重插件基类
    from plugin.deduplicate import DedupPluginBase
    
    # 插件类必须命名为dedupPlugin,并继承自DedupPluginBase.DedupPluginBase
    class dedupPlugin(DedupPluginBase.DedupPluginBase):
        # 实现get_hash函数,返回hash字符串
        def get_hash(self, rasp_result_ins):
            return self.get_hash_default(rasp_result_ins)
    import hashlib
    
    # 计算urlpath、参数、堆栈等数据的hash,连接后生成结果hash
    def get_hash_default(self, rasp_result_ins):
            path_str = rasp_result_ins.get_path()
            stack_hash = rasp_result_ins.get_all_stack_hash()
            param_keys = "".join(rasp_result_ins.get_parameters().keys())
            query_keys = "".join(rasp_result_ins.get_query_parameters().keys())
            json_struct = rasp_result_ins.get_json_struct()
            contact_str = "".join([path_str, stack_hash, param_keys, json_struct, query_keys]).encode("utf-8")
            return hashlib.md5(contact_str).hexdigest()
    ref: rasp-cloud image

    如上图所示:

    1. 虚线下方为安装了 RASP 的服务器,上方为云控后台,云控后台分为 Agent Server 和 Panel Server,Agent Server 负责和 RASP Agent 通信,Panel Server 负责用户与前端的交互。Agent Server 可以部署多个实例,Panel Server只可以部署一个。

    2. Secrete 认证:RaspAgent和云控后台之间的认证方式采用 appID + secrete私钥 的形式进行认证。

    3. 主机注册:在启动阶段,若 RASP Agent 开启远程管理,每隔 5 分钟尝试向 Agent Server 注册一次,直到成功,注册信息将会存入 MongoDB,用于前端展示。

    4. 定时心跳:每隔 3 分钟 RASP Agent与云端通信一次,心跳时间可配置。发送心跳时,同时提交本地配置的版本号。若有更新版本的配置或者插件,云端会通过心跳返回新的配置和插件。

    5. 报警日志上传:图中绿色箭头为报警日志的上传流向,Agent Server 采集日志有两种可选模式,第一种模式直接将 RASP Agent 上传的日志存入 ES,这种方式在日志量较大的情况下会有日志丢失的情况,第二种是将日志写入文件,然后由 logstash 采集并传入 ES,这种方式较为复杂,但日志不易丢失,不同语言的 RASP 内部日志上传方式如下:

      • PHP 版本每隔 10s 检查是否有新的日志。若上传成功,会记录文件读取偏移量,并将状态文件落地。

      • Java 版本使用 Log4j 内置的缓冲区,默认大小是 128 条。若未发送的日志量超过缓冲区大小,最早的日志会被抛弃。

    6. 插件与配置升级:用户通过 Panel Server 下发配置和插件到 MongoDB,然后由 RASP Agent 通过与 Agent Server 心跳取走新的配置和插件。

    PHP 版本

    PHP 版本

    本文档仅适用于基于 glibc2.12 及以上 的 Linux 或 MacOS

    对于 Linux 系统,我们要求使用 g++ 5 或者更高版本进行编译。为了保证最大兼容性,我们建议你使用和生产环境相同的环境进行编译。

    下面,我们以 CentOS 6 为例,讲解如何编译 OpenRASP PHP 扩展。值得注意的是,CentOS 7 的安装方法、要执行的命令完全一样。

    准备环境

    使用如下命令,安装 g++ 5.3.1 以及 xxd 命令

    如果你使用的是发行版自带的 PHP 软件,你还需要安装对应的头文件

    安装完成后,执行如下命令进入编译环境

    安装高版本 cmake

    编译 openrasp-v8 基础库

    在OpenRASP仓库根目录执行以下命令

    编译 OpenRASP PHP 扩展

    进入源代码目录,执行下面的命令即可;如果你的 PHP 是自己编译的,请使用对应路径的 phpize 命令。

    如果 make 命令没有出错,可以继续执行 make install 安装。也可以将生成的扩展 modules/openrasp.so 复制到其它机器安装。对于扩展的具体安装方法,请参考

    Java 版本

    获取源码

    你可以使用 git 命令,也可以直接在 Github 下载 ZIP 包

    准备环境

    为了保证最大兼容性,我们建议使用 JDK 6 进行编译

    为编译所依赖的JNI模块,需要安装 c++ 编译器和 cmake 生成器

    以 CentOS 为例,使用如下命令,安装 g++ 5.3.1

    安装完成后,执行如下命令进入编译环境

    安装高版本 cmake

    编译 openrasp-v8 基础库

    以 64位 Linux 系统为例,在OpenRASP仓库根目录执行以下命令

    更多平台的编译细节请参考

    • https://github.com/baidu-security/openrasp-v8/blob/master/.travis.yml

    • https://github.com/baidu-security/openrasp-v8/tree/master/.travis

    开始编译

    1. 方案1 - 使用 IDEA Intellij 进行操作

      导入 maven 工程,目录选 agent/java,正常编译即可

    2. 方案2 - 使用 mvn 命令编译

      进入命令行,

      最终生成的 JAR 包在 boot/target 和 engine/target

    常见问题

    1. maven 超时

    如果总是出现超时错误,你可以考虑使用阿里云的镜像。

    [ERROR] Plugin org.apache.maven.plugins:maven-resources-plugin:3.0.2 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-resources-plugin:jar:3.0.2: Could not transfer artifact org.apache.maven.plugins:maven-resources-plugin:pom:3.0.2 from/to central (https://repo.maven.apache.org/maven2): Connect to repo.maven.apache.org:443 [repo.maven.apache.org/151.101.196.215] failed: Operation timed out (Connection timed out) -> [Help 1]

    修改方法是编辑 ~/.m2/settings.xml,并填写如下内容

    2. git-commit-id-plugin 错误

    如果你使用 JDK 1.6 编译,可能会遇到如下错误:

    [ERROR] Plugin pl.project13.maven:git-commit-id-plugin:2.1.5 or one of its dependencies could not be resolved: Failed to read artifact descriptor for pl.project13.maven:git-commit-id-plugin:jar:2.1.5: Could not transfer artifact pl.project13.maven:git-commit-id-plugin:pom:2.1.5 from/to central (https://repo.maven.apache.org/maven2): Received fatal alert: protocol_version -> [Help 1]

    这是一个 https 证书错误,解决方法是替换 maven 仓库地址为 http 版本。可以考虑修改 ~/.m2/settings.xml,并添加如下内容

    3. 缺少 Premain-Class 属性

    如果你使用IDE编译,最终可能出现这样的错误:

    Failed to find Premain-Class manifest attribute in D:\apache-tomcat-7.0.82\rasp\rasp.jar

    这是因为IDE没有修改 META-INF 下面的文件。我们建议你使用 maven 编译,或者直接导入 maven 工程

    Hook 函数列表

    本文档列出了我们挂钩的函数列表

    Java 版本

    攻击检测

    其中,SQL注入检测点为 execute/executeUpdate/executeQuery/executeBatch/executeBatchInternal/addBatch 方法之一,具体请看我们在github的源代码,这里不在赘述

    检查内容
    方法名称

    基线检查

    检查内容
    方法名称

    服务器启动检测点

    用途
    方法名称

    Tomcat/Jetty/JBoss/Resin/WebSphere 通用

    用途
    方法名称

    Resin 服务器

    用途
    方法名称

    Jetty 服务器

    用途
    方法名称

    WebSphere 服务器

    用途
    方法名称

    PHP 版本

    攻击检测

    检查内容
    方法名称

    基线检查

    检查内容
    方法名称

    管理后台

    准备工作

    开发环境

    管理后台基于 和 实现,前端界面使用了 模板。若要编译后台,你需要下载如下软件:

    开发插件

    本节介绍如何开发并发布一个 JavaScript 检测插件。

    开发环境准备

    1. 下载并安装 ,Ubuntu 系统可使用 sudo apt-get install -y nodejs 命令进行安装

    代码调试

    Java 版本

    远程调试

    本文以 Tomcat + IntelliJ 为例,介绍如何通过 JPDA - Java Platform Debugger Architecture

    参数说明

    若要实现检测逻辑,插件需要先注册检测方法,e.g SQL注入检测插件可注册 sql 类型的回调

    具体插件可注册的回调类型 type,以及回调参数 params 的样例如下。另外,所有检测点都可以使用 params.stack 参数,以获取当前堆栈信息。

    数据库查询

    云控后台接口

    接口描述

    ** 请求格式 **:

    请求体采用 json 格式,分页页码从 1 开始计数,分页请求格式如下所示:

    ** 分页参数说明 **:

    参数
    说明

    提交你的代码

    当你改进了 OpenRASP,并打算将代码合并,你可以在 Github 上发起 Pull Request。针对不同的改动,我们需要花费不同的时间来进行复审。所以请尽可能的说明你的改动,和目的。

    检测算法改进

    根据算法用途,通常可分为两类,

    • 线上安全防护使用

    git clone https://github.com/baidu/openrasp.git

    二次开发

    当你需要增加更多的安全检测能力,你可以尝试修改源代码,增加更多的hook点,并为之编写检测插件。

    本章节讲解 OpenRASP 内部的一些实现,以及如何进行二次开发

    PHP 服务器安装
    目录下,aka:
    $openrasp_path/agent/java/boot/target/rasp.jar
    和
    $openrasp_path/agent/java/engine/target/rasp.jar
  • 方案3 - 使用 build-java.sh 生成安装包

    如果你使用 Linux 进行编译,可以执行源代码目录下面的 build-java.sh 进行编译和打包操作。这个脚本会在源代码根目录,生成 rasp-java.tar.gz 和 rasp-java.zip 两个文件

  • Java SE Development Kit 6u45
    apache-maven 3.2.3

    golang >= 1.10

  • nodejs >= 10.6

  • 目前我们只在 Linux 下面进行了测试。Windows 也可以编译,但我们没有测试过,不保证稳定性。软件安装完毕后,请将 go、node、npm 加入到 $PATH 中,方便后面调用。

    获取源代码

    你可以使用 git 下载源代码,也可以直接在 github 页面下载 zip 压缩包,

    全自动编译

    直接执行 build-cloud.sh 即可,最终会在源代码根目录生成 rasp-cloud.tar.gz

    手动编译

    编译前端

    进入 rasp-vue 目录,执行如下步骤编译打包,

    若没有出错,前端的文件将保存 rasp-vue/dist 目录

    编译后台

    编译好前端后,进入 cloud/src/rasp-cloud 目录,执行如下命令安装 beego 工具

    复制前端文件到本地目录,

    之后执行如下命令打包,

    生成的文件为 rasp-cloud.tar.gz

    常见问题

    1. go get 卡住

    如果你的网络存在问题,可以尝试使用国外的代理服务器,e.g

    Vue.js
    Golang
    tabler
    安装插件开发工具 openraspjs:

    编写第一个插件

    检测插件针对应用的行为进行检测,当应用执行数据库查询、文件读写等操作,OpenRASP 引擎就会调用检测插件,并将相关参数一并传递过来。一个最小的SQL检测插件如下所示:

    首先,我们调用 plugin.register 注册了SQL查询的检测函数,并将SQL语句打印到插件日志。其中,

    • params 为检查点提供的参数,如SQL语句、要读取的文件等等

    • context 为请求信息,如请求参数,服务器信息等等

    然后,我们在回调函数里,调用 plugin.log 打印了SQL查询语句

    最后,我们在回调函数里,返回检测结果,即 "放行"

    目前我们支持14个检测点,具体请看 参数说明 文档。

    调用插件接口

    我们在 RASP 类里提供了一些接口,可以直接在插件里调用。比如,你可以调用 RASP.sql_tokenize 将SQL语句转化为 token:

    详细 JS API 说明请看 接口说明 文档。

    测试检测插件

    现在,我们已经完成了检测插件,下一步是进行测试。测试有两种方法:

    1. 参考 单元测试,编写JSON测试用例并使用 openraspjs 进行测试

    2. 参考 安装插件,将插件放到安装了 OpenRASP 的应用服务器进行测试

    若你是初次接触插件开发,我们推荐使用第二种方式,即使用 OpenRASP 单机版调试。具体调试方法请参考上述文档,这里不再赘述。

    拦截危险操作

    现在,我们已经能够编写检测插件,并在客户端运行。接下来就是拦截攻击了,在回调函数里,将返回的 action 字段改为 block 即可拦截请求。比如,当SQL语句包含union注入特征,我们想拦截整个请求的话,可以这样写:

    在官方插件里,实际的检测算法要复杂的很多,有兴趣可以参考 official.js 的实现。如果不想拦截攻击,只是想记录攻击日志,可将 action 字段设置为 log。

    最后, confidence 字段用来标记报警的可信度,官方插件的范围是 90~100,越高报警的可靠性越高。

    注意: 当某个插件拦截了攻击,其他插件将不在被调用。

    FAQ

    1. 插件支持 ES6 语法吗?{#faq-1}

    • 插件环境可能不支持某些最新的 JavaScript 语法,请使用 openrasjs 进行语法检查

    • 插件不能使用与平台相关的全局对象,只能使用 JavaScript 标准内建对象

    • 插件可以像编写 Node.js 程序一样引入其他模块,然后通过 webpack 或 browserify 等工具打包成一个文件,但是注意不能引入与平台相关的模块,例如: Node.js 的 http 模块

    2. 如果检测点没有返回对象,或者返回的对象不合法,会怎么样?{#faq-2}

    • 若检查点没有返回对象,等于 ignore

    • 若检查点返回了对象,但 action 值不存在或者不为 block/log/ignore 之一,等价于 log

    NodeJS
    读取目录

    请求参数

    当应用接受到请求时,插件可以对请求进行拦截。(注意: PHP Agent 1.1 开始才支持)

    这里不会传递任何参数,如果需要获取请求相关信息,请使用 API接口

    读取文件

    注意:

    1. 对于 PHP 服务器,若实际读取文件以 https://、http://、ftp:// 之一开头,将会调用 服务器端 HTTP 请求 检测点,不会触发 读取文件 检测点

    写入文件

    出于性能考虑,OpenRASP 目前只会提供文件名和绝对路径两个参数

    注意:

    1. tomcat 等应用服务器,在部署war包时,暂时不会触发这个回调

    2. 对于NTFS数据流,e.g abc.php::$DATA,插件看到的 path 可能是 abc.php::$DATA,realpath 可能是 c:\inetpub\wwwroot\abc.php

    删除文件

    文件包含操作

    url 可能是协议(file、http等等),也能是相对路径(/abc/、abc.txt)

    支持的文件包含方式如下,

    1. Java - JSTL import 方式

      • 只有 url 里出现了 :// 且不为 / 开头时,我们才会调用插件

    2. PHP - include/require/include_once/require_once 四种方式

      • 当 url 里包含 :// 时,调用插件

      • 如果文件以 .php 或者 .inc 结尾,或者真实路径在 webroot 下面,不会进入插件

      • 其他情况进入插件

    具体参数

    WebDAV 操作

    目前仅支持 MOVE、COPY 两种方法

    文件上传

    目前,OpenRASP 支持 org.apache.commons.fileupload 上传组件(SpringMVC、Struts 底层使用)

    出于性能考虑,OpenRASP 只会提取文件前 4 KB 的内容,若要获取更多字节,请参考配置文档

    文件重命名

    当源是文件,且目标不为文件夹(可以不存在)时才会进入插件

    命令执行

    XML 外部实体引用

    目前,PHP不支持XXE检测

    Struts OGNL 表达式解析

    注意: 为了减少性能影响,仅当表达式长度超过 30 时才会调用插件。可手动 ognl.expression.minlength 选项来进行调整

    RMI 反序列化

    服务器端 HTTP 请求

    支持的请求方式包含如下 (对应 function 字段),

    1. JDK 中的 URL.openConnection 的方式 (url_open_connection)

    2. commons-httpclient 框架请求方式 (commons_http_client)

    3. httpclient 框架请求方式 (http_client)

    4. PHP stream 请求、cURL 请求

    服务器端 HTTP 请求 - 重定向之后

    支持的请求方式包含如下 (对应 function 字段),

    1. JDK 中的 URL.openConnection 的方式 (url_open_connection)

    2. httpclient 框架请求方式 (http_client)

    3. PHP stream 请求、cURL 请求

    代码执行

    目前支持 eval/function 两种函数

    类库加载

    目前仅支持 java System.load() 方式

    响应检查

    说明

    1. Java 下面如果 body 过大,会多次分段调用

    2. 当响应类型包含 image、audio、video 字样,不会进入插件

    3. 该检测点不支持拦截

    参数

    yum install -y centos-release-scl vim-common
    yum install -y devtoolset-4-gcc-c++
    yum install -y php-devel
    scl enable devtoolset-4 bash
    # 下载并解压到 /tmp,避免与已有 cmake 冲突
    curl -L  https://github.com/Kitware/CMake/releases/download/v3.15.3/cmake-3.15.3-Linux-x86_64.tar.gz | tar zx -C /tmp
    
    # 增加临时 PATH
    export PATH=/tmp/cmake-3.15.3-Linux-x86_64/bin:$PATH
    # 更新 git submodule
    git submodule update --init
    
    # 编译 openrasp-v8
    mkdir -p openrasp-v8/build && cd openrasp-v8/build
    cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LANGUAGES=php ..
    make
    # 如果之前编译过,清理下临时文件
    phpize --clean
    
    # 生成 configure 文件
    phpize
    
    # 生成 makefile
    ./configure --with-openrasp-v8=../../openrasp-v8/ --with-gettext --enable-openrasp-remote-manager
    
    # 编译
    make
    yum install -y centos-release-scl
    yum install -y devtoolset-4-gcc-c++
    scl enable devtoolset-4 bash
    # 下载并解压到 /tmp,避免与已有 cmake 冲突
    curl -L  https://github.com/Kitware/CMake/releases/download/v3.15.3/cmake-3.15.3-Linux-x86_64.tar.gz | tar zx -C /tmp
    
    # 增加临时 PATH
    export PATH=/tmp/cmake-3.15.3-Linux-x86_64/bin:$PATH
    # 更新 git submodule
    git submodule update --init
    
    # 编译 openrasp-v8
    mkdir -p openrasp-v8/build64 && cd openrasp-v8/build64
    cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LANGUAGES=java ..
    make
    
    # 复制动态链接库到 resources 目录
    mkdir -p ../java/src/main/resources/natives/linux_64 && cp java/libopenrasp_v8_java.so $_
    
    # 编译 v8-1.0-SNAPSHOT.jar,安装 v8-1.0-SNAPSHOT.jar 到 maven 本地仓库
    cd ../java
    mvn install
    cd <openrasp_path>/agent/java
    mvn versions:use-latest-releases -Dincludes=com.baidu.openrasp:sqlparser
    mvn clean package
    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                       http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <localRepository/>
    <interactiveMode/>
    <usePluginRegistry/>
    <offline/>
    <pluginGroups/>
    <servers/>
    <mirrors>
     <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>central</mirrorOf>
      <name>阿里云公共仓库</name>
      <url>https://maven.aliyun.com/repository/central</url>
     </mirror>
     <mirror>
       <id>repo1</id>
       <mirrorOf>central</mirrorOf>
       <name>central repo</name>
       <url>http://repo1.maven.org/maven2/</url>
     </mirror>
     <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>apache snapshots</mirrorOf>
      <name>阿里云阿帕奇仓库</name>
      <url>https://maven.aliyun.com/repository/apache-snapshots</url>
     </mirror>
    </mirrors>
    <proxies/>
    <activeProfiles/>
    <profiles>
     <profile>
         <repositories>
            <repository>
                 <id>aliyunmaven</id>
                 <name>aliyunmaven</name>
                 <url>https://maven.aliyun.com/repository/public</url>
                 <layout>default</layout>
                 <releases>
                         <enabled>true</enabled>
                 </releases>
                 <snapshots>
                         <enabled>true</enabled>
                 </snapshots>
             </repository>
             <repository>
                 <id>MavenCentral</id>
                 <url>http://repo1.maven.org/maven2/</url>
             </repository>
             <repository>
                 <id>aliyunmavenApache</id>
                 <url>https://maven.aliyun.com/repository/apache-snapshots</url>
             </repository>
         </repositories>
      </profile>
    </profiles>
    </settings>
    <?xml version="1.0"?>
    <settings>
      <mirrors>
        <mirror>
          <id>central-no-ssl</id>
          <name>Central without ssl</name>
          <url>http://repo.maven.apache.org/maven2</url>
          <mirrorOf>central</mirrorOf>
        </mirror>
      </mirrors>
    </settings>
    git clone https://github.com/baidu/openrasp.git
    npm install
    npm run build
    export GOPATH=$(pwd)
    go get -u github.com/beego/bee
    rm -rf dist
    cp -R ../../../rasp-vue/dist .
    export PATH=$PATH:$GOPATH/bin
    bee pack
    export https_proxy=XXXX
    export http_proxy=XXXX
    
    go get -u XXXX
    npm install -g openrasp
    const plugin_version = '2018-1000-1000'
    const plugin_name    = 'test-plugin'
    
    'use strict'
    var plugin  = new RASP(plugin_name)
    
    const clean = {
        action:     'ignore',
        message:    'Looks fine to me',
        confidence: 0
    }
    
    // BEGIN ALGORITHM CONFIG //
    
    var algorithmConfig = {}
    
    // END ALGORITHM CONFIG //
    
    plugin.register('sql', function (params, context) {
        plugin.log('SQL query: ' + params.query)
        return clean
    })
    
    plugin.log('plugin-demo: plugin loaded')
    plugin.register('sql', function (params, context) {
        plugin.log('SQL tokens ', RASP.sql_tokenize(params.query, params.server))
        return clean
    })
    plugin.register('sql', function (params, context) {
        plugin.log('SQL tokens ', RASP.sql_tokenize(params.query, params.server))
        
        if (/union.*select.*from.*information_schema/.test(params.query)) {
            return {
                action:     'block',
                message:    '拦截SQL查询,因为XXX',
                confidence: 90
            }
        }
        
        return clean
    })
    plugin.register('sql', function(params, context) { 
        // 实现你的检测逻辑
    })
    type   = sql
    params = {
        "server": "mysql / oracle / pgsql / mssql / sqlite",
        "query":  "select * from users",
    }
    type   = directory
    params = {
        "path":     "/home/servers/tomcat/webapps/mywar/../../../../../../../../../etc/",
        "realpath": "/etc/",
        "stack":    [
            "java.lang.ProcessBuilder.start",
            "sun.reflect.NativeMethodAccessorImpl.invoke0",
            "sun.reflect.NativeMethodAccessorImpl.invoke",
            "sun.reflect.DelegatingMethodAccessorImpl.invoke",
            ...
        ]
    }
    type   = request
    params = {}
    type   = readFile
    params = {
        "path":     "/home/servers/tomcat/webapps/mywar/../../../../../../../../../etc/hosts",
        "realpath": "/etc/hosts"
    }
    type   = writeFile
    params = {
        "path":     "abc.jsp",
        "realpath": "/home/tomcat/webapps/ROOT/abc.jsp",
        "stack": [
            ...
        ]
    }
    type   = deleteFile
    params = {
        "path":     "/home/servers/tomcat/webapps/mywar/../../../../../../../../../tmp/testfile",
        "realpath": "/tmp/testfile"
    }
    # Java 示例
    type   = include,
    params = {
        url:      "file:///etc/passwd",
        function: "jstl_import",
        realpath: "/etc/passwd"
    }
    
    # PHP 示例
    type   = include,
    params = {
        url:      "/home/webroot/footer/../../../../../../../../../etc/passwd",
        function: "require_once",
        realpath: "/etc/passwd"
    }
    type   = webdav,
    params = {
        "source": "/home/rsync/apache-tomcat-7.0.78/webapps/webdav/1.txt",
        "dest":   "/home/rsync/apache-tomcat-7.0.78/webapps/webdav/1.jsp"
    }
    type   = fileUpload
    params = {
        "name":          "file",
        "filename":      "a.jsp",
        "content":       "<% ... %>",
        "dest_path":     "upload/a.jpg",           # v1.2 加入
        "dest_realpath": "/home/www/upload/a.jpg"  # v1.2 加入
    }
    type   = rename,
    params = {
        "source": "/var/www/html/uploads/hello.txt",
        "dest":   "/var/www/html/uploads/hello.php"
    }
    type   = command,
    params = {
        "stack":   [
            "java.lang.ProcessBuilder.start",
            "sun.reflect.NativeMethodAccessorImpl.invoke0",
            "sun.reflect.NativeMethodAccessorImpl.invoke",
            "sun.reflect.DelegatingMethodAccessorImpl.invoke",
            ...
        ]
        "command": "/bin/sh -c 'whoami; ls; '"
    }
    type   = xxe
    params = {
    	"entity": "file:///etc/passwd"
    }
    type   = ognl
    params = {
    	"expression": "_memberAccess" //ognl表达式
    }
    type   = deserialization
    params = {
    	"clazz": "InvokerTransformer" //被反序列化对象的类型
    }
    type   = ssrf
    params = {
        "url":      "http://0x7f.0x0.0x0.0x1:8080/v1/api/get",  // http 请求的 url
        "hostname": "0x7f.0x0.0x0.0x1"                          // http 请求的 hostname
        "ip":       ["1.1.1.1", "2.2.2.2"]                      // 无法解析则为空;目前只解析 IPv4 地址
        "port":     "8080",                                     // 未提供端口为空。对于http模式是80,https默认是443的情况,如果没指定也是空
        "function": "commons_http_client"
    }
    type   = ssrfRedirect
    params = {
        "url":       "http://0x7f.0x0.0x0.0x1:8080/v1/api/get",  // 原始请求的 URL
        "hostname":  "0x7f.0x0.0x0.0x1"                          // 原始请求的域名
        "ip":        ["1.1.1.1", "2.2.2.2"]                      // 原始请求目标 IP
        "port":      "8080",                                     // 原始请求的端口,未提供端口为空。对于http模式是80,https默认是443的情况,如果没指定也是空
    
        "url2":      "http://127.0.0.1:8080/v1/api/get",         // 重定向后的 URL
        "hostname2": "0x7f.0x0.0x0.0x1"                          // 重定向后的域名
        "ip2":       ["1.1.1.1", "2.2.2.2"]                      // 重定向后目标 IP
        "port2":     "8080",                                     // 重定向后的端口,说明同上
        "function":  "commons_http_client"
    }
    type   = eval
    params = {
        "function": "eval",
        "code":  "gzuncompress(base64_decode(...));"
        "stack": [
            ...
        ]
    }
    type   = loadlibrary
    params = {
        "function": "System.load",
        "path":     "\\8.8.8.8\test.dll",
        "realpath": "xxxx"
    }
    type   = response
    params = {
        "content_type": "text/html",
        "content":      "<h1>xxxx</h1>"
    }

    SSRF

    org.apache.commons.httpclient.URI.parseUriReference()

    org.apache.http.client.methods.HttpRequestBase.setURI()

    com.squareup.okhttp3.HttpUrl.parse(String)

    com.squareup.okhttp.HttpUrl.parse(String)

    sun.net.www.protocol.http.HttpURLConnection.connect()

    反序列化

    java.io.ObjectInputStream.resolveClass

    命令执行

    java.lang.UNIXProcess.<init>

    java.lang.ProcessImpl.<init>

    OGNL 表达式执行

    ognl.OgnlParser.topLevelExpression()

    XXE

    com.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl()

    org.apache.xerces.util.XMLResourceIdentifierImpl的setValues()

    JSTL import

    org.apache.taglibs.standard.tag.common.core.ImportSupport.targetUrl()

    DubboRPC

    com.alibaba.dubbo.rpc.filter.ContextFilter.invoke()

    com.alibaba.dubbo.rpc.filter.GenericFilter.invoke()

    SQL 注入

    com.mysql.jdbc.StatementImpl

    com.mysql.jdbc.PreparedStatement

    com.mysql.cj.jdbc.PreparedStatement

    org.sqlite.Stmt

    org.sqlite.PrepStmt

    org.sqlite.jdbc3.JDBC3Statement

    org.sqlite.jdbc3.JDBC3PreparedStatement

    oracle.jdbc.driver.OracleStatement

    oracle.jdbc.driver.OraclePreparedStatement

    com.microsoft.sqlserver.jdbc.SQLServerStatement

    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement

    org.postgresql.jdbc.PgStatement

    org.postgresql.jdbc1.AbstractJdbc1Statement

    org.postgresql.jdbc2.AbstractJdbc2Statement

    org.postgresql.jdbc3.AbstractJdbc3Statement

    org.postgresql.jdbc3g.AbstractJdbc3gStatement

    org.postgresql.jdbc4.AbstractJdbc4Statement

    com.ibm.db2.jcc.am

    com.ibm.db2.jcc.am.Connection

    com.ibm.db2.jcc.DB2Driver.connect()

    org.eclipse.core.launcher.Main.run()

    com.caucho.server.http.ServletInputStreamImpl.read(int)

    com.caucho.server.http.ServletInputStreamImpl.read(byte[],int ,int)

    HTML注入

    com.caucho.server.connection.AbstractHttpResponse.finish()

    com.caucho.server.connection.AbstractHttpResponse.finishInvocation()

    com.caucho.server.http.AbstractHttpResponse.finish()

    com.caucho.server.http.AbstractHttpResponse.finishInvocation()

    命令执行(webshell)

    目录遍历

    XSS(echo)

    文件读取

    文件写入

    文件写入(webshell)

    文件拷贝

    文件移动

    文件上传

    文件包含

    文件运行(webshell)

    SQL注入

    SSRF

    文件上传

    org.apache.commons.fileupload.disk.DiskFileItem.setHeaders()

    org.apache.commons.fileupload.FileUploadBase.parseRequest()

    文件读取

    java.io.FileInputStream(File file)

    文件写入

    java.io.FileOutputStream()

    java.io.FileOutputStream(String name, boolean append)

    文件重命名

    java.io.File.renameTo()

    文件遍历

    数据库连接账号

    com.mysql.jdbc.NonRegisteringDriver.connect()

    com.mysql.cj.jdbc.NonRegisteringDriver.connect()

    org.sqlite.JDBC.connect()

    com.microsoft.sqlserver.jdbc.SQLServerDriver.connect()

    org.postgresql.Driver.connect()

    oracle.jdbc.driver.OracleDriver.connect()

    Tomcat

    org.apache.catalina.startup.Catalina.start()

    Jetty

    org.eclipse.jetty.server.Server.doStart()

    JBoss 4

    org.jboss.system.server.ServerImpl.start()

    JBoss 5

    org.jboss.bootstrap.AbstractServerImpl.start()

    JBoss 6

    org.jboss.bootstrap.impl.base.server.AbstractServer.start()

    Resin

    com.caucho.server.resin.Resin.initMain()

    preRequest

    apache.catalina.connector.CoyoteAdapter.service()

    request

    apache.catalina.core.ApplicationFilterChain.doFilter()

    缓存body

    org.apache.catalina.connector.InputBuffer.readByte(int)

    org.apache.catalina.connector.InputBuffer.read(byte[],int ,int)

    HTML 注入

    org.apache.catalina.connector.OutputBuffer.close()

    preRequest

    com.caucho.server.http.HttpRequest.handleRequest()

    com.caucho.server.http.HttpRequest.handleResume()

    request

    com.caucho.server.dispatch.ServletInvocation.service()

    com.caucho.server.dispatch.ServletInvocation.doResume()

    缓存body

    com.caucho.server.connection.ServletInputStreamImpl.read(int)

    com.caucho.server.connection.ServletInputStreamImpl.read(byte[],int ,int)

    preRequest

    org.eclipse.jetty.server.Server.handle()

    request

    org.eclipse.jetty.server.handler.HandlerWrapper.handle()

    缓存body

    org.eclipse.jetty.server.HttpInput.read(int)

    org.eclipse.jetty.server.HttpInput.read(byte[],int ,int)

    HTML注入

    org.eclipse.jetty.server.HttpOutput.close()

    preRequest

    com.ibm.ws.webcontainer.WebContainer.handleRequest()

    request

    com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters()

    缓存body

    com.ibm.ws.webcontainer.srt.http.HttpInputStream.read(int)

    com.ibm.ws.webcontainer.srt.http.HttpInputStream.read(byte[],int ,int)

    HTML注入

    com.ibm.ws.webcontainer.srt.SRTServletResponse.finish()

    webshell callable

    array_walk

    array_map

    array_filter

    ReflectionFunction::__construct

    命令执行

    passthru

    system

    数据库连接账号

    mysql_connect (仅PHP5)

    mysql_pconnect (仅PHP5)

    mysqli::__construct

    mysqli::connect

    mysqli_connect

    mysqli::real_connect

    java.io.File.list()

    WebSphere

    协议调试 OpenRASP 源代码。整个流程涉及如下两个步骤:
    1. 修改 Tomcat 启动参数,开启远程调试

    2. 配置IDE,连接Tomcat远程调试

    1. 配置 tomcat 服务器

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

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

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

    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 标签页中,配置 Host,Port以及 源码路径,并点击确认保存。

    server标签配置

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

    connect success

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

    断点调试
    断点调试

    已知问题

    1. IntelliJ 断点不生效

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

    断点调试

    2. 在 Intellij 里看不到 OpenRASP 启动信息?{#faq-2}

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

    3. 如何定位 OpenRASP 问题?{#faq-3}

    某支付客户反馈,在 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 点调试日志

    对于单机版,需要编辑 openrasp.yaml 文件,将 debug_level 设置为 1 并重启服务器。

    对于开启管理后台的版本,直接在管理后台修改调试级别即可,设置会在一个心跳周期内生效(默认90s)。

    之后每当服务器收到请求,我们就会在 rasp/logs/rasp/rasp.log 里打印这样的日志,

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

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

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

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

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

    PHP 版本

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

    其他内容不再赘述

    perpage

    状态描述

    data

    具体请求参数

    ** 响应格式 **:

    响应采用 json 格式,示例如下:

    ** 参数说明**:

    参数
    说明

    page

    当前页码

    perpage

    当前每页数量

    total

    数据共有多少条

    total_page

    数据共有多少页

    status

    响应状态码,0 代表成功,非 0 代表有异常

    description

    请求结果描述,如果 status 为 0 则为 ok,否则为异常信息

    ** 接口类型 **:接口分为两类,一类是为前端服务的前端接口,另一类是为 RASP Agent 服务的 Agent 接口,具体接口格式如下文所示。

    Ping 接口

    ** 描述 **:用来测试后台联通性的通用接口

    ** 请求方法 **:GET,POST

    ** 路径 **:v1/ping

    ** 请求体 **:空

    ** 返回结果 **:

    Version 接口

    ** 描述 **:用来获取当前RASP云控后台的版本号

    ** 请求方法 **:POST

    ** 路径 **:v1/version

    ** 请求体 **:空

    ** 返回结果 **:

    前端接口

    认证方式

    认证方式分为两种:

    1. 登陆之后获取 cookie 认证,cookie字段为 RASP_AUTH_ID,cookie有效期默认 7 天。

    2. 通过在请求头中添加静态 token 进行认证,请求头字段为 X-OpenRASP-Token,具体的 token 管理方式,参照下文 token 管理接口。

    登录登出接口

    登录接口

    ** 描述 **:登录接口,初始管理后台用户名:openrasp ,密码:admin@123,登陆成功设置登录 cookie

    ** 请求方法 **:POST

    ** 路径 **:v1/user/login

    ** 请求体 **:

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    username

    String

    是

    用户名

    password

    String

    是

    密码

    ** 返回结果 **:

    登出接口

    ** 描述 **: 退出登录状态,清空 cookie

    ** 请求方法 **:GET

    ** 路径 **:v1/user/logout

    ** 请求体 **:无

    ** 返回结果 **:

    获取是否登录

    ** 描述 **: 获取当前是否为登录状态

    ** 请求方法 **:GET

    ** 路径 **:v1/user/islogin

    ** 请求体 **:无

    ** 返回结果 **:

    默认密码判断接口

    ** 描述 **: 判断当前用户密码是否为默认密码,用于给前端提供是否需要修改密码的提醒

    ** 请求方法 **:GET,POST

    ** 路径 **:v1/user/default

    ** 请求体 **:无

    ** 返回结果 **:

    参数
    说明

    is_default

    是否为默认密码,如果是则为 true,否则为false

    更改密码接口

    ** 描述 **:更改管理员密码,密码长度 8~50 个字节,必须同时包含字母和数组

    ** 请求方法 **:POST

    ** 路径 **:v1/user/update

    ** 请求体 **:

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    old_password

    String

    是

    旧密码

    new_password

    String

    是

    新密码

    ** 返回结果 **:

    插件管理接口

    上传插件

    ** 描述** :上传文件为 .js 结尾的插件文件,插件版本在文件第一行,插件名称在插件的第二行

    ** 请求方法 **:POST

    ** 路径 **:v1/api/plugin?app_id=c593342c72eb78fc8e7393d0a87b8f3fc54dfbec

    ** 请求体 **: form data 格式的文件参数,参数名称 plugin

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    plugin

    file

    是

    插件文件,form-data 格式

    ** 返回结果 **:

    参数
    说明

    id

    插件唯一标识

    app_id

    插件所属的 APP

    upload_time

    上传时间的时间戳

    version

    插件版本

    name

    插件名称

    md5

    插件内容校验和

    下载插件

    ** 描述 ** :根据插件 id 下载插件

    ** 请求方法 **:GET

    ** 路径 **:v1/api/plugin/download?id=47af9da31ec3f233f35a25776f5e06086ebf239ff60a021ada4750b65640d0d24b9ae382

    ** 请求体 **: 无

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    id

    String

    是

    插件唯一标识

    ** 返回结果 **:插件文件,文件名称为 {NAME}-{VERSION}.js,{VERSION} 为插件版本,{NAME}为插件名称

    获取插件基本信息

    ** 描述 ** :根据插件 id 获取插件

    ** 请求方法 **:POST

    ** 路径 **:v1/api/plugin/get

    ** 请求体 **:

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    id

    String

    是

    插件唯一标识

    ** 返回结果 **:

    参数
    说明

    id

    插件唯一标识

    app_id

    插件所属的 APP

    upload_time

    上传时间的时间戳

    version

    插件版本

    name

    插件名称

    md5

    插件内容校验和

    下发算法配置

    ** 描述 ** :给插件下发插件算法开关配置,下发的算法配置会合并到插件中

    ** 请求方法 **:POST

    ** 路径 **:v1/api/plugin/algorithm/config

    ** 请求体 **:

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    id

    String

    是

    插件唯一标识

    config

    object

    是

    算法配置

    ** 返回结果 **:

    恢复插件默认算法配置

    ** 描述 ** :根据插件 id 恢复插件最开始的默认算法配置

    ** 请求方法 **:POST

    ** 路径 **:v1/api/plugin/algorithm/restore

    ** 请求体 **:

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    id

    String

    是

    插件唯一标识

    ** 返回结果 **:

    删除插件

    ** 描述 ** :根据插件 id 删除插件,无法删除被选中的插件

    ** 请求方法 **:POST

    ** 路径 **:v1/api/plugin/delete

    ** 请求体 **:

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    id

    String

    是

    插件唯一标识

    ** 返回结果 **:

    App管理接口

    新增 APP

    ** 描述 ** :新增一个 APP

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app

    ** 请求体 **:

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    name

    String

    是

    APP 名称,名称不能重复

    language

    String

    是

    APP 业务语言

    description

    String

    否

    ** 返回结果 **:

    参数
    说明

    id

    APP 唯一标识

    name

    APP 名称

    description

    APP 描述信息

    language

    APP 使用的编程语言

    create_time

    APP 创建时间

    secret

    APP 秘钥,用于和 RASP 通信认证

    删除 APP

    ** 描述 ** :删除一个 APP ,同时删除该 APP 下所有的 RASP 和插件,当仅剩一个 APP 无法删除,至少保留一个 APP,无法删除还存在在线 RASP 的 APP

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/delete

    ** 请求体 **:

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    id

    String

    是

    APP 唯一标识

    ** 返回结果 **:

    获取 App

    ** 描述 ** :获取所有App,或某一个 id 的 app,如果参数中有 id 参数,则返回相应id的 app,如果没有 id 参数,则需要 page 和 perpage 参数来做分页,返回相应数量的 APP 数组

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/get

    ** 请求体 **:

    获取相应 id APP

    按照APP名称检索

    获取一定数量 APP

    ** 参数说明**:

    参数
    参数类型
    必须
    说明

    app_id

    String

    否

    APP 唯一标识,有该参数则返回相应 id 的 APP

    name

    String

    否

    APP 名称,支持模糊查询

    page

    int

    否

    ** 返回结果 **:

    返回相应 id APP

    返回一定数量 APP

    下发通用配置

    描述:给 app 下发 rasp 通用配置

    请求方法:POST

    路径:v1/api/app/general/config

    请求体:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    config

    object

    是

    通用配置完整内容

    ** 返回结果 **:返回更新之后的完整 APP 信息

    下发白名单配置

    ** 描述 **:给 app 下发 rasp 白名单配置

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/whitelist/config

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    config

    object

    是

    白名单配置完整内容

    ** 返回结果 **:返回更新之后的完整 APP 信息

    下发报警配置

    ** 描述 **:给 app 下发报警配置

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/alarm/config

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    attack_type_alarm_conf

    Object

    否

    如果没有该配置,那么将会按照所有攻击类型会触发所有的报警方式,配置中的 key 是攻击类型,value 是该类型会触发的报警方式的列表,目前报警方式包括 ding,http,email

    email_alarm_conf

    Object

    否

    ** 返回结果 **:返回更新之后的完整 APP 信息

    APP 配置接口

    ** 描述 **:下发 APP 配置,用于配置 APP 名称,语言和描述信息

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/config

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    name

    String

    是

    APP 名称

    language

    String

    是

    ** 返回结果 **:返回更新之后的完整 APP 信息

    获取 APP 下的所有插件

    ** 描述 **:根据 APP ID 获取所有的插件内容

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/plugin/get

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    page

    int

    是

    页码

    perpage

    int

    是

    ** 返回结果 **:

    获取 APP 下发的插件

    ** 描述 **:获取 APP 当前选中的插件,该插件会下发给 APP 下的 RASP

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/plugin/select/get

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    ** 返回结果 **:

    设置 APP 下发的插件

    ** 描述 **:设置 APP 下发给 RASP 的插件

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/plugin/select

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    plugin_id

    String

    是

    插件唯一标识

    ** 返回结果 **:

    导出APP信息{#export-app}

    ** 描述 **:导出所有 APP 的ID、Secret等信息

    ** 请求方法 **:GET

    ** 路径 **:v1/api/app/export

    ** 返回结果 **:包含app信息的 json 文件

    测试邮件报警

    ** 描述 **:测试邮件报警

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/email/test

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    ** 返回结果 **:

    测试钉钉报警

    ** 描述 **:测试钉钉报警

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/ding/test

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    ** 返回结果 **:

    测试 HTTP 报警

    ** 描述 **:测试 HTTP 报警

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/http/test

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    ** 返回结果 **:

    测试 Kafka 报警

    ** 描述 **:测试 Kafka 报警

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/kafka/test

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    ** 返回结果 **:

    获取插件更新信息

    ** 描述 **:如果当前插件是 official.js 的话,判断当前下发插件是否为最新官方插件。如果不是(如 iast.js),返回当前下发插件和最新插件的版本信息

    ** 请求方法 **:POST

    ** 路径 **:v1/api/app/plugin/latest

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    ** 返回结果 **:

    参数
    说明

    is_latest

    当前下发插件是否为最新版本

    selected_version

    当前下发的插件版本

    latest_version

    最新插件版本

    RASP管理接口

    搜索 RASP

    ** 描述 **:按照条件搜索 RASP

    ** 请求方法 **:POST

    ** 路径 **:v1/api/rasp/search

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    id

    String

    否

    RASP 唯一标识

    app_id

    String

    否

    所属的 APP 的 ID

    version

    String

    否

    ** 返回结果 **:

    参数
    说明

    id

    RASP 唯一标识

    app_id

    所属的 APP 的 ID

    version

    RASP 版本

    hostname

    RASP 所在的主机名,该字段支持模糊搜索,并同时搜索 hostname 和 register_ip 字段

    register_ip

    RASP 访问云控后台所使用的 IP 地址

    language

    编程语言

    RASP版本号统计

    ** 描述 **:统计RASP每个版本号下主机个数

    ** 请求方法 **:POST

    ** 路径 **:v1/api/rasp/search/version

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    所属的 APP 的 ID

    version

    String

    否

    指定搜索的版本号

    ** 返回结果 **:

    参数
    说明

    version

    主机版本号

    count

    主机版本号对应的主机个数

    导出 RASP

    ** 描述 **:按条件搜索 rasp,并把搜索结果导出到 csv 文件,app_id 字段为必选,剩余搜索条件为可选

    ** 请求方法 **:GET

    ** 路径 **:v1/api/rasp/csv?app_id=eaGdr22DfthDz51JHF65sd

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    所属的 APP 的 ID

    ** 返回结果 **: csv 文件

    删除 RASP

    ** 描述 **:删除指定条件的 RASP,在线的 rasp 不允许删除,当参数中存在 id,删除指定 id 的 rasp 并忽略其他参数

    ** 请求方法 **:POST

    ** 路径 **:v1/api/rasp/delete

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    id

    String

    否

    RASP 唯一标识

    register_ip

    String

    否

    ** 返回结果 **:

    参数
    说明

    count

    删除 RASP agent 数量

    批量删除 RASP

    ** 描述 **:根据 rasp id 批量删除rasp

    ** 请求方法 **:POST

    ** 路径 **:v1/api/rasp/batch_delete

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    ids

    String Array

    是

    RASP 唯一标识列表

    ** 返回结果 **:

    参数
    说明

    count

    删除 RASP agent 数量

    RASP 备注接口

    ** 描述 **:给指定 id 的 rasp 添加或者修改备注信息

    ** 请求方法 **:POST

    ** 路径 **:v1/api/rasp/describe

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    id

    String

    是

    RASP 唯一标识

    description

    String

    是

    描述信息

    ** 返回结果 **:

    类库信息管理接口{#manage-dependency}

    类库信息聚合{#aggr-attack-time}

    ** 描述 **:按照应用下主机聚合主机的类库信息

    ** 请求方法 **:POST

    ** 路径 **:v1/api/dependency/aggr

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    所属的 APP 的 ID

    ** 返回结果 **:

    参数
    说明

    timestamp

    类库信息上传时间

    app_id

    所属的APP的ID

    hostname

    主机名称

    id

    类库信息唯一标识

    path

    类库依赖路径

    product

    产品名称

    类库信息聚合{#search-dependency}

    ** 描述 **:查看类库信息的详情

    ** 请求方法 **:POST

    ** 路径 **:v1/api/dependency/search

    ** 请求体 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    tag

    String

    key_word

    String

    否

    ** 返回结果 **:

    参数
    说明

    app_id

    所属的APP的ID

    timestamp

    类库信息上传时间

    hostname

    主机名称

    id

    类库信息唯一标识

    path

    类库依赖路径

    product

    产品名称

    静态Token管理接口

    生成/更新 token

    ** 描述 **:当有 token 参数为更新,否则为新增 token

    ** 请求方法 **:POST

    ** 路径 **:v1/api/token

    ** 请求体 **:

    新增token:

    更新token:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    token

    String

    是

    token 内容

    description

    String

    否

    token 描述

    ** 返回结果 **:

    获取 token

    ** 描述 **:获取一定数量的 token 信息

    ** 请求方法 **:POST

    ** 路径 **:v1/api/token/get

    ** 请求体 **:

    ** 返回结果 **:

    删除token

    ** 描述 **:删除 token

    ** 请求方法 **:POST

    ** 路径 **:v1/api/token/delete

    ** 请求体 **:

    ** 返回结果 **:

    操作日志接口

    搜索操作日志

    ** 描述 **:搜索操作日志

    ** 请求方法 **:POST

    ** 路径 **:v1/api/operation/search

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    data

    String

    是

    所有支持搜索的字段,data 中所有字段皆为可选

    start_time

    int

    是

    操作日志的开始时间,毫秒时间戳

    end_time

    int

    是

    ** 返回结果 **:

    参数
    说明

    id

    操作日志唯一标识

    app_id

    所属的 APP 的 ID

    type_id

    日志类型

    time

    操作时间

    user

    操作人

    content

    操作内容

    服务器管理接口

    获取服务器 url

    ** 描述 **:获取 panel 和 agent 服务器的 url 地址

    ** 请求方法 **:POST

    ** 路径 **:v1/api/server/url/get

    ** 参数 **:无

    ** 返回结果 **:

    参数
    说明

    panel_url

    前端 server url 访问地址

    agent_url

    agent server 访问地址列表

    更改服务器地址

    ** 描述 **:更改 panel 和 agent 服务器的访问地址

    ** 请求方法 **:POST

    ** 路径 **:v1/api/server/url

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    panel_url

    String

    是

    前端 server url 访问地址

    agent_url

    String Array

    否

    agent server 访问地址列表

    ** 返回结果 **:

    清空数据

    ** 描述 **:清空数据库中的攻击事件、基线报警、异常日志、请求数量、崩溃信息

    ** 请求方法 **:POST

    ** 路径 **:v1/api/server/clear_logs

    ** 请求体 **:

    ** 参数说明 **:

    参数
    说明

    app_id

    前端 server url 访问地址

    ** 返回结果 **:

    请求统计接口

    请求统计信息聚合

    ** 描述 **:按照时间聚合 RASP 上传的请求统计数据

    ** 请求方法 **:POST

    ** 路径 **:v1/api/report/dashboard

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    需要聚合的 APP

    start_time

    int

    是

    开始时间

    end_time

    int

    是

    ** 返回结果 **:

    参数
    说明

    start_time

    开始时间

    request_sum

    RASP 处理的请求数量

    报警接口

    为了降低 es 压力,所有报警接口起止时间不能超过 366 天,聚合接口 size 不能超过1024

    按照时间聚合攻击日志

    ** 描述 **:按照时间聚合攻击数据

    ** 请求方法 **:POST

    ** 路径 **:v1/api/log/attack/aggr/time

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    需要聚合的 APP

    start_time

    int

    是

    开始时间

    end_time

    int

    是

    ** 返回结果 **:

    参数
    说明

    data

    聚合数据,第一个元素是 info 数据,第二个是 block 数据

    labels

    聚合的横轴时间标签数组,每个元素都是一个毫秒时间戳

    按照类型聚合攻击日志

    ** 描述 **:按照攻击类型聚合攻击数据

    ** 请求方法 **:POST

    ** 路径 **:v1/api/log/attack/aggr/type

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    需要聚合的 APP

    start_time

    int

    是

    开始时间

    end_time

    int

    是

    ** 返回结果 **:

    参数
    说明

    data

    聚合数据,每个数组代表一种类型,每个数组的第一个元素代表类型名称,第二个元素代表该类型的攻击数量

    按照 UA 聚合攻击日志

    ** 描述 **:按照请求 User-Agent 头聚合攻击数据

    ** 请求方法 **:POST

    ** 路径 **:v1/api/log/attack/aggr/ua

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    需要聚合的 APP

    start_time

    int

    是

    开始时间

    end_time

    int

    是

    ** 返回结果 **:

    参数
    说明

    data

    聚合数据,每个数组代表一种类型,每个数组的第一个元素代表 UA 名称,第二个元素代表该 UA 的攻击数量

    漏洞聚合搜索

    ** 描述 **:按照漏洞聚合攻击数据(不同的栈为不同的漏洞)

    ** 请求方法 **:POST

    ** 路径 **:v1/api/log/attack/aggr/vuln

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    否

    漏洞所属的 APP,如果有该参数,那么统计相应的 app 数据,如果没有,则统计所有的数据

    attack_type

    String Array

    否

    攻击类型可以多选,数组为空则什么都不返回,没有该参数,或者参数为null,则不过滤此参数

    rasp_id

    String

    否

    ** 返回结果 **:

    参数
    说明

    data

    漏洞聚合结果,结果按照每个漏洞的最新的攻击时间排序,每个漏洞展示的内容都是该漏洞最新的一个攻击的内容

    攻击报警搜索

    ** 描述 **:搜索攻击日志,结果结果按照时间降序排序

    ** 请求方法 **:POST

    ** 路径 **:v1/api/log/attack/search

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    否

    所属的 APP,如果有该参数,那么统计相应的 app 数据,如果没有,则统计所有的数据

    attack_type

    String Array

    否

    攻击类型可以多选,数组为空则什么都不返回,没有该参数,或者参数为null,则不过滤此参数

    rasp_id

    String

    否

    ** 返回结果 **:

    参数
    说明

    data

    搜索攻击结果

    崩溃报警搜索{#search-crash-alarm}

    ** 描述 **:搜索崩溃日志,结果结果按照时间降序排序。支持按照主机名称、报警信息和报警时间进行检索

    ** 请求方法 **:POST

    ** 路径 **:v1/api/log/crash/search

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    _id

    String

    否

    崩溃信息ID,用于区分不同的崩溃信息

    app_id

    String

    否

    所属的 APP,如果有该参数,那么统计相应的 app 数据,如果没有,则统计所有的数据

    hostname

    String

    否

    ** 返回结果 **:

    参数
    说明

    data

    搜索基线结果

    基线报警搜索

    ** 描述 **:搜索基线日志,结果结果按照时间降序排序

    ** 请求方法 **:POST

    ** 路径 **:v1/api/log/policy/search

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    否

    所属的 APP,如果有该参数,那么统计相应的 app 数据,如果没有,则统计所有的数据

    policy_id

    int Array

    否

    该字段可以多选,数组为空则什么都不返回,没有该参数,或者参数为null,则不过滤此参数

    rasp_id

    String

    否

    ** 返回结果 **:

    参数
    说明

    data

    搜索基线结果

    异常接口

    搜索异常信息

    ** 描述 **:根据条件搜索异常信息

    ** 请求方法 **:POST

    ** 路径 **:v1/api/log/error/search

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    否

    所属的 APP,如果有该参数,那么统计相应的 app 数据,如果没有,则统计所有的数据

    rasp_id

    String

    否

    攻击所属的 RASP 的 ID

    server_hostname

    String

    否

    ** 返回结果 **:

    参数
    说明

    data

    搜索错误日志结果

    RASP接口

    认证方式

    • 增加 APP ID 请求头: X-OpenRASP-AppID: 9b3554a97673f1f8f5c929310298037a660d3b7a

    • 增加 APP Secret 请求头: X-OpenRASP-AppSecret: 2wMG8K9F71CZyvlWu1CRwf7tVDVW7Ud4gxCY5X4aMzO

    RASP 注册接口

    ** 描述 **:注册 RASP 基本信息,如果有 id 参数,那么为更新相应的 RASP 信息,否则为新增 RASP

    ** 请求方法 **:POST

    ** 路径 **:v1/agent/rasp

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    id

    String

    是

    RASP 唯一标识

    version

    String

    是

    RASP 版本

    hostname

    String

    是

    ** 返回结果 **:

    ** 参数说明 **:

    参数
    说明

    id

    RASP 唯一标识

    app_id

    所属 APP 标识

    version

    RASP 版本

    hostname

    RASP 所在机器的主机名

    register_ip

    RASP 所在机器 IP 地址

    language

    RASP 使用的开发语言

    心跳接口

    ** 描述 **:接受 RASP 向云控后台的定时心跳,如果请求参数中的 md5 和后台指定的插件 md5 不同则判定有新插件,如果配置时间小于云控后台的最后配置时间,判定有新配置,每次更新都是插件和配置的全量更新。

    ** 请求方法 **:POST

    ** 路径 **:v1/agent/heartbeat

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    rasp_id

    String

    是

    RASP 唯一标识

    plugin_md5

    String

    是

    当前 RASP 的插件 MD5

    plugin_version

    String

    是

    ** 返回结果 **:

    ** 参数说明 **:

    参数
    说明

    plugin

    插件内容

    config_time

    本次下发配置的时间

    config

    下发的配置,配置项的详细说明:

    统计上报接口

    ** 描述 **:上传 rasp 统计信息

    ** 请求方法 **:POST

    ** 路径 **:v1/agent/report

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    rasp_id

    String

    是

    RASP 唯一标识

    time

    int

    是

    统计时间,毫秒时间戳

    request_sum

    int

    否

    ** 返回结果 **:

    崩溃上报接口

    ** 描述 **:上传 rasp 奔溃信息

    ** 请求方法 **:POST

    ** 路径 **:v1/agent/crash/report

    ** 请求体 **:

    格式: multipart/form-data

    内容:

    crash_log: hs_err_pid25945.log

    hostname: Mac-xxxx-host

    language: java

    rasp_id: d5ged5g54dr1gdr5d5erg5rdg

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    crash_log

    文件

    是

    崩溃日志

    rasp_id

    String

    是

    RASP 唯一标识,RASP 可以不存在

    language

    String

    否

    ** 返回结果 **:

    上传攻击报警日志

    ** 描述 **:上传 RASP 攻击日志

    ** 请求方法 **:POST

    ** 路径 **:v1/agent/log/attack

    ** 请求体 **:

    ** 参数说明 **:攻击日志数组,包含多条攻击日志,日志字段说明:https://rasp.baidu.com/doc/setup/log/main.html

    ** 返回结果 **:

    参数
    说明

    count

    成功处理的日志数量

    上传类库依赖信息{#upload-dependencies}

    ** 描述 **:根据主机上传类库信息

    ** 请求方法 **:POST

    ** 路径 **:v1/agent/dependency

    ** 请求体 **:

    ** 参数说明 **:

    参数
    参数类型
    必须
    说明

    rasp_id

    String

    是

    所属的 RASP

    product

    String

    是

    产品名称

    version

    String

    是

    ** 返回结果 **:

    上传基线报警日志

    ** 描述 **:基线报警内容,基线报警会根据 "stack_trace,rasp_id, policy_id, policy_param “ 几个字段进行去重操作,这几个字段相同的报警只会出现一次。

    ** 请求方法 **:POST

    ** 路径 **:v1/agent/log/policy

    ** 请求体 **:

    ** 参数说明 **:基线日志数组,包含多条基线日志,极限报警字段说明:https://rasp.baidu.com/doc/setup/log/main.html

    ** 返回结果 **:

    参数
    说明

    count

    成功处理的日志数量

    上传异常日志

    ** 描述 **:上传异常日志

    ** 请求方法 **:POST

    ** 路径 **:v1/agent/log/error

    ** 请求体 **:

    ** 参数说明 **:错误日志数组,包含多条错误日志,字段说明同上文基线报警字段说明。

    ** 返回结果 **:

    参数
    说明

    count

    成功处理的日志数量

    RASP Agent认证接口

    ** 描述 **:用于认证 app id 和 app secrete

    ** 请求方法 **:POST

    ** 路径 **:v1/agent/auth

    ** 请求体 **:空

    ** 返回结果 **:

    扫描器接口

    接口描述{#iast-api-description}

    ** 请求格式 **:

    请求体采用 json 格式,分页页码从 1 开始计数,分页请求格式如下所示:

    ** 参数说明 **:

    参数
    说明

    order

    任务类型。

    host

    扫描目标主机

    ** 响应格式 **:

    响应采用 json 格式,示例如下:

    ** 参数说明 **:

    参数
    说明

    data

    扫描器返回给云控后台的内容

    app_id

    APP 唯一标识

    register

    扫描器状态:0表示扫描器未连接,1表示正在连接中,2表示扫描器连接成功,3表示接收响应异常,4表示扫描器连接超时

    data.status

    错误码

    认证方式{#iast-auth}

    • 增加请求头: Content-Type: application/json

    认证接口{#iast-api-auth}

    ** 描述 **:获取当前云控后台版本号

    ** 请求方法 **:POST

    ** 路径 **:v1/iast/version

    ** 请求体 **:空

    ** 返回结果 **:

    扫描任务类{#scanner-task}

    新建扫描{#new-task}

    ** 描述 **:为扫描器新建扫描任务

    ** 请求方法 **:POST

    ** 路径 **:v1/iast

    ** 请求体 **:

    参数
    参数类型
    必须
    说明

    order

    String

    是

    任务类型。startTask表示新建扫描

    host

    String

    是

    扫描目标主机

    port

    String

    是

    ** 返回结果 **:

    参数
    说明

    data

    扫描器返回给云控后台的内容

    app_id

    APP 唯一标识

    register

    扫描器状态。2表示扫描器连接成功

    data.status

    错误码:2 并发扫描任务达到限制 , 3 目标正在被其他任务扫描

    修改配置{#setconfig-task}

    ** 描述 **:修改目标主机的扫描配置

    ** 请求方法 **:POST

    ** 路径 **:v1/iast

    ** 请求体 **:

    参数
    参数类型
    必须
    说明

    order

    String

    是

    任务类型。setConfig表示修改配置

    host

    String

    是

    扫描目标主机

    port

    String

    是

    ** 返回结果 **:

    参数
    说明

    data.status

    错误码:2 白名单正则不合法, 3 代理协议不为http或https

    获取配置{#getconfig-task}

    ** 描述 **:获取目标主机的扫描配置

    ** 请求方法 **:POST

    ** 路径 **:v1/iast

    ** 请求体 **:

    参数
    参数类型
    必须
    说明

    order

    String

    是

    任务类型。getConfig表示获取配置

    host

    String

    是

    扫描目标主机

    port

    String

    是

    ** 返回结果 **:

    参数
    说明

    scan_plugin_status

    插件开关

    max_concurrent_request

    最大并发请求数

    max_request_interval

    最大请求间隔

    min_request_interval

    最小请求间隔

    app_id

    APP 唯一标识

    终止扫描{#stop-task}

    ** 描述 **:立即终止指定的扫描任务

    ** 请求方法 **:POST

    ** 路径 **:v1/iast

    ** 请求体 **:

    参数
    参数类型
    必须
    说明

    order

    String

    是

    任务类型。getConfig表示获取配置

    scanner_id

    Int

    是

    扫描任务id

    app_id

    String

    是

    ** 返回结果 **:

    参数
    说明

    data.status

    错误码:2 指定的扫描任务不存在,3 终止失败

    扫描数据类{#scanner-data}

    获取所有目标{#getall-task}

    ** 描述 **:获取所有安装rasp agent的主机(agent至少发送过一次http请求结果)

    ** 请求方法 **:POST

    ** 路径 **:v1/iast

    ** 请求体 **:

    参数
    参数类型
    必须
    说明

    app_id

    String

    是

    APP 唯一标识

    order

    String

    是

    指令参数。"getAllTasks"表示获取所有目标

    ** 返回结果 **:

    ** 参数说明 **:

    参数
    说明

    app_id

    APP 唯一标识

    host

    扫描器返回的数据,接口说明详见

    port

    端口号

    total

    该目标下的总url数

    scanned

    该目标下的扫描的url数

    failed

    该目标下扫描失败的url数

    清空扫描任务{#clean-task}

    ** 描述 **:清空目标主机的信息(重置为一个未配置的agent状态),或清空url列表

    ** 请求方法 **:POST

    ** 路径 **:v1/iast

    ** 请求体 **:

    参数
    参数类型
    必须
    说明

    order

    String

    是

    任务类型。cleanTask表示清除任务

    host

    String

    是

    扫描目标主机

    port

    String

    是

    ** 返回结果 **:

    参数
    说明

    data.status

    错误码:2 目标正在被扫描

    page

    页码

    线下安全测试使用

    无论是哪种情况,请说明以下几点:

    1. 当前算法存在哪些问题,你需要解决什么问题?

      • 可以同时提供漏洞测试用例

    2. 新算法误报情况如何,是否会影响服务器性能?

      • 如果性能不符合要求,但是算法被接受,我们会合并代码,但默认在配置里禁用这个功能

      • 对于有特殊应用场景,但不通用的算法,处理方法同上

    增加检测点

    对于检测点的改进,请注意:

    1. 如果是SQL相关的改进

      • 请尽量支持全部数据库 - MSSQL、PGSQL、MySQL、SQLite、DB2

        • 如果不能,我们可以先合并代码,但默认在配置里禁用这个新功能

        • 除特殊情况,只有在全部数据库支持后,我们才能正式说明支持了这个功能

        • 如果你没有系统环境,比如 DB2,我们可以排期开发

      • 可以使用 docker 进行自动化测试,这是我们目前使用的镜像列表

        • microsoft/mssql-server-linux:2017-GA

        • alexeiled/docker-oracle-xe-11g

        • mysql:5

    2. 请提供测试用例,包括漏洞利用方法、正常的请求如何发起

    认可你的贡献

    通常,我们在 contributer 名单里加上你的名字。当然,如果你想匿名提交代码,我们也可以不修改这个名单

    性能测试

    在线上部署之前,请先联系QA在测试环境进⾏压⼒测试,并关注下⾯这些问题:

    • 平均请求响应时间下降多少?

    • 如果CPU打满,QPS会下降多少?

    我们测试了大量的业务系统,也测试了多个开源应⽤;很多金融客户帮助我们进行了全链路的压测。性能影响通常 在 2%~4% 之间,接口响应延迟在 2~8ms 之间,完全可以接受。

    如果你发现实际的性能损耗超过了 5%,请参考性能调试 文档,采集调试数据,然后加⼊QQ群联系群主。我们会在第⼀时间进⾏分析,并尽快解决问题。

    本报告只是抛砖引玉,如果你有任何疑问,欢迎加入QQ技术讨论群一起探讨。

    Java 版本

    测试报告#1 - 某金融结算系统

    指标
    未安装 OpenRASP
    安装 OpenRASP
    影响比例

    测试报告#2 - 某后台查询系统

    指标
    未安装 OpenRASP
    安装 OpenRASP
    影响比例

    测试报告#3 - JeeCMS

    JeeCMS 本身存在性能瓶颈,在不安装OpenRASP的情况下,当并发达到15,2个CPU已经打满,所以我们无法模拟更多用户

    指标
    未安装 OpenRASP
    安装 OpenRASP
    影响比例

    PHP 版本

    测试报告#1 - discuz x3.2

    php-fpm 配置为,

    • pm=static

    • max_children=100

    • max_requests=1000

    测试结果

    指标
    未安装 OpenRASP
    安装 OpenRASP
    影响比例

    测试报告#2 - wordpress 4.9.4

    php-fpm 配置为,

    • pm=static

    • max_children=100

    • max_requests=1000

    测试结果

    指标
    未安装 OpenRASP
    安装 OpenRASP
    影响比例

    版本变更

    1.3.7 版本 - 2022.01.28

    优化改进

    管理后台

    • 支持按照主机名、RASP ID或者主机IP搜索报警

    • 增加心跳时间索引,解决大规模主机搜索卡顿问题

    • 为了提高查询效率,主机离线判定方式改为固定的360s,不再根据心跳配置动态计算

    • 支持在后台导出单条报警

    • 支持删除过期依赖库数据,感谢@国产大熊猫反馈

    • 升级beego到v1.12.3,感谢@大剑士反馈后台编译问题

    • Kafka推送时,将@timestamp从数字改为字符串,

    • 增加漏洞级别字段,aka event_level

    • 推送测试报警时,不再使用写死的假报警,而是从ES里搜索最新的报警作为测试数据

    • 合入@strawberrybiscuits的补丁,解决IAST死锁问题

    Java 版本

    • 修复当Java不在$PATH时,resin安装会抛出异常的问题,感谢 @叶 反馈

    • 修复WebLogic Windows下面自动安装失败的问题

    • 修复Weblogic下面无法加载的问题(v1.3.3 引入)

    • 修复log.path配置不生效的问题

    PHP 版本

    • 增加PHP 7.4支持

    • 修复PHP 5.5下面,include检测点可能会崩溃的问题

    检测插件

    • 修复 @月射寒江 发现的Oracle SQL异常无法报警的问题

    • 修复 @mattF123 报告的多个XXE绕过问题

    • 按照 @Holy 的建议,增加反射写jspx文件的检测

    1.3.6 版本 - 2021.02.07

    优化改进

    管理后台

    • 支持按照RASP目录搜索主机

    • 修复部分报警展示问题

    • 依赖库详情页面,改为按照上报时间排序

    • 修复后台审计日志IP伪造问题,感谢 @k4n5ha0 反馈

    Java 版本

    • 支持 MySQL 8.X 驱动

    • 支持开启jnotify、关闭jnotify,或者定期扫描插件目录三种方式;默认改为定期扫描

    • 支持关闭依赖库采集(安装阶段通过 -nodep 参数关闭)

    PHP 版本

    • 扩展 webshell_ld_preload 检测点,支持配置环境变量,新版插件默认支持3个

    • 后端请求错误时,同时打印 cURL 错误描述(之前版本仅有错误码)

    • 依赖库数据增加缺失的来源字段,内容固定为 composer

    检测插件

    • 修复腾讯报告的SQL注入绕过问题

    • 优化身份证合法性校验逻辑

    • 反序列化、OGNL两个检测算法,黑名单支持配置(需要同时升级后台和插件)


    1.3.5 版本 - 2020.09.04

    优化改进

    管理后台

    • 由于早期 ElasticSearch mapping 的问题,当 URL 长度超过一定值,将无法搜索到

      • 后台升级完成后,用户需要手动执行 ./rasp-cloud -upgrade 134to135 来更新 mapping

      • 程序会先修改 alias,将索引指向新的 alias,完成数据复制后才删除以前的索引

      • 复制过程中可以有新的报警数据写入,不会丢失

    Java 版本

    • 修复自定义 header 失效问题

    • 修复XSS检测,会打印空指针日志问题

    • 修复内置检测插件异常时,不会打印URL的问题

    • 修复 java.io.RandomAccessFile 读操作误报问题


    1.3.4 版本 - 2020.07.08

    优化改进

    PHP 版本

    • 修复某些 PHP 5.3 的环境,获取到的 header 可能为空的问题

    • 修复插件里正则写错时,会抛出异常的问题

    • 修复在云控连接成功前,就启动web目录敏感文件检测,导致匹配错误的问题

    • 加强 array_map 兼容性,避免第一个参数为空时打印多余日志

    Java 版本

    • 增加宝兰德BES支持,感谢 @枫舞蝶殇 提交的补丁

    • 修复某些情况下,Tomcat 9 启动时候可能会卡顿的问题

    • 修复某些 yum 安装的 tomcat 服务器,RaspInstall 会失败的问题

    • 增加 yaml 反序列化白名单,感谢 @kkskk 提交的补丁

    检测插件

    • SQL注入: 内部有误报场景,默认关闭十六进制字符串检查

    • 任意文件写入: 拦截基于反序列化写webshell的操作,如fastjson漏洞

    管理后台

    • 应用快速切换,改为动态搜索,并展示前100个匹配结果

    • 攻击事件详情增加RASP版本展示

    • 支持自定义日志路径,配置名称为 LogPath

      • 如不配置,默认为 /home/openrasp/logs


    1.3.3 版本 - 2020.06.02

    优化改进

    通用改进

    • 增加 Alpine docker 环境支持

    Java 版本

    • 捕获 UTF16 转换异常

    PHP 版本

    • 修复 PHP 5.3.18 之前版本,某些情况下RASP进程会意外退出的问题


    1.3.2 版本 - 2020.03.25

    BUG 修复

    管理后台

    • 修复平安报告的 request.param_encoding 默认值错误问题,应该设置为空

    Java 版本

    • 修复 @素十八 报告的攻击无法拦截的问题

    PHP 版本

    • 修复SSRF重定向检测时,若URL不带协议头,cURL会增加 http://,导致误报的问题


    1.3.1 版本 - 2020.03.12

    优化改进

    管理后台

    • 修复Web根目录敏感文件正则默认配置,删除多余的双引号

    • 添加主机界面,优化手动安装提示

    Java 版本

    • 修复 SpringBoot 在开启白名单后,可能会导致所有 Hook 点失效的问题

    PHP 版本

    • 增加 fastcgi SAPI 支持(之前的版本只支持 php-fpm/apache)

    检测插件

    • 敏感信息泄漏检测算法,修正某些情况下手机号识别会误报的问题

    • 当请求JSON解析出错时,对异常日志进行截断,避免硬盘打满

    • 拦截基于 CVE-2020-9547、CVE-2020-8840 的命令执行


    1.3.0 版本 - 2020.02.11

    重大变更

    IAST 扫描工具

    • IAST 控制台合入现有管理后台,降低运维成本(iast 不再监听 18664 端口)

    • IAST 扫描器改为连接 panel 服务器(以前是连接 agent 服务器)

    • IAST 扫描器使用 websocket 连接管理后台,不兼容 v1.3.0 之前的后台

      • 老版本后台用户可使用 pip3 命令安装老版本

    PHP 版本

    • 对于文件相关检测点,若读取文件以流协议开头,将会触发SSRF检测,不会触发文件读写检测

      • 受影响协议为: https/http/ftp

      • 受影响函数为: file/readfile/file_get_content/fopen/copy/include

    • 当 plugin.filter 关闭,文件相关检测点将忽略 open_basedir 配置,继续进入插件检测

    新增功能

    通用改进

    • 增加文件删除测点

    • 增加 SSRF 跳转后检测点,可检测重绑定攻击

    • 增加 HTML 响应检测点,默认每分钟采样5次

    • 增加依赖库信息采集,默认6小时采集一次

    Java 版本

    • 增加 Hibernate SQL 检测点

    • 增加 nio 检测点

    • 增加 SpringBoot 部分注解参数支持

    PHP 版本

    • SSRF 支持 IPv6 地址解析

    • 基线检查: 检测web根目录下是否有压缩包、SQL等敏感文件

    • 增加 mysql_db_query、mysql_unbuffered_db_query 检测点

    • 增加 print 检测点

    管理后台

    • 新增 -s restart / -s stop / -s status 指令,可以重启后台、关闭后台以及获取状态

    • 支持主机设置备注,以及按照备注搜索

    • 白名单支持备注

    • 支持日志写 kafka

    检测插件

    • 增加任意文件删除漏洞检测

    • 增加 header 注入检测(如SQL注入、命令注入)

    • 增加命令执行语法错误监控,以及可疑的注入检测

    • 增加 DNS Rebind 方式的 SSRF 攻击

    BUG 修复

    Java 版本

    • RaspInstall 安装 rasp.jar 时,先重命名再写入新文件

      • 避免修改已经加载的 jar,可能会出现 mmap 问题

      • 老文件以 uuid 随机命名,支持多次安装,会在启动时统一删除

    PHP 版本

    • 当后台下发配置不符合预期,主动上报异常日志

    • 修复 Kali 下面日志只会上传一条的问题,感谢 @亿相逢 反馈

    • 修复某些情况下,会出现多个 rasp-log 进程的问题

    管理后台

    • 客户端版本聚合接口,没有过滤主机在线状态

    • 增加重复白名单校验


    1.2.3 版本 - 2019.12.17

    新增功能

    通用改进

    • Java、PHP 增加崩溃监控(仅支持 Linux/Mac 系统)

      • 监控信号如 segfault/abort 等等

      • 监控范围是 Java主进程、PHP worker/心跳/日志进程/守护进程

      • 崩溃后自动向管理后台发出报警,并上传堆栈日志;后台会同步发出邮件报警

    管理后台

    • 支持客户端版本枚举

    • 支持一键关闭所有报警

    • 当agent无法获取dubbo等应用版本号时,允许agent注册

    BUG 修复

    Java 版本

    • 修复 syslog 地址修改后,依然会向老地址发送日志的问题(感谢 @й阿桂 反馈)


    1.2.2 版本 - 2019.11.28

    升级说明

    管理后台

    • 后台升级完成后,还需要再手动执行 ./rasp-cloud -upgrade 121to122 来更新 MongoDB

      • 增加 X-Protected-By: OpenRASP 相关配置

      • 请求 body 大小限制改为 12KB

    新增功能

    通用改进

    • 彻底解决 v8::Abort() 崩溃问题

    • 升级 v8 到最新版本: 7.8.279.19

    • 支持隐藏 X-Protected-By: OpenRASP 响应头

    自动安装程序

    • 支持通过 -heartbeat/--heartbeat 参数自定义心跳间隔

    Java 版本

    • 增加 WebSphere 7.X 支持。由于IBM JDK限制,文件相关检测点无法生效

    • 当插件没有注册 request/requestEnd 检测点,不再构造相关参数以提高性能

    检测插件

    • 拦截基于 bsh.servlet.BshServlet 的命令执行操作,e.g CNVD-2019-32204

    • 拦截基于 jdk.scripting.nashorn 的命令执行操作

    BUG 修复

    Java 版本

    • 修复部分情况下,Java 无法获取字符流请求 body 的问题

    PHP 版本

    • 修复当关闭 plugin.filter 时,包含 .php/.inc 文件不会进入插件的问题

    • 对于 multipart 请求,单独提取参数,解决产生报警时没有请求 body 的问题

    检测插件

    • 修复用户报告的 replaceAll 函数内存占用过高问题

    • 修复 @Looke 报告的 xss_userinput 绕过问题


    1.2.1 版本 - 2019.10.29

    升级说明

    管理后台

    • 由于早期 ElasticSearch mapping 的问题,对于已经存在的应用,报警消息、基线消息、异常消息均不支持大小写搜索

      • 后台升级完成后,用户需要手动执行 ./rasp-cloud -upgrade 120to121 来更新 mapping

      • 程序会先修改 alias,将索引指向新的 alias,完成数据复制后才删除以前的索引

      • 复制过程中可以有新的报警数据写入,不会丢失

    新增功能

    通用改进

    • 支持自定义 RASP ID

      • 安装时使用 --rasp-id (PHP) 或者 -raspid (Java) 来设置

      • 若没有指定,则按照先前的逻辑,根据网卡、RASP路径等信息计算一个

    管理后台

    • 增加报警日志去重,目前按照 request_id + stack_md5 进行去重

    • 在 系统设置 -> 后台设置 界面,增加一键清理报警数据支持

    • 主机管理界面,自动记住 主机状态 勾选情况

    • 报警查看界面,支持按照报警消息、堆栈MD5搜索;Referer、URL 支持点击

    Java 版本

    • 增加 TongWeb 6.X 服务器部分支持,

    • 简化 JBoss 7 以及更高版本的安装流程,

    • 增加 HSQL 数据库 hook 点,可以检测 WebGoat SQL 注入漏洞

    插件系统

    • 命令执行检测点,增加环境变量信息

    • SQL异常检测改为插件检测,且可在管理后台自定义要监控的错误代码

    • 修复 command_reflect 算法,在某些情况下可能误报的问题

    Bug 修复

    通用修复

    • 增加重新注册支持,当主机离线后被误删除,可自动恢复

    Java 版本

    • 修复当中间件支持 multipart 协议,但是用户没有使用文件时,会产生误报的问题

    • 修复当服务器在启动一段时间后才与管理后台连通,Java Agent 不会再次获取注册IP的问题

    • 修复某些情况下,由于 context.language 为空,不会拦截 WebSphere 反序列化命令执行的问题

    • 修复心跳失败时,sleep 失效,会无限打印日志的问题

    PHP 版本

    • 修复PDO异常监控没有过滤 error code,记录了多余的异常日志的问题


    1.2.0 版本 - 2019.09.05

    重大变更

    通用变更

    • 删除 enforce_policy 配置,基线检测不再支持拦截

    • 去除 MySQL duplicated key 错误监控

    • 删除报警日志里的 stack_trace 字符串字段,统一使用 attack_params.stack 获取堆栈

      • 若 Java/PHP agent 升级到 v1.2.0,那管理后台也必须升级,否则前端堆栈将展示为空值,且漏洞聚合列表将为空

    新增功能

    通用改进

    • 主机名发生变化时,同步到管理后台

    • 增加 host_type 字段,以标识是否为docker容器

    管理后台

    • 修复登录后无法跳回原URL的问题

    插件系统

    • 增加 requestEnd hook 点,请求结束时调用一次

    • 增加 RASP.request() 接口,可在插件里发送 HTTP 请求

    • 增加 RASP.get_version() 接口,可获取 agent 版本信息

    • 增加 context.requestId 等多个字段

    PHP 版本

    • 增加 eval/assert hook 点

    • 增加 debuglevel 配置,避免打印多余日志

    Java 版本

    • 对 JBoss、WebLogic 增加集群支持

    • 修复 v8 在多线程环境运行时,获取 Thread Local 数据会崩溃的问题

    • 增加关键hook点检查: requestEnd, request.parameterMap 不存在时拒绝启动

    • 心跳间隔下限改为 10s

    自动安装程序

    • 增加 SpringBoot 半自动安装,即只释放文件并修改配置,参数名为 -nodetect

    • 增加对 yum 安装的 tomcat 的支持,即 bin 目录与 tomcat_home 分离的情况

    • 增加 -prepend 参数,若开启则将 -javaagent 参数放在最前面

    灰盒扫描工具

    • 发布第一版,结合RASP挖掘漏洞的扫描器

    Bug 修复

    Java 版本

    • 解决 JRockit 兼容性问题,改为 jni 获取网卡信息

    • 解决 org.elasticsearch.client.RestClient 兼容性问题

    • 解决 XXE 代码安全开关和 taglib 不兼容的问题

    • 屏蔽 V8 execstack warning

    PHP 版本

    • 修复报警日志里PHP版本号不对的问题

    插件系统

    • 修复 001-dir-1.jsp 即使在插件里关闭 all_log 也不会拦截的问题


    1.1.2 版本 - 2019.07.11

    通用改进

    管理后台

    • 支持按照攻击类型决定是否报警

    • 主机管理页面,支持导出agent列表

    • 添加主机页面,修正 SpringBoot + Docker 安装命令

    • 优化多处表格体验

    Java 版本

    • syslog tcp 增加连接、发送超时

    • 支持通过 rasp.jar 获取agent版本信息

    检测插件

    • readFile hook 点忽略 war 包相关操作

    Bug 修复

    Java 版本

    • 当主机名没有在 /etc/hosts 里绑定,会触发大量 hostname 命令执行调用的 BUG

    • 传给插件的堆栈,修复过滤不正确的问题

    • 修复 Undertow 解析参数时的空指针异常问题

    • 修复一处 XSS hook 点空指针异常


    1.1.1 版本 - 2019.06.17

    通用改进

    管理后台

    • 开启 gzip 压缩支持,减少网络流量

    • 报警、基线日志保留时间支持自定义,默认 365 天

    • 优化多处前端体验

      • agent 异常日志增加堆栈详情展示

    Java 版本

    • 修复堆栈过滤不全的问题

    • 解决 emoji 表情包可能造成的编码问题

    • openrasp-v8 所有异常同步到 rasp.log

    检测算法

    • 修复 command_reflect 误报问题

    • 删除 xss tag 超过10个就报警的算法


    1.1 版本 - 2019.06.06

    重大变更

    通用变更

    • 升级 Google v8 到 7.2 版本

    • 语法解释器由antlr4替换为flex,降低内存占用

    PHP 版本

    • 替换 libstdc++ 为 libc++

    • 去除 pcre 依赖

    • 二进制包增加 Thread Safety 版本

    Java 版本

    • 替换 rhino 为 openrasp-v8

    • SQL、SSRF 检测逻辑改为JS实现

    • 暂时去除 JRockit JDK 支持,WebLogic 10.3.6 需要设置 JAVA_VENDOR=Sun 来改用 Oracle JDK

    插件系统

    • 精简 console.log 函数,删除颜色相关代码

    • 传给检测插件的堆栈,过滤掉 com.baidu.openrasp 相关内容

    新增功能

    通用变更

    • SQL异常增加密码错误监控

    • 实现数据库连接弱口令检测

    Java 版本

    • 增加XXE代码安全开关,可以直接禁止外部实体加载

    Bug 修复

    通用修复

    • 插件更新成功后,立即发出心跳,解决管理后台版本信息滞后问题

    • 报警堆栈过滤掉 openrasp 相关内容

    Java 版本

    • 修复文件上传检测点误报问题,改为在用户使用了文件之后再检测

    • 修复 Windows下,openrasp.yml 文件编码不正确的问题

    • 修复 JBoss 12 以上无法自动安装的问题

    • 解决 JSP 无法获取堆栈的问题

    管理后台

    • 修复检测插件重复上传问题

    • 前端首页增加缓存失效设置

    • 修复 debug_level 字段不是数字的问题

    • 当应用下面有在线主机,禁止删除应用


    1.0 正式版 - 2019.04.12

    重大变更

    通用变更

    • 报警日志增加 header 字段,并去除最外面的 user_agent、referer 重复字段

    • 单机版配置文件改为 yaml

    • 仅当拦截响应码设置为 302 时才输出 Location 头跳转,使用户可以打印自定义拦截内容

    管理后台

    • 在配置文件里删除 AgentServerURL、PanelServerURL 两个项目,改为在管理后台界面上修改

    • 首次访问后台会自动设置上述两个选项,若要开启负载均衡模式,请手动修正 Agent 服务器列表

    PHP 版本

    • 单机版默认禁用 fswatch。若有需求请使用 --enable-fswatch 编译参数开启

    • 替换 rapidjson 为接口更加灵活的 nlohmann/json

    • cli 模式关闭基线检查,避免多余的日志。若有需求请使用 --enable-cli-support 编译参数开启

    Java 版本

    • 去除 rasp-log4j.xml 相关启动参数。改为动态生成 log4j 配置的方式,用户不再需要配置

    新增功能

    通用功能

    • 新增 JSON 参数解析,即 context.json

    • 新增应用加固功能,可防护点击劫持、MIME嗅探、下载文件自动运行、反射XSS

    • 支持反编译功能,产生报警时可同时获取用户代码(仅 JDK 6-8、PHP 支持)

    PHP 版本

    • 新增 PHP 7.3 支持

    Java 版本

    • 新增 SpringBoot + Undertow 支持

    • 新增 WebLogic 支持

    • 新增 JBoss 6-8 支持(暂不支持自动安装)

    管理后台

    • 改进多处用户体验,提供更加完善的报警搜索体验

    • 新增漏洞聚合展示,避免在漏洞利用阶段攻击刷屏的问题

    • 改进审计日志展示,增加类型字段和展示

    • 新增客户端异常日志展示

    算法改进

    通用改进

    • 增加开发模式开关,开启后会加载一些消耗性能的检测算法

    • 默认开启观察模式

    安全基线

    • Tomcat 后台弱口令增加空密码检查

    Path traversal

    • 修复一处使用绝对路径下载文件,造成的 is_path_endswith_userinput 函数误报问题

    • 拦截 Windows 下面使用 ..\..\ 列出目录的攻击

    File Inclusion

    • 修复在使用百度云BOS业务时,包含 phar:// 文件造成的误报问题

    CMDi

    • 新增常见渗透命令检测支持,默认只打印日志

    SQLi

    • 新增SQL异常检测,如语法错误、报错注入

    • 修复 char/chr() 误报问题,仅当出现5次才报警

    SSRF

    • 调用检测插件时增加端口信息

    • 拦截对阿里云 metadata 的访问

    File Upload

    • 报警日志增加 multipart 参数名称字段,方便构造请求

    XSS

    • 新增 xss_userinput 检测算法,拦截反射XSS

    • xss_echo 算法增加内容过滤,避免非攻击事件造成的报警(此算法无误报)

    WebShell

    • 拦截基于 LD_PRELOAD 的后门

    Deserialization

    • 拦截基于 JNDI 反射执行命令的攻击

    Bug 修复

    管理后台

    • 修复 docker 拉取的 ElasticSearch 无法连接的问题

    PHP 版本

    • 修复当URL没有协议,SSRF检测点拿不到hostname的问题


    1.0.0 RC1 版本 - 2019.1.3

    新增功能

    Java 版本

    • 增加 okhttp/okhttp3 hook点,用于 SSRF 检测

    其他通用功能

    • 发布管理后台第一版

    • 增加远程管理功能,包括日志上传、插件下发、远程配置管理等等

    • syslog 日志增加 tag 字段支持,可自定义

    • LRU 由插件改为agent实现,覆盖 sql, ssrf, readFile, writeFile 几个检测点

    重大变更

    PHP 版本

    • 正式去除 Windows 支持

    算法改进

    命令执行

    • 增加 JBoss EL 反射命令执行的检测

    • 新增 bash 命令解释器,可检测命令注入攻击

    Bug 修复

    • 修复 dubboRPC 下面,log4j 打印日志时因没有 requestMethod 导致空指针的bug

    • 修复 PHP session + mysql handler 一处崩溃问题

    • 修复 SpringBoot 1.5.9 + Embedded Tomcat Server 无法获取服务器版本号的问题


    0.50 版本 - 2018.10.29

    新增功能

    Java 版本

    • 正式支持 WebSphere,目前仅测试了 8.5、9.0 两个版本

    其他

    • 报警日志增加 algorithm 字段,用于标识具体算法名称

    算法改进

    任意文件下载

    • 修复 ThinkPHP rewrite 导致的一个绝对路径误报问题

    0.42 版本 - 2018.09.26

    重大变更

    通用

    • 删除SQL慢查询hook点,但暂时保留代码

    Java 版本

    • 插件获取到的 Dubbo RPC 参数名称,从 openrasp-dubbo-XXX 改为 dubbo-XXX

    新增功能

    • 报警日志增加 request_method 字段,即请求方法

    Bug 修复

    • 修复在某些 tomcat 版本下,获取参数时会产生 No modifications are allowed to a locked ParameterMap 错误的问题

    算法改进

    Rename

    • 修复 rename_webshell 一个潜在的误报问题

    反序列化

    • 堆栈算法增加 commons.collections4 检查


    0.41 版本 - 2018.09.17

    重大变更

    Java 版本

    • block.url 配置选项改名为 block.redirect_url,并支持模板化配置

      • 即自动替换模板里的 %request_id% 关键词为当前请求ID

    PHP 版本

    • openrasp.block_url 配置选项改名为 openrasp.block_redirect_url

      • 并支持模板化配置,同Java版本

    • 所有日志时间改为系统时间,不再使用PHP时区里的时间

    JS API 接口

    • 对于Java服务器,appBasePath 不再指向 webapps 目录,改为应用部署路径,比如 /tomcat/webapps/vulns

    • 数组元素改为字典,并增加token起始坐标、token结束坐标两个参数

      • 改进后,sqli_userinput 算法只需要再执行一遍 tokenize

    新增功能

    Java 版本

    • 为 JBoss 增加基线检查

    • 当请求被拦截,且期望响应类型为 xml/json,用户可以自定义的响应内容

      • 通过配置 block.content_xml

    PHP 版本

    • 支持通过 openrasp.hooks_ignore=all 来禁用全部 hook 点

    • 增加获取客户端真实IP的能力,同 Java 版本

    • 当请求被拦截,且期望响应类型为 xml/json,用户可以自定义的响应内容,同 Java 版本

    • 增加 openrasp.plugin_filter 配置,同 Java 版本

    算法改进

    SSRF

    • 修复 @小猪"\ 报告的 XXE、SSRF 绕过问题,默认拦截 netloc://、jar:// 等更多不安全的协议

    OGNL

    • hook 点改为 Ognl.topLevelExpression,以修复 @阿远 报告的 OGNL 检测报警不正确的问题

    SQLi

    • 增加懒加载和预过滤机制,仅当需要 tokenize 的时候才执行,提升性能

    • 使用链表替换数组,优化JS LRU实现,提升性能

    XXE

    • 修复 @凌霄 反馈的 xxe_file 算法,产生大量报警日志问题

      • 通过忽略扩展名为 dtd/xml 的实体来解决

    文件目录遍历、任意文件包含

    • 增加新的检测算法,当用户输入包含遍历特征,且用户输入位于目录结尾,判定为文件目录遍历

    • 修复 @酒馆游侠 报告的 confluence 5.8 AFD 报警消息不正确的问题

      • 当用户传入 file:///etc/passwd,但实际读取的是 /etc/passwd,会导致绕过,已修复

    文件写入

    • writeFile_script 默认改成 ignore,避免大量无用日志

    重命名监控

    • 增加过滤,当源文件包含扩展名时才进入检测逻辑,以修复 @萝卜 报告的 larvael 框架下的误报问题

    • 增加过滤,当源和目标都是文件的时候才进入检测逻辑

    慢查询

    • 由于无法获取对应的SQL语句,所以默认禁用了慢查询检测;禁用此hook点还可以提高Java版本的性能。

    Bug 修复

    PHP 版本

    • 修复 array_filter 参数处理不正确的问题

    • 修正报警日志里, URL 字段缺少域名的问题


    0.40 版本 - 2018.7.24

    重大变更

    Java 版本

    • 命令执行 hook 点,命令参数统一改为字符串形式

    • 所有报警消息改为英文,下个版本增加翻译支持

    PHP 版本

    • 所有报警消息改为英文,下个版本增加翻译支持

    新增功能

    PHP 版本

    • 正式支持 PHP 7.0-7.2

    • 增加对 SQL prepared statement 的支持

    • 使用 v8 default platform 替换自定义 platform,提供更通用的后台任务能力和错误溯源能力

    Java 版本

    • 增加 rename hook 点

    算法变更

    • 命令执行

      • 增加对 FreeMarker 模板执行命令的识别

      • 修复 @加菲猫 反馈的 cacti 误报问题

      • 默认不再拦截所有的命令执行

    Bug 修复

    PHP 版本

    • 增加60多个单元测试,修复2处参数解析错误问题

    • 优化不同协议的处理逻辑,若协议不支持写操作,将不再进入检测插件

    • 修复一个左右斜杠混用,导致的路径精简失败的问题

    其他变更


    0.32 版本 - 2018.6.8

    算法改进

    • 为所有检测算法增加开关

      • 用户可通过编辑JS插件头部的配置,来控制某个算法是否开启

    • ssrf_common 算法,增加对 ceye.io、transfer.sh 的检测和拦截

    Bug 修复

    • 解决 Resin 3.1.8 一个 classloader 兼容性问题

    • 修复 SQLParser 一处语法解析错误

    • 通过修改包名,解决 mozilla rhino 加载冲突问题

    其他变更

    • 使用v8引擎的snapshot特性,以加快v8实例启动速度


    0.31 版本 - 2018.5.22

    重大变更

    • Java 版本

      • Java 包名改为 com.baidu.rasp

        • 在升级前,用户需要手动删除 rasp/conf/rasp-log4j.xml 文件

    算法变更

    • SQLi 检测算法 #2,默认关闭常量对比算法

      • 在真实业务里,经常有编码不规范的情况,会造成误报,e.g AND ((0='' OR 0='0')

    • 命令执行检测逻辑调整

    新增功能

    • Java 版本增加 ascii banner,启动时打印

    • 增加 JDBC Prepared SQL Hook 点

    • 支持 Resin 3.X、4.X 服务器

    • 增加自定义编码配置,允许用户设置 context.parameter 的编码

    Bug 修复

    • 由 @园长MM 反馈

      • ProcessBuilder 存在绕过,我们将 Hook 点改为了更底层的 UNIXProcess、ProcessImpl 类

    • PHP 版本

      • 当文件不存在,file_put_contents 不会调用检测插件,已修复


    0.30 版本 - 2018.04.27

    重大变更

    • Java 版本

      • 调试开关配置选项,由 debug_level 改为 debug.level

    新增功能

    • 增加对 PHP 5.X 的支持

      • Linux 5.3 ~ 5.6

      • Windows 5.6 (仅线程安全版本)

      • Mac homebrew PHP 5.6

    API 变更

    • directory hook 点,增加 stack 参数

    • ssrf hook 点,增加 ip 参数

    算法改进

    • SQLi 检测算法增强

      • 增加对 UNION NULL 语句的检测

      • 语句规范检查算法,拦截常见盲注函数,e.g ord、chr

    BUG 修复

    • 由 @计算姬 反馈

      • SQLi算法#1 - 当用户输入为纯数字时,且多次出现在SQL语句中,会产生误报,已经解决


    0.24 版本 - 2018.02.02

    BUG 修复

    • 自动安装程序

      • 解决无法识别 JBoss 4.0.3 的问题

    其他变更

    • 抓取 RASP.sql_tokenize 错误信息,并打印到 plugin.log


    0.23 版本 - 2018.01.23

    重大变更

    • 删除 reflection hook 点

      • 部分框架会大量调用反射,影响性能

      • 我们测试了一些金融业务,新版性能损耗由 10% 下降到 5%

    算法改进

    • SSRF 检测算法增强,增加更多常用域名检测


    0.22 版本 - 2018.01.17

    重大变更

    • 对于Java版本,SQLi/SSRF 检测算法改为Java原生实现,进一步提高性能

      • 通过在插件修改 algorithm.config 配置来控制检测逻辑

    • 开源协议由 BSD-3 切换为 Apache License 2.0,方便商用

    新增功能

    • 支持 JBoss 7.X

    • 支持在响应里插入 HTML 代码,可用于检测 CSRF/后台盲打,该功能默认关闭

    • rasp.properties 里的配置选项,除了 hooks.ignore 以外,开始支持动态更新,即修改后立即生效

    • 拦截攻击时,支持自定义响应状态码

    算法改进

    • 正式支持 SSRF 漏洞检测,包括以下三种场景

      • URL.openConnection

      • commons-httpclient

      • httpclient

    API 变更

    • RASP.config() 接口改名为 RASP.config_set(),并增加相关调试日志

    • 增加 RASP.get_jsengine() 接口,用于获取JS引擎名称

    Bug 修复

    • 解决因为没有写权限,导致 rasp-log4j.xml 释放失败的问题

      • 在新版本里,RaspInstall 会主动修改 rasp 目录权限


    0.21 版本 - 2017.12.06

    重大变更

    • 安全基线日志拆分到单独的文件里

      • 方便采集不同类型的日志

      • 升级前,用户需要手动删除 rasp/conf/rasp-log4j.xml 文件

    新增功能

    • 检测 JSTL 方式的文件包含漏洞,或者SSRF漏洞利用

    • 支持 DB2 数据库,我们仅测试了免费版本,9.7 和 10.5

    • 服务器安全基线

    算法改进

    • 公开SQL注入检测算法 #2 - 基于语句规范,可修改插件配置

      • 禁止多语句执行,e.g select 123; select 456

      • 禁止16进制字符串,e.g load_file(0x41424344)

    API 变更

    • ,可获取web应用根目录

    • ,context.session.setSession、context.session.getSession

    其他变更

    • 插件拆分,部分不常用的检测逻辑,比如扫描器识别功能,移动到 目录


    0.20 版本 - 2017.10.26

    重大变更

    • 性能优化

      • 由于 jni 性能太差,我们决定使用 Mozilla Rhino 最新版本替换掉 j2v8

      • 在最坏的情况下,对服务器影响在 2% 左右,具体可查看

    • 放弃对 WebLogic 的支持

    API 变更

    • 增加 SQL tokenize 接口: RASP.sql_tokenize

    • 增加 SESSION 修改接口: context.session.getSession / context.session.setSession

    • readFile 接口,当文件不存在时,将不再调用插件

    Hook 点变更

    • 增加 webdav hook 点,可检查 MOVE、COPY 操作

    拦截日志变更

    • 增加 HTTP Referer 字段

    • 增加 request_id 参数,用于标识一个攻击

    • 增加 event_type 字段,用于标志日志类型

    • attack_time

    新增功能

    • 支持自定义拦截页面

      • 通过 block.url 配置

      • 默认是

    • 增加服务器安全基线检查功能,目前仅支持 tomcat,可以检测如下非安全配置

    算法改进

    • 增加扫描器识别,根据UA、Header(默认关闭,请手动修改插件)

    • SQL注入检测算法 #1 开放

    • 敏感文件下载漏洞检测

    其他改动

    • JBoss XXE Hook 点次数优化,提高性能


    0.13 版本 - 2017.09.22

    Bug 修复

    • 当JS插件发生运行时错误,不应该打印报警日志

    • JS插件出错时,在 plugin.log 打印详细堆栈和错误信息


    0.12 版本 - 2017.09.14

    新增功能

    • 增加一个异常流识别,当某些类通过反射进行调用时,会触发插件检测逻辑


    0.11 版本 - 2017.09.13

    Bug 修复

    • 增加 doFilter hook 点,修复 struts 系列框架下,无法检测漏洞的问题


    0.10 版本 - 2017.08.18

    新增功能

    • 支持多种 Java 服务器、数据库服务器

    • 支持多种 SIEM 应用

    • 完成第一版官方检测插件

    • 支持多个 hook 点

    关于我们

    OpenRASP由百度集团安全团队维护,有任何问题请加入QQ群讨论

    技术支持

    QQ 技术讨论群(推荐)

    Github issues(Bug、Feature 管理)

    友情链接

    添加新的Hook点

    Java版本

    添加hook点

    根据自己的hook点在com.baidu.openrasp.hook包中添加一个继承自AbstractClassHook的类,并实现getType和isClassMatched两个方法进行hook点的匹配,并在hookMethod方法中的内部类的onMethodEnte方法和onMethodExit方法进行hook点前后的逻辑插入,具体代码如下:

    将如上实现的hook点加入com.baidu.openrasp.transformer.CustomClassTransformer的构造方法中,实现字节码的转换,代码如下:

    添加检测类型

    在 com.baidu.openrasp.plugin.checker.CheckParameter 中添加相应的检测类型

    构造参数并进入checker

    编写hook点中调用的 HookHandler.checkStringReplaceEnter 和 HookHandler.checkStringReplaceExit 方法,来实现具体的检测逻辑,检测逻辑中可以调用js插件,示例如下:

    参考资料

    • Javassist 框架参考文档:

    PHP 版本

    新增hook点

    假设我们要新增hook_class下的hook_function方法,其对应的检测类型为hook_type,则新增HOOK过程如下:

    • 在hook文件夹下新建新增hook点对应文件,建议命名方式为openrasp_hook_class.cc,同时将其添加至config.m4及config.w32

    • 引入openrasp_hook.h,根据业务需求,选择合适的HOOK方式:前置HOOK(PRE_HOOK_FUNCTION_EX),后置HOOK(POST_HOOK_FUNCTION_EX)以及前后同时HOOK(HOOK_FUNCTION_EX),根据选择的HOOK方式合理定义前置处理函数及后置处理函数,形如:

    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}"
    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%
    
    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
    2018-07-25T16:28:14+08:00 [event-logger] 999-event-logger: 初始化成功
    2018-07-25T16:28:19+08:00 [event-logger] 读取文件: /etc/hosts
    gdb php -ex "run -S 0.0.0.0:8123"
    {
    	"page":1,
        "perpage":10,
    	"data":{
    		"version":"official-101"
    	}
    }
    {
    	"page": 1,
        "perpage": 10,
        "total": 1,
        "total_page": 1,
    	"status":0,
    	"description":"ok",
    	"data":{
    		"version":"official-101"
    	}
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"data": {
        "version": "1.3.5",
        "build_time": "2020-09-02 17:35:04",
        "commit_id": "055ddf48c789cd776c06c52307c716156b9f6048"
      },
      "description": "ok",
      "status": 0
    }
    {
    	"username":"openrasp",
    	"password":"admin@123"
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"data": {
            "is_default":true,
        },
        "description": "ok",
        "status": 0
    }
    {
    	"old_password":"admin@123",
    	"new_password":"admin*123"
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
        "data": {
            "id": "c593342c72eb78fc8e7393d0a87b8f3fc54dfbec8835250641a6dbd9973ae981b4b7abc4",
            "app_id": "c593342c72eb78fc8e7393d0a87b8f3fc54dfbec",
            "upload_time": 1542177395622,
            "version": "'2018-1025-1600'",
    		"name": "official",
            "md5": "8835250641a6dbd9973ae981b4b7abc4",
            "plugin": "/*js plugin content*/",
            "algorithm_config": {
                "command_other": {
                    "action": "log"
                },
                "command_reflect": {
                    "action": "block"
                },
                "fileUpload_multipart_script": {
                    "action": "block"
                },
                "fileUpload_webdav": {
                    "action": "block"
                }
        },
        "description": "ok",
        "status": 0
    }
    {
    	"id":"47af9da31ec3f233f35a25776f5e06086ebf239ff60a021ada4750b65640d0d24b9ae382"
    }
    {
        "data": {
            "id": "7c70d5ba5547e77a6f9ad5d376b92fe7e47da7c4",
            "app_id": "fcbc4d8ac6bcaac27b1cc4703e5339a4aa6e8a1c",
            "name": "official",
            "upload_time": 1546595795342,
            "version": "2018-1227-1200",
            "md5": "4259002c18ff3a9f40b44e91824ba0cf",
            "algorithm_config": {
                "xxe_file": {
                    "action": "log",
                    "name": "算法2 - 使用 file:// 协议读取文件",
                    "reference": "https://rasp.baidu.com/doc/dev/official.html#case-xxe"
                },
                "xxe_protocol": {
                    "action": "block",
                    "name": "算法1 - 使用 ftp:// 等异常协议加载外部实体",
                    "protocols": ["ftp", "dict", "gopher", "jar", "netdoc"]
                }
                ... 忽略
            }
        },
        "description": "ok",
        "status": 0
    }
    {
    	"id":"47af9da31ec3f233f35a25776f5e06086ebf239f3f35a25776f5e06086ebf239f",
    	"config":{
        	"xxe_file": {
    			"action": "log",
                "name": "算法2 - 使用 file:// 协议读取文件",
                "reference": "https://rasp.baidu.com/doc/dev/official.html#case-xxe"
    		},
    		"xxe_protocol": {
    			"action": "block",
    			"name": "算法1 - 使用 ftp:// 等异常协议加载外部实体",
    			"protocols": ["ftp", "dict", "gopher", "jar", "netdoc"]
    		}
    		... 忽略
    	}
    }
    {
        "data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"id":"47af9da31ec3f233f35a25776f5e06086ebf239ff60a021ada4750b65640d0d24b9ae382"
    }
    {
        "data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"id":"47af9da31ec3f233f35a25776f5e06086ebf239ff60a021ada4750b65640d0d24b9ae382"
    }
    {
        "data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"name":"Java 测试",
    	"language":"java", 
    	"description":"openrasp protected", 
    	"selected_plugin_id":"47af9da31ec3f233f35a25776f5e0608w6ebf239ff60a021ada4750b65640d0d24b9ae382"
    }
    {
        "data": {
            "id": "1107158fb4cd0a901de850b2c64fab5faf0837d3",
            "name": "Java 测试",
    		"language":"java",
    		"create_time":1545984191,
    		"secret":"SFklSJ5_DF125IKn15SDF-1SD141Af1",
    		"description": "openrasp protected",
            "config_time": 0,
            "general_config": {
                "block.content.html": "</script><script>\n                              location.href=\"https://rasp.baidu.com/blocked2/?request_id=%request_id%\"\n                              </script>",
                "block.content_json": "{\"error\":true,\"reason\": \"Request blocked by OpenRASP\",\"request_id\": \"%request_id%\"}",
                "block.content_xml": "<?xml version=\"1.0\"?>\n\t\t\t\t\t\t\t <doc>\n\t\t\t\t\t\t\t <error>true</error>\n\t\t\t\t\t\t\t <reason>Request blocked by OpenRASP</reason>\n\t\t\t\t\t\t\t <request_id>%request_id%</request_id>\n\t\t\t\t\t\t\t </doc>",
                "block.redirect_url": "https://rasp.baidu.com/blocked/?request_id=%request_id%",
                "block.status_code": 302,
                "body.maxbytes": 4096,
                "clientip.header": "ClientIP",
                "ognl.expression.minlength": 30,
                "plugin.filter": true,
                "plugin.maxstack": 100,
                "plugin.timeout.millis": 100
            },
            "whitelist_config": {},
            "selected_plugin_id": "",
            "email_alarm_conf": {
                "enable": false,
    			"tls_enable": false,
                "server_addr": "",
                "username": "",
                "password": "",
                "subject": "",
                "recv_addr": []
            },
            "ding_alarm_conf": {
                "enable": false,
                "agent_id": "",
                "corp_id": "",
                "corp_secret": "",
                "recv_user": [],
                "recv_party": []
            },
            "http_alarm_conf": {
                "enable": false,
                "recv_addr": []
            },
            "attack_type_alarm_conf":null,
            "algorithm_config":{}
        },
        "description": "ok",
        "status": 0
    }
    {
    	"id":"a8604735911f1866029401c6766ba87f685ff037"
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"app_id":"569e8ea7a16123492b5878920fd36985"
    }
    {
      "app_name": "示例"
    }
    {
        "page":1,
        "perpage":10
    }
    {
    	"status":0, 		
    	"description":"ok", 
    	"data":{
    		"id":"569e8ea7a16123492b5878920fd36985"
    		"name":"Java 测试",
    		"description":"openrasp protected",
    		"config_time":155536548555,
    		"create_time":154598419100,
    		"language":"java",
    		"general_config":{
    			"plugin.timeout.millis":500,
    			"security.enforce_policy":true,
                ...
    		}		
            ...
    	}
    }
    {
    	"status":0, 		
    	"description":"ok", 
        "page": 1,
        "perpage": 10,
        "total": 1,
        "total_page": 1,
    	"data":[
            {
                "id":"569e8ea7a16123492b5878920fd36985"
                "name":"Java 测试",
                "description":"openrasp protected",
                "config_time":155536548555,
                "create_time":154598419100,
                "language":"java",
                "general_config":{
                    "plugin.timeout.millis":500,
                    "security.enforce_policy":true,
                    ...
                }
            }
        ]
    }
    {
      "app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f",
      "config": {
        "block.content_html": "</script><script>location.href=\"https://rasp.baidu.com/blocked2/?request_id=%request_id%\"</script>",
        "block.content_json": "{\"error\":true,\"reason\": \"Request blocked by OpenRASP\",\"request_id\": \"%request_id%\"}",
        "block.content_xml": "<?xml version=\"1.0\"?><doc><error>true</error><reason>Request blocked by OpenRASP</reason><request_id>%request_id%</request_id></doc>",
        "block.redirect_url": "https://rasp.baidu.com/blocked/?request_id=%request_id%",
        "block.status_code": 403,
        "body.maxbytes": 12288,
        "clientip.header": "ClientIP",
        "cpu.usage.enable": false,
        "cpu.usage.interval": 5,
        "cpu.usage.percent": 90,
        "debug.level": 0,
        "decompile.enable": false,
        "dependency_check.interval": 100,
        "fileleak_scan.interval": 21600,
        "fileleak_scan.limit": 100,
        "fileleak_scan.name": "\\.(git|svn|tar|gz|rar|zip|sql|log)$",
        "inject.custom_headers": {
          "X-Protected-By": "OpenRASP"
        },
        "log.maxbackup": 30,
        "log.maxburst": 100,
        "log.maxstack": 100,
        "lru.compare_enable": false,
        "lru.compare_limit": 10240,
        "lru.max_size": 1000,
        "ognl.expression.minlength": 30,
        "plugin.filter": true,
        "plugin.maxstack": 100,
        "plugin.timeout.millis": 100,
        "request.param_encoding": "openrasp",
        "response.sampler_burst": 5,
        "response.sampler_interval": 60,
        "security.weak_passwords": [],
        "syslog.enable": false,
        "syslog.facility": 1,
        "syslog.tag": "OpenRASP",
        "syslog.url": ""
      }
    }
    {
    	"app_id":"e64071cf900944b701213a6f17d36e0d18d8b6ab",
    	"config":[
    		{
    			"url":"www.asod.com/sss/sss",
    			"hook":{
    				"sql":true,
    				"ssrf":false
    			},
          "description":""
    		}
    	]
    }
    {
    	"app_id":"47af9da31ec3f233f35a25776f5e06086ebf239f",
        "attack_type_alarm_conf":{
            "sql":["email","ding","http"],
            "xxe":["email"]
        },
    	"email_alarm_conf": { 
    		"enable":false,
    		"tls_enable":false,
    		"server_addr":"email.qq.com:445",
    		"username":"123456789@qq.com",
    		"password":"4354edfwe",
    		"subject":"openrasp alarm", 
    		"recv_addr":["165165@163.com"]
    	},
    	"ding_alarm_conf": { 
    		"enable":false,
    		"agent_id":"1s6ef5w1ef6",
    		"corp_id":"1r5thnb5",
    		"corp_secret":"d512c5f5fg546sdg5",
    		"recv_user":["5sdf5","87njy7uoi"],
    		"recv_party":["8ik44ws"]
    	},
    	"http_alarm_conf": { 
    		"enable":false,
    		"recv_addr":["www.opff.com"]
    	},
      "general_alarm_conf":{
        "alarm_check_interval":120
      },
      "kafka_alarm_conf":{
        "url":"1.1.1.1:6666",
        "user":"",
        "pwd":"",
        "enable":true,
        "topic":"OpenRASP"
      }  
    }
    {
    	"app_id":"47af9da31ec3f233f35a25776f5e06086ebf239f",
    	"name":"myapp",
    	"language":"php",
    	"description":"php应用"
    }
    {
    	"app_id":"47af9da31ec3f233f35a25776f5e06086ebf239f",
    	"page":1,
    	"perpage":15
    }
    {
        "data": {
    		"page": 1,
            "perpage": 15,
            "total": 2,
            "total_page": 1,
            "data": [
                {
                    "id": "47af9da31ec3f233f35a25776f5e06086ebf239ff60a021ada4750b65640d0d24b9ae382",
                    "app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f",
                    "upload_time": 1540992061040,
                    "version": "2018-1016-1000",
                    "md5": "f60a021ada4750b65640d0d24b9ae382"
                    ...
                },
                {
                    "id": "47af9da31ec3f233f35a25776f5e06086ebf239f914450bbf9309777723f38facfa8183f",
                    "app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f",
                    "upload_time": 1540979046327,
                    "version": "2018-1016-0000",
                    "md5": "914450bbf9309777723f38facfa8183f"
                    ...
                }
            ]
        },
        "description": "ok",
        "status": 0
    }
    {
    	"app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f"
    }
    {
        "data": {
            "id": "47af9da31ec3f233f35a25776f5e06086ebf239ff60a021ada4750b65640d0d24b9ae382",
            "app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f",
            "upload_time": 1540985045544,
            "version": "2018-1016-1000",
            "md5": "f60a021ada4750b65640d0d24b9ae382"
    		...
        },
        "description": "ok",
        "status": 0
    }
    {
    	"app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f",
    	"plugin_id":"47af9da31ec3f233f35a25776f5e06086ebf239ff60a021ada4750b65640d0d24b9ae382"
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f"
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f"
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f"
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f"
    }
    {
    	"data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"app_id": "47af9da31ec3f233f35a25776f5e06086ebf239f"
    }
    {
        "data": {
            "is_latest": false,
            "selected_version": "2019-0606-1802",
            "latest_version": "2019-0606-1803"
        },
        "description": "ok",
        "status": 0
    }
    {
    	"page":1,
    	"perpage":10,
    	"data": {
            "id": "426199dc7a15cce89b0c937a65a24a23",
            "app_id": "fcbc4d8ac6bcaac27b1cc4703e5339a4aa6e8a1c",
            "version": "1.0.0-RC1",
            "hostname": "820c2691f452",
            "register_ip": "172.17.0.2",
            "language": "java",
            "language_version": "1.7.0_17",
            "server_type": "tomcat",
            "server_version": "7.0.78.0",
            "rasp_home": "/tomcat/rasp",
            "plugin_version": "2018-1227-1200",
            "heartbeat_interval": 180,
            "online": false,
            "register_time": 1546595808,
            "host_type": "docker"
    	}
    }
    {
        "data": {
    		"page": 1,
            "perpage": 10,
            "total": 2,
            "total_page": 1,
            "data": [    
                {
                    "id": "426199dc7a15cce89b0c937a65a24a23",
                    "app_id": "fcbc4d8ac6bcaac27b1cc4703e5339a4aa6e8a1c",
                    "version": "1.0.0-RC1",
                    "hostname": "820c2691f452",
                    "register_ip": "172.17.0.2",
                    "language": "java",
                    "language_version": "1.7.0_17",
                    "server_type": "tomcat",
                    "server_version": "7.0.78.0",
                    "rasp_home": "/tomcat/rasp",
                    "plugin_version": "2018-1227-1200",
                    "heartbeat_interval": 180,
                    "online": false,
                    "last_heartbeat_time": 1546597790,
                    "register_time": 1546595808,
                    "host_type": "docker",
                    "environ": {
            			"COLORTERM": "gnome-terminal",
                        "DISPLAY": ":0",
                	}
            ]
        },
        "description": "ok",
        "status": 0
    }
    {
        "data":{
            "app_id":"fcbc4d8ac6bcaac27b1cc4703e5339a4aa6e8a1c",
            "version":"1.3.0"
        },
        "page":1,
        "perpage":10
    }
    {
      "data": {
        "data": [
          {
            "version": "1.3.0",
            "count": 1
          }
        ],
        "page": 1,
        "perpage": 10,
        "total": 1,
        "total_page": 1
      },
      "description": "ok",
      "status": 0
    }
    {
    	"app_id":"94892d14c8f1dfcedb63af258cc008929c3ef4f5",
    	"id": "47af9da31ec3f233f35a25776f5e06086ebf239f",
    	"register_ip":"126.23.3.63",
    	"expire_time": 604800,
        "host_type": "docker"
    }
    {
    	"data": {
        	"count":1
        },
        "description": "ok",
        "status": 0
    }
    {
    	"app_id":"94892d14c8f1dfcedb63af258cc008929c3ef4f5",
    	"ids": [
            "47af9da31ec3f233f35a25776f5e06086ebf239f",
            "d64g58d4gc3fs58745sdfgd5g5s7f54e5f4s585s",
            "net1d5ns8bad6584thg1s5dnbs8gbs8af5RFG415"
        ]
    }
    {
    	"data": {
        	"count":1
        },
        "description": "ok",
        "status": 0
    }
    {
    	"id": "47af9da31ec3f233f35a25776f5e06086ebf239f",
    	"description": "this is a description"
    }
    {
        "data": {
        },
        "description": "ok",
        "status": 0
    }
    {
        "data":{
            "app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a"
        },
        "page":1,
        "perpage":10
    }
    {
        "data": {
    		"page": 1,
            "perpage": 10,
            "total": 1,
            "total_page": 1,
            "data": [    
                {
                  @timestamp: 1579597454365,
                  app_id: "4a335d670ec7c9353d3cf7480e68614dda087ded",
                  hostname: "d2e69eebfa7b",
                  id: "d1dd52ff8c82becccf9678b6ed09eca0",
                  path: ["/tomcat/bin/bootstrap.jar"],
                  product: "Apache Tomcat Bootstrap",
                  rasp_count: 1,
                  rasp_id: "3089c8d2672efd1ef5c3e322d9e8fcb1",
                  register_ip: "172.17.0.2",
                  search_string: "Apache Tomcat Bootstrap8.0.5",
                  source: "manifest_implementation",
                  tag: "Apache Software Foundation:Apache Tomcat Bootstrap:8.0.5",
                  vendor: "Apache Software Foundation",
                  version: "8.0.5"
                } 	
            ]
        },
        "description": "ok",
        "status": 0
    }
    {
        "data":{
            "app_id":"0d46b13c2f25722e542b1a89817e1163e190fce1",
            "tag":"org.apache.struts.xwork:xwork-core:2.3.14.2",
            "key_word":"",
            "hostname":""
        },
        "page":1,
        "perpage":10
    }
    {
        "data": {
    				"page": 1,
            "perpage": 10,
            "total": 1,
            "total_page": 1,
            "data": [    
                {
                  @timestamp: 1579612005801,
                  app_id: "0d46b13c2f25722e542b1a89817e1163e190fce1",
                  hostname: "cq02-scloud-docker-trial",
                  id: "148f69b483fff233ee4d4f9fffbfd478",
                  path: ["/tomcat/bin/bootstrap.jar"],
                  product: "xwork-core",
                  rasp_count: 1,
                  rasp_id: "3089c8d2672efd1ef5c3e322d9e8fcb1",
                  register_ip: "10.58.119.17",
                  search_string: "Apache Tomcat Bootstrap8.0.5",
                  source: "manifest_implementation",
                  tag: "Apache Software Foundation:Apache Tomcat Bootstrap:8.0.5",
                  vendor: "Apache Software Foundation",
                  version: "2.3.14.2"
                } 	
            ]
        },
        "description": "ok",
        "status": 0
    }
    {
    	"description":"xxx 认证 token"
    }
    {
    	"token":"44b2b50665c9f11c73090b19c3dd787031611e80",
        "description":"啄木鸟微服务认证token"
    }
    {
        "data": {
            "token": "44b2b50665c9f11c73090b19c3dd787031611e80",
            "description": "扫描器"
        },
        "description": "ok",
        "status": 0
    }
    {
    	"page":1,
    	"perpage":10
    }
    {
        "data": {
    		"page": 1,
            "perpage": 10,
            "total": 5,
            "total_page": 1,
            "data": [
                {
                    "token": "349532e57aa36ee9b72a62fec8907109a016f348",
                    "description": "a token"
                },
                {
                    "token": "f284baaeb786a8285bd1dde04a3dd7502c766c8a",
                    "description": "b token"
                }
            ]
        },
        "description": "ok",
        "status": 0
    }
    {
    	"token":"f284baaeb786a8285bd1dde04a3dd7502c766c8a"
    }
    {
        "data": {
        },
        "description": "ok",
        "status": 0
    }
    {
    	"data":{
    		"id": "389fdbeb0aceb154d5d5d26eba28fea9f402c945",
            "type_id": 1010,
            "app_id": "e64071cf900944b701213a6f17d36e0d18d8b6ab",
            "user": "admin",
            "ip": "127.0.0.1"
    	},
    	"start_time":1,
    	"end_time":1542807647000,
    	"page":1,
    	"perpage":15
    }
    {
        "data": {
            "data": [
                {
                    "id": "389fdbeb0aceb154d5d5d26eba28fea9f402c945",
                    "type_id": 1010,
                    "app_id": "e64071cf900944b701213a6f17d36e0d18d8b6ab",
                    "time": 1542807647000,
                    "user": "admin",
                    "content": "uploaded the plugin: ba41c57afab600c39dba7398987b159d648d0836",
                    "ip": "127.0.0.1"
                }
            ],
            "page": 1,
            "perpage": 15,
            "total": 1,
            "total_page": 1
        },
        "description": "ok",
        "status": 0
    }
    {
    	"data":{
        	"panel_url":"126.56.23.5:8086",
            "agent_url":[
            	"126.56.23.5:8086",
                "10.23.36.122:8086",
                "172.23.233.192:8086"
            ]
        },
        "description": "ok",
        "status": 0
    }
    {
        "panel_url":"126.56.23.5:8086",
        "agent_urls":[
            "126.56.23.5:8086",
            "10.23.36.122:8086",
            "172.23.233.192:8086"
        ]
    }
    {
        "data":{
            "panel_url":"126.56.23.5:8086",
            "agent_urls":[
                "126.56.23.5:8086",
                "10.23.36.122:8086",
                "172.23.233.192:8086"
            ]
        },
        "description": "ok",
        "status": 0
    }
    {
        "app_id":"e64071cf900944b701213a6f17d36e0d18d8b6ab"
    }
    {
        "data": {},
        "description": "ok",
        "status": 0
    }
    {
    	"app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a",  
    	"start_time":1523264521321212,
    	"end_time":1523267821321000,
    	"interval":"hour", 
        "time_zone":"+08:00"
    }
    {
    	"data":[
    		{
    			"start_time":1523264521321212,
    			"request_sum":10000
    		},
    		{
    			"start_time":1523264521340000,
    			"request_sum":87
    		}
    	],
        "description": "ok",
        "status": 0
    }
    {
    	"app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a",
    	"start_time":1535600036,
    	"end_time":1546140836,
    	"interval":"month", 
    	"time_zone":"+08:00"
    }
    {
        "data": {
            "data": [ 
                [
                    0,
                    0,
                    0,
                    1,
                    0
                ],
                [
                    0,
                    0,
                    0,
                    0,
                    0
                ]
            ],
            "labels": [
                1533052800000,
                1535731200000,
                1538323200000,
                1541001600000,
                1543593600000
            ]
        },
        "description": "ok",
        "status": 0
    }
    {
        "app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a",
        "start_time":1535600036,
        "end_time":1546140836,
        "size":10
    }
    {
    	"data":[
    		[
    			"sql", 156
    		],
    		[
    			"xxe", 156
    		]
    	],
        "description": "ok",
        "status": 0
    }
    {
    	"app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a",
    	"start_time":1535600036,
    	"end_time":1546140836,
    	"size":10
    }
    {
    	data:[
    		[
    			"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36", 156
    		],
    		[
    			"Chrome/5.0 (X11; Linux x86_64) AppleWebKit/537.36", 156
    		]
    	],
        "description": "ok",
        "status": 0
    }
    {
    	"data":{
        	"attack_type":["directory","sql"],
    		"app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a",
       		"start_time":1523264521321,
    		"end_time":1523264521421
    	}
    	"page":1,
    	"perpage":10
    }
    {
        "data": {
            "page": 1,
            "perpage": 10,
            "total": 500,
            "total_page": 50,
            "data":[
                {
                    "attack_type":"directory",
                    "stack_md5":"1111121637821204cwwd2e52d62d0aa8",
                    "event_time":"2019-01-27T23:51:15+0800",
                    ...
                }
                ...
            ]
    	},
        "description": "ok",
        "status": 0
    }
    {
    	"data":{
        	"attack_type":["directory","sql"],
    		"app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a",
       		"start_time":"1523264521321",
    		"end_time":"1523264521421"
    	}
    	"page":1,
    	"perpage":10
    }
    {
        "data": {
            "page": 1,
            "perpage": 10,
            "total": 500,
            "total_page": 50,
            "data":[
                {
                    "attack_type":"directory",
                    "intercept_state":"block",
                    "plugin_confidence":100
                    ...
                }
                ...
            ]
    	},
        "description": "ok",
        "status": 0
    }
    {
    	"data":{
        "_id": "3456789cb45678",
    		"app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a",
    		"start_time":"1523264521321",
    		"end_time":"1523264521421",
        "hostname": "127.0.0.1",
        "language": "java",
        "rasp_id": "3089c8d2672efd1ef5c3e322d9e8fcb1",
        "crash_message": "crash"
    	},
    	"page":1,
    	"perpage":10
    }
    {
        "data": {
    		"page": 1,
            "perpage": 10,
            "total": 500,
            "total_page": 50,
    		"data":[
    			{
    				"language":"PHP",
    				... // 此处省略
    
    
    			},
    			... // 此处省略
    		]
    	},
        "description": "ok",
        "status": 0
    }
    {
    	"data":{
        	"policy_id":["3004","3003"],
    		"app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a",
    		"server_hostname":"nmg01.xx.cq",
    		"local_ip":"172.36.2.6",
    		"start_time":"1523264521321",
    		"end_time":"1523264521421"
    	},
    	"page":1,
    	"perpage":10
    }
    {
        "data": {
    		"page": 1,
            "perpage": 10,
            "total": 500,
            "total_page": 50,
    		"data":[
    			{
    				"policy_id":"3004",
    				... // 此处省略
    
    
    			},
    			... // 此处省略
    		]
    	},
        "description": "ok",
        "status": 0
    }
    {
    	"data":{
    		"app_id":"f284baaeb786a8285bd1dde04a3dd7502c766c8a",
    		"server_hostname":"nmg01.xx.cq",
    		"local_ip":"172.36.2.6",
    		"start_time":"1523264521321",
    		"end_time":"1523264521421"
    	},
    	"page":1,
    	"perpage":10
    }
    {
        "data": {
    		"page": 1,
            "perpage": 10,
            "total": 500,
            "total_page": 50,
    		"data":[
    				{
    	  				"message": "HTTP request to http://scloud.baidu.com:8086/v1/agent/rasp failed:",
    	 				 "server_nic": [{
    		  				"name": "en0",
    		  				"ip": "172.24.182.127"
    	  				}],
    	  				"stack_trace": "sun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeMethod)",
    	  				"level": "WARN",
    	  				"event_time": "2019-01-11T13:36:46+0800",
    	  				"app_id": "9b3554a97673f1f8f5c929310298037a660d3b7a",
    	  				"pid": 58353,
    	  				"server_hostname": "localhost",
    	  				"rasp_id": "3089c8d2672efd1ef5c3e322d9e8fcb1"
      				}
    		]
    	},
        "description": "ok",
        "status": 0
    }
    {
    	"id":"569e8ea7a16123492b5878920fd36985",
    	"version" :"v3.2",
    	"hostname":"tyy-OptiPlex-9020",
    	"register_ip":"127.56.23.4",
    	"language" :"java",
    	"language_version":"8.1" ,
    	"server_type":"tomcat",
    	"server_version":"8.5.1" ,
    	"heartbeat_interval":60,
    	"rasp_home":"/home/work/tomcat8/rasp",
        "host_type":"docker",
        "environ":{
            "JAVA_HOME":"/home/java/jdk-7.0.25"
        }
    }
    {
    	"status":0, 		
    	"description":"ok", 
    	"data":{
    		"id":"569e8ea7a16123492b5878920fd36985",
    		"app_id":"023e68ea7a12564492b5878920fd630c8",
    		"version" :"v3.2",
    		"hostname":"tyy-OptiPlex-9020",
    		"register_ip":"127.56.23.4",
    		"language" :"java",
    		"language_version":"8.1" ,
    		"server_type":"tomcat",
    		"server_version":"8.5.1" ,
    		"heartbeat_interval":60,
    		"rasp_home" :"/home/work/tomcat8/rasp",
    		"last_heartbeat_time":"15425645253",
    		"online":true,
            "host_type":"docker",
            "plugin_version":"",
            "plugin_name":"",
            "plugin_md5":"",
        	"environ":{
            	"JAVA_HOME":"/home/java/jdk-7.0.25"
        	},
            "register_time":"15425645253"
    	}
    }
    {
    	"rasp_id":"47af9da31ec3f233f35a25776f5e06086ebf239f",
    	"plugin_md5":"47af9da31ec3f2ebf239f", 
        "plugin_version":"2018-08-15 11:11:12", 
    	"config_time":1536302712000,
        "hostname":"rasp-host"
    }
    {
    	"status":0, 		
    	"description":"ok", 
    	"data":{
    		"plugin":{
    			"version":"2018-08-15 11:11:12"
    			"md5":"569e8ea7a16123492b5878920fd36985",
    			"plugin":"/*javascript*/"
    		},
    		"config_time":1536303412000,
    		"config":{
    			"block.content_html": "</script><script>location.href=\"https://rasp.baidu.com/blocked2/?request_id=%request_id%\"</script>",
                "block.content_json": "{\"xxxx\":\"xxxxxx\"}",
                "block.content_xml": "<?xml version=\"1.0\"?><doc><error>true</error><reason>Request blocked by OpenRASP</reason><request_id>%request_id%</request_id></doc>",
                "block.redirect_url": "https://rasp.baidu.com/blocked/?request_id=%request_id%",
                "block.status_code": 302,
                "body.maxbytes": 4096,
                "clientip.header": "ClientIP",
                "debug.level": 0,
                "decompile.enable": true,
                "inject.custom_headers": {},
                "log.maxbackup": 30,
                "log.maxburst": 100,
                "ognl.expression.minlength": 30,
                "plugin.filter": true,
                "plugin.maxstack": 100,
                "plugin.timeout.millis": 100,
                "syslog.enable": false,
                "syslog.facility": 1,
                "syslog.tag": "OpenRASP",
                "syslog.url": "",
                "hook.white":{
                    "www.test.com/test1":[sql,ssrf],
                    "www.test.com/test2":[sql,ssrf],
                    "*":[all]
                }
    		}
    	}
    }
    {
    	"rasp_id":"569e8ea7a16123492b5878920fd36985",
    	"time":15665422321,
    	"request_sum":10000
    }
    {
    	"status":0, 		
    	"description":"ok",
    	"data":{}
    }
    {
    	"status":0, 		
    	"description":"ok",
    	"data":{}
    }
    [
        {
            "rasp_id":"545e8336cf5b612f358ae51ff0466476",
            "app_id":"5f1b8ba39b85e2f857f6b219156470e648fd2b4f",
            "server_nic": [{
                "name": "cscotun0",
                "ip": "172.23.232.63"
            }, {
                "name": "vmnet8",
                "ip": "172.16.75.1"
            }, {
                "name": "docker0",
                "ip": "172.17.0.1"
            }, {
                "name": "eno1",
                "ip": "172.20.94.78"
            }],
            "event_type": "attack",
            "attack_source": "127.0.0.1",
            "attack_type": "command",
            "plugin_name": "official",
            "url": "http://127.0.0.1:8396/vulns/004-command-1.jsp?cmd\u003dcp+/etc/passwd+/tmp/",
            "header": {
                "cookie": "JSESSIONID\u003dF11746396310A9E88FF1C44F98B958EE; ADMINCONSOLESESSION\u003dv165dQlfGTrfpxDBdDkhTHmqVR2gYbMP57pJyRvyKsD4RcTC12N0!2052002414; JSESSIONID\u003dTkSZdRVGCnpRjYwp15dtrlnZRcFrq2q2qQ2H1fchYLstJX1BkvpF!-354254474",
                "connection": "keep-alive",
                "accept-language": "zh,en-US;q\u003d0.9,en;q\u003d0.8,zh-CN;q\u003d0.7",
                "host": "127.0.0.1:8396",
                "sec-fetch-mode": "navigate",
                "accept": "text/html,application/xhtml+xml,application/xml;q\u003d0.9,image/webp,image/apng,*/*;q\u003d0.8,application/signed-exchange;v\u003db3",
                "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/76.0.3809.87 Chrome/76.0.3809.87 Safari/537.36",
                "accept-encoding": "gzip, deflate, br",
                "referer": "http://127.0.0.1:8396/vulns/004-command-1.jsp",
                "sec-fetch-site": "same-origin",
                "upgrade-insecure-requests": "1"
            },
            "server_type": "tomcat",
            "client_ip": "",
            "server_hostname": "tyy-work",
            "source_code": "",
            "request_method": "get",
            "plugin_confidence": 90,
            "request_id": "d65f0a1cf2e24951b3eb34ed25378e75",
            "intercept_state": "block",
            "server_version": "8.5.30.0",
            "server_ip": "127.0.0.1",
            "attack_params": {
                "command": "cp /etc/passwd /tmp/",
                "stack": ["java.lang.UNIXProcess.\u003cinit\u003e", "java.lang.ProcessImpl.start", "java.lang.ProcessBuilder.start", "java.lang.Runtime.exec", "java.lang.Runtime.exec", "java.lang.Runtime.exec", "org.apache.jsp._004_002dcommand_002d1_jsp._jspService", "org.apache.jasper.runtime.HttpJspBase.service", "javax.servlet.http.HttpServlet.service", "org.apache.jasper.servlet.JspServletWrapper.service", "org.apache.jasper.servlet.JspServlet.serviceJspFile", "org.apache.jasper.servlet.JspServlet.service", "javax.servlet.http.HttpServlet.service", "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter", "org.apache.catalina.core.ApplicationFilterChain.doFilter", "org.apache.tomcat.websocket.server.WsFilter.doFilter", "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter", "org.apache.catalina.core.ApplicationFilterChain.doFilter", "org.apache.catalina.core.StandardWrapperValve.invoke", "org.apache.catalina.core.StandardContextValve.invoke", "org.apache.catalina.authenticator.AuthenticatorBase.invoke", "org.apache.catalina.core.StandardHostValve.invoke", "org.apache.catalina.valves.ErrorReportValve.invoke", "org.apache.catalina.valves.AbstractAccessLogValve.invoke", "org.apache.catalina.core.StandardEngineValve.invoke", "org.apache.catalina.connector.CoyoteAdapter.service", "org.apache.coyote.http11.Http11Processor.service", "org.apache.coyote.AbstractProcessorLight.process", "org.apache.coyote.AbstractProtocol$ConnectionHandler.process", "org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun", "org.apache.tomcat.util.net.SocketProcessorBase.run", "java.util.concurrent.ThreadPoolExecutor.runWorker", "java.util.concurrent.ThreadPoolExecutor$Worker.run", "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run", "java.lang.Thread.run"]
            },
            "plugin_message": "WebShell detected - Executing command: cp /etc/passwd /tmp/",
            "path": "/vulns/004-command-1.jsp",
            "target": "127.0.0.1",
            "event_time": "2019-08-13T20:24:51+0800",
            "plugin_algorithm": "command_userinput",
            "body":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        }
    ]
    {
    	"status":0, 		
    	"description":"ok", 
    	"data":{
    		"count":1
    	}
    }
    {
        "dependency": [{
            "product": "rasp-engine",
            "version": "1.3.0",
            "vendor": "com.baidu.openrasp",
            "path": "/home/work/rasp/rasp-engine.jar",
            "source": "pom"
        }, {
            "product": "rasp-engine",
            "version": "7.0.78",
            "vendor": "Apache Software Foundation",
            "path": "/home/work/rasp/rasp-engine.jar",
            "source": "manifest_implementation"
        }, {
            "product": "Bootstrap",
            "version": "7.0.78",
            "vendor": "Apache Software Foundation",
            "path": "/home/work/rasp/bin/bootstrap.jar",
            "source": "manifest_implementation"
        }],
        "rasp_id": "3089c8d2672efd1ef5c3e322d9e8fcb1"
    }
    {
        "data": {
        },
        "description": "ok",
        "status": 0
    }
    [
    	{
            "app_id": "fcbc4d8ac6bcaac27b1cc4703e5339a4aa6e8a1c",
    		"rasp_id": "426199dc7a15cce89b0c937a65a24a23",
            "event_time": "2019-01-04T09:56:48+0000",
            "event_type": "security_policy",
            "message": "Java security baseline - should not start application server with root account",
            "policy_id": "3002",
            "policy_params": {
                "pid": 431,
                "stack":["java.lang.UNIXProcess.\u003cinit\u003e", "java.lang.ProcessImpl.start", "java.lang.ProcessBuilder.start", "java.lang.Runtime.exec", "java.lang.Runtime.exec", "java.lang.Runtime.exec", "org.apache.jsp._004_002dcommand_002d1_jsp._jspService", "org.apache.jasper.runtime.HttpJspBase.service", "javax.servlet.http.HttpServlet.service", "org.apache.jasper.servlet.JspServletWrapper.service", "org.apache.jasper.servlet.JspServlet.serviceJspFile", "org.apache.jasper.servlet.JspServlet.service", "javax.servlet.http.HttpServlet.service", "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter", "org.apache.catalina.core.ApplicationFilterChain.doFilter", "org.apache.tomcat.websocket.server.WsFilter.doFilter", "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter", "org.apache.catalina.core.ApplicationFilterChain.doFilter", "org.apache.catalina.core.StandardWrapperValve.invoke", "org.apache.catalina.core.StandardContextValve.invoke", "org.apache.catalina.authenticator.AuthenticatorBase.invoke", "org.apache.catalina.core.StandardHostValve.invoke", "org.apache.catalina.valves.ErrorReportValve.invoke", "org.apache.catalina.valves.AbstractAccessLogValve.invoke", "org.apache.catalina.core.StandardEngineValve.invoke", "org.apache.catalina.connector.CoyoteAdapter.service", "org.apache.coyote.http11.Http11Processor.service", "org.apache.coyote.AbstractProcessorLight.process", "org.apache.coyote.AbstractProtocol$ConnectionHandler.process", "org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun", "org.apache.tomcat.util.net.SocketProcessorBase.run", "java.util.concurrent.ThreadPoolExecutor.runWorker", "java.util.concurrent.ThreadPoolExecutor$Worker.run", "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run", "java.lang.Thread.run"]
            },
            "server_hostname": "820c2691f452",
            "server_nic": [{
              "ip": "172.17.0.2",
              "name": "eth0"
            }],
            "server_type": "tomcat",
            "server_version": "7.0.78.0"
    	}
    ]
    {
    	"status":0, 		
    	"description":"ok", 
    	"data":{
    		"count":1
    	}
    }
    [
    	{
    	  "message": "HTTP request to http://scloud.baidu.com:8086/v1/agent/rasp failed:",
    	  "server_nic": [{
    		  "name": "en0",
    		  "ip": "172.24.182.127"
    	  }],
    	  "stack_trace": "sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)\nsun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)\nsun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)\njava.lang.reflect.Constructor.newInstance(Constructor.java:526)\nsun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1676)\nsun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1674)\njava.security.AccessController.doPrivileged(Native Method)\nsun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1672)\nsun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1245)\ncom.baidu.openrasp.cloud.CloudHttp.request(CloudHttp.java:64)\ncom.baidu.openrasp.cloud.Register$RegisterThread.run(Register.java:54)\njava.lang.Thread.run(Thread.java:745)\n",
    	  "level": "WARN",
    	  "event_time": "2019-01-11T13:36:46+0800",
    	  "app_id": "9b3554a97673f1f8f5c929310298037a660d3b7a",
    	  "pid": 58353,
    	  "server_hostname": "localhost",
    	  "rasp_id": "3089c8d2672efd1ef5c3e322d9e8fcb1"
      }
    ]
    {
    	"status":0, 		
    	"description":"ok", 
    	"data":{
    		"count":1
    	}
    }
    {
    	"status":0, 		
    	"description":"ok"
    }
    {
        "order":"startTask",
        "data":{
        		.....
        }
    }
    {
        "data":{
            "data":{
                "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
            },
            "description":"ok",
            "register":2,
            "status":0
        },
        "description":"ok",
        "status":0
    }
    {
        "data":{
            "version":"1.3"
        },
        "description":"ok",
        "status":0
    }
    {
        "order":"startTask",
        "data":{
        		"host":"1.2.3.4", 
        		"port": 80, 
            "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
        }
    }
    {
        "data":{
            "data":{
                "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
            },
            "description":"ok",
            "register":2,
            "status":0
        },
        "description":"ok",
        "status":0
    }
    {
        "order":"setConfig",
        "data":{
            "host":"1.2.3.4",
            "port":80,
            "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec",
            "config":{
                "scan_plugin_status":{
                    "command_basic":{
                        "description":"基础命令注入漏洞检测插件",
                        "enable":true,
                        "show_name":"命令注入检测插件"
                    },
                  ...
                },
                "scan_rate":{
                    "max_concurrent_request":20,
                    "max_request_interval":1000,
                    "min_request_interval":0
                },
                "white_url_reg":"^/path/eg",
                "scan_proxy":"http://127.0.0.1:8080"
            }
        }
    }
    {
        "data":{
            "data":{
                "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
            },
            "description":"ok",
            "register":2,
            "status":0
        },
        "description":"ok",
        "status":0
    }
    {
        "order":"getConfig",
        "data":{
        		"host":"1.2.3.4", 
        		"port": 80, 
            "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
        }
    }
    {
        "data":{
            "data":{
                "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec",
                "scan_plugin_status":{
                    "command_basic":{
                        "enable":true,
                        "show_name":"命令注入检测插件",
                        "description":"xxxx"
                    }
                },
                "scan_rate":{
                    "max_concurrent_request":10,
                    "max_request_interval":1000,
                    "min_request_interval":0
                },
                "white_url_reg":"^/logout"
            },
            "description":"ok",
            "register":2,
            "status":0
        },
        "description":"ok",
        "status":0
    }
    {
        "order":"stopTask",
        "data":{
            "scanner_id":0,
            "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
        }
    }
    {
        "data":{
            "data":{
                "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
            },
            "description":"ok",
            "register":2,
            "status":0
        },
        "description":"ok",
        "status":0
    }
    {
        "order":"getAllTasks",
        "data":{
            "page":1,
            "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
        }
    }
    {
        "status":0,
        "description":"ok",
        "data":{
            "total":0,
            "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec",
            "result":[
              {
                "host":"127.0.0.1",
                "port":8010,
                "total":2,
                "scanned":0,
                "failed":0,
                "last_time":1571303703
              }  
            ]
        }
    }
    {
        "order":"cleanTask",
        "data":{
            "host":"1.2.3.4",
            "port":80,
            "url_only":true,
            "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
        }
    }
    {
        "data":{
            "data":{
                "app_id":"593342c72eb78fc8e7393d0a87b8f3fc54dfbec"
            },
            "description":"ok",
            "register":2,
            "status":0
        },
        "description":"ok",
        "status":0
    }
    postgres:9-alpine

    QPS

    89.2

    86.3

    -3.25%

    响应时间

    1.33s

    1.406s

    TPS

    2062

    2026

    -1.74%

    响应时间

    0.0039s

    0.004s

    QPS

    280

    269

    -3.9%

    响应时间

    100ms

    105ms

    QPS

    20550

    20200

    -1.7%

    响应时间

    233ms

    237ms

    -1.72%

    QPS

    55.09

    54.02

    -1.94%

    响应时间

    1.43s

    1.46s

    -2.1%

    RASP 群2: 595568655
    RASP 群1(满): 259318664
    https://github.com/baidu/openrasp/issues/new
    百度安全应急响应中心
    WEBDIR+ - WebShell 扫描服务
    exec
    shell_exec
    proc_open
    popen
    pcntl_exec
    passthru
    system
    exec
    shell_exec
    proc_open
    popen
    pcntl_exec
    dir
    scandir
    opendir
    echo
    file
    readfile
    file_get_contents
    fopen
    SplFileObject::__construct
    file_put_contents
    fopen
    SplFileObject::__construct
    file_put_contents
    copy
    rename
    move_uploaded_file
    include
    eval
    assert(仅PHP5)
    mysql_query(仅PHP5)
    mysqli_query
    mysqli::query
    mysqli_real_query
    mysqli::real_query
    mysqli_prepare
    mysqli::prepare
    PDO::query
    PDO::exec
    PDO::prepare
    pg_query
    pg_send_query
    pg_prepare
    SQLite3::query
    SQLite3::exec
    SQLite3::querySingle
    curl_exec
    mysqli_real_connect
    PDO::__construct
    pg_connect
    pg_pconnect

    data

    请求结果具体数据

    algorithm_config

    插件内的算法配置

    plugin

    插件内容

    algorithm_config

    插件内的算法配置

    APP 描述信息

    selected_plugin_id

    String

    否

    APP 下发的插件

    config_time

    上一次下发 RASP 相关配置的时间

    general_config

    通用配置,用于给 RASP 下发

    whitelist_config

    拦截白名单配置,用于给 RASP 下发

    selected_plugin_id

    被选中下发的插件 id

    email_alarm_conf

    email 报警配置

    ding_alarm_conf

    钉钉报警配置

    http_alarm_conf

    http 报警配置

    attack_type_alarm_conf

    如果没有该配置,那么将会按照所有攻击类型会触发所有的报警方式,配置中的 key 是攻击类型,value 是该类型会触发的报警方式的列表,目前报警方式包括 ding,http,email

    algorithm_config

    app 当前选中插件的算法配置

    分页页码

    perpage

    int

    否

    每页数据条数

    邮件报警配置

    ding_alarm_conf

    Object

    否

    钉钉报警配置

    http_alarm_conf

    Object

    否

    http 报警配

    email_alarm_conf.enable

    bool

    否

    email 报警开关,默认 false

    email_alarm_conf.tls_enable

    bool

    否

    是否打开 邮件 tls 认证,默认 false

    email_alarm_conf.server_addr

    String

    是

    邮件服务器地址

    email_alarm_conf.username

    String

    否

    邮件账号用户名

    email_alarm_conf.password

    String

    否

    邮件账号密码

    email_alarm_conf.subject

    String

    否

    邮件主题

    email_alarm_conf.recv_addr

    String Array

    是

    邮件报警发送的邮件地址

    ding_alarm_conf.enable

    bool

    否

    钉钉报警开关,默认 false

    ding_alarm_conf.agent_id

    String

    是

    钉钉报警应用 Agent ID

    ding_alarm_conf.corp_id

    String

    是

    钉钉报警的企业 ID

    ding_alarm_conf.corp_secret

    String

    是

    钉钉报警的企业秘钥

    ding_alarm_conf.recv_user

    String Array

    否

    钉钉报警接收的用户列表,列表每个元素是一个用户的ID,不能和 recv_party 参数同时为空

    ding_alarm_conf.recv_party

    String Array

    否

    钉钉报警接收的部门列表,列表每个元素是一个部门的ID,不能和 recv_user 参数同时为空

    http_alarm_conf.enable

    String

    否

    HTTP 报警推送开关,默认false

    http_alarm_conf.recv_addr

    String Array

    是

    HTTP 报警接收地址列表

    general_alarm_conf.alarm_check_interval

    Int

    是

    邮件报警间隔(应用于所有App)

    kafka_alarm_conf.url

    String

    是

    kafka服务器的地址

    kafka_alarm_conf.user

    String

    否

    kafka服务器的用户名

    kafka_alarm_conf.pwd

    String

    否

    kafka服务器的密码

    kafka_alarm_conf.enable

    Bool

    是

    是否开启kafka推送

    kafka_alarm_conf.topic

    String

    是

    写入kafka的topic名称

    APP 使用的编程语言

    description

    String

    否

    APP 描述信息

    单页数量

    RASP 版本

    hostname

    String

    否

    RASP 所在的主机名,该字段支持模糊搜索,并同时搜索 hostname 和 register_ip 字段

    register_ip

    String

    否

    RASP 访问云控后台所使用的 IP 地址

    language

    String

    否

    编程语言

    language_version

    String

    否

    语言版本

    server_type

    String

    否

    服务器类型

    server_version

    String

    否

    服务器版本

    rasp_home

    String

    否

    RASP 安装目录

    plugin_version

    String

    否

    插件版本

    heartbeat_interval

    int

    否

    心跳间隔时间,单位:秒

    online

    bool

    否

    是否在线

    register_time

    int

    否

    注册时间,毫秒时间戳

    host_type

    String

    否

    rasp 所在的主机类型

    server_type

    服务器类型

    server_version

    服务器版本

    rasp_home

    RASP 安装目录

    plugin_version

    插件版本

    heartbeat_interval

    心跳间隔时间,单位:秒

    online

    是否在线

    last_heartbeat_time

    上次心跳时间,毫秒时间戳

    register_time

    注册时间,毫秒时间戳

    host_type

    主机类型,例: docker

    environ

    进程环境变量

    注册 ip

    expire_time

    int

    否

    单位/秒,删除超时时间超过该值的 rasp

    host_type

    String

    否

    rasp 所在的主机类型

    rasp_count

    影响主机数量

    rasp_id

    类库信息所属的RASP

    register_ip

    RASP 所在机器 IP 地址

    search_string

    source

    tag

    vendor

    厂商

    version

    类库的版本号

    关键词

    hostname

    String

    否

    主机名称

    rasp_count

    影响主机数量

    rasp_id

    类库信息所属的RASP

    register_ip

    RASP 所在机器 IP 地址

    search_string

    source

    tag

    vendor

    厂商

    version

    类库的版本号

    操作日志的结束时间,毫秒时间戳

    ip

    操作请求发起者相对于云控后台的 IP

    结束时间

    interval

    String

    是

    聚合粒度,hour小时,month月,day天

    time_zone

    String

    是

    聚合使用的时区

    结束时间

    interval

    String

    是

    聚合粒度,hour小时,month月,day天

    time_zone

    String

    是

    聚合使用的时区

    结束时间

    size

    int

    是

    聚合的攻击类型数目

    结束时间

    size

    int

    是

    聚合的 UA 类型数目

    漏洞所属的 RASP

    server_hostname

    String

    否

    漏洞发生的机器的 hostname

    attack_source

    String

    否

    攻击来源 ip

    url

    String

    否

    攻击的 url

    intercept_state

    String Array

    否

    拦截状态,可选值:block、info,数组为空则什么都不返回,没有该参数,或者参数为null,则不过滤此参数

    local_ip

    String

    否

    攻击的机器的 ip

    start_time

    int

    是

    开始时间

    end_time

    int

    是

    结束时间

    所属的 RASP

    server_hostname

    String

    否

    攻击发生的机器的 hostname 或者 IP,支持模糊搜索

    attack_source

    String

    否

    攻击来源 ip,支持模糊搜索

    url

    String

    否

    攻击的 url,包含搜索,支持模糊搜索

    intercept_state

    String Array

    否

    拦截状态,可选值:block、info,数组为空则什么都不返回,没有该参数,或者参数为null,则不过滤此参数

    local_ip

    String

    否

    攻击的机器的 ip

    request_id

    String

    否

    请求 id

    stack_md5

    String

    否

    攻击栈的 MD5

    plugin_message

    String

    否

    插件返回的监测信息,支持模糊搜索

    start_time

    int

    是

    开始时间

    end_time

    int

    是

    结束时间

    该字段可以多选,数组为空则什么都不返回,没有该参数,或者参数为null,则不过滤此参数

    rasp_id

    String

    否

    所属的 RASP

    language

    String

    否

    RASP 使用的开发语言

    crash_message

    String

    否

    崩溃报警信息,支持模糊搜索

    start_time

    int

    是

    开始时间

    end_time

    int

    是

    结束时间

    所属的 RASP

    server_hostname

    String

    否

    机器的 hostname 或者 IP,支持模糊搜索

    local_ip

    String

    否

    机器的 ip

    message

    String

    否

    基线报警信息,支持模糊搜索

    start_time

    int

    是

    开始时间

    end_time

    int

    是

    结束时间

    机器的 hostname 或 IP ,支持模糊搜索

    local_ip

    String

    否

    机器的 ip

    message

    String

    否

    搜索异常信息包含该值的异常日志,支持模糊搜索

    start_time

    int

    是

    开始时间

    end_time

    int

    是

    结束时间

    RASP 所在机器的主机名

    register_ip

    String

    是

    RASP 所在机器 IP 地址

    language

    String

    是

    RASP 使用的开发语言

    language_version

    String

    是

    RASP 使用的开发语言版本

    server_type

    String

    是

    RASP 使用的服务器种类

    server_version

    String

    是

    RASP 使用的服务器版本号

    heartbeat_interval

    int

    是

    心跳间隔时间,单位:秒

    rasp_home

    String

    否

    RASP 安装目录

    host_type

    String

    否

    主机类型,如 docker

    environ

    String

    否

    服务进程环境变量

    language_version

    RASP 使用的开发语言版本

    server_type

    RASP 使用的服务器种类

    server_version

    RASP 使用的服务器版本号

    heartbeat_interval

    心跳间隔时间,单位:秒

    rasp_home

    RASP 安装目录

    last_heartbeat_time

    上次心跳时间,如果还没有心跳,就是注册时间

    online

    rasp 是否在线,此处该值应为 true

    host_type

    主机类型,如 docker

    plugin_version

    插件版本,注册时还没有下发插件,所以为空

    plugin_name

    插件名称,注册时还没有下发插件,所以为空

    plugin_md5

    插件内容校验和,注册时还没有下发插件,所以为空

    environ

    服务进程环境变量

    register_time

    注册的时间戳,单位:秒

    当前插件的版本

    config_time

    int

    否

    后台配置的最后修改时间,如果没有该字段或者为 0,当做没有下发过配置处理,则会下发配置

    hostname

    String

    否

    主机 hostname,用于运行时更新

    请求数量,默认 0

    RASP 语言

    hostname

    String

    否

    主机名

    版本号

    vendor

    String

    是

    厂商

    path

    String

    是

    类库依赖路径

    source

    String

    否

    来源

    扫描目标端口

    app_id

    String

    是

    APP 唯一标识

    扫描目标端口

    app_id

    String

    是

    APP 唯一标识

    scan_plugin_status

    Object

    是

    配置参数

    scan_rate

    Object

    是

    扫描速率设置

    white_url_reg

    String

    否

    url白名单正则

    scan_proxy

    String

    否

    扫描请求使用的http代理

    扫描目标端口

    app_id

    String

    是

    APP 唯一标识

    APP 唯一标识

    last_time

    最后收到任务的时间

    扫描目标端口

    url_only

    Bool

    是

    是否仅清空url

    app_id

    String

    是

    APP 唯一标识

    https://rasp.baidu.com/doc/setup/others.html
    javassist
    package com.baidu.openrasp.hook;
    
    
    import com.baidu.openrasp.HookHandler;
    import javassist.CannotCompileException;
    import javassist.CtClass;
    import javassist.NotFoundException;
    
    import java.io.IOException;
    
    /**
     * 自定义hook点继承自AbstractClassHook
     */
    public class MyHook extends AbstractClassHook {
        /**
         * 返回自定义的hook点类型名称
         */
        @Override
        public String getType() {
            return "string_replace";
        }
    
        @Override
        protected void hookMethod(CtClass ctClass) throws IOException, CannotCompileException, NotFoundException {
            /*
             * 获取要插入函数开始的代码
             * 参数 "$0,$1,$2" 表示获取带插入函数的 this,第一个参数以及第二个参数
             * 然后用获取的参数调用HookHandler.checkStringReplaceEnter这个静态方法
             * 最后三个参数代表HookHandler.checkStringReplaceEnter方法的参数类型
             */
            String srcBefore = getInvokeStaticSrc(HookHandler.class, "checkStringReplaceEnter",
                    "$0,$1,$2", String.class, String.class, String.class);
            // 在String.replace函数开始的地方,插入刚才获取的代码片段,第三个个参数为函数签名信息
            insertBefore(ctClass, "replace", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", srcBefore);
            /*
             * 获取要插入函数结束的代码
             * 参数 "$_" 代表获取待插入函数的返回值
             * 最后用获取的内容调用HookHandler.checkStringReplaceExit这个静态方法
             */
            String srcAfter = getInvokeStaticSrc(HookHandler.class, "checkStringReplaceExit", "$_", String.class);
            /*
             * 在String.replace函数结束的地方,插入刚才获取的代码片段,第三个个参数为函数签名信息
             * 最后一个参数为true代表在异常退出的地方异常会插入响应的代码段
             */
            insertAfter(ctClass, "replace", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", srcAfter, true);
        }
    
        /**
         * 匹配需要hook的类名
         */
        @Override
        public boolean isClassMatched(String className) {
            return "java.lang.String".equals(className);//该hook点hook的是java.lang.String类
        }
    
    
    }
    public CustomClassTransformer() {
        hooks = new HashSet<AbstractClassHook>();
    
        addHook(new MyHook()); // 将hook点加入transformer
    }
    public enum Type {
            // 添加相应的检测类型,checker使用JsChecker代表该hook点的参数使用js插件检测
            // 除了JsChecker之外还可以根据com.baidu.openrasp.plugin.checker包下面的其他checker进行自定义checker
            // 第一个参数是检测类型名称,第二个是检测使用的checker
            REPLACE("replace", new JsChecker()),
            
            String name;
            Checker checker;
            Type(String name, Checker checker) {
                this.name = name;
                this.checker = checker;
            }
            @Override
            public String toString() {
                return name;
            }
        }
    public static void checkStringReplaceEnter(String str,String regex,String replacement){
         // 如下是构造参数并进入checker的操作
         // 构造参数
         HashMap<String, Object> param = new HashMap<String, Object>();
         param.put("str",str);
         param.put("regex", regex);
         param.put("replacement", replacement);
    
         // 进入第三步中设置的checker,第一个参数是检测类型名称,第二个参数是检测参数map
         doCheck(CheckParameter.Type.REPLACE, param);
    }
    #include "openrasp_hook.h"
    HOOK_FUNCTION_EX(hook_function, hook_class, hook_type);
    void pre_hook_class_hook_function_hook_type(OPENRASP_INTERNAL_FUNCTION_PARAMETERS)
    {
    	//do something
    	...
    }
    void post_hook_class_hook_function_hook_type(OPENRASP_INTERNAL_FUNCTION_PARAMETERS)
    {
    	//do something
    	...
    }
    修复快手公司反馈的字节流Hook错误的问题 #293
  • 修复@killer1278反馈的NIO文件删除hook点类型错误的问题 #280

  • 修复奇安信公司反馈的依赖库代码问题 #265

  • 合入@jekkay的补丁,修复非HTTP攻击报警数据会被覆盖的问题 #264

  • 合入@strawberrybiscuits的3个补丁,修复Apache Dubbo支持问题 #313、#314、#315

  • 合入安天公司的多个补丁,由@xuing提供

    • 修复某些情况下虚拟网卡mac可能为空的问题 #260

    • 修复Windows JDK9以上版本命令执行hook失效问题 #271

    • 修复MySQL 8.X ClientPreparedStatement Hook无效的问题 #277

  • 合入快手公司多个补丁,由@Venscor提供

    • 修复配置合法性校验代码中,未能检查key长度的问题 #307

    • 修复BESResponseBodyHook参数个数错误问题 #306

  • 合入东方通官方提供的补丁

    • 增加TongWeb 7.X版本支持 #318

  • 增加JNDI检测点,并增加一个阻断所有JNDI加载的算法

  • 增加DNS检测点,并增加DNSLog域名的检测算法

  • 安装程序增加-debuglevel参数,支持安装时修改调试级别

  • 修复清空数据时,依赖库信息没有同步删除的问题

    PHP文件上传,展示文件存储路径

  • 增加崩溃信息展示

  • 合并 999-event-logger 功能到官方插件,并支持后台开启

  • 当开启云控后,将不再加载 jnotify
  • 当客户端开启 HTTPS 时,修复 SunJSSE 异常

  • 合入 @liergou9981 的补丁,增加nio支持、优化iast.js #229

  • 修复 SpringBoot 某些情况下采集不到依赖的问题
  • 对于非HTTP请求,修复报警里缺少资产IP的问题

  • 主机搜索接口,改为批量搜索模式

  • 支持保留插件配置,开源版本仅保留 action 字段

  • 支持导出应用数据,并导入到商业版

  • 支持清理离线超过N天的主机,默认是1天,可配置

  • 修复JSON请求数据展示不正确的问题

  • 修复当客户端时间不正确,后台不会发出报警的问题

  • 修复弱口令基线报警,未能正确展示数据库类型的问题

  • Java POM 信息

  • PHP composer.json

  • 补全 SQL 异常检测点

    • PHP 增加 PostgreSQL、SQLite 异常监控

    • Java 增加 PostgreSQL、SQLite、Oracle、SQLServer、HSQLDB、DB2 监控

  • 弱口令列表支持远程下发

  • 加强单机版配置校验

    • 当 yaml 最外层键值无法识别时,打印日志

  • 报警发送间隔改为前端配置

  • 增加报警日志去重,根据请求编号、堆栈MD5、攻击类型计算

  • 后台日志增加大小、文件数量限制,可配置

  • 增加HTTP响应敏感信息泄漏检查,如银行卡、身份证、手机号

    若要测试监控效果,可执行 kill -11 PID 命令触发段错误

    支持在线升级,但执行过程中请不要在后台修改配置

    每隔一段时间采集一次单核CPU占用率,若超过阈值且连续3次,启动熔断机制

  • 当下次采集到的占用率低于阈值,自动恢复防护

  • 本功能默认关闭,采集间隔、CPU占用率均可配置

  • 修复 plugin.filter 在 include hook 点不生效的问题

  • 修复日志推送完毕后,log4j 缓存不会清理的问题(感谢 @忆相逢 反馈)

  • 修复当有多个文件上传时,只会处理第一个文件的问题

  • 修复配置更新失败时,缺少详情的问题

  • 修复 request hook 点无法拦截的问题(感谢 @Looke 反馈)

  • 修复 cloud.X 等配置可以远程下发的问题

  • 修复 SQL prepared statements 产生异常时,不会进入检测插件、不会记录SQL异常的问题

  • 文件上传增加 dest_path/dest_realpath 两个参数(仅PHP版本)
  • 新增 loadLibrary_unc 算法,当要加载的类库来自 UNC 路径时拦截

  • 优化内存占用,减少50%左右
  • 启动时打印 RASP ID,方便排查

  • 解决当 Tomcat 主动 flush() 时不会检测 XSS 的问题

    • 同时优化了XSS检测效率

    • XSS 拦截时不再抛出异常(其他攻击类型还是会抛出)

  • 默认在后面附加
  • 解决 jacoco 的兼容性问题

  • 加强报警搜索功能

  • 支持检测算法高级配置选项

  • 修复 Tomcat 下面 xss 拦截之后不会跳转的问题
  • 修复一次心跳失败后,再也不会心跳的bug

  • 解决 Tomcat 5 下面 html 注入功能不正常的问题

  • 修复不重启安装,卸载后心跳线程残留问题

  • 与PHP版本统一 log.maxbackup 逻辑,配置为1时保留今天和昨天的日志

  • 修复应用加固里 nosniff 拼错的问题,用户保存一次配置即可修复

    rasp-install 增加 SELinux、open_basedir 检查,避免安装后无法使用的问题

    新增 JDK 11 支持
  • 增加应用环境变量采集

  • 加入实验性的不重启安装、不重启卸载功能,暂不支持不重启升级

  • 解决 OpenRASP 报警日志跟 nginx/apache 访问日志无法一一对应的问题
  • 删除 webshell_include 检测点,统一使用JS插件检测

  • 在有攻击的情况下,大幅度提升性能
    、
    block.content_json
    模板来实现
  • 主要为了处理 ajax 请求误报的情况

  • 增加 plugin.filter 配置

    • 适用于 include/rename/readFile 等 hook 点

    • 若开启,当文件不存在时,将不会进入检测逻辑(默认开启)

  • 增加获取客户端真实IP的能力

    • 用户可以在 openrasp.clientip_header 指定从哪个header里获取客户端真实IP

    • 默认是 clientip 请求头

    • 报警日志里的字段为 client_ip

  • 增加 Dubbo RPC 基础数据类型支持

    • JS 插件可以获取到RPC参数,名字为 openrasp-dubbo-X

  • 若完全没有命令执行需求请手动修改 command_other 算法开关为 block

  • 此开关不影响反序列化命令执行的拦截,或者其他算法的检测

  • SSRF

    • 增加对特殊协议的检测,以及对应的检测开关。包括 php://、file:// 等等

    • 用户输入匹配算法,增加对 127.X.X.X 的识别

    • 增加 @dos_man 反馈的一个 dnslog 地址 *.tu4.org

  • 文件目录遍历

    • 修复一个 @Leesec 报告的 /../../ 检出绕过问题

  • PHP 堆栈检测算法

    • 修复 @Ezreal 报告的一个 call\_user\_func 误报问题

  • 后门上传检测

    • 增加对 rename 的监控,防止通过重命名写入 webshell

  • SQL 注入

    • 增加全局LRU缓存,当检测结果为 ignore 时不再重复检测,以提高性能

    • 用户输入匹配算法,参数最短长度可配置

    • 增加对 into outfile 的检测,并增加相应的检测开关

  • 待应用启动后,OpenRASP 会自动生成新的日志配置文件
  • 解决高版本 JDK 兼容性问题,ISSUE: rhino jdk8u162 兼容性问题 #98

  • 为了降低 Hook 点开发成本,Hook 框架改为 JavaAssist

  • RaspInstall - OpenRASP 自动安装程序

    • 为了支持自动卸载,我们调整了 RaspInstall.jar 的命令行参数

      • java -jar RaspInstall.jar -install /home/tomcat

      • java -jar RaspInstall.jar -uninstall /home/tomcat

  • 为了检测非常规的反序列化、命令执行漏洞,当命令执行来自非 HTTP 请求,也将会进入检测点
  • 适合检测 CVE-2016-8735、CVE-2018-1270 等漏洞

  • 增加 jnotify 异常的获取

    解决日志模块一处内存泄露问题

    PHP 安全基线检查

    • INI 配置审计

      • allow_url_include

      • expose_php

    • 数据库连接账号审计

  • 其他 PHP 版本支持的功能

    • SQL 慢查询审计

  • 测试用例增强

    • 增加 PHP 测试用例

    • 增加简易导航页面

    • 统一增加可点击链接,减少对命令行的依赖

  • 增加PHP版本性能测试报告

    • discuz/wordpress 性能损耗,都在 2% 左右

  • 开放基于 docker 的自动化漏洞测试环境 - app-env-docker

  • 为数据库管理器检测算法,单独增加控制开关
  • SSRF 检测算法增强

    • 当请求的URL来自用户输入,且地址是内网地址,将会被并拦截

  • Java - 反序列化检测

    • 拦截通过 ysoserial 执行命令的攻击代码

  • PHP - 增加对中国菜刀的检测

    • 基于堆栈识别异常,拦截文件管理器、命令执行操作

    • 基于用户输入识别,部分样本可直接拦截,e.g <?php eval($_POST[0]); ?>

  • PHP - 拦截异常的回调操作,e.g array_map("system", $whatever)

    • 具体拦截哪些回调,请参考 openrasp.callable_blacklists 默认配置

  • 基于反射的检查,移动到 command hook 点,检测能力不变

    修改 context.parameter 获取逻辑

    • 当JSP脚本读取过参数,JS插件才能读取到。这样可以减少误报,还可以提高SQLi算法#1的性能

  • 支持过期日志自动删除功能,默认保留最近30天日志

    • 通过给 log4j 1.X 打补丁来实现

    • 升级前,用户需要手动删除 rasp/conf/rasp-log4j.xml,程序会在启动时,自动生成新的

  • 默认 400

  • 安全基线

    • 支持 Tomcat Directory Index 检查

  • 预编译JS代码,启动时间由原先的 8s 下降到 3s 左右

  • 增加调试开关,用于收集hook点进入次数、时间消耗等等

  • 基线检查日志,增加调用堆栈信息
    • 当应用使用了高权限数据库账号,方便定位具体代码

  • 重写 catalina.sh 脚本修改逻辑,支持重复安装

    • 在修改的配置周围,增加类似 ### BEGIN OPENRASP ### 的标记

  • 新增数据库连接账号审计功能,e.g 使用 root 连接 mysql、使用 sa 连接 mssql 等等

  • 增加慢查询审计功能

    • 使用 SELECT 语句读取超过500行数据,可配置

  • 支持 Syslog TCP 方式传输报警日志

  • 禁止MySQL版本号注释,e.g /*!12345
  • 禁止数字常量比较操作,e.g SELECT 1 FROM dual WHERE 8778 <> 8778

  • 禁止使用黑名单里的函数,e.g load_file,benchmark,pg_sleep, ...

  • 字段改名为
    event_time
  • attack_params 字段改为 JSON 形式(以前是字符串,需要重新配置ES mapping)

  • manager/html 存在弱口令

  • JSESSION 未开启 httpOnly

  • tomcat 以 root启动

  • 默认的 webapps 没有删除

  • 当发生攻击,插件会额外输出 confidence 字段,用于标识检测结果可靠性

  • 所有响应增加 X-Protected-By: OpenRASP 响应头

  • 支持 HTTP 报警推送

  • 增加对 Jetty、JBoss 5~6 服务器的支持

  • 增加 log.maxstack 配置选项,用于配置 alarm 日志里最大堆栈

  • 感谢 @xizhimen 反馈
    #316
    来自 @superbaimo
    来自 @Lorisy
    增加熔断支持
    灰盒扫描器
    RASP.sql_tokenize
    检查 /jmx-console/HTMLAdaptor 是否开启认证
    增加新的拦截页面
    #84: request.setCharacterEncoding 编码问题
    新增 context.appBasePath 接口
    新增 session 操作接口
    addons
    RaspInstall 源代码开放
    CVE漏洞覆盖列表开放
    性能测试报告
    小恐龙页面

    添加新的插件API

    Java 版本

    Rhino 引擎支持将 Java 中的对象注册到 JavaScript 环境,并被 JavaScript 代码调用

    若你目前还不了解 Rhino,或者不了解如何使用 Rhino 向 JavaScript 环境中注册对象,请先查看 Rhino 官方文档:https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Embedding_tutorial#Expose_Java_APIs

    在 OpenRASP 中,我们注册了 stdout 对象和 sql_tokenize 方法到 JavaScript 环境中,你可以参照我们的代码编写。

    代码清单:

    com/baidu/openrasp/plugin/js/engine/JSStdout.java - stdout 对象实现

  • com/baidu/openrasp/plugin/js/engine/JSTokenizeSql.java - sql_tokenize 方法实现

  • com/baidu/openrasp/plugin/js/engine/JSContextFactory.java - 初始化 JavaScript 环境并注册对象

  • PHP 版本

    待补充

    display_errors
    yaml.decode

    安装测试用例

    为了验证OpenRASP的漏洞检测效果,或者IAST工具的漏洞检测能力,我们提供了多个测试用例,覆盖常见高危漏洞。测试用例的部署也非常简单,复制到 webroot/webapps 目录即可。

    下载测试用例

    常用镜像:

    • 国外镜像: github.com

    文件说明

    文件名
    适用服务器
    说明

    安装测试用例

    PHP 版本

    • 解压 php-vulns.tar.gz 到web目录,并通过浏览器访问

    Java 版本

    • 复制war包到webapps目录,等待一段时间后可通过浏览器访问。若web服务器未开启war包自动解压缩功能,可能需要重启web服务器生效。

    检测能力说明

    请参考如下几篇文章:

    用例使用说明

    在每个测试用例的页面里,我们都给出了正常的请求样例,以及攻击性的请求样例。你可以点击页面上的链接触发,也可以使用 curl 命令发出请求。具体请参考实际的页面:

    攻击拦截说明

    当攻击被拦截,OpenRASP 会显示特定的拦截页面,以及当前 Request ID,事后可根据这个ID去搜索对应的攻击日志。如果你发现 OpenRASP 无法拦截攻击,很有可能是安装没有成功,请参考 文档进行排查,并检查应用启动日志是否有错误,e.g catalina.out

    值得注意的是,默认我们不开启拦截,需要你关闭 系统设置 -> 防护设置 -> 将所有算法设置为「记录日志」模式 开关,保存后等待一个心跳周期生效;单机版需要参考 修改插件,才能开启拦截。

    最后,若要了解报警里有哪些字段信息,请查看 文档。

    FAQ

    1. SpringBoot 如何安装 JSP 测试用例?

    请参考 这篇文章进行操作,或者使用我们的servlet版本测试用例

    2. OpenRASP没有产生报警

    如果OpenRASP没有产生报警,请按照如下方法排查

    1. 确保OpenRASP引擎工作正常

      1. 检查OpenRASP是否支持你的服务器。此类问题Java环境出现较多,比如目前netty就不支持。排查方法是检查<rasp_home>/logs/rasp/rasp.log是否有[main][com.baidu.openrasp.HookHandler] detect server: XXXX字样,如果没有就是没识别到

      2. 检查日志目录是否有写权限。此类问题PHP环境出现较多,可以参考进行排查

    3. OpenRASP产生了报警,但是没有拦截攻击

    如果是单机版,

    请参考修改插件

    如果是远程管理版本

    1. 打开后台,找到 系统设置 -> 防护设置

    2. 关闭总开关,即 将所有算法设置为「记录日志」模式

    3. 对于你想要开启的检测算法,改为 拦截攻击

    4. 点击保存,并等待一个心跳周期生效(也可以通过重启tomcat/php等应用服务器快速生效)

    fastjson-1.2.60.war

    Java

    fastjson 1.2.60 RCE 漏洞

    wxpay-xxe.war

    Java

    某支付系统 XXE 漏洞

    CVE-2019-10173.war

    Java

    xstream 反序列化漏洞

    CVE-2019-12384.war

    Java

    jackson-databind 反序列化漏洞

    确保漏洞存在

    1. WAF基于请求特征检测漏洞,并不关心攻击是否成功、漏洞是否存在。OpenRASP基于行为检测,只有攻击成功的时候才会产生报警,所以需要漏洞真实存在。比如,对于SQL注入漏洞,你应该优先使用sqlmap进行测试,并确保能够读取到业务数据

  • 检查JS检测插件是否正确

    1. 如果你同时在测试IAST,请先把插件换回防护插件,即official.js

  • 如果不是上述问题,需要手动排查原因

    1. 开启行为日志,然后检查<rasp_home>/logs/plugin/plugin.log是否有日志。

      1. 对于远程版本,可以在后台打开打印「行为日志」开关

      2. 对于单机版,请参考修改插件

    2. 如果没有相关行为日志,则说明目前Java、PHP agent不支持你的服务器。你可以提交PR或者联系我们,并提供最小测试用例

    3. 如果有行为日志,则说明目前JS插件无法防护你发起的攻击。同样,你可以联系我们,并提交最小测试用例

  • php-vulns.tar.gz

    PHP

    主要测试用例,包含十几种高危漏洞

    vulns.war

    Java

    主要测试用例,包含十几种高危漏洞

    S2-016.war

    Java

    Struts S2-016 漏洞

    fastjson.war

    Java

    fastjson RCE 漏洞

    国内镜像: packages.baidu.com
    检测能力,覆盖场景以及零规则检测算法介绍
    CVE 漏洞覆盖说明
    常见安装问题
    单机版本 - 开启拦截
    日志说明
    仰望星空 - springboot中使用jsp
    OpenRASP正常拦截攻击,但是alarm.log没有日志
    开启拦截
    blocked
    blocked
    开启行为日志