                             ==Phrack Inc.==

               Volume 0x0b, Issue 0x3c, Phile #0x0a of 0x10


|=--------------------=[ Basic Integer Overflows ]=----------------------=|
|=-------------------=[ by blexim <blexim@hush.com> ]=-----------------=|
|=--------------------------Traduit par X-FaKtOr-------------------------=|

1: Introduction
    1.1 Qu'est ce qu'un entier?
    1.2 Qu'est ce qu'un dbordement d'entier?
    1.3 Pourquoi peuvent ils tre dangereux?

2: Dbordements d'entiers
    2.1 Dbordements de taille
        2.1.1 Exploitation
    2.2 Dbordement arithmtiques
        2.2.1 Exploitation

3: Bugs de signe
    3.1 A quoi ressemble t-ils?
        3.1.1 Exploitation
    3.2 Bugs de signes causs par des dbordement d'entiers

4: Exemples de la vie relle
    4.1 Dbordement d'entiers
    4.2 Bugs de signes


--[ 1.0 Introduction

Dans ce papier je vais dcrire deux classes de bugs de programmation qui
peuvent parfois permettre a un utilisateur malintentionn de modifier le
chemin d'excution des processus affects. Ces deux classes de bugs marchent
en forant des variables  contenir des valeurs inattendues, et donc ne sont
pas aussi directs que certaines classes qui crasent la mmoire,e.g. les
dbordements de tampons ou les bugs de formats. Tous les exemples donns 
dans ce papier sont en C, donc une relative familiarit avec le C est demande.
Une connaissance de la faon dont les entiers sont stocks en mmoire est
aussi utile mais pas essentielle.

----[ 1.1 Qu'est ce qu'un entier?

Un entier, dans le contexte informatique, est une variable capable
de reprsenter un nombre entier sans partie dcimale. Les entiers sont
sont en gnral de la mme taille qu'un pointeur sur le systme sur lequel
ils sont compils(i.e sur une architecture 32 bits, telle que i386 un entier
est long de 32 bits, sur une architecture 64 bits telle que SPARC,un entier
est long de 64 bits). Certains compilateurs n'utilisent pas les entiers et
les pointeurs de la mme taille cependant, pour un soucis de simplicit
tous les exemples se rfrent  des architectures 32 bits avec des entiers,
long et pointeurs sur 32 bits.

Les entiers, comme toutes les variables sont justes des portions de
mmoire. Quand nous parlons d'entiers, nous les reprsentons habituellement
en dcimal, comme c'est le system de numrotation dont les humaine ont le
plus l'habitude. Les ordinateurs, les tres numriques, ne peuvent parler
avec le dcimal, donc  l'intrieur des ordinateurs les entiers sont stocks
en binaire. Le binaire est un autre systme de numrotation des nombres
qui utilise seulement deux chiffres,1 et 0, l'oppos des dix chiffres
utiliss en dcimal. Comme le binaire et le dcimal, l'hexadcimal(base 
seize)est souvent utilis en informatique comme il est trs facile de
convertir du binaire en hexadcimal.

Comme il est souvent ncessaire de stocker des nombres ngatifs, il est
ncessaire d'avoir un mcanisme pour reprsenter les nombres ngatifs
en utilisant juste le binaire. La facon dont cela est accomplis passe
par l'utilisation du bit le plus signifiant (MSB en v.o)d'une variable pour
dterminer le signe: si le MSB est  un 1,la variable est interprt comme
ngative;si il est  0,la variable est positive. Cela peut causer certaines
confusions ,comme cela va tre expliqu dans la section sur les bugs sur
entiers non signs, car toutes les variables ne sont pas signes ce qui
signifie qu'elles n'utilisent pas toutes le MSB pour dterminer si elles
sont positives ou non. Ces variables sont reconnues comme non signes
et peuvent tre assignes seulement  des valeur positives, contrairement
aux variables qui peuvent tre soit ngatives soit positives qui sont
appeles non signes.


----[ 1.2 Qu'est ce qu'un dbordement d'entiers?

Comme un entier  une taille fixe(32 bits dans le cadre de cet article),
il y a une valeur maximum qu'il peut stocker. Quand en tentative est faite
de stocker une valeur suprieure  cette valeur maximum on parle de
dbordement d'entier. Le standard ISO C99 dit qu'un dbordement de tampon
cause "un comportement indfini",ce qui signifie que les compilateurs se
conformant au standard peuvent faire ce qu'il veulent ,de l'ignorement 
complet au dbordement pour arrter le programme. La plupart des
compilateurs semblent ignorer le dbordement, aboutissant  un
rsultat stock inattendu ou erron.

----[ 1.3 Pourquoi peuvent t-ils tre dangereux?

Les dbordement d'entiers ne peuvent pas tre dtects  aprs qu'il ce soit
produits, donc il n'y a pas de manire pour une application de dire si un
rsultat calcul prcdemment est en fait correct. Cela peut devenir 
dangereux si le calcul doit grer la taille d'un tampon ou jusqu'ou un index
peut aller dans un tableau. Bien sur la plupart des dbordement d'entiers
ne sont pas exploitables car la mmoire ne va pas tre directement crase
,mais parfois ils peuvent mener  d'autres types de classes de bugs,
frquemment des dbordement de tampons. Comme ceux-ci, les dbordements
d'entiers peuvent tre difficiles a dtecter, ainsi mme un code bien audit
peut apporter des surprises.

--[ 2.0 Dbordements d'entiers

Donc que se passe t-il se produit un dbordement d'entiers? ISO C99  cela
 dire:

	"Un calcul mettant en jeu des oprandes non-signs ne peut jamais
	tre dbord car un rsultat qui ne peut pas tre reprsent par le
	rsultat d'entiers de type non sign est rduit modulo le nombre qui
	est d'un suprieur  la plus grande valeur reprsentable par le type
	rsultant."

N.B:le modulo arithmtique implique la division de deux nombres et prend
le reste:
	10 modulo 5 = 0
	11 modulo 5 = 1
ainsi la rduction d'une grande valeur par modulo(ENTIERMAX + 1) permet
l'isolement de la valeur qui ne peut rentrer dans un entier et garde le 
reste.
En C, l'oprateur modulo est un caractre %.
</NB>

C'est un peu flou, alors peut tre qu'un exemple dmontrera mieux le fameux
"comportement indfini":

Nous avons deux entiers non signs, a et b, tous les deux sont long de 32 
bits.
Nous assignons  a la valeur maximum qu'un entier de 32 bits peut grer, et 
 b nous assignons 1. Nous ajoutons a et b ensemble et stockons le rsultat dans 
in troisime entier non sign de 32 bits nomm r:

    a = 0xffffffff
    b = 0x1
    r = a + b

Maintenant, comme le rsultat d'une addition ne peut pas tre reprsent sur
32 bits, le rsultat ,en accord avec le standard ISO,est rduit modulo 
0x100000000.

    r = (0xffffffff + 0x1) % 0x100000000
    r = (0x100000000) % 0x100000000 = 0

Rduire le rsultat en utilisant basiquement un modulo arithmtique assure
que le seulement les 32 bits les plus bas du rsultat sont utiliss, donc
les dbordements de tampon forcent les rsultats a tre tronqus a une 
taille qui peut tre reprsente par la variable. C'est souvent appel
un "wrap around", comme le rsultat apparat dans le voisinage de 0

----[ 2.1 Dbordements de taille

Ainsi un dbordement de tampon est le rsultat de la tentative de stocker
une valeur dans une variable qui est trop petite pour le supporter. 
L'exemple le plus simple de cela peut tre dmontr simplement en
assignant le contenu de variables larges  des plus petites:

    /* ex1.c - perte de prcision */
    #include <stdio.h>

    int main(void){
            int l;
            short s;
            char c;

            l = 0xdeadbeef;
            s = l;
            c = l;

            printf("l = 0x%x (%d bits)\n", l, sizeof(l) * 8);
            printf("s = 0x%x (%d bits)\n", s, sizeof(s) * 8);
            printf("c = 0x%x (%d bits)\n", c, sizeof(c) * 8);

            return 0;
    }
    /* EOF */

Le rsultat ressemble  ca:

    nova:signed {48} ./ex1
    l = 0xdeadbeef (32 bits)
    s = 0xffffbeef (16 bits)
    c = 0xffffffef (8 bits)

Comme chaque assignation pousse les limites des valeurs qui peuvent tre 
stocks  tre dpasses, la valeur est tronque donc de faon  ce
qu'elle rentre dans la variable  laquelle elle est assigne.

Il est bon de mentionner la promotion des entiers ici. Quand un calcul 
mettanten jeu des oprandes de diffrentes tailles est ralis,
l'oprande le plus petit est "promus" a la taille du plus grand des
deux. Le calcul est alors fait avec ces tailles promues et, si le
rsultat est apte  tre stock dans la variable la plus petite, le
rsultat est tronqu a la plus petite taille de nouveau.
Par exemple:

    int i;
    short s;

    s = i;

Un calcul est ralis ici avec des oprandes de tailles diffrentes.
Qu'arrive t-il dans le cas ou la variable s est promue en un entier (32 bits
long),alors le contenu de i est copi dans la nouvelle promue s. Aprs cela,
le contenu de la variable promue est "rtrograde" de nouveau a 16 bits dans 
le but de sauver s. Ce rtrogradage peut amener le rsultat  tre
tronqu si il est suprieur  la valeur maximum grable.

------[ 2.1.1 Exploitation

Les dbordements de tampons ne sont pas comme la plupart des classes de bug.
Ils n'autorisent pas un crasement direct de la mmoire ou un contrle 
directe du flot d'excution, mais sont beaucoup plus subtils. Le
racine du problme est li au fait qu'il n'y pas de manire pour un
processus de vrifier le rsultat d'un calcul aprs qu'il se soit
produit, ainsi il peut y avoir une  divergence entre la rsultat
stock  et le rsultat correct. A cause de cela, la plupart des
dbordements d'entiers ne sont pas actuellement exploitables. Mme si,
dans certains cas il est possible de forcer une variable cruciale 
contenir une valeur errone, et  ceci peut mener  des problmes plus
tard dans le code.

A cause de la subtilit de ces bugs, il y a un grand nombre de situations 
dans lesquelles ils peuvent tre exploits, ainsi je ne vais pas
essayer de couvrir toutes les conditions d'exploitations. A la place,
je vais fournir des  exemples dequelques situations qui sont
exploitables, dans l'espoir d'inspirer les lecteurs dans leur propres
recherches.

Exemple 1:

    /* width1.c - exploitation d'un bug trivial de taille */
    #include <stdio.h>
    #include <string.h>

    int main(int argc, char *argv[]){
            unsigned short s;
            int i;
            char buf[80];

            if(argc < 3){
                    return -1;
            }

            i = atoi(argv[1]);
            s = i;

            if(s >= 80){            /* [w1] */
                    printf("Oh no you don't!\n");
                    return -1;
            }

            printf("s = %d\n", s);

            memcpy(buf, argv[2], i);
            buf[i] = '\0';
            printf("%s\n", buf);

            return 0;
    }

Bien qu'une construction comme celle-ci ne se prsenterait probablement 
jamais dans le vie relle,elle va bien nous servir en tant
qu'exemple. Jetez un oeil au code suivant:

    nova:signed {100} ./width1 5 hello
    s = 5
    hello
    nova:signed {101} ./width1 80 hello
    Oh no you don't!
    nova:signed {102} ./width1 65536 hello
    s = 0
    Segmentation fault (core dumped)

L' argument longueur est rcupr a partir de la ligne de commande et stock
dans l'entier i. Lorque cette valeur est transfre dans l'entier court s, 
il est tronqu si la valeur est trop grande pour rentrer dans s(i.e. si la 
valeur suprieure  65535).A cause de cela ,il est possible d'outrepasser la 
vrification des limites  [w1] et de dborder le tampon. Aprs cela,
les techniques  d'crasement standard de la pile peuvent tre
utilises pour exploiter le processus.

----[ 2.2 Dbordements arithmtiques

Comme montr dans la section 2.0, si une tentative est faite afin de
stocker une valeur dans un entier qui est suprieure  la valeur
maximum que peut  supporter l'entier, la valeur sera tronque. Si la
valeur stocke est le rsultat  d'une opration arithmtique,
n'importe quelle partie du programme qui utilisera  plus tard le
rsultat va tourner d'une faon incorrecte du fait que le rsultat
arithmtique soit incorrect. Considrez cette exemple dmontrant la
faille montre plus tt:

    /* ex2.c - un dbordement de tampon */
    #include <stdio.h>

    int main(void){
            unsigned int num = 0xffffffff;

            printf("num is %d bits long\n", sizeof(num) * 8);
            printf("num = 0x%x\n", num);
            printf("num + 1 = 0x%x\n", num + 1);

            return 0;
    }
    /* EOF */

The output of this program looks like this:

    nova:signed {4} ./ex2
    num is 32 bits long
    num = 0xffffffff
    num + 1 = 0x0

Note:
Le lecteur avertis aura not que 0xffffffff est dcimale -1,ainsi il 
apparait que nous venons juste de faire
1 + (-1)= 0
Tandis que c'est une mthode pour voir ce qui se passe ,cela peut causer
quelque confusions car la variable num est assigne et par consquent
toute l'arithmtique effectue sur celle-ci sera non signe. Comme
cela arrive, de nombreux calculs arithmtique signs dpendent des
dbordements  d'entiers, comme ce qui suit le dmontre(supposons que
les deux oprandes sont des variables de 32 bits):

-700       + 800   = 100
0xfffffd44 + 0x320 = 0x100000064

Comme le rsultat de l'addition excde la porte de la variable , les
32 bits les plus faibles sont pris comme rsultat. Ces 32 bits bas sont
0x64,ce qui est gal  100 en dcimal.
</note>

Comme un entier est sign par dfaut, un dbordement d'entier peut causer
un changement dans le signe qui peut souvent avoir des effets intressants
sur le code qui suit. Considrez l'exemple suivant:

    /* ex3.c - changement de signes */
    #include <stdio.h>

    int main(void){
            int l;

            l = 0x7fffffff;

            printf("l = %d (0x%x)\n", l, l);
            printf("l + 1 = %d (0x%x)\n", l + 1 , l + 1);

            return 0;
    }
    /* EOF */

Dont le sortie est:

    nova:signed {38} ./ex3
    l = 2147483647 (0x7fffffff)
    l + 1 = -2147483648 (0x80000000)

Ici l'entier est initialis avec la plus grande valeur positive que
les entiers longs peuvent grer. Quand il est incrment, le bit le plus
signifiant(indiquant le signe) est mis  1 et l'entier est interprt
comme tant ngatif.

L'addition n'est pas l'unique opration arithmtique qui peut causer un
dbordement d'entier. Ainsi n'importe quelle opration qui change la valeur
d'une variable peut causer un dbordement, comme le dmontre l'exemple
suivant:

    /* ex4.c - diffrents dbordements arithmtiques */
    #include <stdio.h>

    int main(void){
            int l, x;

            l = 0x40000000;

            printf("l = %d (0x%x)\n", l, l);

            x = l + 0xc0000000;
            printf("l + 0xc0000000 = %d (0x%x)\n", x, x);

            x = l * 0x4;
            printf("l * 0x4 = %d (0x%x)\n", x, x);

            x = l - 0xffffffff;
            printf("l - 0xffffffff = %d (0x%x)\n", x, x);

            return 0;
    }
    /* EOF */

Sortie:

    nova:signed {55} ./ex4
    l = 1073741824 (0x40000000)
    l + 0xc0000000 = 0 (0x0)
    l * 0x4 = 0 (0x0)
    l - 0xffffffff = 1073741825 (0x40000001)

L'addition cause un dbordement exactement de la mme manire que dans
le premier exemple, de mme que pour la multiplication, mme si cela semble
diffrent. Dans les deux cas le rsultat est trop grand pour rentrer dans
un entier, ainsi il est rduit comme dcrit plus haut. La soustraction
est un peu diffrente, comme elle cause un underflow(comment traduire  
!!!), plutt qu'un overflow. Une tentative est faite de stocker une
valeur plus petite que le minimum grable, causant un wrap
around(???). De cette manire nous somme en mesure de forcer une
addition  soustraire, une multiplication  diviser ou une
soustraction  ajouter.

------[ 2.2.1 Exploitation

L'une des manires le plus courantes dont les dbordements arithmtiques
peuvent tre exploits est lorsque un calcul est fait  propos de la taille
d'allocation d'un tampon. Souvent un programme doit allouer de l'espace pour
un tableau d'objets ,ainsi il utilise les routines malloc(3) ou calloc(3)
pour rserver de la place et calculer combien de place est ncessaire
en multipliant le nombre d'lments par la taille d'un objet. Comme il a
prcdemment t montr, si nous sommes capable de contrler l'un de ces
deux oprandes (le nombre d'lments ou la taille de l'objet) nous pourrions
tre en mesure de contrefaire la taille du tampon comme le code suivant
le montre:

    int myfunction(int *array, int len){
        int *myarray, i;

        myarray = malloc(len * sizeof(int));    /* [1] */
        if(myarray == NULL){
            return -1;
        }

        for(i = 0; i < len; i++){              /* [2] */
            myarray[i] = array[i];
        }

        return myarray;
    }

Cette innocente fonction en apparence peut amener  la fermeture du 
programme
 cause de son manque vrification de ses paramtres. La multiplication [1]
peut tre cre pour mener  un dbordement en soumettant une valeur assez
grande pour que nous puissions forcer le tampon  tre de la taille que l'on
veut. En choisissant une valeur qui convient pour la longueur, nous pouvons 
faire que la boucle [2] crive  la fin du tampon myarray, rsultant  un 
dbordement du tas. Cela peut tre dterminant pour l'excution de code 
arbitraire sur certaines implmentations en crasant les structures de 
contrles de malloc, mais cela dborde du cadre de cette article(un article 
overflow :)N.D)

Autre example:

    int catvars(char *buf1, char *buf2, unsigned int len1,
                unsigned int len2){
        char mybuf[256];

        if((len1 + len2) > 256){    /* [3] */
            return -1;
        }

        memcpy(mybuf, buf1, len1);      /* [4] */
        memcpy(mybuf + len1, buf2, len2);

        do_some_stuff(mybuf);

        return 0;
    }

Dans cet exemple, la vrification [3] peut tre outrepasse en utilisant des
valeurs convenant pour la longueur len1 et len2 qui vont faire que 
l'addition
va craser et devenir un petit nombre. Par exemple les valeurs suivantes:

    len1 = 0x104
    len2 = 0xfffffffc

Lorsque ajoutes l'une  l'autre, cela rsulte  un retour avec un rsultat
de 0x100(256 en dcimal).Cela passerai la vrification [3],alors les 
memcpy(3) [4]
copient les donns colles  la fin du tampon.


--[ 3 Bugs de signes

Les bugs de signes surviennent quand une variables non signes est 
interprte  comme signe. Ce type de comportement peut se produire du
fait qu' l'intrieur de l'ordinateur, il n'y pas de distinction entre
la faon dont les variables signes et non signes sont
stockes. Rcemment, diffrent bugs de signes se  sont montrs dans
les kernels de FreeBSD et de OpenBSD, ainsi il y a de  nombreux
exemples disponibles  lire.


----[ 3.1 A quoi ressemble t-ils?

Les bugs de signes peuvent prendre de nombreuse formes, mais certaines des
choses qu'il faut surveiller sont:
* les entier signs utiliss pour des comparaisons
* les entier signs utiliss en arithmtique
* les entiers non signs qui sont compars  des entier signs

Voici un exemple classique de bug de signe:

    int copy_something(char *buf, int len){
        char kbuf[800];

        if(len > sizeof(kbuf)){         /* [1] */
            return -1;
        }

        return memcpy(kbuf, buf, len);  /* [2] */
    }

Le problme ici est que memcpy prend un entier non sign comme
paramtre, mais la vrification des limites ralise avant le memcpy
est faite en utilisant des entiers signs. En passant une valeur une
valeur ngative pour longueur, il est possible de passer la
vrification [1], mais alors dans le call memcpy[2], la longueur va
tre interprte comme une trs grande valeur non signe, menant la
mmoire  tre crase  la fin du buffer kbuff.

Un autre problme peut tre du  une confusion signs/non signs survient
quand un calcul arithmtique est ralis. Considrez l'exemple suivant:

    int table[800];

    int insert_in_table(int val, int pos){
        if(pos > sizeof(table) / sizeof(int)){
            return -1;
        }

        table[pos] = val;

        return 0;
    }

Comme la ligne
    table[pos] = val;
est quivalente :
    *(table + (pos * sizeof(int))) = val;
Nous pouvons voir que le problme ici est que le code ne s'attends pas 
un  oprande ngatif pour l'addition:il s'attends  ce que(table+ pos)
soit suprieur  table,ainsi soumettre une valeur ngative pour pos
entrane une situation  laquelle le programme ne s'attends pas et
peut de ce fait pas le grer.

------[ 3.1.1 Exploitation

Cet classe de bugs peut tre problmatique  exploiter,  cause du fait
que les entiers signs, lorsqu'ils sont interprts comme non signs,
tendent  devenir normes.Par exemple,-1 lorsque il est reprsent en
hexadcimal est 0xffffffff.Quand il est interprt comme non sign,
il devient la plus grande valeur qu'il est possible de reprsenter
en entier(4,294,967,295),ainsi si cette valeur est passe  memcpy
en temps que paramtres longueur (par exemple), memcpy va tenter de copier
4GB de donnes dans le tampon de destination. Evidemment cela peut causer
un segfault ou si sinon, dtruire une grande quantit de la pile ou du tas.
Quelque fois il est possible de remdier  ce problme en passant un trs 
petite valeur pour l'adresse source et esprer, mais cela n'est pas
toujours  possible.

----[ 3.2 Bugs de signes entrans par les dbordements d'entiers

Quelque fois, il est possible de dborder un entier de manire  ce qu'il 
repasse  une valeur ngative. Comme l' application n'est pas conue pour 
s'attendre  une telle valeur, il peut tre possible de reprer un bug
de signe comme  dcrit ci-dessus

Un exemple de ce type de bug pourrait ressembler  cela:

    int get_two_vars(int sock, char *out, int len){
        char buf1[512], buf2[512];
        unsigned int size1, size2;
        int size;

        if(recv(sock, buf1, sizeof(buf1), 0) < 0){
            return -1;
        }
        if(recv(sock, buf2, sizeof(buf2), 0) < 0){
            return -1;
        }

        /* packet begins with length information */
        memcpy(&size1, buf1, sizeof(int));
        memcpy(&size2, buf2, sizeof(int));

        size = size1 + size2;       /* [1] */

        if(size > len){             /* [2] */
            return -1;
        }

        memcpy(out, buf1, size1);
        memcpy(out + size1, buf2, size2);

        return size;
    }

Cette exemple montre ce qu'il peut parfois se produire dans les dmons  
rseaux,spcialement lorsque quand une information de longueur est
passe en tant qu'une partie d'un paquet (en d'autres mots, lorsque il
y un soumission de la part d'un utilisateur en lequel on n'a pas
confiance).L'addition [1], utilise pour vrifier que les donnes
n'excdent pas les limites du tampon de sortie, peut tre abuse en
mettant size1 et size2  des valeurs qui vont faire que la taille de
la variable  passer  une valeur ngative. Des valeurs exemples
pourraient tre:
    size1 = 0x7fffffff
    size2 = 0x7fffffff
    (0x7fffffff + 0x7fffffff = 0xfffffffe (-2)).
Quand cela se produit, la vrification de limites [2] est passe, et 
beaucoup plus du tampon de sortie peut tre crit que ce qu'il tait
voulu (en fait, de la mmoire arbitraire peut tre crite, comme le
paramtre destination (out+size1) dans le second appel  memcpy qui
peut nous permettre d'atteindre n'importe quelle endroit de la
mmoire).

Ces bugs peuvent tre exploits d'un manire exactement similaire que
les bugs de signes rguliers et comporte les mme problmes associs 
ces derniers- i.e. les valeurs ngatives traduites en norme valeurs
positives qui peuvent facilement causer des segfaults

--[ 4 Exemples de la vie relle

Il y de nombreuses applications dans la vie relle qui contiennent des
dbordements d'entiers et des bugs de signes, particulirement les dmons
rseaux et, frquemment, dans les kernels des systmes d'exploitation

----[ 4.1 Dbordements d'entiers

Cet exemple (non-exploitable) est tir d'un module de scurit pour linux.
Ce code tourne dans le contexte du kernel:

    int rsbac_acl_sys_group(enum  rsbac_acl_group_syscall_type_t call,
                            union rsbac_acl_group_syscall_arg_t arg)
      {
    ...
        switch(call)
          {
            case ACLGS_get_group_members:
              if(   (arg.get_group_members.maxnum <= 0) /* [A] */
                 || !arg.get_group_members.group
                )
                {
    ...
                rsbac_uid_t * user_array;
                rsbac_time_t * ttl_array;

                user_array = vmalloc(sizeof(*user_array) *
                arg.get_group_members.maxnum);   /* [B] */
                if(!user_array)
                  return -RSBAC_ENOMEM;
                ttl_array = vmalloc(sizeof(*ttl_array) *
                arg.get_group_members.maxnum); /* [C] */
                if(!ttl_array)
                  {
                    vfree(user_array);
                    return -RSBAC_ENOMEM;
                  }

                err =
                rsbac_acl_get_group_members(arg.get_group_members.group,
                                                  user_array,
                                                  ttl_array,

                                                  arg.get_group_members.max
                                                  num);
    ...
    }

Dans cet exemple ,la vrification des limites [A] n'est pas suffisante
pour prvenir d'un dbordement d'entier [B] et [C]. En passant une
valeur assez grande(i.e. plus grande que 0xffffffff /4) pour
arg.get_get_group_members.maximum, nous pouvons obliger les
multiplications [B] et [C]  dborder et forcer les tampons ttl_arrays
et user_array  tre plus petit que ce  quoi s'attends
l'application. Comme rsbac_cal_get_group_members copie des donnes
contrles par l'utilisateur dans ces tampons, il est possible
d'crire  la fin des tampons ,ce qui va tout simplement provoquer une
erreur, ainsi cela ne peut pas tre exploit. Mme si , cela fournit
un exemple de ce  quoi ces bugs peuvent ressembler dans du code rel.

Un autre exemple d'une rcente vulnrabilit par dbordement d'entier
de la vie relle tait le problme dans le XDR RPC library (dcouvert
par ISS X-Force).
Dans ce cas, des donnes soumises par l'utilisateur taient utilises dans 
le calcul de la taille d'un tampon allou dynamiquement qui tait
rempli avec les donne fournies par l'utilisateur. Le code vulnrable
tait celui-ci:

    bool_t
    xdr_array (xdrs, addrp, sizep, maxsize, elsize, elproc)
         XDR *xdrs;
         caddr_t *addrp;	/* array pointer */
         u_int *sizep;		/* number of elements */
         u_int maxsize;		/* max numberof elements */
         u_int elsize;		/* size in bytes of each element */
         xdrproc_t elproc;	/* xdr routine to handle each element */
    {
      u_int i;
      caddr_t target = *addrp;
      u_int c;		/* the actual element count */
      bool_t stat = TRUE;
      u_int nodesize;

      ...

      c = *sizep;
      if ((c > maxsize) && (xdrs->x_op != XDR_FREE))
        {
          return FALSE;
        }
      nodesize = c * elsize;    /* [1] */

      ...

      *addrp = target = mem_alloc (nodesize);   /* [2] */

      ...

      for (i = 0; (i < c) && stat; i++)
        {
          stat = (*elproc) (xdrs, target, LASTUNSIGNED);   /* [3] */
          target += elsize;
        }

Comme vous pouvez le voir, en soumettant de grandes valeurs pour
elsize et c(sizep),il tait possible de faire dborder la
multiplication [1] et d'obliger nodesize  tre bien plus petit que ce
qui tait prvu par le programme. Comme nodesize tait alors utilis
pour allouer un tampon[2], le tampon peut mener  un taille errone et
 un dbordement du tas [3]. Pour d'avantages d'informations sur cette
faille, lisez l'avertissement du CERT dont le lien est en appendice.

----[ 4.2 Bugs de signes

Rcemment, diffrent bugs de signes ont t mis en lumire dans le
kernel de FreeBSD. Cela permet  de larges portions de la mmoire du
kernel d'tre lues en passant des longueurs arguments ngatifs 
diffrent appels systmes.
La fonction getpeername(2) comporte un tel problme et ressemble  a:

    static int
    getpeername1(p, uap, compat)
        struct proc *p;
        register struct getpeername_args /* {
            int	fdes;
            caddr_t asa;
            int	*alen;
    } */ *uap;
    int compat;
    {
        struct file *fp;
        register struct socket *so;
        struct sockaddr *sa;
        int len, error;

        ...

        error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
        if (error) {
            fdrop(fp, p);
            return (error);
        }

        ...

        len = MIN(len, sa->sa_len);    /* [1] */
        error = copyout(sa, (caddr_t)uap->asa, (u_int)len);
        if (error)
            goto bad;
    gotnothing:
        error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
    bad:
        if (sa)
            FREE(sa, M_SONAME);
        fdrop(fp, p);
        return (error);
    }

C'est un exemple classique de bug de signe -la vrification [1] ne prends
pas en compte le fait que la longueur pourrait tre ngative, auquel cas
la macro MIN retournerai toujours la longueur. Lorsque ce paramtre ngatif
est pass  copyout, il est interprt en tant qu'entier positif trs grand
qui oblige copyout  copier jusqu' 4GB de mmoire kernel dans l'espace
de l'utilisateur.

--[ Conclusion

Les dbordements d'entiers peuvent tre extrmement dangereux, en partie car
il est impossible de les dtecter aprs qu'il se soient produits. Si un
dbordement d'entier a lieu, l'application ne peut pas savoir que le calcul
qu'il a effectu est incorrect, et va continuer jusqu'
Mme si ils peuvent tre compliqus  exploiter, et frquemment pas du tout
exploitables, ils peuvent entraner des comportements inattendus, ce qui 
n'est jamais une bonne chose dans un systme scuris.

--[ Appendice

L'avertissement du CERT sur le bug XDR:
http://www.cert.org/advisories/CA-2002-25.html
L'avertissement pour FreeBSD: 
http://online.securityfocus.com/advisories/4407


|=[ EOF ]=---------------------------------------------------------------=|


