Hoppa yfir í efnið

HTML og eyðublöð fyrir vefverkefni

HTTP-svar getur innihaldið mynd, JSON eða tóman líkama, en vefsíður byrja oft á HTML. Vafrinn les HTML-textann, býr til skipan af einingum og teiknar síðan síðu. Í CTF er sú skipan kort af viðmótinu: tenglar sýna slóðir, form sýna beiðniaðferðir og reitir sýna hvaða nöfn þjónninn býst við.

Við ætlum ekki að læra vefhönnun eða byggja fallega síðu. Markmiðið er að geta lesið ókunnugt HTML og svarað:

Hvaða slóðir eru nefndar?
Hvaða gögn sendir formið?
Hvað er aðeins falið í viðmótinu?
Hvað kom frá þjóninum og hverju breytti vafrinn?

Verkefnið Formið sem vantaði hefur sendingarkort en engan sýnilegan leitarhnapp. Í HTML-upprunakóðanum er engu að síður að finna heilt eyðublað. Þú þarft að finna aðferðina, slóðina og reitina og senda viðlíka beiðni og eyðublaðið hefði sjálft gert.

HTML gefur vísbendingar, ekki aukið umfang

Skoðaðu aðeins HTML og slóðir sem verkefnið afhendir. Athugasemd eða falinn tengill veitir ekki heimild til að prófa önnur lén eða telja upp ónefndar slóðir.

Einfaldasta HTML-skjalið

HTML, HyperText Markup Language, lýsir uppbyggingu skjals með merkjum:

<!doctype html>
<html lang="is">
  <head>
    <meta charset="utf-8">
    <title>Norðurmarkaðurinn</title>
  </head>
  <body>
    <h1>Sendingar</h1>
    <p>Velkomin á sendingasíðuna.</p>
  </body>
</html>

<!doctype html> segir vafranum að nota nútímalega HTML-túlkun. html umlykur skjalið, head geymir upplýsingar um það og body inniheldur það sem síðan birtir.

HTML-eining (e. HTML element) samanstendur gjarnan af upphafsmerki, innihaldi og lokamerki:

<p>Velkomin á sendingasíðuna.</p>

Sumar einingar, til dæmis img, hafa ekkert textainnihald:

<img src="/static/logo.png" alt="Merki Norðurmarkaðarins">

src og alt eru HTML-eigindir (e. HTML attributes). Eigind er nafn og oft gildi sem lýsir einingunni.

Inndráttur og línuskipti hjálpa fólki að lesa skjalið, en vafrinn reiðir sig öllu heldur á merkin sjálf. Þessi tvö brot fela í sér nákvæmlega sömu skipan:

<p>Halló <strong>Anna</strong></p>
<p>
  Halló
  <strong>Anna</strong>
</p>

Einingar geta verið hreiðraðar hver inni í annarri. Í Elements birtast þær því sem tré sem má opna og loka.

Tenglar og hlutfallslegar slóðir

Tenglar notast við eigindina href:

<a href="/orders/1001">Opna pöntun</a>

Slóð sem byrjar á / vísar alltaf út frá rót sama hýsis. Ef síðan er á:

https://nordurmarkadur.example/account

þá vísar /orders/1001 á:

https://nordurmarkadur.example/orders/1001

Slóð án upphafsskástriks er hlutfallsleg við núverandi slóð. Á síðunni /manuals/index gæti:

<a href="intro">Inngangur</a>

vísað á /manuals/intro.

Fleiri einingar bera slóðir:

<img src="/media/avatar.png" alt="Avatar">
<script src="/static/app.js"></script>
<link rel="stylesheet" href="/static/style.css">
<form action="/login" method="post">

Í CTF er leit að href=, src= og action= handhæg leið til þess að kortleggja þær slóðir sem síðan nýtir sér. Þetta er ekki slóðaskönnun; við erum að lesa efni sem þjónninn afhenti.

Afritaðu raunverulega slóð

Í Elements má oft hægrismella á tengil og velja að afrita slóðina. Líttu jafnframt á hið hráa href-gildi. Vafrinn getur sýnt fulla slóð þótt HTML hafi notað hlutfallslega slóð.

Þegar eyðublað verður að HTTP-beiðni

HTML-eyðublað (e. HTML form) safnar gildum og segir vafranum hvert og hvernig á að senda þau:

<form action="/search" method="get">
  <label>
    Leitarorð
    <input name="q" value="ull">
  </label>
  <button type="submit">Leita</button>
</form>

action er markslóðin. method er HTTP-aðferðin. Eigindin name í inntaksreitnum verður heiti gagnareitsins og núverandi value verður gildi hans.

Þegar formið er sent verður til beiðni á borð við:

GET /search?q=ull HTTP/1.1
Host: nordurmarkadur.example

Ef sama form notar method="post":

<form action="/search" method="post">

rata gögnin venjulega í líkama beiðninnar:

