gdb disas main
Follow sylv1_secu on Twitter

Flux RSS


Derniers billets blog









Version 3.0beta4-tuxfamily

"Mais en fait, non !"

Vous pouvez me contacter directement à sylvain.sarmejeanne.ml AT gmail.com

Blog Logo RSS

News [twitter] Follow me on Twitter

Ca y est, moi aussi j'ai un twitter. Je vais essayer de le mettre plus à jour que ce blog (oui je sais ce sera pas trop dur :).

Posté par sylv1 le 23/02/2010 à 20:26:04
0 commentaire

News [sstic] Le SSTIC 2009 en images

Pour un résumé des talks, je suppose que vous savez où aller :)

Prêts à attaquer le SSTIC 2009 :)
Prêts à attaquer le SSTIC 2009 :)

La keynote sur la sûreté dans les avions
La keynote sur la sûreté dans les avions

Injection de code malicieux dans une Java Card
Injection de code malicieux dans une Java Card


Conférence de Florent sur le data tainting appliqué aux malware

Désobfuscation automatique de binaire
Désobfuscation automatique de binaire


Projet WOMBAT
Projet WOMBAT




ACPI et SMI
ACPI et SMI



Démo de la rootkit
Démo de la rootkit

Compromission via le bus PCI
Compromission via le bus PCI

Solution du challenge SSTIC 2009
Solution du challenge SSTIC 2009

Remise des prix du challenge
Remise des prix du challenge

Fuzzgrind
Fuzzgrind

La GUI de Fuzzgrind
La GUI de Fuzzgrind

Crackme résolu :)
Crackme résolu :)


Convergence fixe mobile
Convergence fixe mobile


Démo d'un fuzzer IKE
Démo d'un fuzzer IKE

Sécurité des smartphones
Sécurité des smartphones

Exemple de logiciel espion
Exemple de logiciel espion


Traçage de traîtres en multimédia
Traçage de traîtres en multimédia



La Barbie Hacker de Marie Barel
La Barbie Hacker de Marie Barel

Security failed
Security failed




Virtualisation matérielle pour protéger le noyau
Virtualisation matérielle pour protéger le noyau

Projet SEC&SI de création d'un OS sécurisé pour Mme Michu
Projet SEC&SI de création d'un OS sécurisé pour Mme Michu




Security failed en live...
Security failed en live...

Social event
Social event

Programme des rump sessions
Programme des rump sessions




Aurélien Bordes et CredSSP
Aurélien Bordes et CredSSP

Une conf marrante sur les attaques via LaTeX
Une conf marrante sur les attaques via LaTeX

Un module PAM ethylomètre :)
Un module PAM ethylomètre :)

Il faut souffler...
Il faut souffler...

La box dont on ne doit pas prononcer le nom...
La box dont on ne doit pas prononcer le nom...

A quand une conf sur la compromission physique des équipements d'hôtels ?
A quand une prez sur la compromission physique des équipements d'hôtels ?


Macaron, une backdoor JavaEE
Macaron, une backdoor JavaEE


IpMorph, unification de la mystification de prise d'empreinte
IpMorph, unification de la mystification de prise d'empreinte


Kolumbo : analyse dynamique depuis le noyau
Kolumbo : analyse dynamique depuis le noyau

Calcul sur cartes grahiques
Calcul sur cartes grahiques

Emanations compromettantes électromagnétiques (une conf remarquable sur le fond comme sur la forme)
Emanations compromettantes électromagnétiques

Pour finir...


/pUn module PAM ethylomètre :)/images/sstic2009/small_dscn2100.jpg
Posté par sylv1 le 05/06/2009 à 22:54:08
0 commentaire

News [linux] Même pas CAP

Je n'avais encore jamais joué avec les capabilities sous Linux. Il n'est jamais trop tard pour bien faire :)

Sur une distro GNU/Linux de base, un plus ou moins grand nombre de binaires setuid root sont présents. Par exemple, sur mon système, j'avais (cherchez l'intrus :)

