← All talks

DOM Based Angular Sandbox Escapes

BSides Manchester · 201748:323.5K viewsPublished 2017-08Watch on YouTube ↗
Speakers
Tags
About this talk
Gareth Heyes demonstrates multiple sandbox escape techniques across different Angular versions (1.2–1.4) in DOM-based contexts. The talk covers sandbox evolution, property descriptor manipulation, rewriter exploitation, and window-object leakage via getters and indirect function calls, with live demonstrations of working exploits.
Show transcript [en]

good afternoon everybody welcome to dom-based angular sandbox escapes in this talk I will demonstrate various sandbox escapes in different different versions of angular and a Dom based context and will be a live demo as well so if you want to join you can actually hack with me and try and break the sandbox so if you want to open your laptop's ready and open chrome then we can do that together if you want it's a little bit about me I'm a researcher at ports mcgerr I consider ports with the other best web security company to work for right now I really enjoy working there I love every presentation always say this but I love hacking javascript

and browsers I recently tweeted this this uses the from function i of the array constructor the from function takes in a real like object in the first argument and converts it to an array and then the second argument calls the function on every element of the array so this results in alert one you can follow me on Twitter I tweet about this sort of stuff and what generally happens I find this stuff and it leads to more interesting research and then I do blog posts and talks about that so the angular sandbox is a lot like an aging Mike Tyson he's tough he can say at the punches but luckily for us he's not fighting anymore angle is shipped on

versions 1.0 without a sandbox so from 1.0 to 1.15 there was no sandbox at all but what happens in angular is that expressions are scored to an object that the developer creates so when you call alert one for example what you're actually doing is calling a work one on the scorp object that the developer has designed and because the alert one function doesn't exist on that score object then the alert function more be called Mario discovered that you can get round the ship restriction and he could execute Arbutus card using expressions and he did that using the constructor function so here constructor refers to the scope object constructor and the scope object constructor is the object constructor

and the constructor of the object constructor is the function constructor and the function constructor allows you to generate cord and execute arbitrary code so this will generate a function you can then call that function and then that will execute alert one angular introduced to basic sandbox in 1.2.0 so they had an ensure safe member name function and that function checks javascript properties for the word constructor and it would throw an exception and prevent access to that it also checks if there was an underscore at the start or at the end of the property name and throw an exception so this is a very basic sandbox eunho and found the first sandbox escape for version one point two point zero so

here this is going to be complicated try to explain it as better camp this he uses an equation new string with constructor in he then creates an object literal then he uses the string that he's already created which is so he uses a string there and then he uses the sub function so the sub function is an ancient JavaScript string method and what that does is basically creates a sub tag and it's been around in JavaScript for years but the reason it uses that is simply as a shortcut in angular to get a function whilst he's got a function he can then use call so a single function call to the call method will call the current function of the

object of the current function so here sub block call would call the sub function well by using call call he gets the generic function method and the generic function call method allows you to choose the function that you want to call so here he uses his of object literal which is defined in be he then uses square brackets and then with the string constructor in to get the object constructor once he's got the object constructor he can then call get on property descriptor and what get on property descriptor does is it returns a descriptor which is like an object literal and it defines what that object property can do so it can it will say if

it's configurable if it's enumerable if it has get is if it has setters and finally if it's its value so he calls get on property descriptor with the first argument as the object that he wants to change to get the descriptor of sorry so here he passes the object literal again with the constructor property he uses get prototype off which gets the prototype of the object that you specify and he passes the sub function shocker again as a means to get a function so that gets the function prototype as the first argument to the get on property descriptor and when the the next augment in the get on property descriptor function is the string constructor so he passes that as a

second argument so this gets the property descriptor for the object literal for the function prototype and the string constructor so then value has a reference to the function constructor because the descriptor as I said returns an object literal and has various properties and the value has the value of that object property so a value will actually be the function constructor then the generic call method accepts another argument so this is the second argument of the generic call method yeah so that method that argument assigns the object that you want the function to execute with but for the function constructor this is not poor important it executes on the window so he provides zero as a minimal value for

so it's not important then he passes the stringer one which will call the function constructor generator way at one and then bypass the Sun box angular improve the someone's quite a bit they created an insurer if remember him well they improved the insurer safe member name function so this time they were checking for these properties directly so if there was a defying getter defined setter lookup getter lookup setter or the pro tour property and it would throw an exception and they also added a new function called ensure a safe object so this is quite a cool function it first checks to see if the object is truth e or not so this will rule out non undefined for example

