📝 TSD3060 Eksamen 2023-2024

Ordinær eksamen - ABC-system

ℹ️ Om denne eksamenen

Type: Blandet kodeanalyse - Systemforståelse, Dockerfile, CGI, HTML, sikkerhet

Fokus: Filroller, Docker-optimalisering, HTTP-metoder, CGI-miljøvariabler

Metode: Skriv egne svar først, sammenlign deretter med sensorveiledning

Oppgave 1 - Systemet 20%

(06%) Del 1: Gi en kortfattet og overordnet beskrivelse av dette eksempelsystemet.

(14%) Del 2: Gi en kortfattet og overordnet beskrivelse av hvilken rolle hver av filene spiller i eksempelsystemet. La svaret hovedsaklig være basert på filnavnene – uten nødvendigvis å gå inn på innholdet i filene.

Filer: compose.yaml, Dockerfile, index.html, abc.js, abc.cgi, abc.dtd, abc.css

✅ Sensorveiledning - Del 1: Systemet (6%)

Dette er et webbasert system med et HTML-basert grensesnitt mot en database. Grensesnittet gir brukeren mulighet til å hente og endre data i databasen.

✅ Sensorveiledning - Del 2: Filroller (14%)

compose.yaml - En fil med parametre som bestemmer systemets tilstand. Gjør det mulig å enkelt håndtere bygging, oppstart, nedstenging og omstart av systemet ved hjelp av docker-compose.

Dockerfile - Beskriver hvordan konteinerbildet skal bygges (ved hjelp av f.eks. Docker). Systemet kjører en webtjener i en kontainer basert på dette bildet.

index.html - Gir brukergrensesnittet i form av et skjema som fylles ut og sendes til et CGI-skript på webtjeneren.

abc.js - Inneholder en funksjon som kjøres ved klikk på en knapp i brukergrensesnittet. Funksjonen gjør en HTTP-PUT-forespørsel mot et CGI-skript – en forespørsel om å gjøre endringer i databasen.

abc.cgi - Inneholder kode som behandler forespørselene (GET eller PUT) fra klienten. Ved GET gjøres oppslag i databasen. Ved PUT gjøres endring i databasen.

abc.dtd - Definerer hva som er gyldig format for XML-dokumentet som sendes (av funksjonen i abc.js).

abc.css - Inneholder bestemmelser om utseende for brukergrensesnittet (fargelegging av knappene).

Oppgave 2 - Dockerfile 20%

(18%): Gi en detaljert beskrivelse, linje for linje, av filen Dockerfile.

(02%): Tre av linjene i filen begynner med ordet RUN. Forklar kort hvorfor det kan være lurt å slå disse sammen til én enkelt linje.

1: FROM alpine
2: RUN apk add busybox-extras libxml2-utils sqlite
3: COPY abc.cgi var/www/cgi-bin/abc.cgi
4: COPY index.html abc.css abc.js abc.dtd var/www/
5: RUN echo "CREATE TABLE abc (a1 SMALLINT PRIMARY KEY, a2 VARCHAR(200))" | \\
6:   sqlite3 var/www/abc.db
7: RUN echo "INSERT INTO abc VALUES (1,'a'),(2,'b');" | \\
8:   sqlite3 var/www/abc.db
9: RUN chmod a+w var/www/abc.db
10: EXPOSE 80
11: CMD httpd -p 80 -h /var/www -f -vv

✅ Sensorveiledning - Linje-for-linje (18%)

Linje 1: Angir at lettvekts-linuxdistroen Alpine skal brukes som grunnbilde. De påfølgende linjene legger lag på lag oppå dette.

Linje 2: Installerer tre programpakker (busybox-extras, libxml2-utils og sqlite). De nye filene vil utgjøre et nytt lag i bildet som bygges.

Linje 3: Kopierer en fil (abc.cgi) inn i et nytt lag i bildet som bygges.

Linje 4: Kopierer fire filer (index.html, abc.css, abc.js og abc.dtd) inn i et nytt lag i bildet som bygges.

Linje 5-6: Oppretter databasen (med en tabell) i en fil i et nytt lag i bildet som bygges.

Linje 7-8: Setter inn verdier i databasen. Ny versjon av databasefila blir opprettet i et nytt lag av bildet som bygges.

Linje 9: Gjør databasenfilen skrivbar (for alle brukere av systemet) slik at det er mulig å gjøre endringer i databasen. Endringen medfører en ny versjon av databasefila – i et nytt lag i bildet som bygges.

Linje 10: Angir at systemet kommer til å bruke TCP-port 80 for å lytte etter innkommende forespørsler.

Linje 11: Angir hvilken kommando som skal utføres når en konteiner, basert på bildet som bygges, igangkjøres. Kommandoen starter en webtjener som er innebygd i busybox.

✅ RUN-kommandoer (2%)

Hver RUN-kommando lager et nytt lag i bildet som bygges. Ved å slå sammen flere RUN-kommandoer reduseres antall lag. Bildene vil dermed bli mer kompakte – mindre lagringsplass, mindre overføringstid og raskere konteiner-oppstart.