# find / -type f -perm -004000
/usr/libexec/lockspool
/usr/libexec/dbus-daemon-launch-helper
/usr/lib/misc/ssh-keysign
/usr/lib/misc/xscreensaver/sonar
/usr/lib/misc/glibc/pt_chown
/usr/bin/smbumount
/usr/bin/Xorg
/usr/bin/rsh
/usr/bin/chage
/usr/bin/rcp
/usr/bin/tshark
/usr/bin/chsh
/usr/bin/newgrp
/usr/bin/expiry
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/sudo
/usr/bin/smbmnt
/usr/bin/lppasswd
/usr/bin/rlogin
/usr/bin/sudoedit
/usr/bin/dumpcap
/usr/kde/3.5/bin/kgrantpty
/usr/kde/3.5/bin/fileshareset
/usr/kde/3.5/bin/start_kdeinit
/sbin/unix_chkpwd
/bin/mount
/bin/passwd
/bin/su
/bin/umount
/bin/ping
/bin/.backdoor

La plupart des gens considèrent le bit suid sur un binaire appartant à root comme le Mal. Ce n'est pas toujours le cas. Par exemple, depuis la version 0.99.7, Wireshark vous permet de sniffer sur eth0 en tant que simple utilisateur, à partir du moment où vous faites partie du groupe wireshark. En fait, tout le code demandant des privilèges élevés est simplement passé dans dumpcap qui est setuid root, groupe wireshark seulement :

$ l `which dumpcap`
-r-sr-s--- 1 root wireshark 55K avril 13 23:47 /usr/bin/dumpcap

Cela vous évite donc de lancer la GUI Wireshark et ses 1.5 millions de lignes de code en root (NDS : tout cela est indiqué sous Gentoo lorsque vous installez le paquet). Le bit suid a donc augmenté la sécurité de votre système.

Mais il est aussi vrai qu'il suffit d'une vuln dans un binaire setuid et c'est game over ; on cherche donc à avoir le plus petit nombre possible de tels binaires. On peut même n'en avoir aucun, et c'est là où les capabilities entrent en jeu.

