phaag / nfdump

Netflow processing tools
Other
777 stars 203 forks source link

Multiple security vulnerabilities in minilzo.c, nffile_inline.c and nfx.c #104

Closed e3prom closed 5 years ago

e3prom commented 6 years ago

Summary

nfdump (commit 27f62a5510096833523b469a56d5d32ed0bcb39a) is affected by multiple security vulnerabilities in:

For obvious security reasons, I voluntarily omitted to mention the affected lines of codes, so the developers should have enough time to fix these issues. The program's author has been contacted with the necessary technical details.

Description

By crafting special malformed nfcapd input files, an attacker can crash the program by forcing it to dereference invalid memory addresses, and may overflow heap chunks to get arbitrary code execution.

Feel free to contact me if more information are necessary.

phaag commented 6 years ago

I will take care about that. As I was not informed beforehand I can not provide fixed immediately.

phaag commented 6 years ago

After detailed investigation I fixed nfx.c and nffile_inline.c to exit nfdump properly, when feeded with garbage input. The issues are not to be considered as security related. Potential exploitation does not result in privileged escalation or similar effects. It can only be exploited on the host nfdump is installed.

The crashes in minilzo are not yet fixed, as this is a third part library. See also www.oberhumer.com/opensource/lzo/. Maybe @e3prom can check those libraries first and get in contact with the author.

e3prom commented 6 years ago

Regarding the heap-based buffer overflow involving minilzo: the buffer can still be written out of bound and it seems to happen in the "redistributed" portion of their code (as it has been pointed out), however the buffer has been previously allocated in the nfdump code through a malloc() call. A similar memory allocation can be found at line 646 of 'bin/nffile.c'. Maybe some checks could be performed to avoid out-of-bound writes, or a bigger buffer could be allocated? I will let the developers figure out what is best in the interests of their users.

I don't think theses issues could be trivially exploited, nor that they provide a lever interesting enough for privilege escalations, however if the attacks on the heap are successful and results in code execution, an attacker could "locally" perform lateral movement via a specially crafted file. I think that's enough to worry about.

While I disagree with the conclusion of @phaag regarding the security implications of the reported issues, I would like to thanks Peter for the provided fixes. They at least allow nfdump to gracefully exit before invalid memory addresses are accessed.

phaag commented 6 years ago

The issue in minilzo need to be fixed by the author of the minilzo code. He knows best his code. It does not help if nfdump allocates a larger buffer. The bug still exists, can be exploited and simply need more bytes to overrun. While we agree that these issues are easy exploitable, I am also convinced that this not a main threat on a system where nfdump is installed. As soon as a fix for minilzo is available I will patch nfdump accordingly. Given the above, I still consider this not to be a main security issue. Anyway, thanks to @e3prom for reporting these issues. It helps to fix bugs and improves the quality of the software.

nluedtke commented 5 years ago

This was assigned CVE-2019-1010057.

hongxuchen commented 5 years ago

Hi, as of fd3d3db, we provided some POCs for the crashes and the backtraces from AddressSanitizer here. Specifically, there are some crashes inside nfx.c, exporter.c, nfdump.c, nffile_inline.c, some of which we think are not observed before; crashes inside minilzo.c are all ignored.

phaag commented 5 years ago

Fixes have been commit for: hbo_exporter.c:249_1, hbo_nffile_inline.c:85_1 and hbo_nfx.c:216_3. All other POCs do not segfault with current code and report correctly corrupted files. Note: In your readme for nfdump: neither -y nor -a is required.

phaag commented 5 years ago

updated minilzo 2.10 and changed to safe lzo decompress

hongxuchen commented 5 years ago

As of 7b26ee9 with regular compilation flow, on my machine the provided inputs such as ghbo_nfx.c:473_1 may still cause segfault with the error messages like:

$ ./nfdump-orig/install/bin/nfreplay -r ./inputs/ghbo_nfx.c:473_1

Skip unknown record type 512

Skip unknown record type 512

Can't process block type 28160. Skip block.

Can't process block type 0. Skip block.

Insert Extension Map:
Extension Map:
  Map ID   = 59647
  Map Size = 7680
  Ext Size = 255

Extension info in slot 59647 already exists: 0x4362624
Different map => continue
Search if extension info exists in extension page_list
Check map: 58623
Map found: 0x4362256 ID: 58623
Insert extension into slot 59647: 0x4362256

Insert Extension Map:
Extension Map:
  Map ID   = 59647
  Map Size = 7680
  Ext Size = 255

Extension info in slot 59647 already exists: 0x4362256
New map has same size, as existing:
Same map => nothing to do
Can't process block type 32256. Skip block.

Can't process block type 0. Skip block.

Can't process block type 0. Skip block.

