# [Misc] Nuclei TCP1P CTF 2023 Writeup

## Nuclei (Misc)

\---

In this challenge, we were given a source code zipped in a file called
`dist.zip`

Unzipping the file, we will have :

\- Source code of a Flask web.  
\- Nuclei YAML Template

```python  
#app.py  
from flask import Flask, render_template, request, redirect, url_for  
import subprocess  
import re

app = Flask(__name__)

@app.route('/', methods=['GET'])  
def index():  
return render_template('index.html')

@app.route('/submit', methods=['POST'])  
def submit():  
url_pattern =
re.compile(r'^(https?://[A-Za-z0-9\\-._~:/?#\\[\\]@!$&\'()*+,;=]+)$')  
url = request.form.get('url')

if url is None:  
return "No URL provided.", 400

if not url_pattern.match(url):  
return "Invalid URL format.", 400

if url:  
command = ['./nuclei', '--silent', '-u', url, '-t', 'custom-templates.yaml']  
try:  
result = subprocess.run(command, capture_output=True, text=True)  
print(result.stdout)  
if 'info' in result.stdout and '/api/v2/echo' in result.stdout and 'custom-
templates' in result.stdout:  
return "TCP1P{fake_flag}"  
else:  
return "Your website isn't vulnerable"  
except subprocess.CalledProcessError:  
return "Error occurred while running command"  
return "Invalid request"

if __name__ == '__main__':  
app.run(host='0.0.0.0', port=5000)  
```

```yaml  
#custom-templates.yaml  
id: custom-templates

info:  
name: Testing nuclei templates  
author: daffainfo  
severity: info  
reference: https://daffa.info  
metadata:  
max-request: 2  
tags: ctf,tcp1p

http:  
\- raw:  
# Detect API Version  
\- |  
GET /api/v1/version/ HTTP/1.1  
Host: {{Hostname}}  
Referer: https://daffa.info/

# XSS and Path Traversal  
\- |  
GET /api/v2/echo/?name=<script>alert(1)</script>&file=/etc/passwd HTTP/1.1  
Host: {{Hostname}}  
Referer: https://daffa.info

req-condition: true  
matchers-condition: and  
matchers:  
\- type: dsl  
dsl:  
\- compare_versions(version, '<= 10.0.5', '> 10.0.1')

\- type: word  
part: body_1  
words:  
\- "\"NAME\":\"TCP1P\""  
\- "\"msg\":\"success\""  
condition: and  
case-insensitive: true

\- type: dsl  
dsl:  
\- "regex('TCP1P{[a-z]}', body_2)"  
\- 'contains(body_2, "<script>alert(1)</script>")'  
\- "status_code_2 == 200"  
condition: and

\- type: status  
status:  
\- 200

extractors:  
\- type: regex  
name: version  
group: 1  
internal: true  
part: body_1  
regex:  
\- "\"version\":\"([0-9.]+)\""  
```

<aside>  
ℹ️ Nuclei powerful open-source tool used to detect and exploit potential
security vulnerabilities in web applications and websites.

</aside>

<aside>  
ℹ️ At the core of Nuclei's functionality are templates, which allow users to
define specific checks and rules for security testing.

</aside>

\---

```python  
if url:  
command = ['./nuclei', '--silent', '-u', url, '-t', 'custom-templates.yaml']  
try:  
result = subprocess.run(command, capture_output=True, text=True)  
print(result.stdout)  
if 'info' in result.stdout and '/api/v2/echo' in result.stdout and 'custom-
templates' in result.stdout:  
return "TCP1P{fake_flag}"  
else:  
return "Your website isn't vulnerable"  
except subprocess.CalledProcessError:  
return "Error occurred while running command"  
return "Invalid request"  
```

By reading the `app.py` code block above, this seems like a simple website
where it will receive a `url input` and run it to Nuclei with the `custom-
templates.yaml`

Which then, will show us the flag **if Nuclei finds a vulnerability on the
specified `url`**

\---

**Well, what does the `custom-templates.yaml` checks for?**

Here’s a breakdown :

1\. **API Version Detection**:  
\- Route: **`/api/v1/version/`**  
\- Reading from the Route: This route reads the response from the
**`/api/v1/version/`** endpoint.  
\- Condition for Matching:  
\- It checks the response for the API version by extracting the version number
using a regular expression. It looks for a pattern like
**`"version":"X.X.X"`** and extracts the **`X.X.X`** part as the version
number.  
\- Then, it compares this extracted version to ensure that it is less than or
equal to 10.0.5 and greater than 10.0.1.  
2\. **XSS and Path Traversal Check**:  
\- Route: **`/api/v2/echo/`**  
\- Reading from the Route: This route reads the response from the
**`/api/v2/echo/`** endpoint.  
\- Condition for Matching:  
\- It applies several matchers to the response:  
\- It checks if the response body (**`body_1`**) contains specific content,
including **`"NAME":"TCP1P"`** and **`"msg":"success"`**. This check is case-
insensitive.  
\- It performs regex matching on **`body_2`**, looking for the pattern
**`TCP1P{[a-z]}`**.  
\- It checks if **`body_2`** contains the string
**`"<script>alert(1)</script>"`**.  
\- It ensures that the HTTP status code is 200 (**`status_code_2 == 200`**).

## Solution

\---

Now, the only way to get the flag is that Nuclei must return
********info******** after scanning (the website that we are scanning matches
the rules specified in the yaml above).

I am pretty sure it’s impossible to find a website which matches the rules
above, especially the `TCP1P{[a-z]}` regex part.

Well, there’s no other way…

**Let’s create and deploy our own website! (which matches the template
rules)**

![https://media1.giphy.com/media/AWj4W9BwVJdHXdckUw/giphy.gif?cid=7941fdc6q45k8sc1cu5aywwedol6pr9tjjrhz74v48qemfqg&ep=v1_gifs_search&rid=giphy.gif&ct=g](https://media1.giphy.com/media/AWj4W9BwVJdHXdckUw/giphy.gif?cid=7941fdc6q45k8sc1cu5aywwedol6pr9tjjrhz74v48qemfqg&ep=v1_gifs_search&rid=giphy.gif&ct=g)

### But dont worry! It’s not gonna be difficult.

You don’t really need to code a whole working vulnerable website.

You just have to create a website that returns **exactly** what the template
yaml rules looks for.

For this challenge, I decided to use **`FastAPI`** because it’s much easier to
code and setup quickly.

```python  
from fastapi import FastAPI, Request

app = FastAPI()

@app.get('/api/v1/version/')  
def api_version():  
response = {  
"version": "10.0.3",  
"NAME": "TCP1P",  
"msg": "success"  
}  
return response

@app.get('/api/v2/echo/')  
async def api_echo(request: Request):  
return "TCP1P{a} <script>alert(1)</script>"

if __name__ == '__main__':  
import uvicorn  
uvicorn.run(app, host="0.0.0.0", port=8000)  
```

Now, **deploy the website code above to a cloud instance or your own
portforwarded server.**

<aside>  
ℹ️ To run the code above:  
`uvicorn <filenamewithoutdotpy>:app --host 0.0.0.0 --port 8000`

</aside>

<aside>  
? Tried to use Ngrok for hosting but it doesn’t work for me. Nuclei request is
blocked by the Ngrok warning, not sure if there’s any ‘quick’ workaround.

</aside>

### Final Step:

Pass in your deployed website url and click on **submit,** and we will get the
flag!

\---

**Thanks for reading my write-up and have a nice day!**

Original writeup (https://vicevirus.github.io/posts/tcp1p-ctf-2023/).