Pour que ça marche, il vous faut :

  • côte noyau : CONFIG_SECURITY_FILE_CAPABILITIES et CONFIG_EXT{2,3}_FS_XATTR (je crois que c'est tout)
  • côte userland : la libcap (je n'ai pas dit libpcap :)

On va prendre l'exemple hyper bateau du binaire ping. L'envoi d'un paquet ICMP nécessite l'ouverture d'une socket en mode RAW, opération privilégiée sous Linux. Pour que tout le monde puisse quand même utiliser ping, le binaire est donc setuid root :

$ l `which ping`
-rws--x--x 1 root root 36K août 31  2008 /bin/ping

On supprime le bit suid, le ping n'est plus possible :

# chmod -s `which ping`

$ ping www.free.fr
ping: icmp open socket: Operation not permitted

Un strace nous indique là où ça coince :

$ strace ping www.free.fr 2>&1 | grep EPERM
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = -1 EPERM (Operation not permitted)

Ne reste plus qu'à regarder à quelle capability ça correspond :

$ egrep -i "socket|raw" /usr/include/linux/capability.h
[...]
/* Allow use of RAW sockets */
#define CAP_NET_RAW          13
[...]

On modifie maintenant les attributs du fichier pour lui rajouter la capability CAP_NET_RAW. Le ping remarche bien :

# setcap CAP_NET_RAW=ep `which ping`

$ ping www.free.fr
PING www.free.fr (212.27.48.10) 56(84) bytes of data.
64 bytes from www.free.fr (212.27.48.10): icmp_seq=1 ttl=120 time=33.2 ms
[...]

Les flags ep correspondent à "Effective" et "Permitted" (cf la doc pour les détails).

A ce point, on a juste remplacé le bit suid par la capability. On aimerait aller plus loin, en attribuant par exemple la capability en fonction de l'utilisateur. C'est possible en appelant setcap avec les flags ei ("Effective" et "Inheritable") au lieu de ep :

# setcap CAP_NET_RAW=ei `which ping`

Il faut ensuite ajouter la ligne suivante dans /etc/pam.d/login :

auth       required     pam_cap.so

Enfin, il faut modifier le fichier /etc/security/capability.conf pour indiquer quel user se verra attribuer la capability :

$ grep sylv1 /etc/security/capability.conf 
cap_net_raw sylv1

Le ping marchera ainsi pour le user sylv1, mais pas pour les autres. En répétant la manip pour les autres binaires, vous obtiendrez ainsi un système sans binaire setuid root. A noter que l'utilisation des capabilities est un domaine d'actualité, par exemple Gentoo devrait par exemple travailler dessus lors du prochain Google Summer of Code.

On vient de voir que les capabilities peuvent être utilisées afin de restreindre les privilèges. Ils peuvent aussi être utilisés pour les augmenter ; si cela est fait intelligemment, cela peut aussi contribuer à améliorer la sécurité du système. Exemple : pour modifier votre conf réseau, vous ouvrez un shell root et lancez ifconfig ou route. Si vous laissez ce shell ouvert sans verrouiller votre session, c'est fini. Alors que vous auriez pu mettre la bonne capability, en l'occurence CAP_NET_ADMIN, et rester dans votre shell standard (évidemment, cela n'est applicable que si vous êtes seul sur le système). A méditer...

Mais ce n'est pas tout. Vous vous souvenez peut-être du MISC 13 (mai-juin 2004, et oui ça remonte :) où la page 50 parlait des capabilities. C'était pour introduire la notion de capability bounding set, un masque où chaque bit représente une capability : si un bit est à 0, la capability associée n'est disponible pour aucun processus. Vous pouvez donc utiliser /proc/sys/kernel/cap-bound (liée à la variable cap_bset du noyau) pour diminuer les capabilities de façon non-réversible (jusqu'au prochain reboot quoi). Problème : si vous oubliez aussi de désactiver CAP_SYS_RAWIO en plus de CAP_SYS_MODULE (chargement de module noyau), un attaquant peut accéder en dur à /dev/mem et écrire la valeur qu'il souhaite dans cap_bset. L'attaque ne date vraiment pas d'hier puisque l'article de MISC semble lui-même tiré d'un article datant de 2000.

De nos jours, c'est-à-dire depuis Linux 2.6.25, /proc/sys/kernel/cap-bound n'existe plus ; ce n'est plus un attribut global mais par thread, qui se transmet par fork/exec. Autrement dit, si vous voulez supprimer une capability pour tout le système, il faudra restreindre dès init. Regardons dans /usr/src/linux/include/linux/init_task.h :

#define INIT_TASK(tsk)	\
{
[...]
    .cap_bset = CAP_INIT_BSET,
[...]

Un peu plus haut :

#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
# define CAP_INIT_BSET  CAP_FULL_SET
#else
# define CAP_INIT_BSET  CAP_INIT_EFF_SET
#endif

Donc il faut modifier CAP_FULL_SET, défini dans /usr/src/linux/include/linux/capability.h :

# define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }})

Par défaut, le cap_bset vaut donc 0xffffffff (toutes les capabilities activées). Si on veut par exemple désactiver le chargement des modules pour tous, même root, on peut donc y rajouter CAP_SYS_MODULE (oui, je sais, c'est moins idiot de désactiver les modules dans la conf du noyau, c'est juste pour l'exemple :) :

# define CAP_FULL_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SYS_MODULE), ~0 }})

N'oubliez pas aussi de désactiver CAP_SYS_RAWIO :)

Références :

Posté par sylv1 le 25/05/2009 à 23:45:00
0 commentaire

News [malware] TLS strikes back

S'il vous arrive d'analyser du malware de temps à autres, il vous est peut-être déjà arrivé de faire ceci :

  • 1. On recupère le binaire :
wget_ie http://site/vx.exe
  • 2. On fait un file pour voir vite fait de quoi il s'agit :
file vx.exe
vx.exe: MS-DOS executable PE  for MS Windows (console) Intel 80386 32-bit, UPX compressed
  • 3. "Tiens, il est compressé en UPX, on tente de le décompresser direct, on sait jamais :"
upx -d vx.exe
[...]
Unpacked 1 file.
  • 4. "Youhou, comment dépacker un malware en 2 secondes ! Le gars qui a fait ça est vraiment naze. Je vais maintenant travailler directement sur la version unpackée."

Oui, mais en fait non. Le raisonnement ci-dessus part du principe suivant : si upx -d marche, alors il s'agissait bien d'un binaire compressé avec UPX et le binaire unpacké aura le même comportement que le binaire packé. Sauf que qu'est-ce qui vous dit que le binaire UPX n'a pas été bidouillé ? Par exemple en ajoutant du code qui s'exécute avant le point d'entrée pour modifier des octets en mémoire juste avant que l'algorithme de décompression ne passe par là ? Par exemple en ajoutant un callback TLS ?

L'idée de ce billet blog m'est venue lorsque j'ai travaillé sur le level 2 du Khallenge 2008 et que je me suis rendu compte que le callback TLS du binaire original (celui qui pose les bases d'une détection de debugger réalisée un peu plus bas dans le code) n'était pas conservé par la décompression UPX. Plutôt marrant.

Bon, je ne vais pas m'étendre outre mesure sur le mécanisme de Thread Local Storage sous Windows. Il s'agit d'une fonctionnalité du loader permettant d'exécuter du code avant le point d'entrée défini dans l'en-tête PE. C'est par exemple utilisé par les malware pour déchiffrer le code situé à l'entry point (cf analyse de PE GRUM par N. Brulez dans MISC 31). Les structures sont les suivantes :

  • dans l'en-tête optionnelle PE, structure IMAGE_DIRECTORY_ENTRY_TLS non vide
  • son champ VirtualAddress contient la VA d'une structure IMAGE_TLS_DIRECTORY
  • elle-même contient un champ AddressOfCallBacks contenant la VA vers un tableau de pointeurs de fonction

Un bon schéma valant mieux qu'on long discours :

IMAGE_DIRECTORY_ENTRY_TLS, IMAGE_TLS_DIRECTORY

On peut ajouter un callback TLS à un binaire UPX pour par exemple :

  • exécuter du code malicieux dans la version compressée mais qui ne sera pas exécuté dans la version décompressée (classique)
  • exécuter du code pour modifier certains octets en mémoire afin de changer le comportement entre les 2 versions (plus rigolo, c'est ce qu'on va faire ici).

On part d'un programme très simple qui affiche une message box :

#include <windows.h>

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MessageBox(NULL, "good", "tls", MB_OK);
    return 0;
}

On compile et on compresse en UPX. Toute la suite se fait dans un éditeur hexa. Première étape : trouver un endroit où stocker nos différentes structures. En parcourant vite fait le binaire, on trouve de la place à l'offset cf0 :

TLS callbacks

On y place notre structure IMAGE_TLS_DIRECTORY :

  • cf0 : StartAddressOfRawData = cf0 (offset) -> 4080f0 (VA)
  • cf4 : EndAddressOfRawData = cf0 (offset) -> 4080f0 (VA)
  • cf8 : AddressOfIndex pointe vers NULL à d00 (offset) -> 408100 (VA)
  • cfc : AddressOfCallBacks = d08 (offset) -> 408108 (VA)
  • d00 : SizeOfZeroFill = 0
  • d04 : Characteristics = 0

Le champ AddressOfCallBacks pointe vers l'offset d08 où on place maintenant notre tableau de pointeurs vers callbacks. On n'en a besoin que d'un seul :

  • d08 : pointeur vers notre callback = d10 (offset) -> 408110 (VA)

Que voulons-nous faire dans ce callback ? On va prendre l'exemple très simple de la modification de la chaine "good" qui se situe à l'offset 7ae, soit à l'adresse virtuelle 4075AE. Un simple MOV sur le contenu présent à cette adresse suffit (oui, je sais c'est particulièrement peu élégant comme méthode, mais c'est juste pour l'exemple...) :

55                         PUSH EBP
89 E5                      MOV EBP, ESP
36 C705 AE754000 6576696C  MOV DWORD PTR SS:[004075AE], 6C697665
b8 0000 0000               MOV EAX, 0
C9                         LEAVE
C3                         RET

En résumé, on obtient ceci :

TLS callbacks

On peut ainsi modifier tout octet dans la version UPXée du binaire (attention, pour patcher certaines zones, il faut aussi patcher le checksum UPX), de façon à obtenir un binaire décompressé en mémoire différent de celui décompressé en statique avec upx -d.

Tout est en place, il ne reste plus qu'à modifier l'en-tête optionnelle PE pour rendre la structure IMAGE_DIRECTORY_ENTRY_TLS non nulle et la faire pointer sur la structure définie plus haut :

  • 140 : VirtualAddress = cf0 (offset) -> 4080F0 (VA)
  • 144 : Size = 18
IMAGE_DIRECTORY_TLS

On obtient ainsi le binaire à télécharger en annexe. Si on va un peu vite à l'analyse et qu'on exécute la version décompressée avec upx -d, il affiche le message défini dans le source, à savoir "good" :

En revanche, quand on exécute le binaire UPX lui-même sous XP, surprise :

Archive : sylv1_tls.zip

Posté par sylv1 le 04/10/2008 à 17:52:07
0 commentaire

News [crypto] Goût de LUKS

Ayant acquis il y a quelques temps un nouveau laptop, je m'étais empressé de le chiffrer avec du DM-Crypt/LUKS et j'avais voulu jouer un peu avec ce système de (dé)chiffrement de disque à la volée et la technique de cold boot. NDS : la plupart des infos qui suivent sont plus ou moins obsolètes depuis la publication des sources du cold boot original ; c'est donc plus pour garder une trace de ce que j'avais fait à l'époque.

La première étape consiste à récupérer un dump de la RAM. J'avais utilisé MsRamDump qui fait très bien l'affaire. Dans ce dump on trouve tout un tas de choses très intéressantes comme le mot de passe root utilisé pour redémarrer le système, à tel point que je n'ai pas pu m'empêcher de grepper sur ma passphrase pour voir si elle s'y trouvait en clair : c'était bien sûr très naïf (ou pas...). La vraie question est donc : "comment récupérer ma clé de chiffrement AES dans ce dump ?", ce qui ramène à la question "mais au fait, elle ressemble à quoi ma clé de chiffrement ?".

Petit tour très rapide dans le monde DM-Crypt/LUKS. A chaque démarrage de l'OS (j'ai bien dit "OS", il ne s'agit pas d'un chiffrement pré-boot au sens strict comme TrueCrypt), un prompt "Enter LUKS passphrase:" me demande ma passphrase pour déchiffrer ma partition root. cryptsetup est l'outil de gestion des clés LUKS. Regardons ses sources de plus près :