because you can't get a property on on a null or undefined object and they check the constructor property so this is a really cool check because the constructor property of the function constructor is always itself so this detects the function constructor so this is a really cool check that works cross them in and they would throw an exception if you've got access to the function constructor because as we've seen with Mario's exploit you can execute arbitrary code then they have a similar check for the window object so they use the window property and compare it to see if it matches itself and this will detect the window and this also works cross them in so it's a really

cool check and they also check for a Dom node so if this condition is true then it will be detected as a Dom node so that could be a document it could be document up body or an image object whatever just a Dom node and it will throw an exception now finally they check the object to see if it matches the object constructor so they do this because the constructor of the object constructor is in fact the function constructor so they compare it directly with the object constructor in order to detect it because this was the only way they could come up with with doing that then we had a bit of a sandbox party me

yam Mateus Gabor and Ian all broke the sandbox and I did a blog post about my particular sandbox escape so notice this is in the reflecting context it's not a Dom based vector but what my sandbox Escape boiled down to was I modified the straw the string prototype I changed the char up function of every string object in JavaScript and what the char up function normally does is return a single character but what I did was overall the string prototype method char out so every string method now had this poison function and what happens is instead of returning a single character so normally when you call char out you can pass like a number and it will return the

character at that position but what actually happens is the string returns all of its value and the joining character whatever you specified and the reason I did this is because this is because in angular when it passes identifiers it checks the result of this function and compares another character to see if it's less than the results of this function but it will always be the case for a single character so you can imagine they have some cord like checking to see if a is less than this and it will always be the case because it's a longer character a longer string and so once we've done that then we can call the eval function and the reason we

need to call the eval function is because we've broke the parser so now we need to get it to execute again so that we can bypass the sambars so the dollar eval function is like an eval function in JavaScript only it works in angular so then angler now thinks that that string is an identifier so we can execute arbitrary code and bypass the sandbox angular decided to leave the party take the toys home and remove the sandbox in version 1.6 you can be if you liked that sparked my forum is the full over though what about under the context what about a Dom based context after my talk in London about JSON hijacking Lewis mentioned to me that angular execute

expressions in an order by filter which I found really fascinating he did a blog post about it which you can find there with some code samples but basically what it boils down to is a developer might introduce something into the score that takes data from the location dot hash and once they've got that data in an NG repeat expression or whatever you call it there they will then so you loop through the friends array so friends is an array of objects and the pipe operator normally in JavaScript is a bitwise or operation well in angular the pipe operator is a filter operation so what you're saying is you take the friends our air with a array of friends

and objects pass it to the order by filter the colon signifies the argument that you want to pass to the order by filter so here we the order by is passed the location to hash so you use it for sorting data so you could sort by telephone number by name etc so it's a convenient way of sorting data and what I found was that angle is executing cord here but the previous unboxer skips didn't work and interestingly the Curly's that are normally required in us angular expressions are not required here the most likely target for this will be a in a Dom based context using location to hash because it provides a convenient way for the developer to

change the state of the application without refreshing the page so from one point zero point one to one point two point two three existing sandbox of skips work but anything greater than one point two point two three they don't work so guess what we need new sandbox the skips so the first question they asked myself in this context is what properties are available to me so in this sandbox environment why are these previous publicly known sandbox escape not working in this context so what properties were available to me so in some box card I got a I extracted all the angular sauce got all the keywords out of the angular sauce and JavaScript keywords and then I went through every

property modified the string prototype with and then prefixed it with an X and passed it property that I wanted to inspect and assigned it with the property that I wanted to inspect so this is a way of getting data out of the sandbox environment in to the normal JavaScript environment so outside of sandbox called I could then loop through this data and gather the information so this would explain what what functions are available is a vowel available for example I also created some helper methods so here we have a keys function that returns the property names of an object then we have a log function that logs the objects of the console but what happened was the helper functions didn't

work so keys didn't work logs didn't work eval dollar eval didn't work and watches didn't work and the reason for this is interesting so you might have remembered the array of objects on the left hand side that was being passed to the water by filter and what happens is the sandbox code is executed in the scope of the element of the array so you're no longer in the developer's scorp object you're in the element of the array so if you wanted these helper methods to work for example then you'd simply modify the array elements and they would work but this would explain why eval wasn't working so I started hunting for books so the first

