On va voir les différentes techniques qui permettent d’engendrer un bug dans une application, et plus particulièrement pour essayer ensuite de détourner le flow d’exécution de cette application.
Un principe très connu… mais connu de l’époque ! A l’époque on utilisait des fonctions non sécurisée pour la lecture d’une entrée, par exemple en C on pouvait utiliser gets(3) qui prend en entrée une adresse et.. c’est tout. Il n’y avait aucun check sur la longueur du texte entré.
Voici un petit one-line pour faire vos plus grosses strings ! :D
python -c "print 'A'*5000"
On commence à rentrer doucement dans le vif du sujet. Il peut arriver que votre programme crash car vous n’avez pas mis le format attendu.
Premièrement au niveau du type, le programme peut s’attendre à un entier, mais vous vous allez mettre “AAAAAA” comme un con, et puis en plus ça marche. Ca peut vous permettre de récupérer un leak d’une adresse par exemple, il arrive que des programmes crash.. mais pas entièrement: on vous donne le code d’erreur, peut-être une adresse, puis hop en fait tout fonctionne, vous avez juste fait planter une petite fonctionnalité de merde qui servait à rien.
Voici un exemple dans la vraie vie
On peut imaginer ce genre de payloads:
undefined
undef
null
NULL
(null)
nil
NIL
true
false
True
False
TRUE
FALSE
None
hasOwnProperty
then
constructor
A une époque on s’en foutait qu’un entier soit signé ou non.. Du coup petite technique, essayez parfois d’aller plus loin que ce qui est prévu. Si ce n’est pas prévu par le programme.. c’est cool pour nous !
En plus, un exemple récent ne peut pas vous faire de mal :)
0
1
1.00
$1.00
1/2
1E2
1E02
1E+02
-1
-1.00
-$1.00
-1/2
-1E2
-1E02
-1E+02
1/0
0/0
-2147483648/-1
-9223372036854775808/-1
-0
-0.0
+0
+0.0
0.00
0..0
.
0.0.0
0,00
0,,0
,
0,0,0
0.0/0
1.0/0.0
0.0/0.0
1,0/0,0
0,0/0,0
--1
-
-.
-,
999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
NaN
Infinity
-Infinity
INF
1#INF
-1#IND
1#QNAN
1#SNAN
1#IND
0x0
0xffffffff
0xffffffffffffffff
0xabad1dea
123456789012345678901234567890123456789
1,000.00
1 000.00
1'000.00
1,000,000.00
1 000 000.00
1'000'000.00
1.000,00
1 000,00
1'000,00
1.000.000,00
1 000 000,00
1'000'000,00
01000
08
09
2.2250738585072011e-308
A l’époque (oui, c’est toujours à l’époque..) on utilisait printf(3), et en plus on l’utilisait mal ! En plus on a un exemple hyper récent avec le SSID Stripping sur iOS
Donc n’hésitez plus à les mettre dans votre payload list !
(Et les mettez pas en brut.. faut echo -e "${payload}"
)
AAAAAAAAA%p%s%s%s%s%n
AAAAAAAAA\t%p%s%s%s%s%n
AAAAAAAAA\n%p%s%s%s%s%n
AAAAAAAAA\f%p%s%s%s%s%n
AAAAAAAAA\x1c_office
Vous pouvez essayer de mettre de l’unicode, des caractères accentués etc dans vos payloads, mais attention, votre payload list ressemblera à rien ! Genre vraiment, à que dalle ! Je vous la donne pas, je suis sûr que vous pouvez la générer vous-même, j’ai pas envie de deface mon site..
La race condition (ou “condition de course” selon bitoduc), c’est juste le fait d’être rapide. Imaginons que votre programme procède de la sorte:
read
wait(5s)
...
Bah ça se trouve vous pouvez intéragir avec la mémoire pendant ces 5 secondes, et ça se trouve, détruire tout le programme !
Les bug logiques (ou business logic bug) sont les plus durs à déceler puisqu’il faut comprendre à 100% comment il fonctione, et ce que font exactement les fonctions. Pour donner un exemple de bug logique, on pourrait essayer de mettre 2 fois le même paramètre:
./prog --file A.txt --file BBBBBBBBBBBBBBBBBBBBB.txt
Quand on parle de bug logique, on parle d’un usecase qui n’a absolument pas été prévu dans le développement et qui permet de détourner le programme.
L’exécution symbolique permet d’analyser un programme pour déterminer quel inputs ont quels conséquences sur le programme. Les outils les plus connu que je connaisse sont angr et KLEE C’est très efficace, on peut aller de la détection de vulnérabilité au build du payload !
Le fuzzing, dernière technique à la mode, et à la mode depuis un petit moment déjà. Si on peut résumer le fuzzing en quelques mots, je dirais ceci: foutre de la merde partout et voir si ça crash, et parfois on fout la merde de manière un peu plus propre. Voilà, et pour ça on a des outils (le mieux étant de créer le sien) comme afl, afl c’est un fuzzer de coverage, il fonctionne en greybox: il a accès au code car vous allez compiler avec.
La suite ici !