$ grep "Enter LUKS passphrase:" -R cryptsetup-1.0.5
cryptsetup-1.0.5/lib/setup.c

La chaîne est présente deux fois, dont une pour __crypt_luks_open() (l'autre pour __crypt_luks_format()) qui semble être la bonne piste. Nous voyons immédiatement que notre chère master key se trouve dans la variable struct luks_masterkey *mk. Pour info :

struct luks_masterkey {
	size_t keyLength;
	char key[];
};

La fonction __crypt_luks_open() fait appel à LUKS_open_any_key() (dans luks/keymanage.c) qui se charge d'énumérer les slots de clé associés à une partition (il est possible de stocker LUKS_NUMKEYS = 8 versions chiffrées avec une passphrase de la clé sur chaque partition) et de débloquer la master key le cas échéant (son checksum étant stocké dans l'en-tête de la partition, cf specs pour les détails). Elle passe ensuite la main à son backend DM-Crypt qui se chargera d'effectuer les opérations de chiffrement de façon transparente.

Bref, pour récupérer la clé, il suffit de poser un printf dans __crypt_luks_open() entre LUKS_open_any_key() et LUKS_dealloc_masterkey(mk). On note au passage l'appel à safe_free(password) pointant vers un rassurant memset(data, 0, n) qui explique le pourquoi du paragraphe 2 :) Une fois la main passée à DM-Crypt, la clé est elle aussi shredée de la mémoire par la fonction LUKS_dealloc_masterkey(). Ce qu'on va trouver dans le dump c'est donc la clé stockée par le composant DM-Crypt du noyau :