interesting thing that I found was array dot C string can be called I could call arena to string as a getter and it calls the join function which you'd probably expect but it's pretty cool so here we modify the function cross sack add a new getter so define gets it defines a getter on that object X is the property of that once I add the getter on and the function I want to call is array dot to string and I define a join function on that object and the John function is called when the getter is accessed this is pretty cool because it also works on window so because window is an object you can

do to string equals array dot to string some in JavaScript normally you're working on the window so this is really window to string and then I add another property of joint and then assigns the alert function and then when to string is called on window the function will be executed I couldn't find a way of passing arguments but if you could then you could bypass the sandbox so to find my first sandbox escape I looked at version 1.3 point 0 in that big long list of property names of that first I found that the function constructor was being called by the join method that as I showed you just before but what was really interesting was I could get a

reference to the object constructor using this technique so here you might notice that I'm using an array in an object accessor so normally in Java scripts you can have square brackets around a an object property to enable you enable you to pass characters that normally won't be allowed it will also accept an expression but here I passing are in and what JavaScript does is it converts that into a string and then that's fine for a for an object property but the ensure a safe member name function is checking for prata but I pass an array and the ensure safe member name function is use these triple equals so it's come it's comparing for the string and it's also convert

purring for the tag so because I pass an array it is an array so it's not a string even though the string when it when it gets converted is proton so this bypasses the insurers safer member name function so once I've got that I can get the on property descriptor function and then I can store a reference to it then we can use the get on property descriptor with the function prototype so I call get on property descriptor I use the sub function shortcut again to forget the function prototype so get on property descriptor ticks the first argument the object to the second argument the property so I pass the function prototype and pass the string

constructor and this will get me a descriptor for the function constructor which is really useful so I store that in Y to use letter so Y will store the object descriptor for the function constructor so now we need to find property and we need defined property so that we can overwrite the constructor property so I store a reference to define property using the same technique with the array and then now we can use defined property to overwrite the constructor property on every function so here I called define property so D contains a reference to the define property function that function accepts three arguments the first argument is the object so I passed this sub function

and get the function prototype again then the constructor is the property that I want to change and the descriptor is just an object literal and I want to change this property to false but why do I want to do that well if you look at the ensure a safe object function it has a truth you check and it's checking the constructor to equal itself so I'm changing that value to false so this will skip that check and that exception will not be from and now I can reuse the I can be used the descriptor and value contains a reference to the function constructor so here we have the Y property that I mentioned before this

is the descriptor the value property refers to the function constructor and if you call the function constructor with the string but you want to call it will generate a new function and then we can call that and that will bypass the sandbox so this is pretty cool and it I got through all that trouble to avoid the word constructor so so the the value property gets the function constructor without mentioning constructor because now constructor is false so that's why I got all that trouble so now this sandbox escape works on one point two point two four to one point two point two six and versions one point three point zero to one point three point one that was cool but I wanted

more I wanted to or more versions of the angular sandbox in this context so I thought why don't we attack the rewriter and the rewriter simply rewrites your JavaScript as valid JavaScript within a sum in a sandbox environment so that you can't execute arbitrary code but what I noticed was invalid JavaScript syntax was being rewritten as valid JavaScript syntax so here we have some Curly's now normally in JavaScript if you begin a statement with Curly's it's a block statement what you did you dev tools console wise to you it gets converted into an object and angular also does the same and converts this into an object so this is really an object literal and then I used dot for the property but

instead of providing a valid dot I use a semicolon I don't guess what the rewrite it is the rewriter converts it into valid JavaScript and you can see the saw heart you can see the semicolon in pink there that's been injected in the rewritten cord as a valid JavaScript property so angular thinks that the semicolon is a JavaScript property this is cool so what if we use quartz so we're using invalid JavaScript syntax using their double quarts of property what will angular do so I injected my Curly's again with a double quote and don't like Sarah I'm terminating quarter columns three to five but what's interesting is that this is a lecture it's not saying syntax error as you

would probably expect so all we need to do is balance the quartz may I present to you the smallest possible angular sandbox escape for version 1.2 point two seven and I challenge you to find a smaller one so here we create an object literal use dark use a double quote use a comma operator call it well continue with another comma operator and then a double quotes and then angular rewrites this chord like so so it breaks out of the double quarts of in the hassle and property call it calls alert one and then continues the string and you can see the rewritten chord has our alert one twice in the rewritten cod but it didn't work on the one point three

