Page cover

πŸ”°[WolvCTF 2023] Writeup Web

Mở Δ‘αΊ§u

TrΖ°α»›c khi bαΊ―t Δ‘αΊ§u Δ‘Γ’y lΓ  source code dΓ nh cho cΓ‘c bαΊ‘n: link

Zoombie 101

BΓ i nΓ y cho source nhΖ°ng mΓ  khΓ‘ basic, nΓ³ dΓ­nh lα»—i XSS:

Payload:

Sau Δ‘Γ³ submit link cho bot->flag; dΓΉng burp suite để bαΊ―t request lαΊ₯y link submit.

Zoombie 201

BΓ i nΓ y thΓ¬ mọi thα»© giα»‘ng bΓ i 1 nhΖ°ng cΓ³ Δ‘iều lΓΊc nΓ y cookie được set http only, nhΖ° trΖ°α»›c Δ‘Γ’y mΓ¬nh học tαΊ­p cΓ³ mα»™t người anh Δ‘Γ£ nΓ³i vα»›i mΓ¬nh lΓ  nαΊΏu Δ‘Γ£ set http only thΓ¬ chỉ cΓ³ leak nΓ³ ra giΓ‘n tiαΊΏp tα»« mα»™t trang cΓ‘c chα»© khΓ΄ng thể leak ra trα»±c tiαΊΏp được.

ChΓΊng ta sαΊ½ vΓ o phΓ’n tΓ­ch nhα»―ng Δ‘oαΊ‘n code:

ChΓΊ Γ½ Δ‘oαΊ‘n code trΓͺn cΓ³ mα»™t endpoint debug ở Δ‘Γ’y nΓ³ sαΊ½ kiαΊΏm tra biαΊΏn allowDebug trong config xem cho phΓ©p hay khΓ΄ng khi Δ‘Γ³ nαΊΏu true thΓ¬ req.headers (TαΊ₯t nhiΓͺn nΓ³ sαΊ½ kΓ¨m cαΊ£ cookie).

Xem xΓ©t tiαΊΏp file docker-compose:

Yaahh! Ở Δ‘Γ’y allowDebug: true , vαΊ­y mọi việc Δ‘Ζ‘n giαΊ£n rα»“i.

Ý tưởng ở Δ‘Γ’y sαΊ½ khai thΓ‘c dα»― liệu tα»« mα»™t endpoint khΓ‘c bαΊ±ng cΓ‘ch exploit tα»« endpoint cΓ³ vuln XSS. CΓ³ thể hiểu Cross-origin resource sharing.

Tα»« Γ½ tưởng trΓͺn mΓ¬nh sαΊ½ cΓ³ mα»™t Δ‘oαΊ‘n payload JS API, mΓ¬nh sα»­ dα»₯ng fetch(Mọi người cΓ³ thể dΓΉng nhα»―ng thα»© khΓ‘c nhΖ° Ajax, HML HTTP Request ....)

MΓ¬nh sαΊ½ giαΊ£i thΓ­ch chi tiαΊΏt Δ‘oαΊ‘n payload trΓͺn cho ai chΖ°a biαΊΏt tα»›i JS:

ĐoαΊ‘n code nΓ y sα»­ dα»₯ng phΖ°Ζ‘ng thα»©c fetch để gα»­i mα»™t yΓͺu cαΊ§u HTTP GET Δ‘αΊΏn Δ‘α»‹a chỉ 'https://zombie-201-tlejfksioa-ul.a.run.app/debug'. Sau Δ‘Γ³, nΓ³ sα»­ dα»₯ng phΖ°Ζ‘ng thα»©c then để xα»­ lΓ½ phαΊ£n hα»“i tα»« mΓ‘y chα»§.

Trong phΖ°Ζ‘ng thα»©c then thα»© nhαΊ₯t, nΓ³ trΓ­ch xuαΊ₯t nα»™i dung cα»§a phαΊ£n hα»“i bαΊ±ng cΓ‘ch gọi phΖ°Ζ‘ng thα»©c text() trΓͺn Δ‘α»‘i tượng response. PhΖ°Ζ‘ng thα»©c text() sαΊ½ trαΊ£ về mα»™t Promise chα»©a dα»― liệu vΔƒn bαΊ£n cα»§a phαΊ£n hα»“i.

Trong phΖ°Ζ‘ng thα»©c then thα»© hai, nΓ³ sα»­ dα»₯ng dα»― liệu được trαΊ£ về tα»« phΖ°Ζ‘ng thα»©c text() để tαΊ‘o mα»™t Δ‘α»‹a chỉ URL mα»›i. Địa chỉ URL nΓ y sαΊ½ chα»©a mα»™t tham sα»‘ "c" vα»›i giΓ‘ trα»‹ lΓ  dα»― liệu vΔƒn bαΊ£n được trαΊ£ về tα»« phαΊ£n hα»“i.