Oppgave 3 - abc.cgi 20%

(03%): Forklar kort funksjon/virkemåte og hensikt med den innledende delen (linjene 1–3)

(06%): Forklar kort funksjon/virkemåte og hensikt med den første kodeblokken i if-setningen (linjene 4–12)

(06%): Forklar kort funksjon/virkemåte og hensikt med den andre kodeblokken i if-setningen (linjene 13–18)

(05%): De to kodeblokkene gjør begge en tilordning av variabelen B (linjene 5 og 14). Dette gjøres på to forskjellige måter. Forklar hvordan og hvorfor det må være ulikt.

1: #!/bin/sh
2: echo "Content-type:text/plain;charset=utf-8"
3: echo
4: if [ "$REQUEST_METHOD" = "GET" ]; then
5:   B=$(echo "$QUERY_STRING" | tr '&' ' ')
6:   for I in $B; do
7:     N=$(echo "$I"|cut -f1 -d=)
8:     V=$(echo "$I"|cut -f2 -d=)
9:       if [ "$N" = "a1" ]; then
10:        echo SELECT '*' FROM abc WHERE a1="$V" | sqlite3 ../abc.db
11:       fi
12:   done 
13: elif [ "$REQUEST_METHOD" = "PUT" ]; then
14:   B=$(head -c "$HTTP_CONTENT_LENGTH")
15:   A1=$(echo "$B" | xmllint --xpath "/abc/a1/text()" -)
16:   A2=$(echo "$B" | xmllint --xpath "/abc/a2/text()" -)
17:   echo UPDATE abc SET a2="'"$A2"'" WHERE a1=$A1 | sqlite3 ../abc.db
18: fi

✅ Sensorveiledning - Innledende del (3%)

Linje 1: Angir stien til programmet som skal tolke de etterfølgende kommandoene. I dette tilfellet angir stien at dette er et shell-skript.

Linje 2: Skriver ut slutten av HTTP-hodet. Siden dette er et CGI-skript, er det webtjenerens ansvar å skrive begynnelsen av hodet. I dette tilfellet angis at kroppen skal tolkes (av HTTP-klienten) som ren tekst.

Linje 3: Angir et skille – slutten av hodet og begynnelsen av kroppen.

✅ Første kodeblokk - GET (6%)

Før webtjeneren starter CGI-skriptet lagrer den informasjon fra HTTP-forespørselen i miljøvariabler som arves av prosessene som kjører CGI-skriptet. I kodeblokken i linjene 4–12 brukes informasjon om type HTTP-forespørsel (REQUEST_METHOD) og spørrestrengen (QUERY_STRING). Den sistnevnte inneholder det som står etter spørsmåltegnet i URL-en.

Om forespørselstypen er GET, gjøres et oppslag i databasen basert på skjemaverdiene som ble sendt inn og kodet som en spørrestreng (etter spørsmåltegnet i URL-en).

Utskriften fra databaseoppslaget skrives til standard utgang (STDOUT). Denne er omdirigert til (en socket som er koblet til) HTTP-klienten. Resultatet hos klienten blir at websiden med skjemaet blir erstattet av resultatet fra databaseoppslaget.

✅ Andre kodeblokk - PUT (6%)

Om forespørselstype er PUT, kjøres kodeblokken i linjene 14–17. Her hentes også informasjon fra tekstfeltene i skjemaet. Denne gangen er de formatert som XML og sendt i HTTP-forespørselens kropp.

Skriptet bruker informasjon om lengden av kroppen for å vite hvor mange byte som skal leses fra standard inngang (STDIN) – som er koblet til HTTP-klienten. Informasjon om kroppslengden er på forhånd satt av webtjeneren i miljøvariabelen HTTP_CONTENT_LENGTH.

Verdiene hentes ut av XML-dokumentet og brukes som grunnlag for en oppdatering i databasen.

Her skrives ingen ting ut. På klientsiden blir websiden med skjemaet stående uendret, siden det ikke finnes kode som endrer den.

✅ Forskjell i tilordning av B (5%)

Med PUT sendes dataene i HTTP-kroppen, og må dermed leses fra standard inngang (STDIN) – som er koblet til HTTP-klienten.

Med GET sendes dataene i URL-en, og må dermed hentes fra en miljøvariabel (QUERY_STRING) som settes av webtjeneren.

Oppgave 4 - index.html 20%

(05%): Forklar hva brukeren ser når filen lastes i en nettleser.

(02%): Forklar betydningen av linjene 1, 2 og 17.

(05%): Forklar betydningen av linjene f.o.m. 3 t.o.m. 8.

(05%): Forklar betydningen av linjene f.o.m. 9 t.o.m. 16.

(03%): Websiden gir brukeren to måter å sende data. Forklar forskjellen på dem.

