cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
6646
Views
0
Helpful
10
Replies

Regular Expression Matching of Custom HTTP Headers - ASA 8.2(4)

lovedam
Level 1
Level 1

I have an application I have to support where there will be two custom HTTP headers inserted into the normal HTTP 1.1 message.  Let's call them "X-Header1" and "X-Header2."

I want to be able to allow only HTTP traffic that has these two headers (and the proper values) and drop everything else.

I've been reading about the default HTTP inspection that I can do, but when I look at inspecting the HTTP header, it appears I can only call a regular expression match against a known header.  I want to call the regex against the entire header and see if these two headers and values are present.  How can I accomplish this?

I am using 8.2(4).  I using the following tech note/document.

http://www.cisco.com/en/US/docs/security/asa/asa80/configuration/guide/inspect.html#wp1431359

>>To match text found in the HTTP request message header, or to restrict the count or length of the header, enter the following command:

>>hostname(config-cmap)# match [not] request header {[field] 
>>[regex [regex_name | class regex_class_name]] |  
>>[length gt max_length_bytes | count gt max_count_bytes]}

>>Where the field is the predefined message header keyword

the last line seems to indicate I would need to do it some other way?  perhaps just define a totally new class and regex against all traffic coming in on port 80?  wouldn't that just crush my throughput?

I am told that using a F5 box I can do this, but I would prefer to stick with using the firewall.

Thanks,

Damon

2 Accepted Solutions

Accepted Solutions

Hi Damon,

You can call your custom header class-map from a policy-map of type inspect http. Then, you just attach that custom policy to the inspection. Here's an example (assuming 10.1.1.1 is a trusted host who can make HTTP requests without the additional headers):

regex header1 "X-Header1"
regex header2 "X-Header2"
!
access-list whitelist extended deny tcp host 10.1.1.1 any eq www
access-list whitelist extended permit tcp any any eq www
!
class-map http-user-class
match access-list whitelist
class-map type inspect http match-any http-header-class
match request header regex header1 regex header1
match request header regex header2 regex header2
!
policy-map type inspect http http-policy
parameters
class http-header-class
  reset log
policy-map global_policy
class http-user-class
  inspect http http-policy
!
service-policy global_policy global

This document might also help answer some question you run across:

https://supportforums.cisco.com/docs/DOC-1268

Hope that helps.

-Mike

View solution in original post

Hi Damon,

I see what you're trying to do now, sorry about that. I misread your original post when you mentioned the header would contain "the proper values". I left out some of the config in my last post for what you're trying to do. Try this instead:

regex any ".*"
class-map type inspect http match-any http-header-class
match request header regex header1 regex any

The 2nd regex referenced in the match command should be the contents of the field matched by the first regex. What I configured should match any string, but for performance reasons you should make a more specific regex if possible.

Hope that helps.

-Mike

View solution in original post

10 Replies 10

mirober2
Cisco Employee
Cisco Employee

Hi Damon,

Give something like this a try:

regex header1 "X-Header1"
regex header2 "X-Header2"
class-map type inspect http match-any http-class
match request header regex header1 regex header1
match request header regex header2 regex header2

That should let you match the fields in the header using a custom regex. From there, you can just reference the http-class in your policy-map.

Hope that helps.

-Mike

Mike,

I have one additional criteria I will need for this map.  I have a whitelist of IPs that can make HTTP requests without the additional headers.  So, I need to check that either the traffic is from the whitelist ACL or that it has the header.  If one of the two isn't true I need to drop the traffic. 

So, I have the class map for the inspection of the header, but how do I classify traffic that *doesn't* meet the whitelist criteria as the only traffic for the HTTP inspection?

do I have to nest class-maps?  I've tried to add the whitelist ACL class-map to the header class-map and it won't let me. 

I have the class you had me create:

>>class-map type inspect http match-any http-class

and I created one:

class-map whitelist-http

match access-list whitelist_acl

however, I am not able to nest these inside another class-map, nor am I able to nest these in a polcy map.

Thanks,

Damon

Hi Damon,