Sau Δ‘Γ³, nΓ³ sα»­ dα»₯ng phΖ°Ζ‘ng thα»©c concat() để ghΓ©p chuα»—i Δ‘α»‹a chỉ IP cα»§a yΓͺu cαΊ§u vΓ o Δ‘α»‹a chỉ URL mα»›i vΓ  sα»­ dα»₯ng Δ‘α»‘i tượng document để chuyển hΖ°α»›ng trΓ¬nh duyệt Δ‘αΊΏn Δ‘α»‹a chỉ URL mα»›i nΓ y.

NαΊΏu cΓ³ lα»—i xαΊ£y ra trong quΓ‘ trΓ¬nh gα»­i yΓͺu cαΊ§u hoαΊ·c xα»­ lΓ½ phαΊ£n hα»“i, Δ‘oαΊ‘n code sα»­ dα»₯ng phΖ°Ζ‘ng thα»©c catch để xα»­ lΓ½ ngoαΊ‘i lệ vΓ  ghi log lα»—i ra console.

MΓ¬nh Δ‘Γ£ đọc qua code thΓ¬ chαΊ―c chαΊ―n debug khΓ΄ng dΓ­nh CSP khi Δ‘Γ³ cΓ‘ch nΓ y lΓ  khαΊ£ thi nhαΊ₯t.

ChΓΊng ta sαΊ½ lαΊ‘i lαΊ₯y link submit cho con bot->flag

Zoombie 301

BΓ i nΓ y giα»‘ng nhα»―ng bΓ i nhΖ°ng nhα»―ng endpoint debug khΓ΄ng thể truy cαΊ­p được.

VαΊ«n nhΖ° lời mα»™t người anh Δ‘Γ£ nΓ³i vα»›i mΓ¬nh muα»‘n đọc được cookie cΓ³ http only thΓ¬ hΓ£y xem file nΓ o chα»©a nΓ³ vΓ  cΓ³ thể leak ra hay khΓ΄ng.

Trong file index.js cΓ³ Δ‘oαΊ‘n nΓ y

VΓ  file Docker cΓ³ vα»‹ trΓ­ rΓ΅ cho chΓΊng ta biαΊΏt vα»‹ trΓ­ file config.

VαΊ­y lΓ  chΓΊng ta cΓ³ vα»‹ trΓ­ file chα»©a flag: /ctf/app/config.json

Payload sαΊ½ nhΖ° bΓ i 201 nhΖ°ng cΓ³ mα»™t cΓ‘i quan trọng nαΊΏu muα»‘n truy cαΊ­p file tα»« mΓ‘y cα»§a chΓ­nh mΓ¬nh thΓ¬ dΓΉng giao thα»©c file://

Yah cΕ©ng cΓ³ mα»™t cΓ‘ch khΓ‘c lΓ  sα»­ dα»₯ng constructor cα»§a JS để return env

Payload:

Mình sẽ giải thích qua như này:

this.constructor lΓ  mα»™t tham chiαΊΏu Δ‘αΊΏn hΓ m constructor cα»§a Δ‘α»‘i tượng hiện tαΊ‘i.(Dα»… hiểu nΓ³ lΓ  Object)

this.constructor.constructor lΓ  mα»™t tham chiαΊΏu Δ‘αΊΏn hΓ m constructor cα»§a hΓ m constructor cα»§a Δ‘α»‘i tượng hiện tαΊ‘i(Dα»… hiểu lΓ  function cα»§a object).

Trong Δ‘oαΊ‘n code nΓ y, this.constructor.constructor('return process.env.FLAG')() được sα»­ dα»₯ng để truy cαΊ­p Δ‘αΊΏn hΓ m constructor cα»§a hΓ m constructor cα»§a Δ‘α»‘i tượng hiện tαΊ‘i. Sau Δ‘Γ³, ('return process.env.FLAG')() được sα»­ dα»₯ng để trαΊ£ về giΓ‘ trα»‹ cα»§a biαΊΏn mΓ΄i trường process.env.FLAG.

CΓ³ mα»™t payload khΓ‘c lΓ  Δ‘Γ‘nh cαΊ―p header kΓ¨m cookie khi server trαΊ£ về browser.

Khi mα»™t cookie được thiαΊΏt lαΊ­p lΓ  http-only, nΓ³ sαΊ½ khΓ΄ng thể truy cαΊ­p được tα»« cΓ‘c client-side script nhΖ° JavaScript, vΓ  chỉ cΓ³ thể được gα»­i Δ‘αΊΏn server thΓ΄ng qua cΓ‘c yΓͺu cαΊ§u HTTP. Tuy nhiΓͺn, việc thiαΊΏt lαΊ­p cookie lΓ  http-only khΓ΄ng cΓ³ tΓ‘c dα»₯ng trong việc ngΔƒn chαΊ·n việc gα»­i cookie tα»« server Δ‘αΊΏn client thΓ΄ng qua cΓ‘c phαΊ£n hα»“i HTTP.