1: <!doctype html>
2: <html>
3:   <head>
4:     <meta charset="utf-8">
5:     <title>ABC</title>
6:     <link rel="stylesheet" type="text/css" href="abc.css" />
7:     <script src="abc.js"> </script>
8:   </head>
9:   <body>
10:     <form action='cgi-bin/abc.cgi' method='get'>
11:       <input name='a1' id='a1' type='text'>
12:       <input name='a2' id='a2' type='text'> 
13:       <input type='submit'>
14:     </form>
15:     <button type="button" onclick='abc1()'> U </button>
16:   </body>
17: </html>

✅ Sensorveiledning - Hva brukeren ser (5%)

Brukeren kan se følgende:

  • Tittelen ABC øverst i arkfane (tab) eller vindu – altså ikke en overskrift i selve dokumentet
  • To felt for innskriving av tekst (tekstfelt)
  • En lysegrønn knapp merket "Submit" eller "Send inn"
  • En mørkegrønn knapp merket "U"

✅ Linjene 1, 2 og 17 (2%)

Linje 1: Angir at dokumenttypen er HTML (HTML5).

Linjene 2 og 17: Angir rot-elementet. Det omslutter selve dokumentet med start- og slutt-merkelapper (-tagger).

✅ Linjene 3-8 (5%)

Linjene 3–8 utgjør HTML-dokumentets hode, som er omsluttet av merkelapper for start (linje 3) og slutt (linje 8).

I hodet ligger informasjon om:

  • Fanens/vinduets tittel
  • Hvilket tegnsett som skal brukes
  • Hvor websidens stilinformasjon er lagret (abc.css)
  • JavaScript-kode som skal kjøres (abc.js)

✅ Linjene 9-16 (5%)

Linjene 9–16 utgjør HTML-dokumentets kropp, omsluttet av merkelapper for start (linje 9) og slutt (linje 16).

I kroppen finner vi:

  • Et skjema med to tekstfelt med både navn og ID
  • Skjemaet har tilknyttet en knapp
  • Det er angitt (med attributter hos form-taggen) hvilken URL skjemaet skal sendes til og hvilken HTTP-metode som skal brukes
  • En ekstra knapp som ved trykk utfører funksjonen abc1() (definert i abc.js)

✅ To måter å sende data (3%)

Den ene knappen utløser en PUT-forespørsel som sender data som en del av HTTP-kroppen (formatert som XML), mens den andre sender en GET-forespørsel som sender dataene i URL-en, som er en del av HTTP-hodet.

Den førstnevnte sender data formatert eksempelvis slik: navn1=verdi1&navn2=verdi2. Dataene blir tilgjengelig i en miljøvariabel i CGI-skriptet.

I sistnevnte tilfelle blir dataene sendt i XML-format og må leses fra standard inngang (STDIN) i CGI-skriptet.

Oppgave 5 - Sikkerhet 20%

Basert på eksistensen av Dockerfile og compose.yaml: Hva kan du si om sikkerhetsmekanismer og prinsipper som er i bruk i systemet?

Linje 12 i filen abc.js antyder en sikkerhetsmekanisme. Forklar hvordan en slik sikkerhetsmekanisme fungerer.

// Linje 12 i abc.js:
credentials: 'include',

✅ Sensorveiledning - Dockerfile og compose.yaml

Eksistensen av filene indikerer bruk av operativsystemvirtualisering/konteiner. Dette betyr at systemet har stor grad av isolasjon/begrensning av ressurser fra vertssystemet. Da er diverse mekanismer innebygd i Linux-kjernen tatt i bruk. Spesielt bør namespaces, cgroups og capabilities nevnes.

Konteinere lages ofte etter prinsipper som innebærer:

  • Ikke inkludere mer enn nødvendig – for å begrense angrepsflate
  • Ikke gi mer rettigheter/ressurser enn nødvendig – for å begrense skade ved sikkerhetsbrudd

Eksistensen av compose.yaml indikerer at et eget nettverkssegment med nettverksadresseoversettelse (NAT) er satt opp og at kun angitte porter er tilgjengelig (som en brannmurfunksjonalitet).

✅ Credentials 'include' (linje 12)

Identitetsbevis (credentials) skal følge med i HTTP-forespørselen. Dette antyder at en autentiseringsmekanisme er implementert ved hjelp av informasjonskapsler (cookies).

Hvordan det fungerer:

  1. Bruker oppgir identitet (typisk brukernavn) og en hemmelighet (typisk passord, evt. flere faktorer)
  2. De innsendte dataene sjekkes av funksjonalitet utført av HTTP-tjeneren (f.eks. ved oppslag i database)
  3. Om identiteten bekreftes, opprettes en unik sesjons-ID som sendes som en informasjonskapsel i HTTP-responsen (Set-cookie: [...])
  4. I påfølgende HTTP-forespørsler fra klienten kan kapselen medsendes som bevis på at brukeren allerede er logget inn og kan knyttes til en pågående sesjon
  5. Klienten medsender da kapselen som en del av HTTP-hodet (Cookie: [...])

📋 Kodevisning - ABC-system

Velg en fil fra listen over for å vise koden...