$ find /usr/src/linux -name '*dm-crypt*'
/usr/src/drivers/md/dm-crypt.c
$ cat /usr/src/drivers/md/dm-crypt.c
[...]
struct crypt_config {
[...]
u8 key[0];
[...]

OK donc maintenant j'ai la master key de la partition qui s'affiche au démarrage :

Dump LUKS master key

On va donc pouvoir regarder comment la récupérer dans le dump. Déjà, notre mk étant connue, on peut écrire un petit prog pour parcourir un fichier de dump et voir à peu près où elle se trouve en mémoire, histoire de faire connaissance :

$ ./searchknownluksmk ramdump
[sylv1] Found LUKS key at offset 922802228
[sylv1] Found LUKS key at offset 922802692
[sylv1] Found LUKS key at offset 923103124
[sylv1] Found LUKS key at offset 923138452
[sylv1] Found LUKS key at offset 923608116
[sylv1] Found LUKS key at offset 923608580

Surprise, la clé est présente à plusieurs endroits :) Raisonnons maintenant dans le "bon" sens et cherchons à déterminer une signature dans le dump permettant de retrouver la clé. Bon, là j'avoue que je me suis pas cassé la tête : j'ai juste remarqué que la clé était présente à l'offset 0x8c après la signature "aes\x00aes)". Je n'ai aucune idée si c'est générique ou spécifique à mon système (si quelqu'un peut tester, je suis preneur, surtout que ça ne correspond pas exactement à ce que d'autres ont trouvé avant moi) :