Khi mα»™t yΓͺu cαΊ§u được gα»­i Δ‘αΊΏn server, server sαΊ½ trαΊ£ về phαΊ£n hα»“i HTTP chα»©a cΓ‘c thΓ΄ng tin header nhΖ° cookie, cΓ‘c thΓ΄ng tin về cache, mΓ£ trαΊ‘ng thΓ‘i vΓ  cΓ‘c thΓ΄ng tin khΓ‘c. TΓΉy thuα»™c vΓ o cΓ‘ch server được cαΊ₯u hΓ¬nh, nΓ³ cΓ³ thể trαΊ£ về cΓ‘c header chα»©a cookie Δ‘Γ£ được thiαΊΏt lαΊ­p lΓ  http-only.

Trong trường hợp cα»§a Δ‘oαΊ‘n mΓ£ trΓͺn, khi mα»™t yΓͺu cαΊ§u được gα»­i Δ‘αΊΏn trang web https://zombie-301-tlejfksioa-ul.a.run.app/ bαΊ±ng phΖ°Ζ‘ng thα»©c fetch, server sαΊ½ trαΊ£ về phαΊ£n hα»“i HTTP chα»©a cΓ‘c thΓ΄ng tin header, bao gα»“m header chα»©a cookie Δ‘Γ£ được thiαΊΏt lαΊ­p lΓ  http-only. Tuy nhiΓͺn, cookie Δ‘Γ³ khΓ΄ng thể truy cαΊ­p được tα»« client-side script, do Δ‘Γ³, nΓ³ khΓ΄ng thể được Δ‘Γ‘nh cαΊ―p bởi cΓ‘c script Δ‘α»™c hαΊ‘i.

Sau Δ‘Γ³, Δ‘oαΊ‘n mΓ£ tiαΊΏp tα»₯c sα»­ dα»₯ng phΖ°Ζ‘ng thα»©c fetch để gα»­i dα»― liệu cα»§a phαΊ£n hα»“i HTTP Δ‘αΊΏn mα»™t Δ‘α»‹a chỉ URL khΓ‘c bαΊ±ng cΓ‘ch sα»­ dα»₯ng thuα»™c tΓ­nh credentials được thiαΊΏt lαΊ­p lΓ  include. NαΊΏu server cα»§a Δ‘α»‹a chỉ URL nΓ y Δ‘Γ£ được cαΊ₯u hΓ¬nh để chia sαΊ» cookie giα»―a cΓ‘c tΓͺn miền khΓ‘c nhau (cross-domain) bαΊ±ng cΓ‘ch thiαΊΏt lαΊ­p header Access-Control-Allow-Credentials: true, thΓ¬ cookie cΓ³ thể được gα»­i Δ‘αΊΏn Δ‘α»‹a chỉ URL khΓ‘c thΓ΄ng qua phΖ°Ζ‘ng thα»©c fetch.

TΓ³m lαΊ‘i, việc thiαΊΏt lαΊ­p cookie lΓ  http-only khΓ΄ng thể ngΔƒn chαΊ·n việc gα»­i cookie tα»« server Δ‘αΊΏn client, nhΖ°ng nΓ³ cΓ³ thể ngΔƒn chαΊ·n việc truy cαΊ­p cookie tα»« cΓ‘c client-side script. Việc sα»­ dα»₯ng thuα»™c tΓ­nh credentials được thiαΊΏt lαΊ­p lΓ  include trong phΖ°Ζ‘ng thα»©c fetch chỉ cho phΓ©p chia sαΊ» cookie giα»―a cΓ‘c tΓͺn miền khΓ‘c nhau nαΊΏu server cα»§a Δ‘α»‹a chỉ URL Δ‘Γ­ch Δ‘Γ£ được cαΊ₯u hΓ¬nh để chia sαΊ» cookie giα»―a cΓ‘c tΓͺn miền khΓ‘c nhau.

Zoombie 401

BΓ i nΓ y cΕ©ng cΓ³ thể solve bαΊ±ng payload cα»§a bΓ i 301 truy cαΊ­p thαΊ³ng file config cα»§a server chα»©a flag

ChΓΊng ta sαΊ½ khΓ΄ng lαΊ₯y được flag ở payload 2 vΓ¬ biαΊΏn mΓ΄i trường lΓΊc nΓ y khΓ΄ng chα»©a flag.

File config.json sαΊ½ dαΊ‘ng:

