title: "Javascript"

Introduction

Nuclei and its community thrives on its ability to write exploits/checks in fast and simple way in YAML format and we aim to make nuclei templates as standard for writing security checks and that comes with understanding its limitations and addressing them as well as expanding its capabilities. It is already possible to write most complex HTTP, DNS, SSL protocol exploits / checks with increasing support and a powerful and easy to use DSL in nuclei engine but we understand this may not be enough for addressing / writing vulnerabilities across all protocols as well as other non-remote domains of security like local privilege escalation checks, kernel etc.

To address this and expand to other domains of security, Nuclei v3 ships with a embedded runtime for javascript that is tailored for Nuclei with the help of Goja.

Features

  • Provider/Driver specific exploit

Some vulnerabilities are specific to software/driver, example a redis buffer overflow exploit or a exploit of specific VPN software or anything that's not a IETF standard protocol. since they are not standard protocols and it doesn't make much sense to add them as a protocol in nuclei. Such exploits cannot be written using 'network' protocol or Very complex to write, such exploits can be written by exposing required library in nuclei (if not already present) and writing actual exploit in javascript protocol minus the boilerplate and scaling issues and other goodies of nuclei

  • Non Network Checks

Security is not limited to network and nuclei also doesn't intend to limit itself to network only. There are lot of security checks that are not network related like

  1. local privilege escalation checks
  2. kernel exploits
  3. account misconfigurations
  4. system misconfigurations etc
  • Complex network protocol exploits

Some network exploits are very complex to write due to nature of protocol or exploit itself example CVE-2020-0796 where you have to manually construct a packet. such exploits are usually written in python but now can be written in javascript protocol itself

  • Multi Step Exploits

Ldap / kerberos exploits usually involves multi step process of authentication and then exploitation etc and not easy to write in YAML based DSL

  • Scalable and maintainable exploits

One off exploits written in code are not scalable and maintainable due to nature of language , boilerplate code and lot of other factors. The goal here is to only write bare minimum code required to run exploit and let nuclei engine handle the rest

  • Leveraging turing complete language

While YAML based DSL is powerful and easy to use it is not turing complete and has its own limitations. Javascript is turing complete thus users who are already familiar with javascript can write network and other exploits without learning new DSL or hacking around existing DSL.

Goja

Goja is ECMAScript/Javascript engine/runtime written in pure go and has full support for ECMAScript 5.1. It is fast, can be used in goroutines and has very small memory footprint which makes it good fit for embedding in nuclei and provides additional layer of security and flexibility due to nature of javascript language and its implementation.

This does not break any nuclei design principle nor does it change how nuclei works and is dependency free. It complements nuclei engine by adding existing turing complete language (i.e javascript) instead of re-inventing the wheel by creating new DSL (domain specific language)

Requirements

  • A bare minimum knowledge of javascript (loops, functions , arrays is enough) is required to write javascript protocol template
  • Nuclei v3.0.0 or above

API Reference

API reference of all exposed modules and functions can be found here.

Javascript Protocol

Javascript protocol is new protocol added in nuclei v3 to allow writing exploits / checks in javascript language but internally are executed in go. And this javscript is tailored towards nuclei ecosystem this means

  • It is not intended to fit / imported with any existing javascript libraries or frameworks outside of nuclei ecosystem.
  • Nuclei Engine provides a set of functions, libraries that are tailor made for writing exploits / checks and only adds required/necessary functionality to compliment existing YAML based DSL.
  • It is not intended to be used as general purpose javascript runtime and does not replace matchers or extractors or any existing functionality of nuclei.
  • Javascript Protocol is intended to bridge gap between network protocol to add any new xyz protocol while adding lot of other functionalities.
  • Nuclei v3.0.0 ships with 15+ libraries (ssh,ftp,rdp,kerberos,redis) tailored for writing exploits/checks in javascript and will be continiously expanded in future.

Here is a simple example of javascript protocol template

id: ssh-server-fingerprint

