• STATISTIQUES
  • Il y a eu un total de 3 membres et 7528 visiteurs sur le site dans les dernières 24h pour un total de 7 531 personnes!


    1 membre s'est inscrit dans les dernières 24h!


    Membres: 2 608
    Discussions: 3 580
    Messages: 32 820
    Tutoriels: 78
    Téléchargements: 38
    Sites dans l'annuaire: 58


  • ANNUAIRE
  • [FR] Newbie Contest
    Crackme: 35, Cryptographie: 49, Hacking: 27, Javascript/Java: 17, Logique: 31, Programmation: 23, Stéganographie: 53
    Challenges
    [FR] Developpez.net
    Un forum communautaire qui se veut pour les développeurs en générale. Avec presque 500 000 membr...
    Programmation
    [EN] PHPFreaks
    PHPFreaks est un site dédié à l'apprentissage et l'enseignement du PHP. Ici vous trouver...
    Programmation
    [EN] Net Force
    Javascript: 9, Java Applets: 6, Cryptography: 16, Exploits: 7, Cracking: 14, Programming: 13, Internet: 15, Steganograph...
    Challenges
    [EN] Astalavista
    Un site aux ressources incontournable depuis plusieurs années, Astalavista est réellement devenue un cl...
    Hacking
    [FR] Hackfest
    Le Hackfest est un évènement de sécurité et de piratage informatique au Québec reg...
    Hacking
    [EN] Lost-chall
    Site de challenge présenté sous la forme de différente saison. Pour passer une saison vous devez avoir accumulÃ...
    Challenges

  • DONATION
  • Si vous avez trouvé ce site internet utile, nous vous invitons à nous faire un don du montant de votre choix via Paypal. Ce don servira à financer notre hébergement.

    MERCI!

    €



Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
[C] Un exemple de jail basée sur ptrace
19-07-2013, 21h53 (Modification du message : 20-07-2013, 10h34 par b0fh.)
Message : #1
b0fh Hors ligne
Membre actif
*



Messages : 210
Sujets : 17
Points: 309
Inscription : Jul 2012
[C] Un exemple de jail basée sur ptrace
Hello,

Je vous partage un petit gadget utilisant une API pas des plus clairement documentées: un exemple de jail linux simple utilisant ptrace pour filtrer les syscalls. (pratique quand on n'a pas de kernel supportant seccomp v2).

Notez que ça ne fonctionne que si les threads sont interdits, dans le cas contraire le filtrage est vulnérable à une course.

C'est un moyen simple de bloquer execve() ou socket() si le programme n'en a pas besoin, et ainsi compliquer considérablement certains scénarios d'exploitation !
Code C :

#include <errno.h>
#include <sys/types.h>
#include <sys/user.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <unistd.h>


/* L'offset du registre a récupérer qui contient le n° de syscall.
 * RAX pour amd64, EAX pour x86. voir <sys/user.h>
 * 90% du code sur le net utilise une technique dégeu genre
 * ORIG_RAX*4, voila une manière un peu plus explicite
 * */


#ifdef __amd64__
#define SYSCALL_REG (offsetof(struct user_regs_struct, orig_rax))
#else
#define SYSCALL_REG (offsetof(struct user_regs_struct, orig_eax))
#endif



extern char **environ;

/* Les syscalls autorisés en nombre illimité */

int whitelist[] = { SYS_read, SYS_write, SYS_mmap, SYS_fstat, SYS_brk,
                    SYS_mprotect, SYS_munmap, SYS_arch_prctl, SYS_close,
                    SYS_exit_group, SYS_access, SYS_uname };


/* Codé en dur parce que le seul endroit possible pour récupérer cette valeur
 * en dehors des headers du kernel contient également des définitions
 * totalement fausses pour les macros SYS_* */


int wl_counter[500];

int jail_debug = 0;

__attribute__((constructor)) void mklookup() {
    int x;
    for (x = 0; x < sizeof(whitelist)/sizeof(whitelist[0]); x++) {
        wl_counter[whitelist[x]] = -1;
    }
    /* Les syscalls autorisés en nombre limité seulement */
    wl_counter[SYS_open] = 2;  /* besoin pour le chargement de ld.so.cache et de la libc */
    wl_counter[SYS_execve] = 1; /* le premier execve après le fork */
}

/* En cas de problème, on tue l'enfant */

void panic(pid_t child) {
    kill(child, SIGKILL);
    exit(254);
}


/* On wrappe tous les appels a ptrace ici, et on tue l'enfant au moindre problème */

long try_ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data) {
    long ret;
    ret = ptrace(request, pid, addr, data);
    if (ret < 0) {
        fprintf(stderr, "Ptrace call failed: %s. Aborting.\n", strerror(errno));
        panic(pid);
    }
    return ret;
}