branch and I wondered why so I looked at the rear and cord in the one point three branch and I noticed the First Alert was injected correctly but not is the second alert is actually producing invalid JavaScript syntax and if it's invalid syntax there's no where chrome is going to execute that so our sandbox escape would fail on that branch so what we need to do is break out of the parentheses and comment out that invalid syntax and then we've got a sandbox a skip for that version so I've modified the vector slightly to work on the entire one point three branch so this works on all the versions of the one point three branch so we inject I we

have a an object literal we used our double quote break out the parentheses execute alert one and use a single line comment so normally in a classic XSS vector the double court isn't required at the end of the comment because it doesn't matter because of the single line comment well in angular we use that double quote to keep the LexA happy so I saw that it will still work and if you look at the rear end cord you'll see the alert one is called then I use the single line comment and luckily for us angular puts all the rewritten code on one line so we can use a single line comment which comments out the invalid

syntax and bypasses the sandbox so I like to give you a demo now and if you've got your laptop open then you can play along with me so if you want to visit ports with your half and labs net slash demo I'm going to use my VM

so here is the URL that you want to visit if you want to do it and here's the vector so if you open up dev tools

and then click the sources tab and then you want to open up the CloudFlare folder online but I'm here is just index files and then you want to open up the angularjs file then if you hit ctrl F or command F whatever they are prayer in system you're on and search for a new space function so this will tell you this will take you to the point in the angular source where they check to see if CSP is active or not so they call the function constructor with the string arguments to see if CSP is activated so we're not interested in that one we need the next one so I'll click search next and now we need to add a breakpoint at 1

1 1 9 2 and then if you scroll across our cord is actually going to be stored on the in the chord variable in this version of angular so now with it we've added the breakpoint we need to inject our vector which is here so click on the end of the URL inject a hash up and curly class curly dart double quark comma oh it's opening parenthesis 1 close parenthesis comma double quote and then now we need to hit return so we've modified the hash but we need to reload the page now saw that the debugger kicks in and stops at that break point so hit reload and then fingers crossed prayer to the demo gods

yes so we've got that break point so if you scroll across the chord variable now contains a string that's got JavaScript in it but what you might notice is it doesn't contain our vector that we've injected and this is because angular is some boxing the chord multiple times for every element of the array what we need to do is hit resume on the debugger five times in order to see our rewritten code so hit resume five times one two three four five and now if we scroll across to that variable you can see our injecting chord appears in the rewritten output so then the next time I hit resume we'll get a flurry of alerts

and this is because it's been Sun boxed multiple times cool so if anybody tried it I hope you had some success so I started hunting for more books I started to look at the 1.4 branch the one point one point four branch was more challenging the object constructor is protected correctly now so I couldn't use the a rare trick with the prot or property to get a reference to the object constructor identifier to check correctly now so I couldn't exercise the V writer so I thought maybe we could over act global variables so as I said angular forces a scope into the scorp object that the developer defines so normally you can't override global variables but if we use an object

literal and we use Pro Tour de prata product proto is the wind or global scope polluter we assign that to an object literal and we use proton our proton is an important part here so we assign prata to null so that that object does not inherit from any other object and we need this in order to keep the assignment to the global scope polluter so the sort of it will work basically and then we have an X property that we assign to one two three and we've got a global variable on window without specifying window dot which is pretty cool and that works in the angular sandbox this works on older versions of ie um sorry it works on ie 11 and older

versions of Safari the thing is we're not really getting a global variable we've got the effects of a global variable but what we're actually doing is we're modifying the global score polluter prot attack so we can create new properties but we can't over our existing ones so I couldn't use this for the hack you might remember the insurer safe object function that I showed you earlier so in angular there's an insurer safe object function and it checks to see if the object is truthy or not so what I thought well what about if I provide an object that is false so here I modify the boolean prot attack and then assign that to the function

constructor so now we've got an object that is false but allows the Turks acute Arbit record so I thought maybe we could use that to skip that security check and it does work but it will only work on the false objects every other property will be checked so it will bypass the sandbox another thought I had was maybe overwrite the function prototype so here I use the function constructor and modify its prototype and assign it to null and what that does is removes the constructor property it's now undefined and because we've made that undefined we need access to the function constructor in order to execute chord so here we can use the function constructor dot prod