Ở Δ‘Γ’y chΓΊng ta sαΊ½ nghiΓͺn cα»©u lαΊ‘i mα»™t xΓ­u thΓ¬ ĐoαΊ‘n mΓ£ trΓͺn sα»­ dα»₯ng thΖ° viện zombie trong Node.js để tαΊ‘o mα»™t trΓ¬nh duyệt khΓ΄ng Δ‘αΊ§u (headless browser).

Chα»‹u khΓ³ tΓ¬m zoombie.js ở git truy cαΊ­p vΓ o file CHANGELOG.md để xem cΓ‘c thay Δ‘α»•i thΓ¬ thαΊ₯y rαΊ±ng:

Zombie phiΓͺn bαΊ£n cuα»‘i cΓΉng lΓ  tα»« nΔƒm 2018, cΓ³ thể chΓΊng ta sαΊ½ tΓ¬m thαΊ₯y mα»™t sα»‘ 1 day https://github.com/assaf/zombie/blob/master/CHANGELOG.md

Ở Δ‘Γ’y mα»™t lΓΊc research thΓ¬ chΓΊng ta cΓ³ mα»™t POC cΓ³ thể đọc file - thα»±c tαΊΏ nΓ³ lΓ  vuln cα»§a nodeJS nhΖ°ng zoombie cΕ©ng gαΊ·p phαΊ£i:

Oke nhΖ°ng tα»« dΓ’y chΓΊng ta cΓ³ thể xΓ’y dα»±ng mα»™t payload khΓ‘c

Payload nΓ y cΓ³ thể dΓΉng RCE được nαΊΏu khΓ΄ng biαΊΏt vα»‹ trΓ­ chα»©a flag:

ChΓΊng ta sαΊ½ giαΊ£i thΓ­ch cΓ‘ch hoαΊ‘t Δ‘α»™ng Δ‘oαΊ‘n payload nay nhΓ©:

DΓ²ng Δ‘αΊ§u mΓ¬nh Δ‘Γ£ giαΊ£i thΓ­ch ở Zoombie 301, nΓ³ chỉ khΓ‘c ở trΓͺn return ra ENV cΓ²n Δ‘Γ’y lΓ  process.

Trong Node.js biαΊΏn toΓ n cα»₯c process (Global) tα»©c lΓ  mọi thα»© đều cΓ³ quyền truy cαΊ­p Δ‘αΊΏn. BαΊ‘n khΓ΄ng cαΊ§n khai bΓ‘o hay import chΓΊng bởi phΖ°Ζ‘ng thα»©c require() mΓ  vαΊ«n cΓ³ thể sα»­ dα»₯ng chΓΊng mα»™t cΓ‘ch trα»±c tiαΊΏp. CΓ‘c Δ‘α»‘i tượng nΓ y cΓ³ thể lΓ  cΓ‘c Module, cΓ‘c hΓ m, cΓ‘c chuα»—i hoαΊ·c cΓ‘c Δ‘α»‘i tượng.(CΓ³ thể hiểu nΓ³ lΓ  mα»™t tiαΊΏn trΓ¬nh tΖ°Ζ‘ng Δ‘Ζ°Ζ‘ng 1 α»©ng dα»₯ng dược chαΊ‘y)

ĐoαΊ‘n code tiαΊΏp, process.mainModule được sα»­ dα»₯ng để xΓ‘c Δ‘α»‹nh module chΓ­nh được sα»­ dα»₯ng trong α»©ng dα»₯ng Node.js. require('child_process') được sα»­ dα»₯ng để yΓͺu cαΊ§u module child_process. execSync('cat config.json') được sα»­ dα»₯ng để thα»±c thi lệnh cat config.json vΓ  trαΊ£ về kαΊΏt quαΊ£. toString() được sα»­ dα»₯ng để chuyển Δ‘α»•i kαΊΏt quαΊ£ trαΊ£ về thΓ nh chuα»—i .

  • child_process lΓ  mα»™t module trong Node.js, cho phΓ©p tαΊ‘o ra cΓ‘c tiαΊΏn trΓ¬nh con (child process) để thα»±c hiện cΓ‘c tΓ‘c vα»₯ bαΊ₯t Δ‘α»“ng bα»™ (asynchronous) mΓ  khΓ΄ng αΊ£nh hưởng Δ‘αΊΏn tiαΊΏn trΓ¬nh chΓ­nh (main process).

VΓ¬ NodeJS hay lΓ  thα»±c hiện xα»­ lΓ½ bαΊ₯t Δ‘α»“ng bα»™ nghΔ©a lΓ  nΓ³ sαΊ½ thα»±c hiện cΓ‘c tΓ‘c vα»₯ nhαΊΉ trΖ°α»›c rα»“i sαΊ½ tα»›i tΓ‘c vα»‹ nαΊ·ng vΓ¬ vαΊ­y chΓΊng ta dΓΉng execSync:

Hidden CSS

