TDT4237 Programvaresikkerhet Exercise 2. Kristian Ekle Stian Hegerland Hagen Thomas Gautvedt Tale Prestmo Martin Rechsteiner Marthe Øynes



Like dokumenter
Agenda. Data og grenser Kontekster XSS XSS og kompliserende kontekster Injection attacks Beskyttelse OWASP

Sikkerhet i Pindena Påmeldingssystem

Sikkerhet i Pindena Påmeldingssystem

HTML5. Skjemaer på nettsider. Skjemaer med. Informasjonsteknologi 1 og 2. Gløer Olav Langslet Sandvika VGS

PERSONVERN, GDPR OG COREPUBLISH

Sikkerhet og tilgangskontroll i RDBMS-er

Eksamen i Internetteknologi Fagkode: IVA1379

Oblig 5 Webutvikling. Av Thomas Gitlevaag

Sikkerhet i Pindena Påmeldingssystem

SVARFORSLAG : Eksamen i IBE102 Webutvikling Våren 2017.

Tilkobling og Triggere

Feilmelding Årsak Løsning

User Input / Output Handling. Innocent Code kap 3-4 INF-329 Øystein Lervik Larsen oysteinl@ii.uib.no 7/11-05

Eksamen i Internetteknologi Fagkode: ITE1526

Brukerveiledning for ArkN4

Kapittel 11. Databasesikkerhet

Elektronisk innlevering/electronic solution for submission:

Database security. Kapittel 14 Building Secure Software. Inf329, Høst 2005 Isabel Maldonado

Sikkerhet og internett. Kan vi være vi trygge? Kan vi beskytte oss? Bør vi slå av nettet

Testsituasjon Resultat Kommentar. Fungerer som det skal!

Prosedyrer. Lars Vidar Magnusson. October 26, Lars Vidar Magnusson () Forelesning i DAS October 26, / 19

if-tester Funksjoner, løkker og iftester Løkker og Informasjonsteknologi 2 Læreplansmål Gløer Olav Langslet Sandvika VGS

Produksjonssettingsrapport

EN PRAKTISK INNFØRING I KRYPTERT E-POST FRA UDI

Trådløsnett med. Wireless network. MacOSX 10.5 Leopard. with MacOSX 10.5 Leopard

Innocent Code Kapittel 1: The Basics Kapittel 2: Passing Data to Subsystems

HØGSKOLEN I SØR-TRØNDELAG

som blanker skjermen (clear screen). Du får en oversikt over alle kommandoene ved å skrive,

WP-WATCHER WORDPRESS SIKKERHET

Pen- tes'ng av webservices. Asbjørn Reglund Thorsen Gruppe- og utviklingsleder UIO/FSAT

Brukermanual. Itpays W3 Publish. Sette opp, logge inn og komme i gang. Redigert den 23. mai

Administrator guide. Searchdaimon ES (Enterprise Server)

HØGSKOLEN I SØR-TRØNDELAG

Lotus Traveler - Manual for installasjon

Utvikling av dynamiske nettsteder med PHP og databaser, høsten 2006

en hjemmeside Lesson Introduksjon Du kjenner en del HTML tagger, så nå er det på tide å lage din første hjemmeside! La oss begynne med en gang.

Produktdokumentasjon. Madison Møbler Administrasjonsside og Nettbutikk

Overordnet beskrivelse og arkitekturskisse

Oversikt over flervalgstester på Ifi

EKSAMEN. Emne: Webprogrammering med PHP (kont.) Webprogrammering 1 (kont.) Eksamenstid:

Sikkerhet og internett

NKKN typeforslag versjon Definisjon av grunntypene

PowerOffice Server Service

1. Profiler og variabler

Erlend Oftedal. Risiko og sikkerhet i IKT-systemer, Tekna

Eksamen i Internetteknologi Fagkode: ITE1526

the web Introduksjon Lesson

Steg 1: Regneoperasjoner på en klokke

!!!!!!!!!!!! !!!!!!!!!!! WP-WATCHER WORDPRESS SIKKERHET

Brukermanual. Studentevalueringssystem

lagring med HTML5 Offline lagring Offline Informasjonsteknologi 2 Gløer Olav Langslet Sandvika VGS