Signature to LUKS key

En tout cas, cela nous donne le petit programme fourni en annexe pour retrouver une master key AES-256 (pour être plus générique sur la taille, on peut aller chercher les infos dans l'en-tête LUKS de la partition, mais là j'ai pas le temps :).

$ ./searchluksmk ramdump
[sylv1] Found sig at 0xa56f08, LUKS master key is:
0123ABCD...

Une fois la clé connue, il suffit de modifier la source de cryptsetup pour forcer l'utilisation de cette master key lors de l'ouverture du périphérique (toujours dans __crypt_luks_open()) :

A partir du dump mémoire, on récupère ainsi la main sur le filesystem sans connaître la passphrase :

# cryptsetup luksOpen /dev/sda8 ineednopass
Enter LUKS passphrase: *simple appui sur entree*
[sylv1] Forcing master key to 0123ABCD....
Command successful.
# mount /dev/mapper/ineednopass /mnt/test
# ls /mnt/test
bin   dev  home  lost+found  mnt  proc  sbin  tmp  var
boot  etc  lib   media       opt  root  sys   usr
# echo gagné :)
gagné :)

Petite remarque au passage : si vous n'utilisez pas le mode "clé chiffrée en gpg sur périphérique usb avec passphrase", votre partition /boot reste en clair, ce qui permet donc à votre voisin de rooter votre bécane en patchant le noyau et/ou votre initramfs pendant que vous avez le dos tourné.

Source : searchluksmk.c

Posté par sylv1 le 10/09/2008 à 00:11:22
0 commentaire

News [sstic] Le SSTIC 2008 en images

Voici d'autres photos, en plus de celles déjà publiées :

Conférence sur les green data centers
Conférence sur les green data centers

Sid et la dépérimétrisation
Sid et la dépérimétrisation

Du beau monde à la tribune, juste avant les rump
Du beau monde à la tribune, juste avant les rump

Liste des rump
Liste des rump

Netfilter en 3D
Netfilter en 3D

Hynesim
Hynesim

Diode réseau
Diode réseau

Le Cryptographic Packer de Benjamin Caillat
Cryptographic Packer

PhotoRec
PhotoRec

NFQUEUE
NFQUEUE