BΓ i nΓ y chΓΊng ta sαΊ½ gα»­i mα»™t url tα»›i bot. VΓ  chΓΊng ta sαΊ½ xem qua source code cα»§a chall nΓ y.

Ở Δ‘Γ’y pritvate-server sαΊ½ chαΊ‘y ở locale, chΓΊng ta sαΊ½ phΓ’n tΓ­ch code private:

Ở Δ‘Γ’y Γ½ tưởng chΓΊng ta sαΊ½ dΓΉng mα»™t Δ‘oαΊ‘n css nΓ³i ở prefix, nΓ³ gọi lΓ  CSS Injection

Ý tưởng ở Δ‘Γ’y chΓΊng ta sαΊ½ bypass tαΊ₯t cαΊ£ Δ‘iều kiện cα»§a server private vΓ  lαΊ₯y giΓ‘ trα»‹ cα»§a biαΊΏn css.

Payload sαΊ½ nhΖ° sau:

PhΓ’n tΓ­ch qua cΓ‘ch thα»©c hoαΊ‘t Δ‘α»™ng cα»§a Δ‘oαΊ‘n payload trΓͺn:

Trong Δ‘oαΊ‘n payload, chΓΊng ta Δ‘ang sα»­ dα»₯ng mα»™t đường dαΊ«n http://0:1337/css để lαΊ₯y nα»™i dung CSS. Trong đường dαΊ«n nΓ y, chΓΊng ta Δ‘ang truyền tham sα»‘ prefix vα»›i giΓ‘ trα»‹ p {--flag:". Điều nΓ y sαΊ½ lΓ m cho Δ‘oαΊ‘n CSS trαΊ£ về chα»©a mα»™t biαΊΏn --flag vα»›i giΓ‘ trα»‹ bαΊ±ng rα»—ng vΓ  tiαΊΏp Δ‘Γ³ được nα»‘i vα»›i giΓ‘ trα»‹ cα»§a biαΊΏn FLAG trong Δ‘oαΊ‘n code server.

TiαΊΏp theo, chΓΊng ta sα»­ dα»₯ng JavaScript để lαΊ₯y giΓ‘ trα»‹ cα»§a biαΊΏn --flag tα»« id #payload. Điều nΓ y cΓ³ thể được thα»±c hiện bαΊ±ng cΓ‘ch sα»­ dα»₯ng hΓ m getComputedStyle để lαΊ₯y cΓ‘c thuα»™c tΓ­nh CSS cα»§a phαΊ§n tα»­ vΓ  sau Δ‘Γ³ sα»­ dα»₯ng getPropertyValue để lαΊ₯y giΓ‘ trα»‹ cα»§a biαΊΏn --flag.

Cuα»‘i cΓΉng, chΓΊng ta sα»­ dα»₯ng hΓ m fetch để gα»­i giΓ‘ trα»‹ cα»§a biαΊΏn --flag Δ‘αΊΏn mα»™t Δ‘α»‹a chỉ IP bαΊ₯t kα»³ để lαΊ₯y giΓ‘ trα»‹ cα»§a Flag.

TΓ³m lαΊ‘i, Δ‘oαΊ‘n payload nΓ y sα»­ dα»₯ng lα»— hα»•ng CSS Injection để lαΊ₯y giΓ‘ trα»‹ cα»§a biαΊΏn --flag tα»« Δ‘oαΊ‘n CSS trαΊ£ về vΓ  sau Δ‘Γ³ gα»­i giΓ‘ trα»‹ nΓ y Δ‘αΊΏn mα»™t Δ‘α»‹a chỉ IP bαΊ₯t kα»³ để lαΊ₯y giΓ‘ trα»‹ Flag.

Tα»›i Δ‘Γ’y cΓ³ nhiều bαΊ‘n cΓ³ thể sαΊ½ thαΊ―c mαΊ―c tαΊ‘i sao nαΊΏu dΓΉng p{flag: } hoαΊ·c p{color: }.... thΓ¬ khΓ΄ng thể truy xuαΊ₯t được giΓ‘ trα»‹ flag trαΊ£ về.

VΓ¬, thα»© nhαΊ₯t flag ở trong css nΓ³ khΓ΄ng cΓ³, tiαΊΏp theo color hay background-color, font-size... tαΊ₯t cαΊ£ đều lΓ  thuα»™c tΓ­nh trong CSS vΓ  nΓ³ Δ‘Γ£ cΓ³ sαΊ΅n nΓͺn khi bαΊ‘n gọi tα»›i nΓ³ thΓ¬ nΓ³ sαΊ½ trαΊ£ về giΓ‘ trα»‹ mαΊ·c Δ‘α»‹nh tαΊ‘i endpoint CSS, thay vΓ o Δ‘Γ³ bαΊ‘n phαΊ£i khai bΓ‘o mα»™t biαΊΏn ở CSS --ten-bien lΓΊc nΓ y nΓ³ sαΊ½ lΓ  biαΊΏn vΓ  nΓ³ cΓ³ giΓ‘ trα»‹ rα»—ng(nhα»› kα»Ή lΓ  rα»—ng lΓ  nΓ³ khΓ΄ng hề cΓ³ trong endpoint CSS) khi Δ‘Γ³ chΓΊng ta cΓ³ thể lαΊ₯y được flag nhΖ° Δ‘oαΊ‘n giαΊ£i thΓ­ch payload trΓͺn.

