Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I want to add some rules or download some ready rules to detect DNS label Decoding DoS (Cross Reference at DNS decompression) can anyone know how can I do this?

share|improve this question
add comment

1 Answer

I am not aware of any known DoS attacks against the label decoding/compression trick that DNS uses (references perhaps?). That said, you can design a rule to detect the presence of a compression pointer using byte_test as such: byte_test:2,&,0xc000,0;. This uses a bitwise AND to mask out all but the two highest bits and see if they are both '11', which is the marker for a compression pointer (the remaining 14 bits specify the offset from the start of the payload to the referenced DNS label). If that byte_test returns true, you've detected such a pointer, and you can then build the rest of the rule around that. It's up to you to walk the DNS packet until you arrive at the place where you expect such a pointer to exist.

Have a look over the DNS protocol for any further oddities of this clever trick.


Edit:

Thinking about it, I think it's really only possible with the second byte of the packet. Unfortunately, Snort resets the doe_ptr to the start of the payload with each new rule option unless you specify a relative to any of the byte_* options (I think). I do not believe that one byte option can be relative to a previous byte option, only to content matches.

So, given that 99% of your DNS packets will never use the remaining 6 bits of the second high byte, you can start by looking for the hex value 0xc0, which in binary is 11000000. This can replace the first byte_test.

alert udp any 53 -> any 1024: (msg:"DNS recursive Ptr test"; content:"|c0|"; byte_extract:1,0,dns_comp_ptr,relative,little; byte_test:1,=,dns_cmp_ptr,dns_comp_ptr,little; sid:12345; rev:1; classtype:yadda-yadda;)

In order:

  1. content:"|c0|"; - Find a compression pointer.
  2. byte_extract:1,0,dns_comp_ptr,relative,little; - grab the next byte and store it to the variable dns_comp_ptr (untested! My offset may be incorrect -- might need to add +1).
  3. byte_test:1,=,dns_cmp_ptr,dns_comp_ptr,little; - test one byte and see if it is equal to the value stored in dns_comp_ptr, after jumping the value indicated by dns_comp_ptr, in little-endian format (which is how we see it as displayed in Wireshark).

If the last byte_test returns true, then the rest of the rule will validate and alert. All in theory, of course. Totally untested and I offer no guarantees that it will work. But it encompasses the basic idea of needing to check every compression pointer in a DNS response (with a response on a Google domain, expect several of these) to see if that pointer points back to itself by following it at least once.

The only way, that I can think of anyways, to test both bytes, is you would need a way to jump the doe_ptr to the byte immediately prior to the compression pointer, i.e., via a content. Snort doesn't have a rule option that directly says to move the doe_ptr by a specified value all by itself (though that really would be a cool idea, TBH).

Once you have the doe_ptr placed properly, you use byte_test:2,&,0xc000,1,relative,little; to mask out all bits except the first two and see if they match the hex 0xc000. Then you do byte_extract:2,0,dns_comp_ptr,little,bitwiseand 0x3fff; then byte_test:2,=,dns_comp_ptr,dns_comp_ptr,little;. Again untested, so my offsets are probably wrong. I forget how Snort twiddles with the byte placement precisely.

Also, that bitwiseand 0x3fff thingy is my own creation. byte_extract currently has no way to do bitmasking (which is a bitwise AND operation) to only extract out a few bits in a byte. I made the operand up.

PS, I have no packets available to actually test this. Maybe I can hack one together at some point and try it out.

share|improve this answer
    
    
Ahh, recursive pointers. Clever. Well, current Snort would be able to detect a recursive pointer using byte_extract and then testing the contents of the variable in a byte_test if my thinking is correct. But only on the lower byte of the two-byte pointer. Currently, byte_jump and byte_extract have no way to mask out the upper two bits of the high byte to drop the '11' from their calculations. So for small DNS packets, I think it is very possible to design a rule around this. –  Kumba May 31 '11 at 9:22
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.