Skráarupphleðsla
Skráarupphleðsla flytur meira en hrá bæti. Beiðnin ber líka skráarheiti, innihaldstegund og heiti eyðublaðsreits. Þjónninn ákveður síðan hvar skráin lendir, hvort hún er opnuð eða umbreytt og hvernig hægt er að sækja hana aftur.
Í CTF getur veikleikinn legið í hverju skrefi. Skráarheitið getur stjórnað slóð, Content-Type getur aðeins verið fullyrðing biðlarans og mynd getur verið endurkóðuð áður en hún birtist. Við byrjum því ekki á því að hlaða upp tuttugu skrám með ólíkum endingum. Við rekjum eina skrá frá HTTP-beiðni yfir í geymslu og næsta svar.
Verkefnið Avatarinn notar skráarheitið óbreytt við vistun. Markmiðið er ekki að keyra upphlaðinn kóða. Við látum filename fara úr uploads/ yfir í afmarkaða public/-systurmöppu og skrifum þekkt gildi í message.txt.
Aðeins litlar, skaðlausar verkefnisskrár
Prófaðu aðeins afmarkaðar texta- eða myndaskrár í þessu verkefni. Ekki hlaða upp spilliforriti, gagnvirkum skeljum, risaskrám, þjöppunarsprengjum eða efni sem reynir að skrifa utan þess markmiðs sem verkefnið nefnir. Upphleðslusandkassinn er ekki skotmark.
Hvað fer í upphleðslubeiðni?
Vafrar senda skrár yfirleitt sem margþætt formgögn (e. multipart/form-data). Hver hluti fær eigin hausa og afmarkari skilur hlutana að:
POST /avatar/upload HTTP/1.1
Host: nordurmarkadur.example
Content-Type: multipart/form-data; boundary=BOUNDARY
--BOUNDARY
Content-Disposition: form-data; name="avatar"; filename="mynd.png"
Content-Type: image/png
...hrá bæti skrárinnar...
--BOUNDARY--
Þarna stjórnar biðlarinn að minnsta kosti:
- reitarheitinu
avatar, - skráarheitinu
mynd.png, - uppgefnu innihaldstegundinni
image/png, - og hráu innihaldi skrárinnar.
Vafrinn velur venjulega skráarheitið úr skránni á tölvu notandans. Burp eða curl getur hins vegar smíðað annað filename. Þjónninn fær ekki trausta sönnun um upprunalegt heiti úr tölvu notandans.
curl -F býr til afmarkarann og multipart-líkamann:
curl -i https://nordurmarkadur.example/avatar/upload \
-F 'avatar=@mynd.png;filename=mynd.png;type=image/png'
Ekki setja Content-Type: multipart/form-data handvirkt með -H þegar curl -F er notað. Þá gæti vantað nákvæma boundary-gildið sem curl valdi.
Fjórar ólíkar lýsingar á sömu skrá
Skrá getur haft nafn, endingu, uppgefna MIME-gerð og raunverulegt innihald. Þetta eru tengdar vísbendingar en ekki sama staðreynd.
filename="avatar.png" ← notandastýrt heiti
ending: .png ← hluti heitisins
Content-Type: image/png ← notandastýrður HTTP-haus í hlutanum
fyrstu bæti: 89 50 4e 47 ... ← PNG-skráarauðkenni
Skráarending getur sagt forriti hvernig það eigi að reyna að opna skrá, en að breyta texti.txt í texti.png breytir ekki bætunum. Innihaldstegund kemur frá biðlaranum í upphleðslunni og má breyta í Repeater. Skráarauðkenni (e. file signature eða magic number) eru þekkt bæti inni í skránni.
Ekkert eitt þeirra er fullkomin lýsing. Fjölsniðsskrá getur verið gild samkvæmt fleiri en einu skráarsniði, og sum snið leyfa aukagögn sem annað forrit túlkar. En í byrjenda-CTF er betra að spyrja fyrst hvaða athugun þjónninn framkvæmir en að smíða fjölskrá af vana.
MIME-gerð og Content-Type
MIME-gerð er heiti eins og image/png eða text/plain. Content-Type er HTTP-hausinn sem ber slíkt gildi. Í multipart-beiðni hefur allur líkaminn multipart/form-data, en einstaki skráarhlutinn getur haft sitt eigið Content-Type: image/png.
Rekjum skrána í gegnum þjóninn
Gagnlegt líkan er:
multipart-beiðni
↓
skráarheiti + uppgefin gerð + bæti
↓
vistun eða afleidd vinnsla
↓
geymsluslóð
↓
opinber birting, niðurhal eða frekari túlkun
Skoðaðu upphleðslusvarið. Skilar það nýju heiti, auðkenni eða slóð? Færist mynd.png á /uploads/mynd.png, eða býr þjónninn til slembið heiti eins og /media/8f31...? Breytist stærðin þegar skráin er sótt aftur?
Ef þú getur sótt skrána aftur skaltu bera bæti eða tætigildi saman:
sha256sum mynd.png nidurhalad-mynd.png
Sama tætigildi bendir til að bætin hafi varðveist. Ólíkt gildi getur bent til endurkóðunar, smámyndar, lýsigagnahreinsunar eða þess að þú sóttir annað svar en skrána sjálfa.
Skráarheitið sem slóð
Einfaldur Flask-kóði gæti verið:
UPLOADS = Path("/tmp/challenge/uploads")
uploaded = request.files["avatar"]
target = UPLOADS / uploaded.filename
uploaded.save(target)
Með filename="mynd.png" verður markslóðin:
/tmp/challenge/uploads/mynd.png
Með:
filename="../public/message.txt"
verður hún:
/tmp/challenge/uploads/../public/message.txt
sem skráakerfið samræmir sem:
/tmp/challenge/public/message.txt
Þetta er slóðaflakk við skrif. Í fyrri kafla stjórnaði file hvaða skrá var lesin; nú stjórnar multipart-hausinn hvar innihaldið er vistað.
Vafraform getur fjarlægt möppuhluta úr skráarheiti áður en það sendir. Það segir ekki hvað þjónninn samþykkir frá handsmíðaðri multipart-beiðni. Í CTF staðfestum við því raunverulega filename-gildið í Network eða Burp.
Yfirskrift og samnefndar skrár
Ef tvær upphleðslur nota sama markheiti getur seinni skráin yfirskrifað þá fyrri. Afleiðingin ræðst af því hvað var þar:
- venjulegur avatar gæti breyst,
- opinber textaskrá gæti fengið nýtt innihald,
- stillinga- eða sniðmátsskrá gæti haft áhrif á aðra virkni,
- eða skráarkerfisheimildir gætu hafnað skrifinu.
200 OK eftir upphleðslu sannar ekki að yfirskrift hafi tekist. Sæktu markskrána eða kallaðu á þá leið sem notar hana. Í Avatarnum les /message nákvæmlega afmarkaða message.txt, svo við höfum skýra mælingu án þess að kanna aðrar skrár.
Samnefnd upphleðsla getur líka fengið nýtt heiti, til dæmis mynd-1.png. Slíkt svar mælir gegn beinni yfirskrift með upprunalega heitinu. Skráðu heitið sem þjónninn skilar, ekki aðeins það sem þú sendir.
Opinber birting er sérstakt skref
Skrá getur verið vistuð en ekki aðgengileg yfir HTTP. Hún getur líka verið birt frá öðrum uppruna eða í gegnum niðurhalsleið sem setur hana sem viðhengi.
Vefrót (e. web root) er mappa sem vefþjónn tengir beint við slóðir. Ef upphleðsla lendir þar gæti /uploads/mynd.svg orðið opinber. Ef hún lendir utan vefrótar þarf sérstaka leið eins og /download?id=... að sækja hana.
Í CTF skaltu leita að slóð í upphleðslusvarinu og skoða Content-Type og Content-Disposition þegar skráin er sótt. Content-Disposition: attachment bendir til niðurhals, en innfelld birting getur látið vafra túlka HTML, SVG eða annað virkt efni.
Opinber birting er ekki sama og kóðakeyrsla á þjóninum. Flask keyrir ekki sjálfkrafa upphlaðna .py-skrá. PHP-þjónn sem hefur keyrslu virka í upphleðslumöppu getur hins vegar túlkað .php. Tæknistaflinn og vefþjónsstillingin ráða; skráarending ein gerir ekki skel.
Endurkóðun mynda
Myndaþjónusta getur opnað upphlaðna mynd og vistað nýtt eintak. Þetta er endurkóðun (e. image re-encoding):
upphlaðin PNG-bæti → myndþáttari → dílar → ný PNG-skrá
Viðbættur texti aftan við skrá, sum lýsigögn og önnur ósýnileg bæti geta horfið. Stærð, þjöppun og litasnið geta líka breyst. Ef verkefnið endurkóðar allar myndir og skilar aðeins nýja eintakinu er lausn sem treystir á óbreytt aukabæti ólíkleg.
Afleidd skráarvinnsla (e. derived file processing) getur einnig búið til smámynd, keyrt OCR, lesið EXIF eða dregið safnskrá út. Þá getur veikleikinn legið í þáttaranum eða útdrættinum fremur en upphaflegri vistun. Verkefnið ætti að gefa vísbendingu um slíka vinnslu; ekki hlaða upp handahófskenndum skráarsniðum til að sjá hvað hrynur.
Stærðarmörk og þjöppunarsprengjur
Þjónn getur hafnað stórri beiðni með:
HTTP/1.1 413 Content Too Large
Hann getur líka takmarkað myndstærð, fjölda hluta í safnskrá eða vinnslutíma. 413 er vísbending um stærðarmörk, ekki boð um að finna leið til að senda stærra efni.
Þjöppunarsprengja er lítil þjöppuð skrá sem þenst út í gríðarlegt magn. Hún getur eytt minni, diski eða vinnslutíma og á ekki að búa til í þessari leið. Ef CTF fjallar um fyrirbærið á það að nota fyrirfram mæld, skaðlaus gervigögn og sérstaka þjónustu. Avatarinn þarf aðeins örlitla textaskrá.
Göngudæmi: Avatarinn
Byrjaðu á venjulegri textaskrá með einstöku prófmerki:
printf 'AVATAR_PROF_42\n' > /tmp/avatar-prof.txt
curl -i "$BASE_URL/avatar/upload" \
-F 'avatar=@/tmp/avatar-prof.txt;filename=avatar-prof.txt;type=text/plain'
Skoðaðu upphleðslusvarið og staðfestu að skráin hafi verið samþykkt. Finndu multipart-beiðnina í Burp og athugaðu hvar filename birtist miðað við hráu bætin.
Verkefnið gefur sérstakt markgildi sem /message býst við. Settu aðeins það gildi í litla skrá:
printf '%s\n' '<markgildi úr verkefninu>' > /tmp/message.txt
Sendu sömu upphleðslu en breyttu filename yfir í slóðina að systurmöppunni:
curl -i "$BASE_URL/avatar/upload" \
-F 'avatar=@/tmp/message.txt;filename=../public/message.txt;type=text/plain'
Kallaðu síðan á mælingarleiðina:
curl -i "$BASE_URL/message"
Ef hún skilar fánanum hefur skráarheitið stjórnað markslóðinni og yfirskriftin haft sýnileg áhrif. Kaflinn gefur ekki upp markgildið eða fánann.
Ef upphleðslan tekst en /message breytist ekki skaltu skoða svar þjónsins. Var skráin endurnefnd? Var ../ fjarlægt? Var reitarheitið rétt? Berðu venjulega og breytta beiðni saman og breyttu ekki MIME-gerð, innihaldi og slóð samtímis.
Hagnýtar vísbendingar um annað
Ef þjónninn býr alltaf til nýtt slembiheiti og skilar aðeins auðkenni er notandastýrða filename líklega ekki notað sem geymsluslóð. Ef Path.name, basename() eða sambærileg aðgerð sést í frumkóða tapast möppuhlutinn. Ef skrifanleg geymsla er utan vefrótar og niðurhal fer aðeins í gegnum auðkenni er bein opinber birting ólíkleg.
Raunveruleg myndendurkóðun mælir gegn nytjahleðslu sem treystir á aukabæti eða lýsigögn. Vefþjónn sem skilar upphleðslum alltaf sem application/octet-stream og attachment mælir gegn beinni HTML-túlkun í vafra. Flask-forrit án nokkurrar leiðar sem flytur upphlaðinn Python-kóða í túlk mælir gegn einfaldri .py-keyrslu.
Á hinn bóginn eru óbreytt filename í slóðasamsetningu, opinber slóð sem varðveitir heitið og sama tætigildi eftir niðurhal sterkar vísbendingar um hvaða próf er skynsamlegt næst.
Samantekt
Upphleðsla ber skráarheiti, uppgefna innihaldstegund og hrá bæti. Þjónninn getur endurnefnt, flokkað, endurkóðað, birt eða túlkað skrána. Við rekjum þessi skref í stað þess að treysta endingunni eða Content-Type einum saman.
Notandastýrt filename getur orðið að slóðaflakki við skrif og samnefnd skrá getur verið yfirskrifuð. Opinber birting er annað skref en vistun og kóðakeyrsla ræðst af tæknistafla, ekki aðeins skráarendingu. Endurkóðun og afleidd vinnsla breyta því hvaða bæti lifa upphleðsluna.
Í næsta kafla sendir notandinn ekki skrá heldur vefslóð. Þjónninn sækir hana sjálfur, og við skoðum hvort sú beiðni nær til innri leiða sem vafrinn okkar nær ekki beint.