TDT4165 PROGRAMMING LANGUAGES. Exercise 02 Togvogn-skifting

Programmering i C++ Løsningsforslag Eksamen høsten 2005

Tillitsforvaltning og inndatavalidering

EKSAMEN (Konvertert fra en gammel PHP-eksamen)

SQL Server guide til e-lector

JSP - 2. Fra sist. Hvordan fungerer web? Tjenerside script HTML. Installasjon av Web-tjener Et enkelt JSP-script. Ønsker dynamiske nettsider:

Brukerveiledning for Intelligent Converters MySQL Migration Toolkit IKA Trøndelag IKS 2012

Applikasjonsutvikling med databaser

TDT4102 Prosedyre og Objektorientert programmering Vår 2014

Vanlige spørsmål om EndNote (april 2013)

Administrering av SafariSøk

Siteimprove analytics Tekniske spesifikasjoner

Compello Fakturagodkjenning Versjon 10 Software as a service. Tilgang til ny modulen Regnskapsføring

Elektroniske sjekklister

Brukermanual for kommuneansvarlig og testleder

Innføring i bruk av CGI4VB

Compello Fakturagodkjenning Versjon 10.5 As a Service. Tilgang til Compello Desktop - Regnskapsføring og Dokument import

Brukerdokumentasjon Prosjekt nr PayEx Logistics

GraphQL. Hva, hvorfor, hvordan

EKSAMEN. Emne: Webprogrammering med PHP (kont.) Webprogrammering 1 (kont.) Eksamenstid:

Multi-Faktor Autentisering. Brukerveiledning

Programmet er utviklet av

Hvordan å lage og publisere ditt personlige visittkort

Ble ferdig med prosjektskisse. Sett på forskellige rammeverk for php. Lager milepæl for to uker.

Bachelorprosjekt i informasjonsteknologi, vår 2017

Fjerninnlogging over Internett

Bygg et Hus. Steg 1: Prøv selv først. Sjekkliste. Introduksjon. Prøv selv

OWASP Norway, 24.april Ståle Pettersen

Innhold. Innledning... 13

TESTAPI. Deviations and Reporting

DBS18 - Strategier for Query-prosessering

Øvingsforelesning 3 Python (TDT4110)

Hjelpemidler: 4 A4-sider (2 to-sidige ark eller 4 en-sidige ark) med egenproduserte notater (håndskrevne/maskinskrevne)

For å sjekke at Python virker som det skal begynner vi med å lage et kjempeenkelt program. Vi vil bare skrive en enkel hilsen på skjermen.

HØGSKOLEN I SØR-TRØNDELAG

Småteknisk Cantor Controller installasjon

Testrapport Prosjekt nr Det Norske Veritas

JavaScriptbibliotek. Introduksjon MVVC. Informasjonsteknologi 2. Gløer Olav Langslet Sandvika VGS

GENERELL BRUKERVEILEDNING WEBLINE

Brukerdokumentasjon. Webservices og webklient for kodeverk/ kodeverdi verifisering

TDT4110 IT Grunnkurs Høst 2012

Øvingsforelesning 5 Python (TDT4110)

Veiledning til Grønt Flagg søknadsportal

Øvingsforelesning 5 Python (TDT4110)

KPS kontaktdatase Driftsveiledning

RUTEPLANLEGGINGSSYSTEM BRUKERVEILEDNING

Om verktøyet. Installering av MySQL Migration Toolkit. Installer toolkitet. Brukerveiledning til Intelligent Converters MySQL Migration Toolkit

Brukerveiledning for For å opprette en ny bruker vennligst send en epost til

9. ASP med databasekopling, del II

Transkript:

TDT4237 Programvaresikkerhet Exercise 2 Kristian Ekle Stian Hegerland Hagen Thomas Gautvedt Tale Prestmo Martin Rechsteiner Marthe Øynes 20. oktober 2014