You can call your custom header class-map from a policy-map of type inspect http. Then, you just attach that custom policy to the inspection. Here's an example (assuming 10.1.1.1 is a trusted host who can make HTTP requests without the additional headers):

regex header1 "X-Header1"
regex header2 "X-Header2"
!
access-list whitelist extended deny tcp host 10.1.1.1 any eq www
access-list whitelist extended permit tcp any any eq www
!
class-map http-user-class
match access-list whitelist
class-map type inspect http match-any http-header-class
match request header regex header1 regex header1
match request header regex header2 regex header2
!
policy-map type inspect http http-policy
parameters
class http-header-class
  reset log
policy-map global_policy
class http-user-class
  inspect http http-policy
!
service-policy global_policy global

This document might also help answer some question you run across:

https://supportforums.cisco.com/docs/DOC-1268

Hope that helps.

-Mike

Mike,

thanks for the help!

I have this implemented and it works, kinda... the whitelisted IPs work no problem in accessing the web server.  The non-whitelisted IPs don't work, however, no matter what I put into the regex command.  So, I tried an easy test and made the regex expression just look at a standard header ("User-Agent").  I can see from wireshark that that header is being sent out in my request.

Here is the simplified class-map and regex:

regex header1 "User-Agent"
!
class-map type inspect http match-any http-header-class
match request header regex header1 regex header1

!

In my testing I can see in the log that the inspection engine is dropping my request to the web server - (log says "terminated by inspection engine , reason - reset unconditionally").

So, I know the class-map is being executed, but I also know that in the packet capture that the header "User-Agent" is in the HTTP request.  Not sure where to go from here.  It seems like the regex isn't setup correct.

Thanks,

Damon

Hi Damon,

I see what you're trying to do now, sorry about that. I misread your original post when you mentioned the header would contain "the proper values". I left out some of the config in my last post for what you're trying to do. Try this instead:

regex any ".*"
class-map type inspect http match-any http-header-class
match request header regex header1 regex any

The 2nd regex referenced in the match command should be the contents of the field matched by the first regex. What I configured should match any string, but for performance reasons you should make a more specific regex if possible.

Hope that helps.

-Mike

Mike,

well... I am still getting the drops by the inspection engine.  I used the "Modify Headers" add-on for firefox and made a header named "damon" with a value of "100"  Here is my simple config.  It still won't match... at least it appears that way. I used the regex match for any value that you gave me.

I want to drop traffic if it doesn't have the header... I have tried every combination of "class-map match-all" "class-map match-any" coupled with "match" and "match not" statements and none works.  I have included a packet capture from the ASA to show that the header is coming through.

>>regex anymatch ".*"

>>regex damonheader "damon"

>>class-map type inspect http match-any akamai-hls-header-class

>> match request header regex damonheader regex anymatch

>>class-map hls-whitelist-class

>> match access-list hls-request-whitelist

>>policy-map type inspect http hls-http-policy

>> parameters

>> class akamai-hls-header-class

>>  reset log

policy-map global_policy

class inspection_default

  inspect dns preset_dns_map

  inspect ftp

  inspect h323 h225

  inspect h323 ras

  inspect ip-options

  inspect netbios

  inspect rsh

  inspect rtsp

  inspect skinny 

  inspect esmtp

  inspect sqlnet

  inspect sunrpc

  inspect tftp

  inspect sip 

  inspect xdmcp

class hls-whitelist-class

  inspect http hls-http-policy

3: 19:42:15.443336 67.111.135.8.3752 > 65.106.138.170.80: P 3722474074:3722474460(386) ack 1053130832 win 65535

0x0000   4500 01aa 5a93 4000 7d06 0b2f 436f 8708        E...Z.@.}../Co..

0x0010   416a 8aaa 0ea8 0050 dde0 725a 3ec5 8050        Aj.....P..rZ>..P

0x0020   5018 ffff 5c05 0000 4745 5420 2f41 4143        P...\...GET /AAC

0x0030   5f44 6174 612f 2048 5454 502f 312e 310d        _Data/ HTTP/1.1.

0x0040   0a48 6f73 743a 2036 352e 3130 362e 3133        .Host: 65.106.13

0x0050   382e 3137 300d 0a55 7365 722d 4167 656e        8.170..User-Agen