POST /search HTTP/1.1
Host: nordurmarkadur.example
Content-Type: application/x-www-form-urlencoded

q=ull

HTML-form styður venjulega GET og POST. Aðferðir eins og PUT sem við sáum í HTTP-kaflanum eru oft sendar með JavaScript eða beinum HTTP-tólum.

Hvaða reitir eru sendir?

Eyðublað sendir ekki gagnrýnislaust allan þann texta sem birtist á síðunni. Það sendir einungis gildar innsláttarstýringar (e. successful form controls) sem tilheyrir forminu og hefur yfirleitt name.

<form action="/account/update" method="post">
  <input name="display_name" value="Anna">
  <input value="Þessi reitur hefur ekkert name">
  <input name="role" value="user" disabled>
  <input type="hidden" name="account_id" value="42">
  <button type="submit" name="action" value="save">Vista</button>
</form>

Ef notandinn smellir á hnappinn gæti líkaminn verið:

display_name=Anna&account_id=42&action=save

Mikilvæg smáatriði eru:

  • Reitur án name fylgir almennt ekki með í beiðninni.
  • disabled-reitur fylgir almennt ekki með í beiðninni.
  • type="hidden"-reitur fylgir með þrátt fyrir að vera hulinn sjónum.
  • Submit-hnappur með name og value fylgir með ef sá hnappur var notaður til að senda eyðublaðið.
  • Óhakaður checkbox-reitur fylgir að jafnaði ekki með.

Þess vegna þarf stundum að skoða Payload í Network í stað þess að álykta út frá HTML einu. JavaScript getur einnig breytt gildum rétt áður en formið er sent.

hidden og disabled þýða ekki „þjónninn treystir þessu“. Biðlari getur smíðað beiðni með hvaða reitum sem er. Þjónsvarið segir hvað var í raun samþykkt.

Falið er ekki það sama og leyndarmál

HTML hefur fleiri en eina leið til að fela efni:

<form hidden>...</form>
<input type="hidden" name="warehouse" value="north">
<div style="display: none">...</div>
<div class="visually-hidden">...</div>

Allt þetta er enn í HTML eða DOM og sést í View Source eða Elements. CSS getur falið einingu sjónrænt án þess að fjarlægja hana. hidden-eigind lætur vafrann ekki teikna eininguna. type="hidden" er formreitur sem er ætlaður til sendingar án sýnilegs innsláttarreits.

HTML-athugasemd birtist heldur ekki á síðunni:

<!-- Gamla formið er enn á /sending/finna -->

Hún blasir þó við í upprunakóðanum. Í CTF getur athugasemd verið viljandi vísbending. Í raunverulegum vef er athugasemd ekki sjálfkrafa heimild til að prófa nefnda þjónustu; umfangið gildir áfram.

data-*-eigindir geyma gögn sem JavaScript getur lesið:

<article data-order-id="1001" data-owner="anna">
  Pöntun Önnu
</article>

Þær eru jafn notandaaðgengilegar og aðrar eigindir. Leitaðu að data-, hidden, disabled og HTML-athugasemdum þegar viðmótið virðist vanta næsta skref.

View Source og Elements

View Source sýnir HTML-svarið sem þjónninn sendi. Elements sýnir lifandi DOM eftir að vafrinn hefur þáttað HTML og JavaScript mögulega breytt því.

Eftirfarandi HTML-kóði er gallaður:

<p>Fyrsta málsgrein
<p>Önnur málsgrein

Vafrinn veit að nýtt p lokar yfirleitt fyrri málsgrein og býr til tvær einingar í DOM. Elements getur því sýnt lokunarmerki sem voru ekki skrifuð í upprunasvarið.

Töflur, hreiðruð eyðublöð og ranglega lokaðar einingar geta orðið fyrir enn frekari sjálfvirkum lagfæringum af hálfu vafrans. Þetta skiptir máli í CTF þegar þú þarft að vita hvort:

  • þjónninn sendi tiltekið merki,
  • vafrinn bjó það til við þáttun,
  • eða JavaScript bætti því við síðar.

Byrjaðu með View Source eða hráa Network-svarið. Notaðu síðan Elements til að sjá hvað vafrinn gerði úr textanum.

Breyting í Elements er staðbundin

Ef þú fjarlægir hidden, breytir value eða bætir við hnappi hefurðu aðeins breytt DOM í þínum vafra. Þetta kann vissulega að hjálpa þér að knýja vafrann til að senda beiðni, en breytir ekki frumkóða eða reglum þjónsins. Endurhleðsla sækir nýtt svar og staðbundna breytingin hverfur.

HTML-stafatilvísanir

Sum tákn hafa sérstaka merkingu í HTML. HTML-stafatilvísun (e. HTML character reference) birtir tákn án þess að það verði hluti af merkjaskipan:

&lt;strong&gt;Halló&lt;/strong&gt;

Vafrinn birtir:

<strong>Halló</strong>

en vafrinn myndar enga nýja strong-einingu í DOM-trénu.