int main(int argc, char **argv) {

    pid_t child;
    long call_id;
    int status;
    int enter = 0;

    if (getenv("JAIL_DEBUG")) jail_debug = 1;

    if (!(child = fork())) {
        /* L'enfant commence par activer le traçage */
        try_ptrace(PTRACE_TRACEME, 0, NULL, NULL);

        /* On stoppe, le temps que le parent aie le temps de configurer les bonnes options */
        raise(SIGSTOP);

        /* execve en décalant tous les arguments de 1. Dépend du fait que argv[argc] == NULL. */
        execve(argv[1], argv+1, environ);
    }

    /* Dans le parent, on bloque en attendant le premier SIGSTOP */
    wait(NULL);

    /* L'enfant étant stoppé, on peut fiablement configurer les options */
    try_ptrace(PTRACE_SETOPTIONS, child, NULL, (void *)(PTRACE_O_TRACESYSGOOD));

    for( ; ; ) {
        /* On relance l'exécution et on attend le prochain trap*/
        try_ptrace(PTRACE_SYSCALL, child, NULL, NULL);
        wait(&status);

        /* Si l'enfant a terminé normalement, on termine aussi */
        if (WIFEXITED(status)) break;

        /* On teste si l'enfant a déclenché un syscall trap */
        if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {

            /* On récupère le n° du syscall dans EAX */
            call_id = try_ptrace(PTRACE_PEEKUSER, child, (void *)SYSCALL_REG, NULL);

            /* Le flag enter garde trace de l'état du syscall (enter ou exit), on ne veut réagir qu'aux enter */
            if (enter ^= 1) {
                if (jail_debug) fprintf(stderr, "Entering syscall %ld (%d remaining)\n", call_id, wl_counter[call_id]);

                /* On stoppe si le compteur de syscalls autorisé est 0, et on le décrémente s'il  est positif */
                if (!(wl_counter[call_id] < 0 || wl_counter[call_id]-- > 0)) {
                    fprintf(stderr, "Called forbidden syscall: %ld\n", call_id);
                    if (!jail_debug) panic(child);
                }
            }
        }
    }

    /* On retourne avec le même code d'erreur que l'enfant */
    return status >> 8;
}
 
+1 (4) -1 (0) Répondre
20-07-2013, 03h33
Message : #2
notfound Hors ligne
#!/usr/bin/env bash
*



Messages : 687
Sujets : 47
Points: 271
Inscription : Sep 2012
RE: [C] Un exemple de jail basée sur ptrace
Y'a juste un fail dans ton code, à cause des balises de code.

Code C :

    for(; {     /* instead of */    for ( ;; ){...}
 
+1 (1) -1 (0) Répondre
20-07-2013, 10h23
Message : #3
Kiwazaru Hors ligne
Padawan d'un super escargot
*



Messages : 284
Sujets : 26
Points: 139
Inscription : Mar 2012
RE: [C] Un exemple de jail basée sur ptrace
J'ai pas bien pigé le principe du code, j'ai compris dans la généralité qu'il hook certains syscall, like a ptrace, mais au final, ça reviens à coder un ptrace like, ou tout simplement un autre projet dont je n'ai pas compris le but? :p
Toucher au Kernel, c'est un peut comme se shooter au LSD, on pense pouvoir tout faire mais ça finit souvent mal.
+1 (0) -1 (0) Répondre
20-07-2013, 10h48
Message : #4
b0fh Hors ligne
Membre actif
*



Messages : 210
Sujets : 17
Points: 309
Inscription : Jul 2012
RE: [C] Un exemple de jail basée sur ptrace
Ahoui, merci pour la remarque sur le formatage. Saleté de moteur de rendu.

C'est pas du ptrace-like, c'est du ptrace. C'est juste que l'API est assez imbitable et la documentation pas des mieux organisées (man 2 ptrace n'est pas vraiment fourni en exemples.)

Du coup, c'était surtout pour donner un exemple simple qui illustre les détails chiants, comme par exemple le danger d'appeler PTRACE_SETOPTIONS quand le process tracé n'est pas encore dans l'état stoppé, ou le fait qu'il faille distinguer a la main les syscall-enter des syscall-exit et des occurrences de signaux, et bien sur le florilège de macros pour disséquer le retour de wait().
+1 (0) -1 (0) Répondre
20-07-2013, 11h07
Message : #5
gruik Hors ligne
gouteur de savon
*



Messages : 757
Sujets : 44
Points: 482
Inscription : Oct 2012
RE: [C] Un exemple de jail basée sur ptrace
(20-07-2013, 10h48)b0fh a écrit : Saleté de moteur de rendu.

oui, bon.. je pense pas que geshi soit vraiment en cause, plutot la facon dont c'est intégré à mon avis :x

Citation :C'est juste que l'API est assez imbitable et la documentation pas des mieux organisées

"ptrace is unique and arcane" ;o

en tous cas c'est un code de mini-sandbox clair et concis pour le coup, thx Big Grin
+1 (0) -1 (0) Répondre


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)
N-PN
Accueil | Challenges | Tutoriels | Téléchargements | Forum | Retourner en haut