0x0060   743a 204d 6f7a 696c 6c61 2f35 2e30 2028        t: Mozilla/5.0 (

0x0070   5769 6e64 6f77 7320 4e54 2035 2e32 3b20        Windows NT 5.2;

0x0080   7276 3a32 2e30 2e31 2920 4765 636b 6f2f        rv:2.0.1) Gecko/

0x0090   3230 3130 3031 3031 2046 6972 6566 6f78        20100101 Firefox

0x00a0   2f34 2e30 2e31 0d0a 4163 6365 7074 3a20        /4.0.1..Accept:

0x00b0   7465 7874 2f68 746d 6c2c 6170 706c 6963        text/html,applic

0x00c0   6174 696f 6e2f 7868 746d 6c2b 786d 6c2c        ation/xhtml+xml,

0x00d0   6170 706c 6963 6174 696f 6e2f 786d 6c3b        application/xml;

0x00e0   713d 302e 392c 2a2f 2a3b 713d 302e 380d        q=0.9,*/*;q=0.8.

0x00f0   0a41 6363 6570 742d 4c61 6e67 7561 6765        .Accept-Language

0x0100   3a20 656e 2d75 732c 656e 3b71 3d30 2e35        : en-us,en;q=0.5

0x0110   0d0a 4163 6365 7074 2d45 6e63 6f64 696e        ..Accept-Encodin

0x0120   673a 2067 7a69 702c 2064 6566 6c61 7465        g: gzip, deflate

0x0130   0d0a 4163 6365 7074 2d43 6861 7273 6574        ..Accept-Charset

0x0140   3a20 4953 4f2d 3838 3539 2d31 2c75 7466        : ISO-8859-1,utf

0x0150   2d38 3b71 3d30 2e37 2c2a 3b71 3d30 2e37        -8;q=0.7,*;q=0.7

0x0160   0d0a 4b65 6570 2d41 6c69 7665 3a20 3131        ..Keep-Alive: 11

0x0170   350d 0a43 6f6e 6e65 6374 696f 6e3a 206b        5..Connection: k

0x0180   6565 702d 616c 6976 650d 0a64 616d 6f6e        eep-alive..damon

0x0190   3a20 3130 300d 0a74 6573 7431 313a 2032        : 100..test11: 2

0x01a0   3334 3933 3430 0d0a 0d0a                       349340....

Mike,

I have gotten this to work, but I can only block traffic when the header is present, not the other way around. 

Wouldn't I take this:

>>class-map type inspect http match-any akamai-hls-header-class

>> match request header regex damonheader regex anymatch

and either make it a "match not" statement?  I tried that and it has no affect.  Also, I tried making the class-map a "match-all" and that had no affect.

what special logic do I need?  I want to drop the packet when the "damonheader" is *not* in the HTTP packet...  The logic I have so far drops is when it is in the header.

Thanks,

DAmon

Mike,

What's weird is that I can get the example working where I can allow the user only to go to a specific URI.  I am guessing that perhaps becuase I am using a special header that the regex cannot be used in a "not" statement.

Thanks,

Damon

Mike,

I got this to work, but not using the regex commands I tried before.  Instead of this:

>>class-map type inspect http match-any akamai-hls-header-class

>> match request header regex damonheader regex anymatch

I used the header length greater than zero and this works.

class-map type inspect http match-any special-headers

match not request header regex Header1 count gt 0

match not request header regex Header2 count gt 0

so, when either doesn't have a length greater than zero it will drop the traffic.

Thanks very much for the help.

Damon

Mike,

I have had another requirement levied on me   I now need to create another rule to allow a HTTP request with a different set of headers.  Originally I had the rule such that both of these headers had to be present:

"X Header A 1"

"X Header A 2"

now I need to add a rule that says they request may also have these two headers (both must be present)

"X Header B 1"

"X Header B 2"

how do I make the inspection rule such that it is a "AND" for both headers of a type included but an "OR" on whether it is X Header A or X Header B?  Or do I chain rules together such that it is a fall through rule set?

Thanks,

Damon

Review Cisco Networking for a $25 gift card