Algengar tilvísanir eru:

HTML Tákn
&lt; <
&gt; >
&amp; &
&quot; "
&#39; '

Þetta er mikilvægt þegar XSS-samhengi er rannsakað síðar. Ef notandatextinn <b>merki</b> kemur í hráa svarinu sem &lt;b&gt;merki&lt;/b&gt; sýnir vafrinn hann sem texta. Ef hann kemur óbreyttur milli HTML-merkja getur vafrinn búið til nýja einingu.

Samhengið skiptir þó máli. Kóðun sem hentar HTML-texta er ekki sjálfkrafa rétt fyrir JavaScript-streng eða vefslóð. Í þessum kafla þurfum við aðeins að þekkja muninn á bókstaflegum texta og merkjaskipan.

enctype og upphleðsla skráa

Formeiginleikinn enctype segir hvernig POST-líkami er kóðaður. Sjálfgefið er oft:

<form method="post" enctype="application/x-www-form-urlencoded">

Skráarupphleðsla notar:

<form method="post" enctype="multipart/form-data">
  <input type="file" name="avatar">
</form>

Ef enctype vantar á skráareyðublað getur vafrinn ekki sent hrá skráarbæti með venjulegum hætti. Í Network sérðu lokaákvörðun vafrans í Content-Type og líkamanum.

text/plain er einnig mögulegt en sjaldgæfara. Ekki giska á líkamasnið þegar formið eða Network sýnir það beint.

Göngudæmi: Formið sem vantaði

Opnaðu verkefnið og skoðaðu sendingarkortið. Skráðu rakningarnúmerið sem síðan birtir. Opnaðu síðan View Source og leitaðu að form, action, hidden eða orðinu sending.

Þú ættir að finna form með þessari lögun:

<form action="<slóð úr verkefninu>" method="post" hidden>
  <input name="tracking" value="<rakningarnúmer>">
  <input type="hidden" name="warehouse" value="<vöruhús>">
  <button type="submit" name="mode" value="<hamur>">Sækja</button>
</form>

Þessi kafli gefur hins vegar ekki upp raunveruleg gildi. Lestu þau úr þínu HTML-svari.

Fyrri lausnarleiðin er að finna formið í Elements, fjarlægja hidden og smella á submit-hnappinn. Hafðu Network opið og skoðaðu POST-beiðnina sem vafrinn myndar.

Hin leiðin er að endursmíða formið í curl:

BASE_URL='https://slod-verkefnisins.example'

curl -i -X POST "$BASE_URL/<action úr forminu>" \
  --data 'tracking=<gildi úr forminu>' \
  --data 'warehouse=<gildi úr forminu>' \
  --data 'mode=<gildi submit-hnappsins>'

Berðu curl-beiðnina saman við Network. action ræður slóðinni, method aðferðinni og formstýringarnar mynda líkamann. Ef allt passar skilar þjónninn fánanum.

Ef svarið segir að reit vanti skaltu athuga hvort submit-hnappurinn hafi name og value. Ef þú kallaðir form.submit() úr Console getur hnappsgildið hafa vantað, því enginn ákveðinn hnappur var valinn. Venjulegur smellur eða handsmíðuð beiðni með öllum þremur pörum leysir þann mun.

Hagnýtar vísbendingar um annað

Tengill sem er í HTML en skilar venjulegri innskráningarsíðu er alls engin sönnun fyrir brotinni aðgangsstýringu. Falinn reitur sem þjónninn hunsar er ekki veikleiki aðeins vegna þess að hægt er að breyta honum.

Ef form hefur enga action sendir vafrinn það almennt á núverandi slóð. Ef method vantar er sjálfgefin aðferð yfirleitt GET. Ef input hefur ekkert name er sýnilegt value ekki endilega sent.

View Source getur líka sýnt gamalt, ótengt form inni í athugasemd. Staðfestu með Network eða einni afmarkaðri beiðni hvort slóðin og reitirnir eru enn notuð. HTML er upphaf rannsóknar, en HTTP-svarið er mælingin.

Samantekt

HTML lýsir síðu með einingum og eigindum. Tenglar, myndir, skriftur og form bera slóðir sem hægt er að kortleggja án skönnunar. Form tengir action, method, enctype og nefndar formstýringar við HTTP-beiðni.

hidden, type="hidden", það að fela efni með CSS og HTML-athugasemdir gera efni ósýnilegt í venjulegu viðmóti en ekki leynt. disabled-reitur og reitur án name fara yfirleitt ekki með, en falinn reitur gerir það. View Source sýnir svar þjónsins; Elements sýnir DOM eftir þáttun og mögulegar JavaScript-breytingar.

Í næsta kafla bætum við JavaScript við þessa mynd. Þar sjáum við hvernig atburðir breyta DOM, hvernig fetch() býr til HTTP-beiðnir og af hverju sannprófanir biðlarans (e. client-side validation) segja ekki ein og sér hvað þjónninn samþykkir.