# $Id: avoiding_snort_alerts.txt,v 1.4 2006/01/27 13:27:29 andreaso Exp $ # # Copyright (C) 2004-2006 Andreas Östling How to stop Snort alerts from being generated / how to (not) ignore traffic --------------------------------------------------------------------------- Intro ----- This document is not a guide about how to fine-tune a sensor to nail out false positives and such, it just tries to summarize different approaches you can take after deciding that you in fact want to stop an alert from firing. Also, while Snort supports different kind of thresholding, this document is only about how to shut down specific alerts completely. The content reflects my personal opinions, which may not be valid in your environment, or even correct. Remember that this document is not a substitution for the official Snort documentation, where the actual configuration details are explained further. Documentation you should also read: - The Snort manual at http://www.snort.org/docs/snort_manual/ - The Snort FAQ at http://www.snort.org/docs/FAQ.txt - The doc/README.* files in the Snort distribution Alerts can be generated not only by regular Snort signatures (rules) but also by other parts of Snort such as its internal packet decoder and the preprocessors. Turning off alerts generated by rules is different than turning non-rule alerts, so they will be described in different sections. Alerts generated by rules ------------------------- There are basically five ways to stop an alert from firing because of a matching rule, You can either remove the rule completely (1), suppress the alert globally or only when involving specific hosts (2), rewrite the rule (3) or make Snort ignore the packet so that the rule will never see it at all (4 and 5). Ignoring traffic completely will obviously stop the alert from firing but it may also have other implications. Of course, there are times when ignoring traffic is actually what you really want. Just choose the method that is right for the situation. 1) Disabling the rule: If there is a rule that generates alerts you never care about regardless of the hosts involved, the best way to stop those alerts is to simply disable that rule. You disable the rule by locating the rules file containing it and then commenting it out by placing a "#" in front of it (or simply delete the rule). Don't forget to restart Snort to activate the change. As every active rule consumes valuable resources on your sensor, this is the very best way to disable alerts for a rule globally. Remember that when updating your rules, your disabled rules may get activated again unless you do it right. There are several tools that can assist you in keeping your disabled rules disabled between updates, e.g. Oinkmaster (http://oinkmaster.sf.net/). Don't let the rules updating be an excuse for choosing another way of turning off specific alerts globally instead if disabling the rule. 2) Suppression: Write a "suppress" statement for the rule (see Snort's doc/README.threshold for details). When suppressing alerts for a rule, Snort still processes packets/rules as usual but when it decides that a packet matched a rule and it's time to generate an alert, it first checks if there is a matching "suppress" statement. If there is, the alert is not generated. Suppression is most likely the way to go if there is a rule you really want to use (i.e. you can't disable it completely) but there is one or a few hosts generating alerts because of that rule and you want to stop the alert from firing when involving only those hosts. You can also suppress rules globally so that they never trigger regardless of the involved addresses, but that is a real waste of valuable CPU cycles for your Snort sensor as Snort would still have to process the rules as usual anyway. In such cases, you should disable the rule instead. (If you find it easier to add "suppress" statements for rules you don't want to use instead of disabling the rule completely, you should probably improve your rules management setup.) 3) Pass rules: A pass rule is just like any other rule except when a packet matches a pass rule, Snort will consider itself done with that packet and go on with the next one. Don't forget to read the Snort FAQ 4.8 to make sure your rules are processed the order you expect, or the pass rule may have no effect (hint: check out the -o flag). You may be tempted to take an unwanted rule, copy it, and replace "alert" with "pass". You should never ever do this. Pass rules should usually not be the primary way to avoid alerts since they're hard to maintain and easy to get very wrong. For example, one pass rule can easily render multiple other signatures useless. Assume there is a signature like this one, watching for "GET /cgi-bin/": alert tcp any any -> any 80 (msg: "/cgi-bin/ access"; \ content: "GET /cgi-bin/";) If you wanted to stop this signature from firing by using a pass rule, perhaps you would simply copy the rule and replace "alert" with "pass": pass tcp any any -> any 80 (msg: "/cgi-bin/ access"; \ content: "GET /cgi-bin/";) It's true that the rule will no longer alert. However, what if this signature also exists which watches for "GET /cgi-bin/cmd.exe": alert tcp any any -> any 80 (msg: "/cgi-bin/cmd.exe access"; \ content: "GET /cgi-bin/cmd.exe";) Since the pass rule above will pass ALL packets containing "GET /cgi-bin/", it will also match the signature that would otherwise alert on "GET /cgi-bin/cmd.exe". This particular example is very obvious but the problem is common and can be very subtle. Also, what happens when the alert rule is modified but the pass rule is not? Or if a new rule is added that one of your existing pass rules happen to match as well? The result can be hard to predict and you may end up ignoring way more traffic than intended, while wasting CPU cycles. Pass rules can be very useful for fine-tuning, for example to avoid false positives on specific hosts without turning off the rule or suppressing that alert for those hosts completely. If you however actually do want to stop the specific alert for specific hosts completely, you should consider using suppression. Note: Some people have argued that "pass" rules are the only way to set a flowbit without generating an unwanted extra alert. This is wrong, check out the "flowbit: noalert" part in the Snort manual. 4) Rewriting the rule: Assume you want to see all packets containing the string "foo" by using the following rule: alert ip any any -> any any \ (msg: "foo"; content: "foo";) And let's say you have one or a few hosts generating such alerts but you want to avoid generating the alerts when coming from those. You can rewrite the rule like this: alert ip ![192.168.0.1,10.0.0.1] any -> any any \ (msg: "foo"; content: "foo";) Now the alert will only be generated for hosts that are not in the that list (which you may want to have as a variable instead). For some rules, rewriting like this may not be possible (or be hard to maintain), but for some situations it can be a good approach. Hint: Oinkmaster can modify rules like this on the fly while still being able to keep them updated automatically. 5) BPF filter: You can use a BPF filter (aka "tcpdump filter") when starting Snort. BPF filters is a way to ignore packets so that Snort doesn't even see them. They are very powerful and useful for ignoring traffic, but for the purpose of suppressing alerts, it's not always the best choice. Assume again that our host 192.168.0.1 trigger some alert. You can stop those alerts by using the filter "not src host 192.168.0.1" when starting Snort. However, now Snort will never ever see a single packet from that host. Not only will that stop ALL alerts from that host, but it may also break preprocessors and rules trying to be stateful as Snort will now only see traffic in one direction. If however 192.168.0.1 was a high bandwidth host (or a dedicated scanner host or whatever) and you're sure you never care about any alerts to or from that host. Then, a BPF filter such as "not host 192.168.0.1" would be a good choice since packets involving that host would never even be seen by Snort, so you'll save a lot of valuable CPU cycles as well. More information about writing BPF filters can be found in the tcpdump manual. Quick summary: If you want alerts from a rule to stop completely, disable/remove the rule. If you want to use the rule but stop the alert from firing when involving specific hosts, use suppression. If you have very specific needs on how to make Snort pass some packets, use pass rules. If you want Snort to never even see some packets, use BPF filters. Alerts generated by non-rules ----------------------------- Disabling rules or creating pass rules as described above is useful for avoiding alerts from the actual rules, but alerts generated by other parts of Snort can not be avoided this way. If this doesn't make sense to you, remember that packets traverse the following stages in order (very simplified): BPF -> Snort's internal alerts / preprocessors -> rules (pass/alert/log) Now you see that if you get an alert from a preprocessor, you can't stop it by writing a pass rule since the preprocessors see packets before they reach the rules stage. How to avoid such alerts depends on which specific part of Snort generated it. You should normally consult the Snort manual to find out how to quiet down that part of Snort. For example, if the alert is generated by Snort's internal packet decoder (shows up as coming from snort_decoder), consult the Snort manual for the "config disable_..._alerts" options. Or if you want to exclude some hosts from the original portscan plugin, see the manual for the portscan processor about portscan-ignorehosts, and so on. To find out if the alert was generated by a rule or by another part of Snort (also know as another "generator"), inspect the part of the alert that looks something like "[1:12345:2]". First number is the generator responsible for generating the alert (1 means it's generated by a rule, see gen-msg.map), 12345 is the SID and 2 is the revision of the signature. Good news is that "suppress" statements works for all different kind of alerts, not just the ones generated by regular rules. This means that regardless of which part or Snort generated it you can always use suppression even though it's sometimes better to tune the preprocessor (or whatever is generating the alert) than to turn off the alerts completely. When suppressing alerts, you need to know the generator ID and signature ID responsible for it. If you want to suppress all alerts for the rule with SID 12345 coming from the host 192.168.0.1, use something like this (remember that regular rules use generator ID 1): suppress gen_id 1, sig_id 12345, track by_src, ip 192.168.0.1 Next, assume you get this alert: 03/17/04-10:59:40 [**] [111:15:1] (spp_stream4) TTL LIMIT Exceeded [**] {TCP} 192.168.0.1:80 -> 10.0.0.1:3896 This alert is not generated by a rule so you can not avoid it by using pass rules or by disabling some rule. So what is left is to either tweak the preprocessor's configuration (if possible), use a BPF filter or suppression. The [111:15:1] means that what generated this alert is generator ID 111 and the signature ID is 15 (see the gen-msg.map file to confirm that this is indeed the stream4 preprocessor). To suppress this alert completely, you could use something like this: suppress gen_id 111, sig_id 15 Another way to avoid alerts generated by non-rules is to use BPF filters as described for the rules, since that will make the packets never even reach the Snort process. But again, you may end up ignoring way more traffic than you intended so be careful when writing such filters.