Insert Extension Map:
Extension Map:
  Map ID   = 59647
  Map Size = 12032
  Ext Size = 0
  ID   0, ext   1 = Required extension: IPv4/IPv6 src/dst address
  ID   0, ext 768 = (null)
  ID   0, ext 3456 = (null)
[1]    25963 segmentation fault  ./nfdump-orig/install/bin/nfreplay -r ./inputs/ghbo_nfx.c:473_1

$ echo $?
139
phaag commented 5 years ago

I can not confirm:

% ./nfreplay -r ghbo_nfx.c:473_1 Can't process block type 0. Skip block. .. .. more error messages .. Can't process block type 32256. Skip block.

Can't process block type 0. Skip block.

Can't process block type 0. Skip block.

PANIC! - Verify map id 59647: ERROR: element id 768 out of range [49]!

% echo $? 255

nfreplay ends cleanly with a processing error.

No segfault with current repo code!

ZjuYTW commented 5 years ago

Hi, I tried to use ghbo_nfx.c:473_1 as inputs, and the result turned out saying there is a segmentation fault, as:

and I used gdb to debug, still use ghbo_nfx.c:473_1 as inputs:

gdb ./bin/nfreplay gdb$ break 473 /which is the line where the segmentation fault happens/ gdb& run -r ghbo_nfx.c:473_1 Can't process block type 0. Skip block. .. ..more error messages ..

Insert Extension Map: Extension Map: Map ID = 59647 Map Size = 7680 Ext Size = 255

Extension info in slot 59647 already exists: 0x93824994460096 Different map => continue Search if extension info exists in extension page_list Check map: 58623 Map found: 0x93824994459728 ID: 58623 Insert extension into slot 59647: 0x93824994459728

Insert Extension Map: Extension Map: Map ID = 59647 Map Size = 7680 Ext Size = 255

Extension info in slot 59647 already exists: 0x93824994459728 New map has same size, as existing: Same map => nothing to do Can't process block type 32256. Skip block.

Can't process block type 0. Skip block.

Can't process block type 0. Skip block.

Insert Extension Map: Extension Map: Map ID = 59647 Map Size = 12032 Ext Size = 0

Breakpoint 1, PrintExtensionMap (map=map@entry=0x7ffff6b7301c) at nfx.c:473 473 printf(" ID %3i, ext %3u = %s\n", extension_descriptor[id].user_index, id, extension_descriptor[id].description );

gdb$ n ID 0, ext 1 = Required extension: IPv4/IPv6 src/dst address 471 while (map->ex_id[i]) {

gdb$ n

Breakpoint 1, PrintExtensionMap (map=map@entry=0x7ffff6b7301c) at nfx.c:473 473 printf(" ID %3i, ext %3u = %s\n", extension_descriptor[id].user_index, id, extension_descriptor[id].description );

gdb$ n ID 0, ext 768 = (null) / id is 768 which excess the range of extension_descriptor array / 471 while (map->ex_id[i]) { gdb$ n

Breakpoint 1, PrintExtensionMap (map=map@entry=0x7ffff6b7301c) at nfx.c:473 473 printf(" ID %3i, ext %3u = %s\n", extension_descriptor[id].user_index, id, extension_descriptor[id].description );

.. more step-run to breakpoint .. gdb$ n

Breakpoint 1, PrintExtensionMap (map=map@entry=0x7ffff6b7301c) at nfx.c:473 473 printf(" ID %3i, ext %3u = %s\n", extension_descriptor[id].user_index, id, extension_descriptor[id].description ); gdb$ n

Program received signal SIGSEGV, Segmentation fault. PrintExtensionMap (map=map@entry=0x7ffff6b7301c) at nfx.c:473 473 printf(" ID %3i, ext %3u = %s\n", extension_descriptor[id].user_index, id, extension_descriptor[id].description ); gdb$ print id $12 = 0x206e

From above debug process, I speculate @phaag 's run environment has mechanism to handle the array out of bound exception, thus throw a 'PANIC!' and stop the program. If the index is too large for the memory(as the above id, 0x206e), it will cause a segmentation fault.

phaag commented 5 years ago

There is nothing special on my run environment. The panic error message is generated by nfx.c function FixExtensionMap, which does a sanity check on the map and exists if anything is not correct. According to your output, you compiled nfdump with DEVEL developer code enabled, which is actually not the normal running condition. Your nfreplay test crashes in a developer enabled code which prints the map before doing the sanity check. In a development cycle this is pretty much ok. This code is not compiled into the binaryl in normal operation, therefore it can not crash and the sanity check blocks ghbo_nfx.c:473_1

In order to be consistent with nfdump.c, I inserted the early generic record size check also into the other nfdump binaries. This already blocks ghbo_nfx.c:473_1.