I rewrote a bit of the first issue to better understand it, and also provide a patch:

## 1. Integer Underflow in `raptor_uri_normalize_path()`

There's an integer underflow in a path length calculation in `raptor_uri_normalize_path()`.

This can be triggered by running the PoC below:

```
utils/rapper -i turtle memcpy_int_underflow.poc
rapper: Parsing URI file:///memcpy_int_underflow.poc with parser turtle
rapper: Serializing with serializer ntriples
free(): invalid pointer
Aborted
```

With an ASAN build of `rapper` we can more clearly see the issue without the need of a debugger:

```
raptor-asan/utils/rapper -i turtle memcpy_int_underflow.poc
rapper: Parsing URI file:///memcpy_int_underflow.poc with parser turtle
rapper: Serializing with serializer ntriples
=================================================================
==2406522==ERROR: AddressSanitizer: negative-size-param: (size=-5)
    #0 0x5f90a3e1cf33 in __interceptor_memcpy (/raptor/raptor-asan/utils/.libs/rapper+0x3cf33) (BuildId: 31b11a035fdbbfb23ddb7c1a5db60302956622be)     #1 0x7c902fa96e5a in raptor_uri_resolve_uri_reference (/raptor/raptor/src/.libs/libraptor2.so.0+0x19e5a) (BuildId: 9edf75a105deaf007b9332b0a0367c8ad4af744d)     #2 0x7c902fa9741c in raptor_new_uri_relative_to_base_counted (/raptor/raptor/src/.libs/libraptor2.so.0+0x1a41c) (BuildId: 9edf75a105deaf007b9332b0a0367c8ad4af744d)     #3 0x7c902fa9747a in raptor_new_uri_relative_to_base (/raptor/raptor/src/.libs/libraptor2.so.0+0x1a47a) (BuildId: 9edf75a105deaf007b9332b0a0367c8ad4af744d)     #4 0x7c902fab93fc in turtle_lexer_lex (/raptor/raptor/src/.libs/libraptor2.so.0+0x3c3fc) (BuildId: 9edf75a105deaf007b9332b0a0367c8ad4af744d)     #5 0x7c902fabc3ec in turtle_parser_parse (/raptor/raptor/src/.libs/libraptor2.so.0+0x3f3ec) (BuildId: 9edf75a105deaf007b9332b0a0367c8ad4af744d)
    #6 0x7c902fabebb9 in turtle_parse turtle_parser.c
    #7 0x7c902fabf3ff in raptor_turtle_parse_chunk turtle_parser.c
    #8 0x7c902fa92de4 in raptor_parser_parse_chunk (/raptor/raptor/src/.libs/libraptor2.so.0+0x15de4) (BuildId: 9edf75a105deaf007b9332b0a0367c8ad4af744d)     #9 0x7c902fa92fc1 in raptor_parser_parse_file_stream (/raptor/raptor/src/.libs/libraptor2.so.0+0x15fc1) (BuildId: 9edf75a105deaf007b9332b0a0367c8ad4af744d)     #10 0x7c902fa93174 in raptor_parser_parse_file (/raptor/raptor/src/.libs/libraptor2.so.0+0x16174) (BuildId: 9edf75a105deaf007b9332b0a0367c8ad4af744d)     #11 0x5f90a3ed9492 in main (/raptor/raptor-asan/utils/.libs/rapper+0xf9492) (BuildId: 31b11a035fdbbfb23ddb7c1a5db60302956622be)     #12 0x7c902f7816c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #13 0x7c902f781784 in __libc_start_main csu/../csu/libc-start.c:360:3
    #14 0x5f90a3e01650 in _start (/raptor/raptor-asan/utils/.libs/rapper+0x21650) (BuildId: 31b11a035fdbbfb23ddb7c1a5db60302956622be)

(...)

SUMMARY: AddressSanitizer: negative-size-param (/raptor/raptor-asan/utils/.libs/rapper+0x3cf33) (BuildId: 31b11a035fdbbfb23ddb7c1a5db60302956622be) in __interceptor_memcpy
==2406522==ABORTING
```

The crash occurs because `raptor_uri_normalize_path()`, which does some complicated jiggling to normalize paths, and fails to take into account integer underflows. The function will not be shown here as it is quite complex.

`raptor_uri_normalize_path()` is called from `raptor_uri_resolve_uri_reference()` to normalize a path, and the crash occurs in a juicy `memcpy()` inside `raptor_uri_resolve_uri_reference()` (`raptor_rfc2396.c:664`) where `result.path_len` is the underflowed integer (ASAN's `negative-size-param`), and `result.path` is attacker controlled:

```c
  if(result.path) {
    memcpy(p, result.path, result.path_len);
    p+= result.path_len;
  }
```

The non-ASAN crash in `free()` shown at the top occurs in line 685:

```c
  if(path_buffer)
    RAPTOR_FREE(char*, path_buffer);
```

The fix, however, is rather simple! The function contains several of these checks after each calculation:

```c
#if defined(RAPTOR_DEBUG)
  if(path_len != strlen((const char*)path_buffer))
    RAPTOR_FATAL3("Path length %ld does not match calculated %ld.", (long)strlen((const char*)path_buffer), (long)path_len);
#endif
```

If we remove the `#if defined` / `#endif` around this code in lines 396 and 399, we get an error instead of a crash: `raptor_rfc2396.c:397:raptor_uri_normalize_path: fatal error: Path length 0 does not match calculated -5.Aborted`


### 1.1 Steps to reproduce

`rapper -i turtle memcpy_int_underflow.poc`

Contents of `memcpy_int_underflow.poc`:

```
@base <http:o/www.w3.org/2001/sw/DataA#cess/df1.ttl> .
@prefix bdf: <.&/../?D/../../1999/02/22-rdf-syntax-ns#>/dbpe
```

### 1.2 Patch

```diff
diff --git a/src/raptor_rfc2396.c b/src/raptor_rfc2396.c
index 89183d96..f58710c5 100644
--- a/src/raptor_rfc2396.c
+++ b/src/raptor_rfc2396.c
@@ -393,10 +393,8 @@ raptor_uri_normalize_path(unsigned char* path_buffer, size_t path_len)
   }


-#if defined(RAPTOR_DEBUG)
   if(path_len != strlen((const char*)path_buffer))
     RAPTOR_FATAL3("Path length %ld does not match calculated %ld.", (long)strlen((const char*)path_buffer), (long)path_len);
-#endif

   /* RFC3986 Appendix C.2 / 5.4.2 Abnormal Examples
    * Remove leading /../ and /./

```


Regards,

Pedro

Reply via email to