info:
  name: Fingerprint SSH Server Software
  author: Ice3man543,tarunKoyalwar
  severity: info
  

javascript:
  - code: |
      var m = require("nuclei/ssh");
      var c = m.SSHClient();
      var response = c.ConnectSSHInfoMode(Host, Port);
      to_json(response);
    args:
      Host: "{{Host}}"
      Port: "22"

    extractors:
      - type: json
        json:
          - '.ServerID.Raw'

In above nuclei template we are fingerprinting SSH Server Software by connecting in Non-Auth mode and extracting server banner. Lets break down the template.

Code

Code contains actual javascript code that is executed by nuclei engine at runtime In above template we are

  • importing nuclei/ssh module/library
  • creating a new instance of SSHClient object
  • connecting to SSH server in Info mode
  • converting response to json

Args

Args can be simply understood as variables in javascript that are passed at runtime and support DSL usage

Output

Value of Last expression is returned as output of javascript protocol template and can be used in matchers / extractors. If server returns an error instead then error variable is exposed in matcher/extractor with error message.

Example

SSH Password Bruteforce Template

id: ssh-brute

info:
  name: SSH Credential Stuffing
  author: tarunKoyalwar
  severity: critical
  

javascript:
  - pre-condition: |
      var m = require("nuclei/ssh");
      var c = m.SSHClient();
      var response = c.ConnectSSHInfoMode(Host, Port);
      // only bruteforce if ssh server allows password based authentication
      response["UserAuth"].includes("password")

    code: |
      var m = require("nuclei/ssh");
      var c = m.SSHClient();
      c.Connect(Host,Port,Username,Password);

    args:
      Host: "{{Host}}"
      Port: "22"
      Username: "{{usernames}}"
      Password: "{{passwords}}"

    threads: 10
    attack: clusterbomb
    payloads:
      usernames: helpers/wordlists/wp-users.txt
      passwords: helpers/wordlists/wp-passwords.txt

    stop-at-first-match: true
    matchers:
      - type: dsl
        dsl:
          - "response == true"
          - "success == true"
        condition: and

In above nuclei template we are bruteforcing ssh server with list of usernames and passwords. We can tell that this might not have been possible to achieve with network template Let's break down the template.

Pre-Condition

pre-condition is a optional javascript code that is executed before running "code" and acts as pre-condition to exploit. In above template before attempting to bruteforce we are checking if

  • address is actually a ssh server
  • ssh server is configured to allow password based authentication

Furthur explaination

  • If pre-condition returns true only then code is executed otherwise it is skipped
  • In code section we import nuclei/ssh module and create a new instance of SSHClient object
  • and then we attempt to connect to ssh server with username and password
  • this template uses payloads to launch a clusterbomb attack with 10 threads and exits on first match

Looking at this template now we can tell that javascript template is very powerful to write multi step and protocol/vendor specific exploits which is primary goal of javascript protocol.

Init

init is a optional javascript code that can be used to initialize template and it is executed just after compiling template and before running it on any target. Although rarely needed, it can be used to load and preprocess data before running template on any target. For example in below code block we are loading all ssh private keys from nuclei-templates/helpers directory and storing them as a variable in payloads with name keys, if we were loading private keys from 'pre-condition' code block then it would have been loaded for every target which is not ideal.

variables:
  keysDir: "helpers/"  # load all private keys from this directory

javascript:
    # init field can be used to make any preperations before the actual exploit
    # here we are reading all private keys from helpers folder and storing them in a list
  - init: |
      let m = require('nuclei/fs');
      let privatekeys = m.ReadFilesFromDir(keysDir)
      updatePayload('keys',privatekeys)

    payloads:
      # 'keys' will be updated by actual private keys after init is executed
      keys: 
        - key1
        - key2

Two special functions that are available in init block are

FunctionDescription
updatePayload(key,value)updates payload with given key and value
set(key,value)sets a variable with given key and value

A collection of javascript protocol templates can be found here.

Contributing

If you want to add a new module or function to nuclei javascript runtime please open a PR with your changes, refer Contributing for more details.