sack constructor and we can execute away at one or in angular there is no way to override the function prata to the function constructor you could you can only modify every function so once you've modified unassigned the proto property to null then constructor is removed on every function so that you can't access that later so the attack failed but interestingly another thing I found was in Firefox 51 you can get the caller using a lookup getter so if we have a function of X which calls Y then the Y for has a look-up getter method we call the lookup getter and get the call a getter and then we can call the caller get it

and provide Y as the argument and this will return the caller for that function so this is quite a cool hack to get a caller without specifying caller and it only works on Firefox it doesn't work on any of the browser but we don't have any functions in angular so I couldn't use this technique but you'll see this later lookup Gator did prove very interesting another thought I have was maybe aliasing the function constructor and this is quite a cool trick so we use the sub function shortcut again we modify the function prototype we define a new getter and then it and the getter is X and the function that we want to call is

value of now what that does is returns the value of the object so now the function constructor has a property of X that allows us to execute our beauty called without specifying function constructor so you can see where as going with this you could also use prot or the ProTour get it in this way so normally in angular the ProTour getter requires an object and you can provide that object using bind for example so this provides using define getter provides a way of doing that providing the object to the function without specifying bind so here we have an object literal we use define getter we define nugatory of X we use lookup getter get the proto getter so

when the getter is called the proto getter is called and that will return the proto of the current object so it's just a cool way of providing an object that normally that normally a function requires that object but what I need he was can anybody guess see what you see window leak I need a window so I thought maybe I could use lookup get it in the scope of window so this is really cool so what in chrome what happens is when you ileus a function like this so here i use l and you assign it to lookup getter so I normally look up getter is a member function so it requires an object using

a reference to a function in this way converts it to a general function and when it's a general function it loses the reference to the object and now we can execute that function with in the scope of window so chrome is the only browser that does this so I call lookup getter ask for the document getter I get the document getter call the document getter and that return the document then default view we returns the current window so we've got our window leak and then I can execute away at one define Center also works in this way so again our reference I used defined setter this time I called define setter which works on window so it adds a new setter on

window of Y and calls a function alert so when you assign to Y then the alert function will be called and chrome will be using the window object but would this work in angular no it wouldn't and the reason it wouldn't is because the score object is being forced on the function call and so what we need to do is find a way of forcing angular to execute as a general function not as a member function so a member function is when you call it from an object a general function is when you've just calling the function without an object and what we need to do we need to talk about direct and indirect calls because

we can use this technique to force angular to executing as a general function not as a member function so of direct calls execute in the global scope so if we have a wire property of global so we start to global and we have a function of X and a lochley sculpt y variable which is assigned to local and when you call eval this is a direct call to eval a direct call means that the chord is val is knitted Coralville and its identifier is also eval if those two conditions are true then that's a direct call so what Y is assigned is in the local scope so when alert is called y is in the local

scope and so you get that data in direct calls are anything that the eval identifier is not about so an indirect call is like this so we have a parenthesis expression we use one Comet eval so the comma operator returns the rightmost expression which is about so the parentheses expression will have a reference to eval but because the eval function doesn't have an identifier of it Val that's an indirect call and an indirect call executes in the global scope so when that alert function is called Y will be in the scope of window saw it will be global so I needed an indirect call to fool angular angular doesn't support the comma operator so I

had to look at perfection kills comm it's a really cool resource check it out and there's plenty of indirect call examples on them so I've showed you the classic one we first discovered this on slackers slackers was like a security forum many years ago that everybody did research on we this saw for example here that the avowal on the left is not important because the comma operator always returns the expression on the right so it's just another example of the one above ternary operations also produce an indirect call so here we have a parenthesis expression one evaluates to true it returns a vowel the parentheses X expression returns eval we can then call eval as in the global

scope and interestingly an assignment also works as an indirect call too so I attempted to break 1.4 so I created an object literal I had a reference to the lookup getter function using the array trick then I have an assignment so I have a nice ax or L equals L so L is equal to itself so that's an assignment that's Lac and indirect call so we forcing angular to execute as a general function not as a member function we call lookup getter Crom execute that in the window Scot we get the document getter we call the document getter and we've got the document don't write that should work any observant among you might wonder at

