Saturday, September 19, 2009

Snort ( 2.8.* < 2.8.5stable) Unified1 output bug

I have published a bug of snort 2.8. There are two proof of concept scripts here in this tar.gz and a deep explanation of the problem in the .pdf

Here is the advisory :)


Advisory:
=========
Snort unified 1 IDS Logging Alert Evasion, Logfile Corruption/Alert Falsify


Log:
====
30/06/2009 Bug detected.
20/07/2009 First mail with snort team.
20/07/2009 Snort team answer they will fix it in the next release (2.8.5).
16/09/2009 Snort 2.8.5 released, bug fixed.


Affected Versions:
==================
snort-2.8.1
snort-2.8.2
snort-2.8.3
snort-2.8.4
snort-2.8.5.beta*


Discussion:
===========
snort-2.8.* is susceptible to a Denial Of Service Vulnerability with Snort unified 1 binary format.
It occurs when snort.conf use the classic unified 1 output configuration as follows:
output unified: filename snort.log, limit 128

and Stream5 preprocessor is enabled.

This issue is due to the application's failure to properly set the offset of a memory buffer write when logging packet rebuilt streams data, resulting in corrupted unified log header and data in the logfile, out-of-bounds offsets, making impossible to parse/view the generated alerts with a normal parser/alert frontend.

When an alert has packet data information (the raw packet) the function UnifiedLogStreamCallback() write the raw packet data overwriting the UnifiedLog header, that has the type and size of the alert, followed by the alert information.

--output-plugins/spo_unified.c line 803 at least in snort-2.8.4 function UnifiedLogStreamCallback()
-------->SafeMemcpy(write_pkt_buffer, packet_data,...
should be
-------->SafeMemcpy(write_pkt_buffer + offset, packet_data,...

With this bug, the alert type and size are overwritten with the MAC addresses of the raw packet, so with malformed packets (Eth/IP/TCP/Data with modified MAC addresses), the size and the type (and other information) can be set falsifing alerts for a later parsing process. If an attacker build malformed packets, so an alert is falsified the size is bigger than 128M (the unified log limit size by default), snort will continue inserting alerts in the file, but a parser when reading that alert will try to jump 128M skipping the alerts inserted after the falsified one.

An attacker can also insert a complete list of falsified alerts malforming packets, because the raw packet has TCP data that you can fill with falsified UnifiedLog alert structures (with the binary data), so would need to adjust the packet headers to set the "size of the alert" (overwritten with the MACs of the packet) making that the parser read the next alert in the offset that the TCP data will overwrite(the list of falsified alerts).


Impact:
=======
With this bug an attacker can break the alert log headers, making impossible for a parser to extract the alert information correctly. An attacker can also insert falsified alerts in the logfiles by injecting unified structures with false alerts, false pcaps (Ethernet/Ip/Tcp/Data) by malforming the packets of a TCP stream that match a normal alert, which wont be even correctly inserted.


Proof of concept:
=================

To reproduce the bug you must have a unified 1 parser accepting unified logs with the configuration in snort.conf as " output unified: filename snort.log, limit 128" and the Stream5 preprocessor enabled. Then you need to send a content payload that will generate an alert, but this payload must be divided in two parts, sending them in two consecutive (and different) packets so Stream5 will reassemble as a PKT_REBUILT_STREAM. The header of the unified Alert log will be overwritten with the raw packet information. There are two proof of concept scapy scripts, one generate a pcap that insert an alert overwriting the header so that a parser think that the alert is bigger than 128M, and another that insert a falsified alert.

The pcaps can be processed in snort with snort -r "the_file.pcap"...


Fix:
====
Install snort-2.8.5 or add the offset and recompile snort:
--output-plugins/spo_unified.c line 803 at least in snort-2.8.4 function UnifiedLogStreamCallback()

SafeMemcpy(write_pkt_buffer + offset, unifiedData->logheader,
sizeof(UnifiedLog), write_pkt_buffer,
write_pkt_buffer + sizeof(DataHeader) +
sizeof(UnifiedLog) + IP_MAXPACKET);

offset += sizeof(UnifiedLog);

unifiedData->data->current += sizeof(UnifiedLog);

if(packet_data)
{
-------->SafeMemcpy(write_pkt_buffer, packet_data,
offset + unifiedData->logheader->pkth.caplen,
write_pkt_buffer, write_pkt_buffer +
sizeof(DataHeader) + sizeof(UnifiedLog) + IP_MAXPACKET);

if(fwrite(write_pkt_buffer, offset + unifiedData->logheader->pkth.caplen,
1, unifiedData->data->stream) != 1)
FatalError("SpoUnified: write failed: %s\n", strerror(errno));

unifiedData->data->current += unifiedData->logheader->pkth.caplen;
}
else
--+ 825

Look at that closely and you'll see that the buffer is overwritten if packet_data is not 0, and then the buffer is written to the log file. The fix is really simple. Just write to write_pkt_buffer +offset, instead of write_pkt_buffer.

-------->SafeMemcpy(write_pkt_buffer, packet_data,...
-------->SafeMemcpy(write_pkt_buffer + offset, packet_data,...

or use unified 2.

Conclusions:
========
An attacker can:
1. Corrupt the log files.
2. Perform attacks after malformed packets in order prevent that they would get
logged/displayed.
3. Make a DOS for the parsers by inserting alerts with header size > than the filesize limit
(They would loose a lot of alerts...).
4. Insert a complete falsified attack session by encapsulating many alerts in the malformed
tcp packets.
5. We can patch it and be happy with our systems using Stream5 and the rest of the
preprocessors :)
6. It's extremely recommended to use unified2 if you're not using it yet.
7. If you still using unified1, use alert_unified or (log_unified), or just unified but patching snort.


Thanks to:
==========
Jaime Blasco and Juan Blanco working on the ossim-agent "arakiri".
Matt Jonkman and Victor Julien (a pcap generated with the splicer script was the starting point for the scapy scripts).
Carlos Terrón for his great unified1 parser.
The OSSIM project.


Credits:
========
Pablo Rincón Crespo 31/07/2009
pablo.rincon.crespo
at gmail

No comments:

Post a Comment