Innhold 1 Secure password storage 1 1.1 The password is not salted to prevent parallell attack and precomputated/rainbow tables..................... 1 1.2 The password is not hashed iteratively with bcrypt/scrypt/pbkdf2....................... 1 1.3 Need better password policy. Short passwords must be disallowed 2 1.4 Password leak in HTML comment on show user page....... 2 1.5 Password input field should be type=password.......... 3 2 SQL-injections 3 3 XSS 3 4 CSRF 4 5 Authentication mechanisms 5 5.1 Session id in cookie is not regenerated after login to prevent session fixation.............................. 5 5.2 Timing attack on the hash comparison because equals operator is used................................. 6 5.3 Cookie tampering allows normal users to become admin..... 6 5.4 Missing access control on the actual delete on admin page.... 7 6 Data Validation 7 6.1 Username can be arbitrarily long.................. 7 7 General other stuff 7 7.1 The webapp should be served entirely over TLS.......... 7 7.2 Missing throttling and IP bans on excessive requests towards forms 8 7.3 The Slim debug variable should be set to false........... 8 Extension of the application 9 1 Password Recovery 9 2 Profile picture 10 2.1 File name extension verification................... 10

2.2 Limited filesize............................ 11 3

Vulnerabilities in the webapp I denne rapporten omtaler vi forskjellige filer og kode fra applikasjonen. For å indikere hvilke filer det snakkes om, opplyser vi filsti og navn på fila (uten filendelse). Fordi alle filene vi bruker ligger i src/webapp/ har vi valgt å fjerne dette fra stien vår. Det betyr at filstien til src/webapp/models/user.php blir omtalt som models/user. Om enkeltmetoder i en klasse er omtalt, blir denne addressert som Klasse/metode, hvor metode kan gjenkjennes fordi den har liten forbokstav, til forskjell fra klassene. 1 Secure password storage 1.1 The password is not salted to prevent parallell attack and precomputated/rainbow tables Vi løste dette problemet ganske enkelt ved å introdusere individuelle salt for alle brukerne i hele applikasjonen. Dette krevde et ekstra felt i database-tabellen users, samt et nytt felt i klassen models/user. For å kunne bruke attributten i models/user ble vi også nødt til å opprette getters og setters for den. Samtidig måtte vi også legge til salt som et argument i metoden Hash/make, og alle andre steder hvor objektet interakterer med databasen. I Hash/make måtte metoden utvides med et argument salt slik at den kan returnere et saltet passord for brukeren. Tilsvarende har ikke funksjonen Hash/check bruk for dette. Hashemetoden vi brukte (bcrypt) lagrer informasjon om salt i selve hashen. Når vi skal sammenligne et hashet passord med et klartekstpassord trenger vi derfor ikke å sende saltet med, fordi metoden henter ut dette saltet direkte fra det ferdighashede passordet. 1.2 The password is not hashed iteratively with bcrypt/scrypt/pbkdf2 Applikasjonen brukte sha512 til å generere hashene. Selv om dette er en relativt grei algoritme, finnes det mange som er veldig mye bedre. Spesielt er algoritmer som hasher iterativt svært bra. Det som er forskjellen på disse algoritmene og 1

en stock implementasjon av sha512 er at iterative hasher gjør hashingen flere ganger, som oftes flere hundre ganger, noe som selvsagt gjør innlogging o.l. betydelige sikrere. Fordelen med dette er at det tar lengre tid å generere hashen. Når man hasher passord og sensitiv data vil det være ønskelig at dette tar så lang tid som mulig. Grunnen til dette er at når man hasher et passord en gang, som gjøres når man f.eks logger inn, eller validerer en login, så har ikke denne ekstra tiden så veldig mye å si. Når man derimot gjør brute force attacks og kjører flere millioner hashinger, vil forskjellene være enorme. Vi researchet de forskjellige alternativene og valgte bcrypt, da vi fant ut at den var veldig godt implementert i PHP. Ettersom testserveren kjører versjon 5.5.9 av PHP, finnes også bcrypt implementert direkte i PHP uten behov for eksterne biblioteker. 1.3 Need better password policy. Short passwords must be disallowed Når man oppretter en bruker blir brukernavn evaluert. Det samme blir formatet på brukernavnet. Disse testene skjer i models/user. Da vi skulle evaluere passord ble vi nødt til å gjøre det utenfor models/user, fordi dette krever et uhashet passord. Modellen inneholder kun det hashede passordet av sikkerhetsmessige årsaker. Implementasjonen ble derfor litt rotete. Sjekken på lengden av passordet finner sted i controllers/usercontroller og sjekker enkelt og greit om passordet er 6 tegn eller lengre. 1.4 Password leak in HTML comment on show user page http://localhost:8080/user/ I templates/showuser.twig har man følgende markup: <!-- {{ user. passwordhash raw --> Vi fjernet enkelt og greit denne linja. 2

