参数说明
若要实现检测逻辑,插件需要先注册检测方法,e.g SQL注入检测插件可注册 sql
类型的回调
plugin.register('sql', function(params, context) {
// 实现你的检测逻辑
})
具体插件可注册的回调类型 type
,以及回调参数 params
的样例如下。另外,所有检测点都可以使用 params.stack
参数,以获取当前堆栈信息。
- 数据库查询
- 读取目录
- 请求参数
- 读取文件
- 写入文件
- 删除文件
- 文件包含操作
- WebDAV 操作
- 文件上传
- 文件重命名
- 命令执行
- XML 外部实体引用
- Struts OGNL 表达式解析
- RMI 反序列化
- 服务器端 HTTP 请求
- 服务器端 HTTP 请求 - 重定向之后
- 代码执行
- 类库加载
- 响应检查
数据库查询
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",
...
]
}
请求参数
当应用接受到请求时,插件可以对请求进行拦截。(注意: PHP Agent 1.1 开始才支持)
type = request
params = {}
这里不会传递任何参数,如果需要获取请求相关信息,请使用 API接口
读取文件
注意:
- 对于 PHP 服务器,若实际读取文件以
https://
、http://
、ftp://
之一开头,将会调用服务器端 HTTP 请求
检测点,不会触发读取文件
检测点
type = readFile
params = {
"path": "/home/servers/tomcat/webapps/mywar/../../../../../../../../../etc/hosts",
"realpath": "/etc/hosts"
}
写入文件
出于性能考虑,OpenRASP 目前只会提供文件名和绝对路径两个参数
注意:
- tomcat 等应用服务器,在部署war包时,暂时不会触发这个回调
- 对于NTFS数据流,e.g
abc.php::$DATA
,插件看到的path
可能是abc.php::$DATA
,realpath
可能是c:\inetpub\wwwroot\abc.php
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"
}
文件包含操作
url
可能是协议(file
、http
等等),也能是相对路径(/abc/
、abc.txt
)
支持的文件包含方式如下,
- Java - JSTL import 方式
- 只有
url
里出现了://
且不为/
开头时,我们才会调用插件
- 只有
- PHP - include/require/include_once/require_once 四种方式
- 当
url
里包含://
时,调用插件 - 如果文件以
.php
或者.inc
结尾,或者真实路径在 webroot 下面,不会进入插件 - 其他情况进入插件具体参数
- 当
# 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"
}
WebDAV 操作
目前仅支持 MOVE
、COPY
两种方法
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"
}
文件上传
目前,OpenRASP 支持 org.apache.commons.fileupload
上传组件(SpringMVC、Struts 底层使用)
出于性能考虑,OpenRASP 只会提取文件前 4 KB
的内容,若要获取更多字节,请参考配置文档
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; '"
}
XML 外部实体引用
目前,PHP不支持XXE检测
type = xxe
params = {
"entity": "file:///etc/passwd"
}
Struts OGNL 表达式解析
注意: 为了减少性能影响,仅当表达式长度超过 30
时才会调用插件。可手动 ognl.expression.minlength
选项来进行调整
type = ognl
params = {
"expression": "_memberAccess" //ognl表达式
}
RMI 反序列化
type = deserialization
params = {
"clazz": "InvokerTransformer" //被反序列化对象的类型
}
服务器端 HTTP 请求
支持的请求方式包含如下 (对应 function 字段),
- JDK 中的
URL.openConnection
的方式 (url_open_connection) commons-httpclient
框架请求方式 (commons_http_client)httpclient
框架请求方式 (http_client)- PHP stream 请求、cURL 请求
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"
}
服务器端 HTTP 请求 - 重定向之后
支持的请求方式包含如下 (对应 function 字段),
- JDK 中的
URL.openConnection
的方式 (url_open_connection) httpclient
框架请求方式 (http_client)- PHP stream 请求、cURL 请求
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"
}
代码执行
目前支持 eval/function 两种函数
type = eval
params = {
"function": "eval",
"code": "gzuncompress(base64_decode(...));"
"stack": [
...
]
}
类库加载
目前仅支持 java System.load()
方式
type = loadlibrary
params = {
"function": "System.load",
"path": "\\8.8.8.8\test.dll",
"realpath": "xxxx"
}
响应检查
说明
- Java 下面如果 body 过大,会多次分段调用
- 当响应类型包含
image
、audio
、video
字样,不会进入插件 - 该检测点不支持拦截参数
type = response
params = {
"content_type": "text/html",
"content": "<h1>xxxx</h1>"
}