Exploit

Ban Δ‘αΊ§y mΓ¬nh chαΊ‘y thαΊ³ng file payload.html lΓͺn local sau Δ‘Γ³ dΓΉng ngrok chαΊ‘y payload lΓͺn internet, nhΖ°ng khΓ΄ng thể exploit.

VΓ¬: ngrok sα»­ dα»₯ng protocol https nhΖ°ng local mΓ¬nh dΓΉng http vΓ  thαΊ» link cα»§a mΓ¬nh cΕ©ng dΓΉng http://0:1337..vΓ  ip-request cΕ©ng http nΓͺn nΓ³ chαΊ·n script mαΊ·c dΓΉng vαΊ«n hiển thα»‹ nα»™i dung nhΖ°ng script khΓ΄ng được thα»±c hiện.

Sau Δ‘Γ³ mΓ¬nh dΓΉng python deploy lΓͺn trα»±c tiαΊΏp vα»›i Δ‘α»‹a chỉ lΓ  ip mΓ‘y nhΖ°ng server khΓ΄ng nhαΊ­n, sau Δ‘Γ³ thα»­ build bαΊ±ng flask cΕ©ng khΓ΄ng được.

Sau mα»™t lΓΊc mΓ¬nh mΓ² ở request-ip mΓ¬nh cΓ³ mα»₯c response vΓ  sα»­a được nΓͺn mΓ¬nh Δ‘Γ£ up payload lΓͺn Δ‘Γ³ vΓ . LΓΊc nΓ y ip-request chα»©a Δ‘oαΊ‘n payload vΓ  nhαΊ­n response cα»§a challenge.

BΓ’y giờ chỉ cαΊ§n gα»­i link cho bot vΓ  nhαΊ­n flag:

Adversal

Bài này cho source code, nhưng trước khi tới source code chúng ta sẽ interface có gì.

Ở Δ‘Γ’y sαΊ½ cΓ³ mα»™t endpoint opt sαΊ½ cho chΓΊng ta mα»™t Δ‘oαΊ‘n code vΓ  cΓ³ mα»™t biαΊΏn ad cho chΓΊng ta truyền bαΊ₯t kα»³ giΓ‘ trα»‹ nΓ o.

BÒy giờ chúng ta sẽ xem qua source code của chall:

ChΓΊng ta xem xΓ©t Δ‘oαΊ‘n code opt nΓ y:

Endpoint opt nΓ y bαΊ‘n cΓ³ thể Δ‘iền thΓͺm giΓ‘ trα»‹ ở biαΊΏn ad vΓ  sau Δ‘Γ³ render ra opt. CΓ³ Δ‘iều Δ‘Γ‘ng nΓ³i ở trΓͺn Δ‘Γ£ được set header CSP nΓͺn khi Δ‘Γ³ chα»‹u, khΓ΄ng thể khai thΓ‘c XSS hoαΊ·c Cors, nhΖ° trΓͺn cΓ³ Δ‘oαΊ‘n cmt chỉ rαΊ±ng opt lΓ  endpoint mΓ  bot visit. Γ€ opt ở Δ‘Γ’y sαΊ½ được random vα»›i 12 chα»― cΓ‘i a-zA-Z0-9

Ở Δ‘Γ’y mΓ¬nh nghΔ© cΓ³ thể dΓΉng cΓ‘ch khai thΓ‘c CSS Injection:

Brute-foce 12 kΓ½ tα»± sαΊ½ ra nhΖ°ng cΓ³ Δ‘iều khΓ‘ lΓ’u cΓ³ mα»™t bΓ i về kα»Ή thuαΊ­t CSS Injection ở giαΊ£i ctf khΓ‘c, cΓ³ thể xem ở Δ‘Γ’y: link

NαΊΏu cΓ³ Δ‘α»§ opt cα»§a bot khi Δ‘Γ³ sαΊ½ cΓ³ flag. NhΖ°ng chΓΊng ta sαΊ½ xem xΓ©t tα»›i mα»™t vuln khΓ‘c ở Δ‘Γ’y:

ĐÒy lΓ  mα»™t hΓ m visitUrl, nΓ³ tαΊ‘o mα»™t trΓ¬nh duyệt αΊ©n danh mα»›i vΓ  mở mα»™t trang web vα»›i đường dαΊ«n được cung cαΊ₯p. Sau Δ‘Γ³, nΓ³ tΓ¬m kiαΊΏm phαΊ§n tα»­ Δ‘αΊ§u tiΓͺn cα»§a trang web lΓ  mα»™t thαΊ» input vΓ  lαΊ₯y giΓ‘ trα»‹ cα»§a thuα»™c tΓ­nh β€œvalue” cα»§a nΓ³. NαΊΏu khΓ΄ng tΓ¬m thαΊ₯y phαΊ§n tα»­ input, giΓ‘ trα»‹ cα»§a biαΊΏn otp sαΊ½ lΓ  null. Cuα»‘i cΓΉng, nΓ³ Δ‘Γ³ng trang web vΓ  trΓ¬nh duyệt αΊ©n danh vΓ  trαΊ£ về giΓ‘ trα»‹ cα»§a biαΊΏn otp. NαΊΏu cΓ³ bαΊ₯t kα»³ lα»—i nΓ o xαΊ£y ra trong quΓ‘ trΓ¬nh nΓ y, chΓΊng sαΊ½ được bαΊ―t vΓ  xα»­ lΓ½ trong khα»‘i try-catch-finally cuα»‘i cΓΉng.

Yaahh nαΊΏu bαΊ‘n đọc Δ‘oαΊ‘n trΓͺn cΕ©ng hiểu vuln ở Δ‘Γ’u rα»“i chα»© nαΊΏu chΖ°a thΓ¬ xem xΓ©t kα»Ή hΖ‘n:

ĐoαΊ‘n code trΓͺn lΓ  mα»™t chα»©c nΔƒng JavaScript được sα»­ dα»₯ng để trΓ­ch xuαΊ₯t giΓ‘ trα»‹ cα»§a input tα»« mα»™t trang web Δ‘Γ£ cho.

Đầu tiΓͺn, biαΊΏn otp được khởi tαΊ‘o vα»›i giΓ‘ trα»‹ null. Chα»©c nΔƒng nΓ y sα»­ dα»₯ng thΖ° viện Puppeteer để tαΊ‘o mα»™t trΓ¬nh duyệt Δ‘Ζ‘n giαΊ£n. Sau Δ‘Γ³, chα»©c nΔƒng sα»­ dα»₯ng phΖ°Ζ‘ng thα»©c setUserAgent() để thiαΊΏt lαΊ­p user agent lΓ  "puppeteer".

TiαΊΏp Δ‘Γ³, chα»©c nΔƒng nΓ y sα»­ dα»₯ng phΖ°Ζ‘ng thα»©c goto() để truy cαΊ­p Δ‘αΊΏn Δ‘α»‹a chỉ url Δ‘Γ£ cho. Tham sα»‘ Δ‘αΊ§u tiΓͺn cα»§a phΖ°Ζ‘ng thα»©c nΓ y lΓ  Δ‘α»‹a chỉ url cαΊ§n truy cαΊ­p. Tham sα»‘ thα»© hai lΓ  mα»™t Δ‘α»‘i tượng chα»©a cΓ‘c tΓΉy chọn, trong Δ‘Γ³ timeout được thiαΊΏt lαΊ­p lΓ  20000 (20 giΓ’y) vΓ  waitUntil được thiαΊΏt lαΊ­p lΓ  'networkidle2', cho phΓ©p trang web đợi cho Δ‘αΊΏn khi mαΊ‘ng khΓ΄ng cΓ³ hoαΊ‘t Δ‘α»™ng nΓ o trΖ°α»›c khi tiαΊΏp tα»₯c.

Sau khi Δ‘Γ£ truy cαΊ­p vΓ o trang web, chα»©c nΔƒng nΓ y sα»­ dα»₯ng phΖ°Ζ‘ng thα»©c $eval() để trΓ­ch xuαΊ₯t giΓ‘ trα»‹ cα»§a thαΊ» input Δ‘αΊ§u tiΓͺn trΓͺn trang web. Đối sα»‘ Δ‘αΊ§u tiΓͺn cα»§a phΖ°Ζ‘ng thα»©c nΓ y lΓ  mα»™t chuα»—i CSS selector để xΓ‘c Δ‘α»‹nh phαΊ§n tα»­ HTML cαΊ§n được truy cαΊ­p. Trong trường hợp nΓ y, phαΊ§n tα»­ HTML lΓ  thαΊ» input Δ‘αΊ§u tiΓͺn trΓͺn trang web. Đối sα»‘ thα»© hai cα»§a phΖ°Ζ‘ng thα»©c nΓ y lΓ  mα»™t hΓ m chα»©a cΓ‘c thao tΓ‘c để lαΊ₯y giΓ‘ trα»‹ thuα»™c tΓ­nh cα»§a phαΊ§n tα»­ HTML. Trong trường hợp nΓ y, chΓΊng ta sα»­ dα»₯ng phΖ°Ζ‘ng thα»©c getAttribute() để lαΊ₯y giΓ‘ trα»‹ cα»§a thuα»™c tΓ­nh "value" cα»§a phαΊ§n tα»­ HTML Δ‘Γ³.

