FACULTEIT WETENSCHAPPEN Departement Computerwetenschappen Afdeling Informatica // DistriNet
Narcissus-gebaseerde beveiligingsarchitectuur voor JavaScript
door
Sam SEGERS Andy DEBROUWER
Promotor: Piessens Frank Promotor: Desmet Lieven Begeleider: De Rycke Philippe Begeleider: Van Acker Steven
Proefschrift ingediend tot het behalen van de graad van Master in de Toegepaste Informatica
Academiejaar 2011-2012
Voorwoord Op deze plaats wensen wij een woord van dank te richten aan onze promotoren en begeleiders. TODO Sam Segers, Andy Debrouwer
i
Inhoudsopgave Voorwoord
i
1 Inleiding 1.1 Achtergrond . . . . . . . . . 1.1.1 Dynamische Websites 1.1.2 Web Mashups . . . . 1.1.3 JavaScript . . . . . . 1.2 Security Requirements . . . 1.3 Current state of practice . . 1.3.1 Script inclusion . . . 1.3.2 IFrame integration . 1.4 Current state of the art . . . 1.4.1 CaJa, AdSafe . . . . 1.4.2 WebJail, Conscript . 1.5 Doelstellingen . . . . . . . .
. . . . . . . . . . . .
1 1 1 1 1 2 2 3 4 4 4 4 5
. . . . . . . . .
6 6 6 7 8 9 10 11 14 14
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
2 Narcissus 2.1 Werking . . . . . . . . . . . . . . . 2.1.1 Narcissus context . . . . . . 2.1.2 Code uitvoering in Narcissus 2.2 Testprocess . . . . . . . . . . . . . 2.2.1 De Testsuite . . . . . . . . . 2.2.2 Tests . . . . . . . . . . . . . 2.2.3 Patches . . . . . . . . . . . 2.2.4 Resultaten . . . . . . . . . . 2.2.5 Conclusie . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . .
3 Imlementatie 16 3.1 TODO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4 Evaluatie 17 4.1 TODO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
ii
Hoofdstuk 1 Inleiding 1.1 1.1.1
Achtergrond Dynamische Websites
Tegenwoordig zijn er steeds meer dynamische websites te vinden op het internet. Dynamisch op verschillende manieren, enerzijds omdat de data die getoond wordt afhankelijk kan zijn van gebruiker tot gebruiker, en anderzijds kan de actieve gebruiker ook zelf inhoud toevoegen aan websites. Dit in tegenstelling tot de statische websites, waarbij kant-enklare HTML-pagina’s op de webserver staan te wachten om opgevraagd te worden door een gebruiker.
1.1.2
Web Mashups
Een aansluitende trend is het toenemend aantal web mashups, waarbij een website (de integrator) functionaliteit en/of gegevens van derden toevoegt (third party componenten). Dit om als resultaat een nieuwe flexibele client-side applicatie te verkrijgen, met de bedoeling een toegevoegde waarde te bieden. Bijvoorbeeld een formulier waar een adres ingegeven moet worden. Vroeger werd dit meestal gedaan door een input veldje waar men plain text moest invoeren met o.a. straat, plaats,.. Dit kan nu bijvoorbeeld worden vervangen door gebruik te maken van een google maps plugin. In dit geval is de website met het formulier de integrator, en de google maps plugin de third party component.
1.1.3
JavaScript
Buiten de server-side webtalen (E.g. PHP) is er binnen deze opstelling ook een clientside programmeertaal van belang, JavaScript genaamd. JavaScript code kan meegestuurd worden in de HTML-pagina om op de client-side uit te voeren. Dit om bijvoorbeeld een meer interactieve web ervaring aan de gebruiker te bieden. Ook communicatie tussen
1
HOOFDSTUK 1. INLEIDING
2
Figuur 1.1: Voorbeeld web mashup: IGoogle (http://www.google.com/ig/ ) verschillende componenten is mogelijk via JavaScript, eventueel beperkt door de SameOrigin Policy (zie Sectie 1.3).
1.2
Security Requirements
Een nadeel van het gebruik van third party componenten is dat een third party component mogelijk onbetrouwbaar is. Deze kan zelf ook JavaScript code uitvoeren op de client side. Bijvoorbeeld IGoogle (Figuur 1.1) is een bekend voorbeeld van een web mashup. Men kan allerlei componenten toevoegen (e-mail, weerbericht, nieuwsberichten, ..), waarbij weersvoorspellingen of nieuwsberichten bijvoorbeeld gebaseerd kunnen worden op locatie. Daarintegen is het niet wenselijk dat deze componenten emails kunnen lezen, laat staan ze kunnen aanpassen. Er is nood aan een least privilege principe, waarbij elke component beperkt is tot de functionaliteit die deze nodig heeft om zijn eigen taken te kunnen uitvoeren. Bovendien is deze nood toegenomen, voornamelijk door de mogelijkheden van de nieuwe HTML5-specificaties[1]. Zo zal het mogelijk zijn om via JavaScript o.a. de geolocation van de gebruiker te raadplegen, audio en video op te nemen, data op te slaan en op te halen aan de client-side, te communiceren met verschillende windows en zelfs met externe servers. Dit maakt het uitvoeren van een potenti¨ele aanval veel interessanter, zelfs als het script beperkt is tot het uitvoeren binnen zijn eigen origin (zie Sectie 1.3).
1.3
Current state of practice
Het idee achter web mashups is dus om meerdere componenten te integreren en hun code, data en/of uitvoeringsresultaten samen te mengen. Er bestaan verscheidene (al dan niet gratis) verkrijgbare web applicaties, die APIs beschikbaar stellen om als component te
HOOFDSTUK 1. INLEIDING
3
Figuur 1.2: Same-Origin Policy voorbeeld: Website a met iframe b kunnen gebruiken in web mashups. Om deze mashup mogelijk te maken moet de mashup integrator de nodige glue code voorzien om eigen componenten en third party componenten op de pagina te kunnen laden en ze eventueel te laten samenwerken. Hiervoor worden 2 technieken onderscheiden, Script inclusion en Iframe integration.
Same-Origin Policy De same-origin policy is het standaard beveiligingsconcept voor de client-side programmeertalen dat in alle huidige browsers aanwezig is. De same-origin policy scheidt code over verschillende uitvoeringscontexten gebaseerd op hun origin. Een origin is gedefinieerd als een triple bestaande uit; een domeinnaam, applicatie laag protocol en poortnummber (bv. (www.voorbeeld.be, http, 80)). De same-origin policy laat nu toe dat stukken code die van dezelfde origin afkomstig zijn, hun context volledig delen. D.w.z. dat ze aan elkaars functies en inhoud kunnen. Als stukken code verschillende origins hebben kunnen ze dit niet. Dit dient om te voorkomen dat er gevoelige data van andere sites kan gestolen worden zoals bijvoorbeeld cookies of login gegevens. Ook het sturen van requests naar de server is niet mogelijk vanuit een andere origin (zie Figuur 1.2).
1.3.1
Script inclusion
HTML script tags worden gebruikt om JavaScript te laten uitvoeren tijdens het laden van de webpagina. Deze code kan afkomstig zijn van een andere server dan de server die de webpagina inlaadt (integrator). Dit wil zeggen dat de browser de code zal uitvoeren alsof het van dezelfde origin afkomstig is dan de code van de integrator zelf, zonder enige beperking van de same-origin policy. De ge¨ıntegreerde code zal uitgevoerd worden in dezelfde JavaScript context, toegang krijgen tot de volledige inhoud van de webpagina waarin het wordt uitgevoerd. Alle gevoelige JavaScript functionaliteiten die toegankelijk zijn voor de pagina waarin de code uitgevoerd wordt, zullen ook toegankelijk zijn voor de ge¨ıntegreerde code.
HOOFDSTUK 1. INLEIDING
1.3.2
4
IFrame integration
HTML iframe tags kunnen worden gebruikt om een document in te laden in een andere frame. Het ge¨ıntegreerde document wordt in zijn eigen omgeving ingeladen net alsof het in een aparte browser window geladen zou worden. Het voordeel bij het gebruik van iframe integration is dat ge¨ıntegreerde componenten met verschillende origines ge¨ısoleerd zijn van elkaar dankzij de same-origin policy. De code die in de frame uitgevoerd wordt zal wel nog steeds aan dezelfde gevoelige JavaScript functionaliteiten geraken als de pagina waarin het ge¨ıntegreerd wordt, al zijn deze beperkt tot hun eigen context. De third party component zou bijvoorbeeld gebruik kunnen maken van de local storage APIs, maar zal enkel toegang hebben tot de local storage van zijn eigen origine.
1.4
Current state of the art
Momenteel bestaan al reeds enkele technieken die een oplossing bieden voor de vooropgestelde security requirements.
1.4.1
CaJa, AdSafe
CaJa[5] is gebaseerd op de principes van object-capabilities. Door het verwijderen van problematische JavaScript features (zoals prototypes) en DOM APIs(innerHTML). Dit moet leiden tot het scheiden van componenten ongeacht het domein. Ze kunnen nog communiceren via expliciet gedeelde objecten, die betrouwbaarheid en integriteit aanbieden. Ook ADsafe (waarop CaJa gebaseerd is) gebruikt zo’n techniek. Ze laten wel bepaalde onveilige functionaliteiten[3] niet toe zoals eval en with, ook het gebruik van this is verboden omdat het properties heeft die referenties naar het global Object kunnen lekken (met de referenties naar de originele functies). Dit is een van de belangrijkste nadelen van deze aanpak.
1.4.2
WebJail, Conscript
WebJail[6] en Conscript[4] hebben een andere opstelling, hier hoeft geen code herschreven te worden. WebJail laat toe de integrator een policy aan een ge¨ıntegreede component op te leggen. Er wordt gebruik gemaakt van een extra laag tussen de uit te voeren code en de browsercode die de uiteindelijke JavaScript code gaat uitvoeren (waar dit bij CaJa door object-capabilities werd gedaan). Het prototype van WebJail is een Add-on voor Firefox, en dit is het grote nadeel. Het volstaat niet dat de integrator policies oplegt aan de externe component, de client moet ook de add-on ge¨ınstalleerd hebben met de aangepaste versie van Firefox.
HOOFDSTUK 1. INLEIDING
1.5
5
Doelstellingen
Het doel van deze thesis is om een manier aan te bieden om veilig externe componenten te integreren in web mashups, zonder de gekende nadelen van de huidige implementaties. Het moet mogelijk zijn voor de integrator om de policy te bepalen die op de externe component moet worden toegepast. Belangrijk hierbij is dat de third party component niet aangepast moet worden om te kunnen werken, alle onveilige functies blijven bestaan indien gewenst. Afblokken van functionaliteiten moet kunnen gebeuren op een veilige manier, alle paden naar dezelfde functie moeten hetzelfde resultaat geven. (E.g. XMLHttpRequest / document.XMLHttpRequest). Het prototype mag ook geen aanpassingen aan de client side vragen, m.a.w. de client moet niets extra installeren of aanpassen en merkt het verschil niet tussen de website met of zonder het prototype. Het is de bedoeling dat er een least privilige principe kan afgedwongen worden door de integrator, zodat enkel de nodige functionaliteit uitgevoerd kan worden.
Hoofdstuk 2 Narcissus Voor het JSWebjail prototype zal er gebruik gemaakt worden van Narcissus, een open source JavaScript engine die geschreven is in JavaScript, en juist dit laatste maakt het interessant. Het feit dat Narcissus volledig in de client side JavaScript kan uitgevoeren, maakt het mogelijk om een veiligheidsarchitectuur te ontwikkelen waarvoor geen client side aanpassingen nodig zijn. Code van third party componenten zou kunnen uitgevoerd worden in een aagepaste versie van Narcissus, waarin er bepaalde policy’s kunnen afgedwongen worden om fucties af the schermen. Dit hoofdstuk beschrijft de werking van Narcissus, het testproces en de testresultaten.
2.1
Werking
Alhoewel het concept van een JavaScript engine die geschreven is in JavaScript vrij verwarrend kan zijn, is de manier hoe Narcissus in elkaar zit helemaal niet zo bijzonder. Het is makkelijker in te beelden dat het een andere programmeertaal evalueert, het blijft qua concept hetzelfde. Narcissus werkt zelf als een doorsnee interpreter, zo wordt er gebruik gemaakt van een lexer en een parser om de programma tekst om te zetten in een interne gegevensstructuur die een abstract syntax tree of parse tree genoemd wordt. Deze gegevensstructuur wordt dan diepte eerst afgelopen en zo gevalueerd. Narcissus is onderverdeeld in verschillende bestanden die een van deze functies vervult.
2.1.1
Narcissus context
Code die gevalueerd wordt in Narcissus, draait binnen een andere context dan de code van Narcissus zelf. De code van Narcissus wordt in de context van SpiderMonkey, de JavaScript engine van Firefox, uitgevoerd. Code die uitgevoerd word in de context van Narcissus heeft geen invloed op de code die uitgevoerd word in de context van SiderMonkey.
6
HOOFDSTUK 2. NARCISSUS
7
Figuur 2.1: Diagram: werking van Narcissus 1 2
var a = 1; Narcissus . interpreter . evauate ( " alert ( a ) ; " ) ; // var a undefined in Narcissus context
Listing 2.1: Voorbeeld afscherming van SpiderMonkey context. Dit wilt echter niet zeggen dat als variabelen gedeclareerd worden binnennNarcissus, ze ook rechtstreeks beschikbaar zijn in de global scope van SpiderMonkey. Hiermee wordt enkel bedoeld dat ze vanuit SpiderMonkey enkel toegankelijk zijn via Narcissus. 1 2 3
Narcissus . interpreter . evaluate ( " var a = 1 " ) ; alert ( a ) ; // var a undefined in SpiderMonkey context Narcissus . interpreter . evaluate ( " alert ( a ) ; " ) ; // var a beschikbaar via Narcissus
Listing 2.2: Voorbeeld afschemring van Narcissus context. Narcissus werkt als een sandbox waar niet uitgebroken kan worden, een veronderstelling dat we in latere hoofstukken zullen onderzoeken. Het heeft een eigen omgeving waar de variabelen opgeslagen worden. De variabelen gedeclareert in de Spidermonkey context zijn daarin niet beschikbaar. Dit is belangrijk omdat het niet wenselijk zou zijn dat de structuur van Narcissus van binnen uit aangepast zou kunnen worden. voor bepaalde functies kan het zijn dat Narcissus letterlijk de versie gebruikt van Spidermonkey. In die zin wordt er wel functionaliteit gebruikt uit Spidermonkey. Dit kan potentile gevaren opleveren, en kan best in het achterhoofd gehouden worden. Uiteraard wanneer er onbetrouwbare code uitgevoerd wordt, zal dit binnen de context van Narcissus moeten gebeuren.
2.1.2
Code uitvoering in Narcissus
Het inladen van Narcissus is zeer eenvoudig. De bestanden waaruit Narcissus bestaat, kunnen via de script-tag aan de pagina worden toegevoegd.
HOOFDSTUK 2. NARCISSUS 1 2 3 4
8
< script type = " text / javascript ; version =1.7 " src = " lib / jsdefs . js " > < script type = " test / javascript ; version =1.7 " src = " lib / jslex . js " > ... < script type = " text / javascript ; version =1.7 " src = " lib / jsexec . js " >
Listing 2.3: Inladen van Narcissus. Scripts uitvoeren in Narcissus is het best te vergelijken met de eval functie van javascript. Deze neemt een string aan als argument, die genterpreteerd wordt als code en meteen uitgevoerd wordt. 1 2 3
< script type = " text / javascript ; version =1.7 " > Nacissus . interpreter . evaluate ( ’ alert (" Hello , world !") ; ’) ;
Listing 2.4: Inladen van Narcissus. Narcissus heeft zelf nog geen methode om de code vanuit bestanden in te lezen, hiervoor is een methode geschreven die dit wel mogelijk maakt. Dit is niet enkel belangrijk voor de tests, ook in het prototype zal er uit bestanden moeten kunnen worden gevalueerd. Deze methode maakt gebruik van de XHR. 1 2 3
< script type = " application / javascript ; version =1.7 " > Nacissus . interpreter . evaluateUrl ( ’ http :// example . com / myJSfile . js ’) ;
Listing 2.5: Externe bestanden uitvoeren. 1 2 3 4 5 6 7 8
function evaluateUrl (u , p , f , l ) { eval_req . open ( ’ GET ’ , u , false ) ; eval_req . send ( null ) ; if ( eval_req . status !== 200) { throw new Error ( " Error loading " + u ) ; } return evaluate ( eval_req . responseText ,p ,f , l ) ; }
Listing 2.6: Implementatie van Narcissus.evaluateUrl() (in lib/jsdefs.js).
2.2
Testprocess
Omdat Narcissus slechts een research prototype is, was het nodig om de geschiktheid van Narcissus om verder gebruikt te worden in deze thesis grondig te onderzoeken. Hiervooer hebben we een testsuite ontwikkeld die Narcissus test op het correct uitvoeren van JavaScript.
HOOFDSTUK 2. NARCISSUS
2.2.1
9
De Testsuite
Een goede beschrijving van wat JavaScript moet doen is terug te vinden in de ECMAScript specificaties [2]. Hiervoor zijn ook al reeds tests geschreven, die deze functionaliteiten testen. Deze testsuite bevat meer dan 11000 tests en kan gewoon in de browser uitgevoerd worden via http://test262.ecmascript.org. Ook SpiderMonkey gebruikt deze tests. Aangezien de tests in Narcissus moeten uitgevoerd worden, moest er een alternatieve methode gezocht worden om deze tests toch te kunnen uitvoeren. De tests die gebruikt worden zijn ook te downloaden via die site, in totaal dus iets meer dan 11000 bestanden die allen een stukje JavaScript code bevatten dat een functionaliteit test. De bestanden zijn verspreid over verschillende mappen per hoofdstuk. Dit kan later interessant zijn om te kunnen achterhalen welke delen van Narcissus nog onvoldoende ondersteund worden. Zoals reeds aangehaald zullen ook onder andere DOM, XHR en cookie nodig zijn. Sommige functionaliteiten zoals onder andere DOM, XHR, en cookie, vallen niet binnen de ECMA specificaties. Voor deze functionaliteiten zullen er aanvullende tests geschreven moeten worden. Aandpassingen aan de Testsuite Het is onwenselijk dat 2 tests elkaar benvloeden, om dit te vermijden is het dus best om geen 2 tests achter elkaar in hetzelfde venster uit te voeren. In de online testsuite wordt er telkens een nieuwe frame aangemaakt, daarin word de test met het script geladen en zo de resultaten opgevraagd. Dit bleek niet zo makkelijk te dupliceren te zijn, zeker om Narcissus telkens opnieuw mee in te laden en de test correct in Narcissus te laten uitvoeren. De methodes die nagaan of het correcte resultaat is verkregen zijn mits een lichte aanpassing wel gekopieerd (e.g. De methode die aangeeft dat een test een ander resultaat dan verwacht verkregen heeft). Deze functies moeten mee ingeladen worden in Narcissus voor de eigenlijke test ingeladen wordt, omdat de methodes in de tests ook in Narcissus uitgevoerd worden. Ook deze methodes zijn op voorhand getest, dat er geen tests uit de testsuite zouden falen door het falen van de hulpmethodes. Zo kan er al getest worden voor elke test of deze slaagt. Uiteraard is het onbegonnen werk om ze allemaal n per n af te gaan en de resultaten te noteren. Daarvoor is er een script gemaakt dat zichzelf na het uitvoeren van een test kan doorsturen naar de volgende tot er geen test meer overblijft. Opnieuw niet zo magisch, het aanpassen van document.location laadt de ingegeven url in de frame waar het script uitgevoerd wordt. D.w.z. Dat de gehele frame opnieuw wordt geladen, ook de bestanden van Narcissus. Voor te bepalen welke test er geladen moet worden en welke test de volgende moet zijn is er nood aan een dynamische webtaal. Aangezien PHP eenvoudig te gebruiken is, wordt daarvoor geopteerd, in samenhang met een MySQL database. Een eerste script zorgt dat elke test in de database terecht komt en een uniek volgnummer krijgt, dit moet slechts eenmaal gebeuren. Vanaf dan kan er eenvoudig naar de volgende test doorverwezen worden. Door te beginnen met nummer 1 en elke keer te verhogen tot de nummer groter
HOOFDSTUK 2. NARCISSUS
10
Figuur 2.2: Testresultaten. is dan het aantal tests in de database. 1 2 3 4
$testfile = $test_model - > getTest ( $_GET [ " scriptnr " ]) ; loadTest ( " " ) ; ... window . location = " chain . php ? scriptnr = " +( scriptNR +1) :
Voor het bijhouden van de resultaten kan dan dezelfde database gebruiken. Na het uitvoeren er van, kan de eventuele fout weggeschreven worden voor die bijhorende test. Dit kan met XHR, waarvoor een apart PHP script zorgt voor de afhandeling van de database operaties. Er mag niet naar de volgende test gegaan worden alvorens er melding is gedaan van de eventuele fout. Als dit niet correct gedaan wordt en de XHR request is niet tijdig verzonden, zal de request ook niet verder afgehandeld worden, waardoor de mogelijkheid bestaat dat falende tests niet worden opgemerkt. Om hier zeker te kunnen van zijn kan er gebruik gemaakt worden van de callback parameter van XHR, die opgeroepen wordt na het verkrijgen van de response van de server. Door de methode die het doorverwijzen naar de volgende test afhandelt uitvoert als callback te nemen, kan er geen foutmelding overgeslagen worden.
2.2.2
Tests
Aangezien de tests ook voor Spidermonkey gebruikt worden, is het interessant om de vergelijking te maken met deze JavaScript Engine die zich al bewezen heeft op het wereldwijde web. Mede ook omdat Narcissus uitgevoerd wordt in Spidermonkey, waardoor falende tests aan de basis kunnen liggen van falende tests in Narcissus. Van de 10405 geteste files faalden er slechts 174 in SpiderMonkey. Narcissus doet het minder goed, er falen in totaal 2446 files (zie figuur 2.2). Gefaalde tests zijn in de eerste plaats de tests die niet slagen omdat de ERRORof FAIL methode wordt opgeroepen in de test. Deze 2 methodes zitten in de test om aan te geven of een test al dan niet faalt. Maar ook de tests waarbij een error gegooid wordt in SpiderMonkey, hierover later meer.
HOOFDSTUK 2. NARCISSUS
2.2.3
11
Patches
Nu de resultaten ter beschikking zijn, moet er gekeken worden wat de oorzaak is van deze falende tests. In de hoop dat enkele kleine aanpassingen, veel problemen oplossen. Deze analyse zal een eerste bijdrage zijn aan de volledige thesis. De patches die gedaan zullen worden kunnen gemeld worden aan Mozilla ter ondersteuning van de ontwikkeling van Narcissus. Het is niet de bedoeling om Narcissus foutloos te krijgen, een minimum aan functionaliteit ondersteunen volstaat voor het prototype. Patch 1: Undefined variables Een eerste probleem dat onderzocht is geweest, is het gebruik van ongedefinieerde variabelen en functies. Indien men een variabele x wilt gebruiken zonder dat deze eerst ergens is gedeclareerd, wordt er verwacht dat JavaScript een ReferenceError gooit. 1 2 3 4 5 6
try { eval ( " onbekende_var ; " ) ; $ERROR ( " 2.1.3 ACCESS UNDEFINED VARIABLES > ERROR EXPECTED " ) ; } catch ( e ) { success ( " 2.1.3 ACCESS UNDEFINED VARIABLES / ERROR EXCPETED : " + e . message ) ; }
Listing 2.7: Faalende test. Na analyze van Narcissus blijkt dat Narcissus wel degelijk de verwachte fout gooit maar in de context van SpiderMonkey. Omdat de test draaien in de context van Narcissus kunnen zij deze fout niet vangen. Dit probleem kan opgelost worden door de fout door Narcissus te laten evalueeren. 1 2 3 4 5 6 7 8 9 10 11 12 13 14
// oude Narcissus code function getValue ( v ) { ... throw new ReferenceError ( v . propertyName + ’ is not defined , ’ + v . node . filename + ’ , ’ + v . node . lineno ) ; ... } // aangepaste code function getValue ( v ) { ... var e = ’ throw new ReferenceError (" ’+ v . propertyName + ’ is not defined , ’ + v . node . filename + ’ , ’ + v . node . lineno + ’ ") ; ’; Narcissus . interpreter . evaluate ( e ) ; ... }
Listing 2.8: Oplossing. Het blijkt dat een groot deel van de tests faalt om gelijkaardige reden, fouten die vanwege de context niet kunnen opgevangen worden (Zie Figuur 2.5). Voor een deel van de gevallen is dit opgelost, zonder hierbij nieuwe tests te doen falen.
HOOFDSTUK 2. NARCISSUS
12
Patch 2: intanceof Een andere reden waardoor verschillende tests faalde, was het gebruik van instanceof. Buiten het testen van de instanceof functionaliteit waren er nog een hoop tests die afhingen van het correct werken ervan. In het vorige voorbeeld wordt er bijvoorbeeld nagegaan dat de opgevangen fout een instantie is van ReferenceError. In Narcissus werd een eigen implementatie gebruikt van instanceof. Deze werkte niet correct en is vervangen door de instanceof van SpiderMonkey. Patch 3: XMLHttpRequest Er was ook een probleem met de contructor van het XMLHttpRequest (XHR) object, bij het oproepen van deze contructor zou er een TypeError gesmeten worden. Dit kwam omdat Narcissus een bepaalde functie, construct (), van XHR niet kon vinden. Dit was een functie die Narcissus zelf aan de prototype van het Function object zou moeten toegevoegd hebben die het gebruikt bij het evalueeten van contructoren. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
definitions . defineProperty ( Function . prototype , " __construct__ " , function (a , x ) { a = Array . prototype . splice . call (a , 0 , a . length ) ; switch ( a . length ) { case 0: return new this () ; case 1: return new this ( a [0]) ; case 2: return new this ( a [0] , a [1]) ; case 3: return new this ( a [0] , a [1] , a [2]) ; default : var argStr = " " ; for ( var i =0; i < a . length ; i ++) { argStr += ’a [ ’ + i + ’] , ’; } return eval ( ’ new this ( ’ + argStr . slice (0 , -1) + ’) ; ’) ; } } , true , true , true ) ;
Listing 2.9: Narcissus definieert het construct functie op de prototype van het Function object. De reden dat deze functie niet gedefinieert werd op de (XHR), wat raar is want de XHR is zelf ook een functie en zou dus alle functionaliteiten van Function moeten overherven, is dat de XHR een speciale prototype heeft. Het XHR word namelijk beschikbaar gesteld aan JavaScript door Firefox via het XPCON systeem (een systeem dat c++ objecten beschikbaar kan stellen aan JavaScript code) en daardoor is het prototype van ¨ XHR een zogenaamde XPCON wrapped native object¨. Deze prototype is zo beveiligd dat zijn eigenschappen niet aangepast kunnen worden. Het was daardoor nodig om de construct () fucntie rechtsreeks aan de XHR toe te voegen.
HOOFDSTUK 2. NARCISSUS
13
Figuur 2.3: Testresultaten na het patchen. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
definitions . defineProperty ( XMLHttpRequest , " __construct__ " , function (a , x ) { a = Array . prototype . splice . call (a , 0 , a . length ) ; switch ( a . length ) { case 0: return new this () ; case 1: return new this ( a [0]) ; case 2: return new this ( a [0] , a [1]) ; case 3: return new this ( a [0] , a [1] , a [2]) ; default : var argStr = " " ; for ( var i =0; i < a . length ; i ++) { argStr += ’a [ ’ + i + ’] , ’; } return eval ( ’ new this ( ’ + argStr . slice (0 , -1) + ’) ; ’) ; } } , true , true , true ) ;
Listing 2.10: De
construct () functie word rechtreeks gedefinieert op de XHR
Kleinere patches Daarbuiten zijn er ook kleinere patches gedaan. Het inlezen van getallen die beginnen met een punt of getallen die beginnen met een 0 gevolgd door een punt. Deze problemen situeerde zich in de lexer, bij het omzetten van de string werd teruggegeven het hoeveelste token het was in plaats van de waarde ervan. Op zich waren dit geen grote aanpassingen, maar het geeft wel een zicht op de werking van de lexer. Uiteraard lossen deze patches slechts enkele testgevallen op.
HOOFDSTUK 2. NARCISSUS
14
Figuur 2.4: Testresultaten per hoofdstuk.
2.2.4
Resultaten
Voor de niewe Narcissus skagen 292 test meer dab de versie waarmee er de eerste keer getest is geweest (zie Figuur 2.4). De falende tests zijn verspreid over de veschillende hoofdstukken (zie Figuur 2.5). De hoofdstukken beschrijven: • Chapter 7: Lexical Conventions • Chapter 8: Types • Chapter 9: Type Conventions • Chapter 10: Executable Code and Execution Contexts • Chapter 11: Expressions • Chapter 12: Statements • Chapter 13: Function Definition • Chapter 14: Program • Chapter 15: Standard Built-in ECMAScript Objects Er is dus geen n specifiek hoofdstuk dat slecht of niet ondersteund wordt, de grootste delen van elk hoofdstuk zijn ondersteund. Van de overblijvende fouten falen er nof steeds 1041 omdat er een fout in SpideMonkey context gesmeten word dat niet in Narcissus context opgevangen kan worden. Verder zijn er 286 van de fouten de wijten aan het feit dat Narcissus u niet ondersteund (Zie Figuur 2.5). ¨se sctrict¨
2.2.5
Conclusie
Hierbij wordt het testprocess rond Narcissus afgerond. Van de overblijvende fouten die falen door dat de fouten die gesmeten worden in SpiderMonkey context niet opgevangen kunnen worden in Narcissus context, zijn er waarschijnlijk een deel die nog kunnen
HOOFDSTUK 2. NARCISSUS
15
Figuur 2.5: Verhouding van tests die falen door uncaught Exceptions. opgelost worden op dezelfde manier dan deze eerder beschreven. Het is wel zeker dat er nog fouten zijn die een fout smijten in SpiderMonkey context door andere redenen. De tests die hier als 1 test beschouwd worden, zijn eigenlijk tesbestanden die bestaan uit meerdere tests. Elke test controleert dan een gelijkaardige functionaliteit. Het gebeurt dan wel dat juist een van de laatste tests uit een bestand faalt. Meestal is dit ook een iets ¨exotischer¨geval, waarbij meer uitzonderlijk functionaliteit getest wordt. Dit kan een vertekend beeld geven, omdat hetzelfde percentage van ondersteunde functionaliteit hoger ligt dan uit de tests blijkt. Narcissus staat zeker niet op punt maar het word nog steeds verder ontwikkeld door Mozilla. Narcissus ondersteund de basis functionaliteiten van JavaScript zo goed als volledig, het is vooral te wijten aan de meest exotischere features van JavaScript dat er zoveel tests falen. Daardoor hebben we besloten dat Narcissus geschikt is om verder gebruikt te worden in onze JSWebjail prototype.
Hoofdstuk 3 Imlementatie 3.1
TODO
text to come
16
Hoofdstuk 4 Evaluatie 4.1
TODO
text to come
17
Bibliografie [1] Introduction to HTML5. https://developer.mozilla.org/en/HTML/HTML5. [2] Sandard ECMA-262 version 5.1 ECMAScript Language Specification http://www.ecma-international.org/publications/standards/Ecma-262.htm. June 2011. [3] YAHOO! developer network. What are caja’s limitations? http://developer.yahoo.com/yap/guide/what-are-cajas-limitations.htm. [4] Benjamin Livshits Leo A. Meyerovich. Conscript: enforcing fine-grained security policies for javascript http://research.microsoft.com/pubs/120969/paper.pdf.
Specifying and in the browser
[5] B. Laurie I. Awad M. S. Miller, M. Samuel and M. Stay. Caja: Safe active content in sanitized javascript. http://google-caja.googlecode.com/files/caja-spec-200801-15.pdf. January 2008. [6] L. Desmet F. Piessens W. Joosen S. Van Acker, P. De Ryck. Webjail: Least-privilege integration of third-party components in web mashups.
18