1.5 Password input field should be type=password Disse endringene ble gjort i templates/login.twig og templates/newuserform.twig. Her var type på passord-feltet satt til text, noe som ikke skjuler det faktiske innholdet i feltet. Vi byttet ut disse attributtene med password, som gir den gjenkjennelige oppførselen hvor innholdet i boksen blir erstattet med stjerner. Dette er for å skjule verdien for folk som sitter rundt personen som skriver inn sitt passord. 2 SQL-injections For å fikse SQL-injections i applikasjonen måtte vi gjøre om måten alle databasespørringer blir utført på. Tidligere ble disse gjort ved å sette inn verdier direkte i en spørring og kjøre den med enten pdo->query eller pdo->exec. Disse metodene er ikke sikre mot SQL-injections når man ikke bruker prepared statements. Vi skrev derfor om koden til å bruke nettopp dette. Prepared statements trenger ikke korrekt escaping av innholdet fordi verdiene av parameterne blir sendt etter selve spørringen, og utført på en annen måte en normale spørringer. På grunn av dette vil alle spørringene automatisk være garantert sikre mot SQL injections. Et eksempel på hvordan dette er implementert finner vi i models/movie hvor den originale koden er slik: $query = " SELECT * FROM movies WHERE id = $id "; $result = self :: $app ->db ->query ( $query ); Og den nye koden er: $query = " SELECT * FROM movies WHERE id = : id"; $result = self :: $app ->db -> prepare ( $query ); $result -> execute ( array ( : id => $id )); Tilsvarende endringer er implementert i alle spørringene i applikasjonen. 3 XSS XSS er sikkerhetshull hvor det er mulig å kjøre javascript i nettleseren til en bruker, mot hans eller hennes ønske. Dette er kode som ikke er implementert 3

i selve applikasjonen, men som har funnet veien til nettsiden gjennom inputfelter og andre parametere som brukeren kan manipulere. Et typisk sted i denne applikasjonen hvor man kunne legge til et XSS i applikasjonen før vi tettet sikkerhetshullene var i controllers/moviecontroller når man la til en filmanmeldelse. PHP har en innebygget funksjon for å unngå slike sikkerhetshull. Funksjonen heter htmlentities og escaper HTML-karakterer til sine respektive HTMLentities. Blant annet er < ( mindre enn -tegnet) encodet som <. En liste over HTML-entities kan finnes her: http://dev.w3.org/html5/html-author/charref. Alt vi trengte for å tette disse hullene var derfor å legge til htmlentities alle de stedene hvor det var mulig for brukeren å legge til HTML-karakterer og potensielt skadelig kode. I controllers/moviecontroller har vi gjort dette slik: $author = htmlentities ( $request ->post ( author )); $text = htmlentities ( $request ->post ( text )); 4 CSRF CSRF er et sikkerhetskonsept som ligner mye på XSS. Det bygger på at man submitter en form eller går til en side hvor en bruker er logget inn eller har tilgang, uten at vedkommende selv ønsker dette. Forskjellen er at XSS utføres med javascript eller clientside-språk og utføres på en side som sender informasjonen videre til en ondsinnet side. Dette er på grunn av same-origin policy som ellers vil nekte en slik request fra å bli gjennomført. CSRF, derimot, kan gjøres ved å sende en request til en nettside uten at personen som browser selv ønsker dette. Hvis du f.eks er logget inn i en bank kan ondsinnet kode gjøre en request til banken, og fordi du har en aktiv session her, kan koden gjøre hva den vil. Sikkerhetstiltaket for å stoppe CSRF gjøres ved å opprette en token, eller tilfeldig generert string, og validere denne i alle forms som blir sendt. Hver gang siden blir oppdatert blir det generert en ny token. Dette gjør det umulig for en mellommann å snappe opp denne token, for deretter å bruke den i et ondsinnet 4