Sau khi trΓ­ch xuαΊ₯t được giΓ‘ trα»‹ cα»§a intput, chα»©c nΔƒng Δ‘Γ³ng trΓ¬nh duyệt vΓ  kαΊΏt thΓΊc phiΓͺn lΓ m việc bαΊ±ng cΓ‘c lệnh page.close() vΓ  ctx.close(). Cuα»‘i cΓΉng, giΓ‘ trα»‹ cα»§a biαΊΏn otp được trαΊ£ về. NαΊΏu khΓ΄ng tΓ¬m thαΊ₯y giΓ‘ trα»‹ cα»§a trường nhαΊ­p liệu, giΓ‘ trα»‹ cα»§a biαΊΏn otp sαΊ½ vαΊ«n lΓ  null.

BαΊ‘n đọc kα»Ή phαΊ§n mΓ¬nh bΓ΄i mΓ u nhΓ©. TiαΊΏp xem Δ‘αΊΏn endpoint visit:

TiαΊΏp theo xem endpoint index /

Tα»•ng kαΊΏt lαΊ‘i:

GiΓ‘ trα»‹ otp sαΊ½ được hΓ m visitUrl lαΊ₯y ở input Δ‘αΊ§u tiΓͺn thΓ¬ ở endpoint / cΕ©ng cΓ³ input, khi Δ‘Γ³ nαΊΏu khΓ΄ng cΓ³ giΓ‘ trα»‹ otp thΓ¬ nΓ³ sαΊ½ tα»± gαΊ―n session.opt = opt. NαΊΏu tΓ¬m cΓ‘ch chuyển hΖ°α»›ng về /

VαΊ­y nαΊΏu khi Δ‘Γ³ chΓΊng ta chỉ cαΊ§n submit thΓ¬ cΓ³ thể lαΊ₯y được flag, nhΖ°ng phαΊ£i trong cΓΉng session.

Sau khi bot truy cαΊ­p trang, nΓ³ sαΊ½ tΓ¬m thαΊ» input Δ‘αΊ§u tiΓͺn vΓ  trΓ­ch xuαΊ₯t giΓ‘ trα»‹ cα»§a nΓ³ vΓ  trαΊ£ về dΖ°α»›i dαΊ‘ng OTP.

Khi Δ‘Γ³ để cΓ³ flag thΓ¬

Đoẑn payload của chúng ta sẽ như này:

Trong Δ‘oαΊ‘n payload, yΓͺu cαΊ§u GET tα»›i endpoint /visit được gα»­i Δ‘αΊΏn trang web cα»§a α»©ng dα»₯ng vα»›i mα»™t tham sα»‘ truy vαΊ₯n (query parameter) ad chα»©a mα»™t Δ‘oαΊ‘n mΓ£ HTML. Tuy nhiΓͺn, Δ‘oαΊ‘n mΓ£ nΓ y khΓ΄ng phαΊ£i lΓ  mα»₯c Δ‘Γ­ch chΓ­nh cα»§a cuα»™c tαΊ₯n cΓ΄ng, mΓ  chỉ lΓ  mα»™t cΓ‘ch để tαΊ‘o ra mα»™t yΓͺu cαΊ§u Δ‘αΊΏn α»©ng dα»₯ng web mΓ  khΓ΄ng cαΊ§n sα»± tΖ°Ζ‘ng tΓ‘c cα»§a người dΓΉng.

Sau khi yΓͺu cαΊ§u GET /visit Δ‘Γ£ được gα»­i, payload tiαΊΏp tα»₯c gα»­i mα»™t yΓͺu cαΊ§u GET tα»›i endpoint /flag vα»›i mα»™t tham sα»‘ truy vαΊ₯n otp được Δ‘Γ­nh kΓ¨m. NhΖ°ng vΓ¬ Δ‘Γ£ sα»­ dα»₯ng mα»™t Δ‘α»‘i tượng session để thα»±c hiện cαΊ£ hai yΓͺu cαΊ§u GET nΓ y, α»©ng dα»₯ng web sαΊ½ xΓ‘c Δ‘α»‹nh Δ‘Γ’y lΓ  hai yΓͺu cαΊ§u được thα»±c hiện bởi cΓΉng mα»™t người dΓΉng vΓ  sαΊ½ cho phΓ©p yΓͺu cαΊ§u /flag được thα»±c hiện mΓ  khΓ΄ng cαΊ§n xΓ‘c thα»±c lαΊ‘i người dΓΉng.

Last updated