the ensure a safe object function if we recap on the ensure safe object function and this particular Lam it detects a Dom element so a document will be detected as a Dom element and an exception will be thrown and access will be prevented I love chrome 57 chrome 57 was like a birthday present to a security of searches such as myself because before the 57 updates the only get is on window where proto and document but after 57 there are a lot more and that was the list to get and extracted all the getters on window so already with my son boxes skip I could call history dot back for example but that's a bit lame I

could also call local storage and getting set local storage but again that's still a bit lame but what really stood out was the event object getter using the events object getter I was able to break the sandbox again and he is a sandbox escape for 1.4 so we create an object literal we use the array trick on the object successor to get the lookup get a function we use our indirect lag call so l equals L and then we call the event getter we call the event getter and then target contains a reference to the document object then default view contains a reference to window then we can you assign to location and bypass the

sandbox so interestingly you might be wondering why target is not detected as a document and why default view is not detected as a window and I think it's because after the function call for performance reasons angular doesn't bother checking those properties luckily for me and if you replace the location of salmon for example with an alert one that will be detected as the window and so the expert will fail so this is why use a location assignment this vector works on one point four point zero to one point four point five I was gonna end my presentation there but it kept bugging me how can we make previous unboxer escapes work there's no eval right dollar eval doesn't work how can I

do it we need to go deeper we need order by with in order by so if we call order back with in order by we've got our of our so angular house filters which are called from expressions so here for example the string on the left is converted to uppercase with the filter on the right so it's not a bitwise or operation it's a filter operation so order by isn't a vowel and it's a filter so we can call order by from within order by and here's the sandbox escape for 1.5 so we create an object literal we use a wire property so normally in angular in this version you're prevented from assigning to the string processor

because of my char at attack so here I have a reference to the string prototype to get round the check in angular and then once I can get access to the string prototype and assign it I can alright the char out function and all red giant and as we've seen that breaks the identify check so then we have an array on the left the array is not important we just need the order by filter to be our vowel basically so the array is passed to the order by filter the column signifies the argument and the argument we provide is arbitrary code so we can execute whatever cork you like and angular will think this is an

identifier the sandbox will be bypassed this works on versions one point five point zero to one point five point eight I also attempted to break the latest version of the angular sandbox saw a version one point five point eleven so normally angular prevents you in this version of angular that trick that I've just showed you on the previous slide doesn't work now it will prevent access to modifying the string prototype but if you pass it in an array and use the pipe operator in angular the filter operation and then that will get passed to the order by a filter then we can modify the string prot attack so because X doesn't exist angular quite helpfully creates an

object and then we had a wire property with one two three so this allows us to modify the string prototype with an undefined object it's cool but it's not really useful and also we can modify the replace function value off so if you could modify the replace function then you could bypass the one point five point eleven version but here I'd change value after one to two three so I can only change properties two levels deep I can't change just one level deep but maybe you come I come back plus one point five point eleven but you can have a got try and do it but I couldn't leave it there either I needed to break one

point five point eleven and what happens in angular if you have an onclick event so in angular that's ng - click angular has a dollar event object that it assigns to the event objects in the JavaScript function and interestingly in chrome this event object has a path property that path property is an array and in that area you might notice the last element is the window object so if I pass the path array to the order by filter the sandbox cord will be executed in the scope of the array element so it will loop through every element of the array until it gets to the window so here we have an ng-click we pass the

path property to the order by filter the order by filter will like execute the cord in the scope of the array elements and eventually you get it'll get to window and then we can call alert 1 and bypass the sandbox but this doesn't work on the CSP mod and the reason it doesn't work on the CSP mod is because angular doesn't execute the cord with the function constructor but you might remember the vector that I started off with in in the earlier slides and you can get around that and bypass CSP mod using the from function so we pass the half property to the order by filter also we pass the path property to the order by filter and then

use array dot constructor to get the array constructor call the from function with array 1 that gets converted to an array even though it's already an array and then alert will be called on every element of the array and then bypass the sandbox and that works in CSP mode thanks so much thank Mario Hyun Mateus cowboy Ian and the I'd also like to thank ports with therefore enabling me to do the research so my question to you is can you find an exploit for greater than one point five point eight outside of CSP more Thanks any questions sorry can you repeat that no they've no sandbox in angular so it wasn't much fun for me because yeah you

come back our CSP mod because there's no sandbox but angular changes how you use HTML so yeah it's not really interesting from [Music] [Applause]