HTTP, slóðir og ástand
Í fyrri kafla fundum við beiðni í vafranum og endurtókum hana með curl og Burp Repeater. Nú ætlum við að taka slíka beiðni í sundur. Þegar við vitum hvað aðferð, slóð, haus og líkami gera getum við breytt rétta hlutanum í stað þess að prófa handahófskennda texta.
Kaflinn fylgir verkefninu Rétt aðferð. Vefurinn sýnir leiðbeiningu þegar hann er opnaður, en venjulegt GET skilar ekki fánanum. Þjónninn vill mjög ákveðna HTTP-beiðni. Verkefnið er því ekki leit að duldum veikleika heldur æfing í að lesa svör og smíða beiðni sem passar við samskiptareglurnar.
Verkefnisslóðin afmarkar leyfið
Sendu aðeins beiðnir á hýsinn sem Örvangur úthlutar verkefninu eða á eigin þjónustu á 127.0.0.1. Ekki prófa sömu slóðir, aðferðir eða hausa á öðrum vefjum. HTTP-þekking lýsir hvernig samskiptin virka; hún veitir ekki heimild til að rannsaka óskyld kerfi.
Hvað segir vefslóðin?
Vefslóð (e. URL) segir biðlara hvert hann á að senda beiðni og hvaða efni hann biður um. Skoðum tilbúna slóð:
https://nordurmarkadur.example:8443/search?q=ull&sort=price#results
└─┬─┘ └──────────┬──────────┘└┬─┘└──┬──┘└───────┬───────┘└──┬──┘
skema hýsir tengi slóð fyrirspurnarstrengur brot
Skemað (e. scheme) er https. Það segir hvaða samskiptamáta á að nota. Algengustu vefskemin eru http og https.
Hýsirinn (e. host) er nordurmarkadur.example. Hér er hann lén, en hýsir getur einnig verið IP-tala eins og 127.0.0.1.
Tengið er 8443. Ef það er ekki tilgreint styðst biðlarinn að jafnaði við sjálfgefið tengi skemans, 80 fyrir HTTP eða 443 fyrir HTTPS.
Slóðarhlutinn (e. path) er /search. Hann auðkennir leið eða efni hjá þjóninum. Þetta er ekki endilega raunveruleg skrá á diski; veframmi getur tengt /search beint við fall í forriti.
Fyrirspurnarstrengurinn (e. query string) byrjar á ?. Hér eru tvö pör, q=ull og sort=price, aðskilin með &. Bæði heiti og gildi eru notandastýrð gögn sem þjónninn þarf að túlka.
Brotið (e. fragment) byrjar á #. Mikilvæg CTF-regla er að vafrinn sendir brotið venjulega ekki með HTTP-beiðninni. Það er notað innan vafrans, til dæmis til að fara að fyrirsögn á síðu eða halda utan um stöðu JavaScript-forrits.
Þjónninn fær því þessa beiðnislóð:
/search?q=ull&sort=price
en ekki:
/search?q=ull&sort=price#results
Ef þú breytir textanum á eftir # og svarið frá þjóninum breytist ekki er það líklega ekki dularfull sía. Gögnin fóru einfaldlega aldrei til þjónsins.
Röð og endurtekin heiti
Slóðin ?tag=ull&tag=lopi inniheldur sama heiti tvisvar. Veframmar geta túlkað það sem lista, tekið fyrsta gildið eða tekið það síðasta. Gerðu ekki ráð fyrir neinni einni og fastmótaðri túlkun; skoðaðu frekar hvað verkefnið sýnir eða prófaðu afmarkað í æfingaumhverfinu.
Frá léni að dulkóðuðu samtali
Þegar vafri sér https://nordurmarkadur.example þarf hann fyrst að finna IP-tölu hýsisins. DNS sér um þá uppflettingu. Síðan tengist biðlarinn þjóninum og HTTPS notar TLS til að vernda gögnin á leiðinni og tengja þjóninn við vottorð fyrir lénið.
Við þurfum ekki að greina DNS-pakka eða handaband dulritunar til að leysa fyrsta HTTP-verkefnið. Tvö atriði skipta þó máli:
- HTTPS verndar flutninginn en breytir ekki rökfræði vefþjónsins. Vefur getur verið með gilt vottorð og samt innihaldið viljandi CTF-veikleika.
- Hýsisheitið skiptir máli. Margar vefsíður geta deilt sömu IP-tölu og þjónninn notar hýsisupplýsingar til að velja réttan vef.
Í dæmigerðri HTTP/1.1-beiðni birtist hýsirinn í Host-hausnum. Í nýrri útgáfum HTTP er framsetningin önnur, en DevTools, curl og Burp sýna okkur sömu hugmynd: beiðnin þarf bæði áfangastað og heiti þjónustunnar sem hún á við.
HTTP/1.1, HTTP/2 og HTTP/3
Þú munt sjá mismunandi HTTP-útgáfur í verkfærum. Hráu textadæmin í bókinni nota oft HTTP/1.1 því þau eru auðlesin. Aðferðin, slóðin, hausarnir, líkaminn og stöðukóðinn hafa áfram sömu merkingu þótt flutningssniðið sé annað.
Bygging HTTP-beiðni
Hrá HTTP/1.1-beiðni skiptist í upphafslínu, hausa, auða línu og stundum líkama:
PUT /api/lausn?stage=2 HTTP/1.1
Host: nordurmarkadur.example
Content-Type: application/json
Accept: application/json
X-Verkefni: synidaemi
Content-Length: 20
{"svar":"synidaemi"}
Upphafslínan inniheldur HTTP-aðferð, beiðnislóð og útgáfu. Hausarnir lýsa beiðninni. Auða línan aðskilur hausana frá líkamanum og líkaminn inniheldur gögnin sjálf.
Heiti hausa eru óháð há- og lágstöfum, svo Content-Type og content-type merkja sama hausinn. Hausgildi geta hins vegar haft eigin reglur. Það er því ekki óhætt að breyta gildi í hástafi nema samskiptareglan segi að það skipti ekki máli.
Aðferðin er hluti af beiðninni
Slóðin ein og sér auðkennir ekki alla aðgerðina. Þessar beiðnir geta farið í ólíkan kóða þótt slóðin sé sú sama:
GET /api/pontun/42 HTTP/1.1
Host: nordurmarkadur.example
DELETE /api/pontun/42 HTTP/1.1
Host: nordurmarkadur.example
Algengar aðferðir eru:
| Aðferð | Algeng merking |
|---|---|
GET |
Sækja efni eða upplýsingar |
POST |
Senda gögn eða hefja aðgerð |
PUT |
Setja eða skipta út tiltekinni auðlind |
PATCH |
Breyta hluta auðlindar |
DELETE |
Eyða auðlind |
HEAD |
Sækja hausa eins og með GET, en ekki svarlíkama |
OPTIONS |
Spyrja hvaða samskiptamöguleika leið styður |
Þetta eru venjur, ekki sönnun fyrir því hvað forritið gerir. CTF-þjónn getur til dæmis sett lesaðgerð á POST eða gleymt að meðhöndla HEAD á sama hátt og GET. Við rýnum ávallt í raunveruleg svör verkefnisins.
Með curl veljum við aðferð með -X:
curl -i -X PUT https://nordurmarkadur.example/api/lausn
curl velur einnig sumar aðferðir sjálfkrafa. Venjulegt kall notar GET, en --data leiðir yfirleitt til POST. Í lausnarskýrslu er samt gagnlegt að hafa aðferðina skýra þegar hún er lykilatriði.
HTTP-svarið
Svar hefur svipaða byggingu:
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Allow: PUT
Content-Length: 46
{"villa":"Þessi leið býst við PUT-beiðni."}
Fyrsta línan inniheldur HTTP-stöðukóða (e. HTTP status code). Kóðinn er þriggja stafa tala og fyrsta talan gefur grófan flokk:
| Bil | Merking |
|---|---|
1xx |
Upplýsingar meðan samskipti halda áfram |
2xx |
Beiðnin tókst |
3xx |
Biðlarinn þarf að leita annað eða nota vistað eintak |
4xx |
Beiðnin passar ekki við það sem þjónninn samþykkir |
5xx |
Þjónninn lenti í villu |
Í CTF er stöðukóði mæling, ekki bara grænt eða rautt ljós. 404 eftir eina slóð og 403 eftir aðra segir að þjónninn meðhöndli þær ekki eins. 500 eftir sérstöku inntaki getur bent til þess að inntakið hafi náð inn í kóða sem venjuleg beiðni snertir ekki. Ein villa sannar þó ekki veikleika; krafist er mælanlegs og endurtekanlegs mismunar.
Nokkrir kóðar koma sífellt fyrir:
| Kóði | Heiti | Hagnýt túlkun |
|---|---|---|
200 |
OK | Svar með efni tókst |
201 |
Created | Ný auðlind var búin til |
204 |
No Content | Aðgerð tókst en enginn svarlíkami fylgir |
301, 302, 303, 307, 308 |
Redirect | Location vísar á næstu slóð; aðferð getur varðveist eða breyst eftir kóða |
400 |
Bad Request | Beiðnin er gölluð eða vantar vænt gögn |
401 |
Unauthorized | Auðkenningu vantar eða hún er ógild |
403 |
Forbidden | Þjónninn neitar aðgerðinni |
404 |
Not Found | Leið eða auðlind fannst ekki, eða þjónninn vill ekki staðfesta tilvist hennar |
405 |
Method Not Allowed | Slóðin er þekkt en þessi aðferð ekki leyfð; skoðaðu Allow |
415 |
Unsupported Media Type | Content-Type passar ekki við það sem leiðin les |
429 |
Too Many Requests | Of margar beiðnir bárust á skömmum tíma |
500 |
Internal Server Error | Óvænt villa kom upp í þjóninum |
401 heitir sögulega Unauthorized, en merkir oft að notandi sé ekki auðkenndur. 403 merkir frekar að þjónninn skilji beiðnina en neiti henni. Raunveruleg forrit nota kóðana þó ekki alltaf fullkomlega rétt, svo svarlíkaminn og hausarnir skipta líka máli.
Hausar segja fyrir um hvernig túlka beri gögnin
HTTP-haus (e. header) er nafn og gildi, aðskilin með tvípunkti:
Content-Type: application/json
Sumir hausar lýsa beiðninni, aðrir svarinu og sumir geta birst báðum megin. Þessir koma oft fyrir í CTF-rannsókn:
| Haus | Hvar? | Hvað segir hann? |
|---|---|---|
Host |
Beiðni | Hvaða hýsir á að fá beiðnina |
Content-Type |
Bæði | Hvaða snið líkaminn notar |
Accept |
Beiðni | Hvaða svarsnið biðlarinn vill helst |
Cookie |
Beiðni | Kökur sem vafrinn sendir þjóninum |
Set-Cookie |
Svar | Fyrirmæli til vafrans um að geyma köku |
Location |
Svar | Áfangastaður framsendingar |
Authorization |
Beiðni | Auðkenningarupplýsingar samkvæmt tilteknu skema |
Allow |
Svar | Aðferðir sem leiðin segist styðja |
Sérsniðnir hausar eru einnig afar algengir. Heiti sem byrja á X- sjást enn víða, þótt það sé ekki lengur almenn krafa fyrir sérsniðna hausa. Í Rétt aðferð er einn slíkur haus hluti af samskiptunum. Það þýðir ekki að allir X-*-hausar séu lyklar; verkefnið þarf að gefa vísbendingu sem styður þá túlkun.
Content-Length segir stærð líkamans í bætum. curl, vafrinn og Burp uppfæra hann yfirleitt fyrir okkur þegar líkaminn breytist. Sláir þú inn ranga lengd handvirkt getur þjónninn beðið eftir fleiri bætum eða lesið aðeins hluta gagnanna.
Sami texti, ólík gagnasnið
Þjónn getur túlkað sama sýnilega texta á ólíkan hátt eftir innihaldstegund (e. content type eða media type). Að senda rétt gildi á röngu sniði er því ekki sama beiðni.
Eyðublaðsgögn
Hefðbundið HTML-eyðublað sendir oft:
POST /login HTTP/1.1
Host: nordurmarkadur.example
Content-Type: application/x-www-form-urlencoded
notandi=anna&adgangsord=lopapeysa
Sniðið líkist fyrirspurnarstreng: pör eru tengd með & og nafn er aðskilið frá gildi með =. Með curl má senda það svona:
curl -i https://nordurmarkadur.example/login \
--data 'notandi=anna&adgangsord=lopapeysa'
--data velur sjálfgefið POST og application/x-www-form-urlencoded.
Prósentukóðun
Slóðir og eyðublaðsgögn nota prósentukóðun (e. percent-encoding) þegar bæti hafa sérstaka merkingu eða henta ekki beint í textann. Bil getur til dæmis birst sem %20, skástrik sem %2F og jafnaðarmerki sem %3D.
rauð peysa → rau%C3%B0%20peysa
Í application/x-www-form-urlencoded er bil einnig oft táknað með +. Þá er + ekki endilega bókstaflegt plúsmerki. Þetta samhengi skiptir máli:
q=raud+peysa
q=raud%20peysa
geta bæði táknað leit að tveimur orðum, en:
q=2%2B2
táknar bókstaflega 2+2.
Prósentukóðun er ekki dulritun og felur ekkert. Hún er aðeins framsetning. Leyfðu curl að sjá um hana þegar hægt er:
curl -G https://nordurmarkadur.example/search \
--data-urlencode 'q=rauð peysa'
-G setur gögnin í fyrirspurnarstreng í stað líkama.
JSON
Vefforritaskil nota oft JSON:
PUT /api/lausn?stage=2 HTTP/1.1
Host: nordurmarkadur.example
Content-Type: application/json
{"svar":"nordur","tilraun":1}
JSON notar tvöfaldar gæsalappir utan um heiti og textagildi. Talan 1 er tala, en textinn "1" er strengur; þjónn getur gert greinarmun þar á.
Nýrri útgáfur curl styðja --json, sem bæði setur hausinn og sendir líkamann:
curl -i -X PUT 'https://nordurmarkadur.example/api/lausn?stage=2' \
--json '{"svar":"synidaemi"}'
Almennari útgáfa, sem virkar einnig í eldri curl, er:
curl -i -X PUT 'https://nordurmarkadur.example/api/lausn?stage=2' \
-H 'Content-Type: application/json' \
--data '{"svar":"synidaemi"}'
Einfaldar gæsalappir utan um JSON hjálpa skelinni að láta tvöföldu gæsalappirnar inni í JSON í friði.
Margþætt eyðublað
Skráarupphleðsla notar oft multipart/form-data. Líkaminn skiptist þá í hluta með afmarkara (e. boundary), og hver hluti hefur eigin hausa:
POST /avatar/upload HTTP/1.1
Host: nordurmarkadur.example
Content-Type: multipart/form-data; boundary=BOUNDARY
--BOUNDARY
Content-Disposition: form-data; name="lysing"
Ný mynd
--BOUNDARY
Content-Disposition: form-data; name="mynd"; filename="avatar.png"
Content-Type: image/png
...hrá bæti myndarinnar...
--BOUNDARY--
Sjaldnast þurfum við að skrifa afmarkarann handvirkt. curl -F býr hann til ásamt réttum líkamaskilum:
curl -i https://nordurmarkadur.example/avatar/upload \
-F 'lysing=Ný mynd' \
-F 'mynd=@avatar.png;type=image/png'
Ekki setja Content-Type: multipart/form-data handvirkt með -H nema þú smíðir einnig réttan afmarkara. Að öðrum kosti getur þjónninn ekki greint hvar einn hluti endar og sá næsti hefst.
HTTP man engar fyrri beiðnir af sjálfu sér
HTTP notar í grunninn ástandslaus samskipti (e. stateless communication). Margar beiðnir berast einfaldlega sem aðskilin og sjálfstæð skilaboð. Samt geta vefir munað að Anna hafi skráð sig inn eða sett vöru í körfu. Til þess tengir forritið beiðnir saman með gögnum, oft vefköku (e. cookie).
Fyrsta svar getur beðið vafrann að geyma köku:
HTTP/1.1 200 OK
Set-Cookie: session=abc123; Path=/; HttpOnly
Content-Type: text/html
Velkomin, Anna
Í seinni beiðni sendir vafrinn hana til baka:
GET /account HTTP/1.1
Host: nordurmarkadur.example
Cookie: session=abc123
Þjónninn notar gildið abc123 til að finna veflotu Önnu. Kakan er ekki endilega notandanafnið eða öll lotugögnin; oft er hún aðeins ógegnsætt auðkenni.
curl geymir ekki kökur milli aðskildra keyrslna nema við biðjum um það. -c vistar kökur og -b les þær aftur:
curl -i -c cookies.txt https://nordurmarkadur.example/login
curl -i -b cookies.txt https://nordurmarkadur.example/account
Einnig má senda eina tilbúna köku beint:
curl -i -b 'session=abc123' https://nordurmarkadur.example/account
Í CTF er algengt að beiðni virki í vafra en ekki í curl vegna þess að lotukökuna vantar. Berðu Cookie-hausana saman áður en þú ályktar að slóðin sé röng. Notaðu aðeins gervilotur verkefnisins; raunverulegt lotuauðkenni getur veitt sama aðgang og innskráning.
Framsendingar og milliskref
Framsending (e. redirect) er svar úr 3xx-flokknum með Location-haus:
HTTP/1.1 302 Found
Location: /login
Set-Cookie: return_to=%2Faccount; Path=/
Vafri fylgir yfirleitt framsendingunni sjálfkrafa. Þú sérð þá lokasíðuna /login, en gagnleg vísbending gæti hafa verið í milliskrefinu: 302, Location eða Set-Cookie.
curl fylgir ekki framsendingu sjálfgefið. Það er gagnlegt við rannsókn:
curl -i https://nordurmarkadur.example/account
Að lokinni skoðun á milliskrefinu má fylgja framsendingum eftir með -L:
curl -i -L https://nordurmarkadur.example/account
Í Burp HTTP history birtist hvert skref sem sérstök færsla. Í Network geturðu einnig séð keðjuna. Ekki horfa aðeins á síðasta 200-svarið.
301, 302 og 303 geta valdið því að vafri breyti næstu beiðni í GET, en 307 og 308 eiga að varðveita aðferð og líkama. Þetta skiptir máli ef POST eða PUT virðist hverfa eftir framsendingu.
Skyndiminni getur endurnýtt gamalt svar
Vafrar og milliþjónar geta geymt svar í skyndiminni (e. cache) og endurnýtt það. Hausar eins og Cache-Control, Age, ETag og Last-Modified lýsa þeirri hegðun. Stöðukóðinn 304 Not Modified segir biðlara að nota eintak sem hann á nú þegar.
Í DevTools getur Network sýnt (memory cache) eða (disk cache) í stað þess að senda nýja beiðni. Þegar þú rannsakar hvort lítil breyting hafi áhrif geturðu hakað við Disable cache meðan DevTools er opið og endurhlaðið. Vertu þó á verði, því skyndiminnið getur sjálft leikið hlutverk í lausn verkefnisins; skráðu hvaða stillingu þú notar.
Gættu þess að bæta ekki handahófskenndum fyrirspurnarreit við allar slóðir einungis til þess að „brjóta upp skyndiminnið“. Fyrirspurnarstrengurinn er inntak og getur breytt rökfræði leiðarinnar. Gakktu fremur úr skugga um það fyrst í Network-flipanum hvort svar barst í raun úr skyndiminni.
Göngudæmi: smíðum réttu beiðnina
Opnaðu Rétt aðferð og hafðu Network eða Burp HTTP history opið. Fyrsta beiðnin er líklega venjulegt GET. Skoðaðu stöðukóðann, svarhausana og líkamann áður en þú breytir nokkru. Verkefnið á að veita nægilegar vísbendingar til þess að svara eftirfarandi spurningum:
- Hvaða slóð á að fá beiðnina?
- Hvaða HTTP-aðferð býst hún við?
- Hvaða fyrirspurnarreitur þarf að fylgja?
- Hvaða snið á líkaminn að nota?
- Hvaða sérsniðni haus og JSON-reitur eru nefnd?
Sendu fyrst af stað beiðni sem færir þig einungis einu skrefi nær markmiðinu. Ef GET skilar 405 og Allow: PUT, breyttu aðeins aðferðinni í PUT og sendu aftur. Nýtt 400 eða 415-svar er framför ef það segir nákvæmar hvað vantar. Þjónninn virkar þá eins og leiðbeinandi þáttari: hvert svar segir hvaða hluti beiðninnar var lesinn og hvar túlkunin stöðvaðist.
Í curl getur vinnubeiðnin litið svona út, með gildum úr verkefninu í stað hornklofanna:
BASE_URL='https://slod-verkefnisins.example'
curl -i -X PUT "$BASE_URL/api/lausn?stage=2" \
-H 'Content-Type: application/json' \
-H 'X-Verkefni: <gildi úr vísbendingu>' \
--data '{"svar":"<gildi úr vísbendingu>"}'
slod-verkefnisins.example er frátekið dæmi, ekki lifandi þjónusta. Notaðu úthlutaða Örvangursslóð verkefnisins.
Í Repeater er sama vinnuferli sjónrænt. Sendu upphafsbeiðnina úr HTTP history í Repeater, breyttu aðferðinni, settu stage=2 í slóðina, bættu við Content-Type og skrifaðu JSON-líkamann. Burp uppfærir yfirleitt Content-Length. Bættu sérsniðna hausnum við síðast svo þú getir séð hvaða svarbreyting tengist honum.
Lokabeiðnin hefur í grófum dráttum þessa lögun:
PUT /api/lausn?stage=2 HTTP/1.1
Host: <hýsir verkefnisins>
Content-Type: application/json
X-Verkefni: <gildi úr verkefninu>
{"svar":"<gildi úr verkefninu>"}
Ef svarið gefur ekki fána skaltu bera það saman við síðasta svar, ekki byrja upp á nýtt með ágiskunum. 405 bendir á aðferðina, 415 á innihaldstegundina og 400 oft á slóðargögn eða líkama. 403 gæti bent á að sérsniðna hausinn vanti eða sé rangur, en svar verkefnisins á að afmarka það betur.
Algengur ruglingur við fyrstu HTTP-verkefnin
Beiðnihausar og svarhausar líta eins út á skjánum en ferðast í gagnstæða átt. Set-Cookie kemur venjulega frá þjóninum; Cookie fer frá biðlaranum. Accept lýsir því sem biðlarinn vill fá; Content-Type lýsir því sem líkaminn er nú þegar.
Slóð og fyrirspurnarstrengur eru heldur ekki líkami. Í þessari beiðni:
POST /search?q=ull HTTP/1.1
Content-Type: application/json
{"page":2}
hefur þjónninn að minnsta kosti tvo inntaksstaði: q í slóðinni og page í JSON-líkamanum. Ef þú breytir q inni í JSON ertu að breyta öðrum gögnum en leiðin gæti verið að lesa.
Skelin getur jafnframt breytt skipun áður en tólið curl fær að sjá hana. & setur skipun í bakgrunn ef slóðin er ekki innan gæsalappa og tvöfaldar gæsalappir inni í illa afmörkuðu JSON geta horfið. Settu slóð með & og JSON-líkama því innan viðeigandi gæsalappa.
Að síðustu getur vafrinn fylgt framsendingu, sent köku og notað skyndiminni án þess að það sjáist á síðunni. Þegar curl og vafri fá ólík svör skaltu bera saman raunverulegar beiðnir í Network eða Burp. „Sama slóð“ þýðir ekki sjálfkrafa „sama HTTP-beiðni“.
Samantekt og næsta skref
Vefslóð skiptist í skema, hýsi, tengi, slóð, fyrirspurnarstreng og stundum brot. HTTP-beiðni bætir við aðferð, hausum og mögulegum líkama. Svarið gefur stöðukóða, hausa og líkama til baka. Gagnasnið eins og eyðublaðsgögn, JSON og multipart/form-data ráða hvernig þjónninn túlkar bæti, en kökur tengja annars sjálfstæðar beiðnir saman í lotu.
Þegar CTF-þjónn svarar öðruvísi eftir einni breytingu höfum við mælingu sem hægt er að vinna með. Við lesum 405, 415, Location, Set-Cookie og sérsniðna hausa sem hluta af samtalinu í stað þess að horfa aðeins á síðuna sem vafrinn teiknar.
Í næsta kafla skoðum við HTML og eyðublöð. Þar tengjum við einingar eins og tengla, reiti og hnappa við HTTP-beiðnirnar sem vafrinn býr til. Síðan bætum við JavaScript og lifandi DOM við myndina.