Skip to content

JavaScript plugin development

Aaron Lewis edited this page Jun 9, 2019 · 6 revisions

Most of our detection algorithm are implemented in JavaScript plugin system, and it runs seamlessly on all supported platforms. A plugin method is called when a specific checkpoint is triggered in the agent, e.g SQL query, file read or write.

A plugin should be placed in the following directory:

  • Java agents: <app_home>/rasp/plugins
  • PHP agents: <openrasp_rootdir>/rasp/plugins

Since directory monitoring in Java agent, we will load/unload the plugin immediately when you add/remove a plugin. Also, only files with .js extension is accepted.

A minimized plugin looks like the following:

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
}

plugin.register('sql', function (params, context) {
    plugin.log('SQL query: ' + params.query)
    return clean
})

plugin.log('plugin-demo: plugin loaded')

In the example above,

  1. We've register a callback with plugin.register. The agent will pass in two parameters:
    • params: checkpoint parameters, complete SQL query, filename to read, ...
    • context: current HTTP request parameters, headers, url, ...
  2. We logged the SQL query to rasp/logs/plugin.log
  3. We didn't block the request in the callback. Supported actions are:
    • block: block and redirect the request
    • log: log the request and let it go
    • ignore: ignore the request and don't log it

Available checkpoints and parameters

SQL query

type   = sql
params = {
    "server": "mysql / oracle / pgsql / mssql / sqlite",
    "query":  "select * from users",
}

Reading directory contents

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",
        ...
    ]
}

Reading files

type   = readFile
params = {
    "path":     "/home/servers/tomcat/webapps/mywar/../../../../../../../../../etc/hosts",
    "realpath": "/etc/hosts"
}

Writing files

type   = writeFile
params = {
    "path":     "abc.jsp",
    "realpath": "/home/tomcat/webapps/ROOT/abc.jsp",
    "stack": [
        ...
    ]
}

Including files

# 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 requests (Java only)

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"
}

File uploading

type   = fileUpload
params = {
    "name": "file",
    "filename": "a.jsp",
    "content":  "<% ... %>"
}

Renaming files

type   = rename,
params = {
    "source": "/var/www/html/uploads/hello.txt",
    "dest":   "/var/www/html/uploads/hello.php"
}

Command execution

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; '"
}

Loading XML entities

type   = xxe
params = {
    "entity": "file:///etc/passwd"
}

OGNL execution

type   = ognl
params = {
    "expression": "_memberAccess"
}

Deserialization

type   = deserialization
params = {
    "clazz": "InvokerTransformer"
}

HTTP request

type   = ssrf
params = {
    "url":      "http://0x7f.0x0.0x0.0x1:8080/v1/api/get",
    "hostname": "0x7f.0x0.0x0.0x1"                          
    "ip":       ["1.1.1.1", "2.2.2.2"]                      
    "port":     "8080",                                     
    "function": "commons_http_client"
}