angrep. Et slikt angrep vil feile, fordi neste gang siden lastes har token forandret seg, og en ny CSRF vil være gyldig. Vi har implementert dette i applikasjonen vår gjennom Auth. Den komplette koden ser slik ut: if ( self :: $csrf_token == null ) { self :: $csrf_token = md5 ( rand (0, 10000000000). kebab. time ()); $_SESSION [ csrf ] = self :: $csrf_token ; $_SESSION [ csrf_age ] = time (); return self :: $csrf_token ; Koden vår ville ikke fungert om token ble generert på nytt hver gang metoden blir kalt. På grunn av dette lagrer vi token i en statisk variabel i klassen og setter denne til null. Når metoden blir kalt vil den generere en token kun om verdien fortsatt er null. Vi har også en variabel som indikerer hvor lenge en token er gyldig. I funksjonen som validerer token har vi satt en grense på 10 minutter før en token er utdatert. Dette krever riktignok at brukeren ikke har besøkt en annen side i mellomtiden, fordi dette vil føre til at token er ugyldig igjen. Løsningen kan med andre ord være noe upraktisk sett fra brukerens side, selv om den er betydelig mye sikrere enn den tidligere. 5 Authentication mechanisms 5.1 Session id in cookie is not regenerated after login to prevent session fixation Dette er et sikkerhetshull som gjør at man kan highjacke session-iden til en bruker og bruke denne selv for å stjele identiteten til en bruker. Dette krever riktignok at man har tilgang til cookiesene til vedkommende, men er fremdeles en ganske stor risiko. Heldigvis er dette et veldig enkelt hull å tette. PHP har en innebygget funksjon session regenerate id som gjør nettopp dette. Vi la til denne kommandoen i controllers/usercontroller og controllers/logincontroller, hvor brukeren logger ut og inn. 5

5.2 Timing attack on the hash comparison because equals operator is used Timing attack på hash-sammenlikning er en metode man kan bruke for å knekke kryptering i et program. Det baserer seg på at man kalkulerer tiden det tar å sammenligne to hasher med hverandre. I den originale koden var metoden check i Hash slik: return self :: make ( $plaintext ) === $hash ; Vi har skrevet om denne til å bruke: return password_verify ( $plaintext, $hash ); password verify er en innbygget funksjon i PHP og brukes sammen med password hash. Fordi password verify funker på den måten den funker, trenger vi ikke informasjon om salt eller cost i algoritmen check, så vi trenger ikke å endre antall argumenter funksjonen trenger, eller antall argumenter vi sender til funksjonen. 5.3 Cookie tampering allows normal users to become admin Dette var et stort sikkerhetshull i måten applikasjonen var bygget opp. Applikasjonen skjekket om en bruker er admin kun ved en cookie. Cookies blir lagret lokalt hos bruekren og kan endres. Sikkerhetshullet kommer fra Auth hvor koden var som følger: return $_COOKIE [ isadmin ] === yes ; Dette er naturligvis ikke en sikker måte å gjøre valideringen på. Vår fiks sjekker om brukeren er logget inn (ved å sjekke session), deretter prøver den å hente brukeren fra databasen og sjekker databasefeltet direkte. if ( isset ( $_SESSION [ user ])) { $user = User :: findbyuser ( $_SESSION [ user ]); if ( $user!== null ) { return $user -> isadmin (); 6

5.4 Missing access control on the actual delete on http://localhost:8080/admin/delete/ Dette var ganske enkelt et sikkerhetshull i applikasjonen hvor man kunne gå til /admin/delete/<brukernavn> og slette en bruker (dersom brukernavnet ble funnet) uten å være admin (eller å i det heletatt være logget inn). Vi tettet dette sikkerhetshullet ved å kjøre en enkel sjekk mot: Auth :: isadmin () Før en eventuell sletting ble utført. 6 Data Validation 6.1 Username can be arbitrarily long Det finnes allerede metoder for å validere minimumslengden på brukernavn. Vår implementasjon på dette problemet gjør nøyaktig det samme som den originale koden. I models/user: if ( strlen ( $user ->user ) < self :: MIN_USER_LENGTH ) { array_push ( $arr, " Username too short. Min length is ". self :: MIN_USER_LENGTH ); if ( strlen ( $user ->user ) > self :: MAX_USER_LENGTH ) { array_push ( $arr, " Username too long. Max length is ". self :: MAX_USER_LENGTH ); 7 General other stuff 7.1 The webapp should be served entirely over TLS. All requests towards HTTP should redirect to HTTPS. HSTS and secure cookie flag should be on. Som det står nevnt i punktet er ikke dette noe vi trenger å tenke over, men det hadde vært ønskelig å benytte oss av HTTPS i denne applikasjonen. Ved bruk av HTTP sendes passord i klartekst over nettverket under både opprettelse av 7

ny bruker, og under login. Samtidig er også cookie for session mulig å snappe opp om man easedropper på nettverket. Dette krever riktignok at man er på samme nettverk (enten trådløst, eller via kabel), men er like fullt et potensielt hull. Ettersom HTTPS trenger et sertifikat er dette noe vi har sett bort i fra. Vi har derfor benyttet oss av normal HTTP/1.1 på hele vår applikasjon. 7.2 Missing throttling and IP bans on excessive requests towards forms Vi implementerte logging av feilede loginforsøk i applikasjonen vår. Vi gjorde dette ved å opprette en ny modell som vi kalte Ip. Modellen blir kalt og brukt i Auth. Auth har metoder for å legge til feilet login, samt å sjekke om en IPadresse allerede er bannet. Endringer ble også gjort i controllers/logincontroller hvor metoden for å legge til feilet login blir lagt til dersom brukernavn og/eller passord er feil. Samtidig vil ikke koden for å prøve å logge inn bli kjørt dersom systemet oppdager at en IP-adresse er bannet. I controllers/logincontroller: if ( Auth :: isbanned ()) { // [... feilmelding...] else { // [... valider login...] Spørringen for å sjekke om en IP-adresse har prøvd å logge inn 1000 ganger i løpet av den siste timen er slik: $query = " SELECT COUNT ( id) as num FROM logins WHERE ip = : ip"; $query.= " AND login > ". ( time () - 3600); Etterpå gjøres det en sjekk om num er større eller er lik 1000, noe som indikerer at personen har overgått grensen. 7.3 The Slim debug variable should be set to false to minimize leakage of useful info, (e.g. system paths and technology stack) Dette ble gjort i app.php hvor debug var et argument i initialiseringen til Slim. 8

Extension of the application 1 User can reset their password if they forget it Applikasjonen har ingen glemt passord -funksjonalitet. På grunn av dette måtte brukere som har glemt sitt passord lage ny bruker eller ta kontakt med systemansvarlig for å komme seg inn på siden igjen. I vår implementasjon la vi til en link på login-siden som peker til /recover, hvor brukeren blir møtt av et skjema. I dette skjemaet kan brukeren skrive inn sitt brukernavn og få tilsendt epost med nytt passord. E-posten sendes til e-postadressen knyttet til brukernavnet. Det tilsendte passordet er generert av metoden Hash/randomPassword: static function randompassword () { $alphabet = " abcdefghijklmnopqrstuwxyzabcdefghijklmnopqrstuwxyz0123456789 "; $pass = array (); $alphalength = strlen ( $alphabet ) - 1; for ( $i = 0; $i < 8; $i ++) { $n = rand (0, $alphalength ); $pass [] = $alphabet [ $n ]; return implode ( $pass ); Dersom e-postutsendingen går uten problemer, blir brukerens gamle passordet overskrevet av et nytt passord, som også blir sendt i klartekst på e-post. Passordet blir hashet med saltet som tilhører den aktuelle brukeren. For å sende mail brukes et bibliotek som heter PHPMailer. Det er lagt til i composer.json: " require ": { " slim / slim ": " 2.* ", " slim / views ": " 0.1.* ", " twig / twig ": " 1.16.* ", + " phpmailer / phpmailer ": " 5.2.* " PHPMailer har funksjonalitet for å sende mail gjennom en spesifisert SMTPserver. I applikasjonen er det for enkelhets skyld valgt gmail sin SMTP-server, 9

med en gmail-bruker som autentiseres hver gang en epost skal sendes. Funksjonen som sender ut epost ligger i Mail og eposten som blir sendt, er: $mail -> Subject = " Password Recovery "; $mail ->Body = " Hello ". $username. "\ nyour password has been "; $mail ->Body.= " reset and is now ". $newpass ; $mail -> AddAddress ( $email ); Dersom funksjonen returnerer true, vil eposten være sendt og det nye passordet lagres på brukeren. Det gamle passordet vil ikke lengre fungere og brukeren kan kun logge inn med det nye passordet. 2 User can upload and change their profile picture Vi implementerte også metode for å laste opp profilbilder til brukerne. Dette ble implementert på siden hvor man kan redigere sin personlige informasjon. Koden ble lagt inn i controllers/usercontroller, models/user ble endret, og vi la til en ny fil /Upload, hvor selve opplastningen skjer. I databasen ble modellen utvidet med et nytt felt, photo, som inneholder filstien til profilbildet. 2.1 File name extension verification Vi er nødt til å forsikre oss at en angriper ikke kan laste opp hvilke som helst filer. Hvis man har mulighet til å laste opp et PHP script vil man kunne få full tilgang til serveren. Vi begynner med å validere at filen har riktig MIME-type ved å bruke den innebygde PHP-funksjonen getimagesize(). Det vil nå ikke være mulig å laste opp en fil som ikke er en korrekt bildefil. $file_info = getimagesize ( $file [ tmp_name ]); Problemet er at en fil kan være en helt korrekt bildefil men samtidlig inneholde et PHP script. De fleste bildeformater tilater at man legger inn en kommentar for å beskrive bildet og her kan man legge kodesnutter som kan bli executed på serveren. getimagesize() vil derfor se en helt vanlig bildefil når den validerer bildet. Derimot hvis PHP går gjennom filen vil den se etter <?php og kjøre scriptet som ligger inne i bildefilen. 10

PHP kan kun parse bildefilen hvis filendingen er.php. For å utnytte dette kan en bruker som laster opp en bildefil som inneholder PHP-kode kalle denne bilde.php. Hvis angriperen deretter etterspør denne filen vil scriptet bli kjørt. Ettersom dette krever at filendelsen er.php, er vi derfor nødt til å sjekke at filer som blir lastet opp ikke inneholder noen andre filendinger enn de vi ønsker å støtte. const VALID_FILE_EXTENSIONS = /\.(?: png jpg jpeg gif )$/ ; const VALID_MIME_TYPES = [ image / gif, image / jpeg, image / png ]; private static function validate_extension ( $file_name, $mime_type ) { if (! in_array ( $mime_type, Upload :: VALID_MIME_TYPES )! preg_match ( Upload :: VALID_FILE_EXTENSIONS, $file_name )) { throw new UploadException ( Uploaded file has an invalid file type. ); Med denne sjekken kan vi nå være sikre på at ingen laster opp filer som vil kunne kjøre skadelige script. Det er fortsatt mulig å laste opp en bildefil som inneholder et script, men det er ingen måte å execute denne koden på, ettersom webserveren til tolke filen som en bildefil. 2.2 Limited filesize Et annet potensielt sikkerhetshull er DDosing ved å laste opp gigantiske filer. Det er en fordel å begrense størrelsen på opplastninger av filer for å forhindre at serveren kneler. På grunn av måten PHP snakker med webserveren er en slik begresning ikke mulig å implementere i applikasjonen. Dette er fordi PHP mottar filen før den kan kontrollere filstørrelsen. På grunn av dette er en slik begresning kun mulig å implementere i Apache2 eller nginx, som kjører webserveren. Det lønner seg selvfølgelig å sjekke dette i frontend med Javascript for å gi brukeren en fin tilbakemelding om størrelsen er for sto. Det lønner seg også å dobbeltsjekke dette i PHP for å forsikre seg om at Javascript-valideringen ikke ble lurt. En implementasjon som vi snakket om er fint for å forhindre angrep på serveren og forfalskning av forespørsler. 11