La doc Scapy vue par Sid (photo issue d'une ancienne conférence ; pour mémoire, on avait déjà un diagramme UML)
La doc Scapy vue par Sid

Bruno Kerouanton et son Parc Jurassique
Bruno Kerouanton et son Parc Jurassique

Les SOC
Les SOC

Nikoteen et les attaques "humaines"
Nikoteen et les attaques humaines

Posté par sylv1 le 08/06/2008 à 16:03:14
0 commentaire

News [windows] J'ai la pagedpool qui flanche

Je suis tombé (presque...) par hasard sur une page d'IBM à propos du switch /3GB et de Domino, qui me donne l'occasion de me rafraîchir la mémoire (hem :) sur le sujet. Cette option du noyau Windows (cf C:\boot.ini) en version "Pro" permet de modifier le split de la mémoire virtuelle de chaque processus de 2/2 à 3/1 (user/kernel, on se place sur une archi 32 bits évidemment ; pour info, c'est déjà à 3/1 sur Linux par défaut, grep CONFIG_PAGE_OFFSET /usr/src/linux/.config pour s'en convaincre). Au premier abord, ça a l'air bien cool de pouvoir augmenter la mémoire virtuelle utilisateur des processus, mais ce n'est malheureusement pas aussi simple.

Premier problème : il faut que l'application soit 3GB-aware, c'est-à-dire compilée avec l'option /LARGEADDRESSAWARE de Visual Studio. C'est par exemple le cas d'Exchange, de SQL Server et de Domino. Si le switch /3GB est activé et que l'application n'a pas été compilée avec cette option, le GB restant est perdu.

Deuxième problème : le noyau a la moitié moins d'espace virtuel, et cela affecte tous les processus. En pratique, cela va laisser moins de place pour le cache disque, la paged pool, la non-paged pool et les PTE. Par exemple la valeur maximum de la Paged Pool (celle qui peut être déportée sur disque, ça doit vous rappeler quelquechose) va passer de 491 à 256 MB. Il y a donc plus de chances que les événements 2019 (NonPaged Pool) ou 2020 (Paged Pool) apparaissent dans l'event log. Sous Vista, ça va un peu mieux puisque les tailles des différentes zones du noyau sont dynamiques, ce qui essaie d'empêcher le cas où une zone atteint sa limite maximale alors qu'une autre a encore plein de place.

En plus de /3GB, il est aussi possible sous Windows 2003 de spécifier le switch /USERVA=n, où n est la taille en MB de l'espace virtuel utilisateur (entre 2048 et 3072). Utile pour spécifier un juste milieu entre 2 et 3 GB pour éviter que le noyau ne s'étouffe.

Le switch /3G ne doit pas être confondu avec /PAE, qui permet au noyau de reconnaître plus de RAM, jusqu'à 64 GB selon les systèmes (grep pae /proc/cpuinfo). A moins que les deux switches ne soient utilisés en même temps, ce qui limite à 16 GB. A noter que pour adresser au-delà des 4 GB, un processus doit passer par l'API Address Windowing Extensions.

Les clés de registre pour gérer tout ça se situent dans HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management, en particulier DisablePagingExecutive, LargeSystemCache, NonPagedPoolSize, PagedPoolSize et SystemPages. Sous WinDBG, !vm et !poolused sont vos amis.

Happy kernel memory tuning :)

PS : pendant qu'on parle des switches de boot de Windows, je suis étonné de ne pas voir plus de commentaires à propos de l'arrivée de la fonction SetProcessDEPPolicy() (le seul en Français est là). Allez, /NOEXECUTE=ALWAYSON et on en parle plus.

Posté par sylv1 le 02/06/2008 à 23:45:47
0 commentaire

News [windows] The Lord of the Token

Doublé remarqué ces derniers jours : deux papiers ont en effet été publiés à propos des jetons d'accès ("access tokens"), pièces maîtresses du modèle de sécurité de Windows.

Je vais commencer par celui publié en deuxième (raison : il s'agit d'un article et non de slides, donc plus facile à suivre off-line :), intitulé Security Implications of Windows Access Tokens Whitepaper, écrit par Luke Jennings de MWR InfoSecurity. Les résultats du "paper" ne sont pas à proprement parler nouveaux puisqu'ils ont déjà été présentés à la Defcon 15 et au CCC en 2007, mais c'est l'occasion d'un petit rafraîchissement. Rappelons qu'un jeton d'accès contient le contexte de sécurité d'un processus ou d'un thread (SIDs, privilèges, niveau d'usurpation, etc). Le noyau s'en sert pour vérifier les droits d'accès lorsque ce processus ou thread interagit avec un objet sécurisable ou demande à effectuer une action privilégiée. Un processus possède un jeton primaire, qui sera par défaut celui de ses fils et de ses threads ; un thread a cependant la possibilité, à condition de posséder le privilège SeImpersonate, d'obter pour un niveau de sécurité différent du processus qui l'a créé : il reçoit alors un jeton d'"impersonation" (usurpation). Ce jeton possède un niveau d'usurpation parmi 4 :

  • Anonymous
  • Identity
  • Impersonate
  • Delegate

Les niveaux les plus intéressants sont les deux derniers car ils permettent de réellement changer le contexte de sécurité du thread : en local pour Impersonate et local+distant pour Delegate (typiquement lors d'une connexion interactive à un système en console ou TSE). Ces jetons sont présents en mémoire sous la forme de structures noyau accessibles en userland via des handles. Après l'exploitation réussie d'un composant du serveur visé, l'idée est donc de parcourir la mémoire à leur recherche, puis de les réutiliser afin d'augmenter ses privilèges soit localement (pour passer de NETWORK SERVICE à SYSTEM par exemple), soit sur le domaine (pour passer d'admin local à maître du monde).

La première étape consiste donc à énumérer les jetons d'accès. Jenning propose pour cela d'utiliser l'API NtQuerySystemInformation. En passant une InformationClass à SystemHandleInformation, on peut lister tous les handles du système. Il suffit alors d'appeler NtQueryObject sur chaque objet pour déterminer s'il s'agit d'un jeton d'accès. Pour récupérer les informations qu'il contient, il ne reste plus qu'à utiliser GetTokenInformation. La création d'un nouveau processus avec les droits de ce jeton peut alors être réalisée avec CreateProcessAsUser.

Le "paper" présente Incognito qui n'est autre qu'une implémentation de ces concepts dans une optique pentest (disponible en standalone ou en tant qu'extension de Meterpreter). Je n'ai pas encore eu le temps de le tester mais il a l'air plutôt sympa. Il permet de lister les jetons d'un système, puis de lancer des processus dans le contexte de l'un d'entre eux. Pour résumer : vous vous connectez en tant qu'admin local d'une machine, vous recherchez le jeton de délégation de l'admin du domaine en mémoire puis vous lancez cmd.exe avec ce jeton. Donc ça c'est fait.

Cerise sur le gâteau, Jennings indique que les jetons ne sont pas effacés de la mémoire lorsque l'utilisateur ciblé, en l'occurrence l'administrateur (pour combien de temps ?) du domaine, se déconnecte. Ils ne le seront qu'au prochain reboot (ce n'est plus le cas à partir de 2003 SP1).

La question est donc : quelles machines dois-je exploiter pour trouver le jeton magique ? Deux méthodes sont proposées :

  • via le Messenger Service, mais il est désactivé par défaut sur 2003 et XP SP2
  • via l'API NetWkstaUserEnum, ce qui nécessite un compte utilisateur du domaine (shouldn't be a problem)

Le deuxième (enfin, le premier...) papier a été écrit par Cesar Cerrudo d'Argeniss (vous savez, les gens qui ont vendu leurs 0-days à Gleg) et s'intitule Token Kidnapping. Il présente cette fois-ci une vulnérabilité d'élévation de privilèges qui a été reconnue par Microsoft dans son bulletin 951306. Elle permet par exemple à un attaquant pouvant créer ses propres pages pour IIS (typiquement un client d'un système mutualisé) ou un administrateur MSSQL d'exécuter du code avec les droits SYSTEM.

Sous Windows XP/2003, la vulnérabilité repose sur la combinaison de deux failles :

  1. en appelant une API communiquant avec un service, il est possible d'obtenir le jeton d'usurpation de ce service (tous les services ont le privilège SeImpersonate). Par exemple, en appelant DtcGetTransactionManagerEx, on obtient un jeton NETWORK SERVICE.
  2. une fois obtenu un tel jeton, on peut interagir via un APC avec les threads du service RpcSS qui lui possède un jeton d'usurpation SYSTEM (c'est donc une cible de choix)

Pour Vista et 2008 :

  1. en interagissant avec des pools de threads, il est possible de contourner la protection induite par le fait d'avoir un SID distinct par service (nouvelle fonctionnalité de Vista et 2008)
  2. la protection des services par SID distincts ne s'applique pas aux processus non services s'exécutant en tant que NETWORK SERVICE ou LOCAL SERVICE, par exemple WmiPrvSE qui usurpe un jeton SYSTEM. Il devient donc lui aussi une cible de choix avec laquelle on peut interagir via les fonctionnalités WMI.
  3. seuls quelques services utilisent les jetons de protection en écriture (c'est aussi une nouveauté)

Happy tokening :)

Posté par sylv1 le 25/04/2008 à 00:47:42
0 commentaire

Le contenu du blog est publié sous la licence CC-BY-SA.

[ Site créé par Sylvain Sarméjeanne ]
Cette page a été générée par mes scripts en 0.173 secondes :)
[Valid XHTML 1.1!] [Valid CSS!] [[Valid RSS]]