ASA Application Inspection

  • Post author:
  • Post category:ASA / Cisco

The ASA inspection engine is required for services that embed IP addressing information in the user data packet or open secondary channels on dynamically assigned ports. Application Inspection uses the Modular Policy Framework to creates services policies, refer to this previous post for more information.

It is important to understand the ASA Order of Operations for connections.

  1. A TCP SYN packet is routed to the ASA to establish a new connection.
  2. The ASA checks the Access Control List (ACL) to determine if the connection is allowed.
  3. If allowed, an entry is created in the connection database (XLATE and CONN tables).
  4. The ASA checks the inspections database to determine if the connection requires application-level inspection.
  5. After the application inspection engine performs any actions, the ASA forwards the packet to the destination.
  6. The destination responds to the request.
  7. The ASA receives the reply packet, looks up the connection in the connections table and forwards the packet, as the packet belongs to an established session.

Application Inspection uses the following features:

  • An ACL to match the L3/L4 parameters of the traffic flow
  • Regular expressions to match conditions for use in class-maps
  • L3/L4 class-map to match the traffic flow, reference the ACL or regex
  • L5/L7 class-map to match the L7 application traffic, such as FTP commands (filename, filetype, server, username or request-command), regular expressions (regex) and HTTP response/request header/body etc
  • L5/L7 policy-map to inform the inspection engine of the type of action to take on the traffic that matches the L5/L7 class-map
  • L3/L4 policy-map implements the action in the L3/L4 class-map
  • A Service Policy enabled globally or per interface

This post covers some of the more common use cases for application inspection on the ASA.

FTP Inspection

FTP application inspection inspects the FTP connections and performs the following:

  • Prepare dynamic secondary data connections
  • Tracks the FTP commands
  • Generates and audit trail
  • Translates the embedded IP address

The following FTP commands can be matched in a policy:

  • APPE—Append to a file.
  • CDUP—Changes to the parent directory of the current working directory.
  • DELE—Delete a file on the server.
  • GET—Gets a file from the server.
  • HELP—Provides help information.
  • MKD—Makes a directory on the server.
  • PUT—Sends a file to the server.
  • RMD—Deletes a directory on the server.
  • RNFR—Specifies the “rename-from” filename.
  • RNTO—Specifies the “rename-to” filename.
  • SITE—Used to specify a server-specific command. This is usually used for remote administration.
  • STOU—Stores a file using a unique file name.

Regular Expressions (regex) can be used to match on the following:

  • Filetype
  • Filename
  • Server
  • Username

The following additional parameters can be set:

  • Mask-banner – masks the FTP server greeting banner
  • Mask-syst-reply – mass the reply to syst command

FTP Commands

In this scenario FTP connections only from a certain IP address will be allowed to upload files using FTP, the commands to download, rename or delete will be denied.

Create an ACL to match the traffic flow

access-list FTP-FROM-COMPANY-A extended permit tcp host 3.3.3.10 any

Create a L3/L4 class-map, to reference the ACL that matches the traffic flow

class-map FTP
 match access-list FTP-FROM-COMPANY-A

Create a L5/L7 policy-map that defines the parameters to be inspected.

policy-map type inspect ftp FTP-POL
 parameters
 match request-command appe get rnfr rnto dele
  reset

Create a L3/L4 policy-map which matches the L3/L4 class-map and inspects the parameters as defined in the L5/L7 policy-map.

policy-map OUTSIDE-POLICY
 class FTP
  inspect ftp strict FTP-POL

Enable the service-policy OUTSIDE-POLICY on the OUTSIDE interface.

service-policy OUTSIDE-POLICY interface OUTSIDE

In addition to the specific FTP inspection policy above, all other FTP connections will mask the FTP banner, this is applied using the global service-policy.

policy-map type inspect ftp MASK-BANNER
 parameters
  mask-banner
!
policy-map global_policy
 class inspection_default
  inspect ftp strict MASK-BANNER

Verification

Test connectivity to the FTP server prior to configuring the FTP inspection. From the screenshot below, notice the FTP banner is displayed.

Apply the FTP inspection as per the configuration above.

Connect to the FTP server from an IP address NOT defined in the ACL “FTP-FROM-COMPANY-A”.

Run show conn detail, from the screenshot below we can confirm the inbound connection is from 3.3.3.200 – which is not defined in the ACL.

From the screenshot below, notice there is now no banner displayed. Connectivity is tested by uploading (put) and downloading (get) some files, notice Transfer Complete.  This is correct, as the connection will match the global inspection policy, instead of the OUTSIDE interface policy. Only masking the banner is defined on the global policy.

Retest connectivity from the IP address as defined in the ACL “FTP-FROM-COMPANY-A”.

From the screenshot below, we notice the banner is displayed – this is because the interface service-policy is only blocking certain FTP commands. The mask-banner command is applied globally, which has no affect if the connection matches an interface service policy. Notice that put (upload) command completed successfully, but the get (download) failed and the connection is reset (closed), this confirms the interface service-policy worked as expected.

From the ASA CLI, run the command show service-policy interface OUTSIDE. From the screenshot below we can determine that the reset-drop counter has increased when the denied commands (get) are used, confirming that FTP inspection is working.

FTP Filename/Username

In this scenario the FTP commands username and filename will be combined in a policy which ensures that a specific user cannot download a specific file.

Create regular expressions (regex) objects are defined to match the filename and username.

regex FTP-FILE "secret.txt"
regex FTP-USER "user1"

Create a L5/L7 class-map matches both REGEX attributes above, to ensure the user called “user1” cannot download the file called “secret.txt”

class-map type inspect ftp match-all FTP-FILE-USER-CLASS
 match filename regex FTP-FILE
 match username regex FTP-USER

Create a L5/L7 policy-map matches the L5/L7 class-map, then resets and logs the connection.

policy-map type inspect ftp FTP-FILE-USER-POLICY
 parameters
  class FTP-FILE-USER-CLASS
   reset log

Create a L3/L4 class-map is created to match TCP/21 (FTP) traffic.

class-map FTP-CLASS
 match port tcp eq ftp

Create a L3/L4 policy-map references the L3/L4 class-map FTP-DENY and inspects FTP using the L5/L7 policy-map FTP-FILE-USER-POLICY.

policy-map OUTSIDE-POLICY
 class FTP-CLASS
  inspect ftp strict FTP-FILE-USER-POLICY

Enable the service-policy OUTSIDE-POLICY on the OUTSIDE interface.

service-policy OUTSIDE-POLICY interface OUTSIDE

Verification

Login to the FTP server as user1, run the command get secret.txt. From the output below we can confirm that user1 connected to the FTP server and when attempting to get the secret.txt file, the connection was reset.

On the ASA the following SYSLOG message is generated.

%ASA-5-303005: Strict FTP inspection matched Class 22: FTP-FILE-USER-CLASS in policy-map FTP-FILE-USER-POLICY, Reset connection from OUTSIDE_1:3.3.3.10/50732 to INSIDE:192.168.10.50/21

Run the command show service-policy interface OUTSIDE, from the screenshot below we can confirm that the counter for reset-drop is 3.

Any other user can login to the FTP server and download the secret.txt file.

HTTP Inspection

Basic HTTP inspection is used for protecting against some specific HTTP attacks, maintaining protocol conformance, and blocking URLs.

A L5/L7 class-map is used to match the following:

  • Traffic with a content-type field in the HTTP response that does not match the accepted field.
  • Text found in the HTTP request message arguments
  • Text found in the HTTP request message body or traffic that exceeds the maximum HTTP request message body length
  • Text found in the HTTP request message header or restrict the count or length of the header
  • Text found in the HTTP request message method
  • Text found in the HTTP request message URI
  • Text found in the HTTP response message body
  • Text found in the HTTP response message header
  • Text found in the HTTP response message status line

A L5/L7 policy-map is used to check for HTTP protocol violations.

HTTP URL Filtering

To test HTTP inspection, we will configure the following scenarios:

  • Match the HTTP message URI to deny any http traffic with the word’s malware or dodgy in anywhere in the URL.
  • Match the HTTP header host to deny http traffic to specific domain names.

Create regex expressions for traffic matching, that represents an exact domain www.specificdomain.com, to any domain ending *.domain.com, match the words malware and dodgy.

regex HTTP-DOMAIN-1 "www\.specificdomain\.com"
regex HTTP-DOMAIN-2 "[a-z]+\.domain\.com"
regex URI-MALWARE "malware"
regex URI-DODGY "dodgy"

Create a L5/L7 class-map to the header host (domain name of the web server) within the specified regex.

class-map type inspect http match-any HTTP-DOMAIN
 match request header host regex HTTP-DOMAIN-1
 match request header host regex HTTP-DOMAIN-2

Create a L5/L7 class-map to match the http URI as specified within the regex.

class-map type inspect http match-any HTTP-URI
 match request uri regex URI-MALWARE
 match request uri regex URI-DODGY

Create a L5/L7 policy-map to reference the L5/L7 class-maps, resetting and logging connections if matched.

policy-map type inspect http HTTP-POLICY
 parameters
class HTTP-DOMAIN
 reset log
class HTTP-URI
 reset log

Create a L3/L4 policy-map, inspecting http and referencing the L5/L7 policy-map.

policy-map OUTSIDE-POLICY
 class HTTP
  inspect http HTTP-POLICY

Enable a service-policy on the OUTSIDE interface.

service-policy OUTSIDE-POLICY interface OUTSIDE

Verification

From a test computer we will generate traffic, making a connection attempt to www.domain.com. The screenshot below confirms the connection attempt was reset by peer (the ASA).

The output below represents the ASA log messages, which confirms the connection attempt matched the HTTP-POLICY and the connection was reset.

%ASA-6-302013: Built inbound TCP connection 348 for OUTSIDE_1:3.3.3.10/35998 (3.3.3.10/35998) to INSIDE:192.168.10.5/80 (1.1.1.5/80)
%ASA-5-415008: HTTP - matched Class 27: HTTP-DOMAIN in policy-map HTTP-POLICY, header matched - Resetting connection from OUTSIDE_1:3.3.3.10/35998 to INSIDE: 192.168.10.5/80
%ASA-5-304001: 3.3.3.10 Accessed URL 192.168.10.5:http://www.domain.com/

Making another http request to another website to www.domain.co.uk, this time the connection was successful and was NOT reset.

The output below confirms the connection was established and the URL was accessed successfully.

%ASA-6-302013: Built inbound TCP connection 349 for OUTSIDE_1:3.3.3.10/36000 (3.3.3.10/36000) to INSIDE:192.168.10.5/80 (1.1.1.5/80)
%ASA-5-304001: 3.3.3.10 Accessed URL 192.168.10.5:http://www.domain.co.uk/
%ASA-6-302014: Teardown TCP connection 349 for OUTSIDE_1:3.3.3.10/36000 to INSIDE:192.168.10.5/80 duration 0:00:00 bytes 1096 TCP FINs from OUTSIDE_1

Accessing the same URL but this time with a keyword of malware in the URL – http://www.domain.co.uk/malware the connection is reset.

The output below confirms the request to www.domain.co.uk/malware, the connection matched the HTTP-URI defined in the HTTP-POLICY and the connection was reset.

%ASA-6-302013: Built inbound TCP connection 351 for OUTSIDE_1:3.3.3.10/36004 (3.3.3.10/36004) to INSIDE:192.168.10.5/80 (1.1.1.5/80)
%ASA-5-304001: 3.3.3.10 Accessed URL 192.168.10.5:http://www.domain.co.uk/malware
%ASA-5-415006: HTTP - matched Class 30: HTTP-URI in policy-map HTTP-POLICY, URI matched - Resetting connection from OUTSIDE_1:3.3.3.10/36004 to INSIDE:192.168.10.5/80

HTTP Protocol Violation

HTTP Inspection can verify that HTTP messages confirm to RFC 2616, if they do not the connection can be dropped.

Modify the existing L5/L7 policy-map to add protocol-violation action drop-connection log

policy-map type inspect http HTTP-POLICY
 parameters
  protocol-violation action drop-connection log
class HTTP-POLICY
 reset log
class HTTP-URI
 reset log

Verification

To test HTTP protocol violation telnet to a webserver behind the ASA on port 80. The connection may well be tcp/80, but this is not a proper formatted HTTP connection request.

The ASA will display the following messages, which confirms the connection violated the HTTP-POLICY and the connection is dropped.

%ASA-5-415011: HTTP - policy-map HTTP-POLICY:Protocol violation - Dropping connection from OUTSIDE_1:3.3.3.1/43682 to INSIDE:192.168.10.5/80
%ASA-4-507003: tcp flow from OUTSIDE_1:3.3.3.1/43682 to INSIDE:192.168.10.5/80 terminated by inspection engine, reason - disconnected, dropped packet.

HTTP User Agent

HTTP inspection can match against the user-agent, which is the software agent used to make the connection request. The user-agent is a web browser or application such as Firefox, Chrome or a CLI application such as curl. In this scenario, the curl user-agent will be denied, with connection request reset.

Create a regular expression defining the user-agent

regex HTTP-USER-AGENT "curl"

Create a L5/L7 class-map to inspect http to match the regex previously created

class-map type inspect http match-all HTTP-USER-AGENT
 match request header user-agent regex HTTP-USER-AGENT

Modify the L5/L7 policy-map to reference the class-map for the user-agent and reset the connection.

policy-map type inspect http HTTP-POLICY
 parameters
  protocol-violation action drop-connection log
class HTTP-POLICY
 reset log
class HTTP-URI
 reset log
class HTTP-USER-AGENT
 reset log

Verification

From a ubuntu linux device we run curl to establish a connection to the webserver behind the ASA.

The ASA logs confirm the connection matched the HTTP-USER-AGENT class-map, defined in the HTTP-POLICY and the connection was reset.

ASA-1# %ASA-6-302013: Built inbound TCP connection 39 for OUTSIDE_1:3.3.3.1/49580 (3.3.3.1/49580) to INSIDE:192.168.10.5/80 (1.1.1.5/80)
ASA-1# %ASA-5-415008: HTTP - matched Class 31: HTTP-USER-AGENT in policy-map HTTP-POLICY, header matched - Resetting connection from OUTSIDE_1:3.3.3.1/49580 to INSIDE: 192.168.10.5/80
%ASA-5-304001: 3.3.3.1 Accessed URL 192.168.10.5:http://www.domain.co.uk/

Enabling debugs using the command debug appfw event and debug appfw regex provides more useful information. From the output below we can confirm the User-Agent is curl (matching the class-map), we can confirm a regex match and the connection was reset.

sapi_inspect_http: ====== Opening New Connection 10264A80 =====
10264A80:request:before deobfuscation httpState=sHTTP_START saveState=sHTTP_START matchState=0
data|GET / HTTP/1.1..Host: www.domain.co.uk..User-Agent: curl/7.58.0..Accept: */*....| Len:80 Req#:0
0x00007f2010264a80:request:Deobfuscated 75 bytes
0x00007f2010264a80:Number of outstanding requests=1
10264A80:request:After deobfuscate httpState=sHTTP_FINAL  matchState=103 meth=2
URI=/
Header=.Host: www.domain.co.uk.User-Agent: curl/7.58.0.Accept: */*
URI Len:1 ARG Len:0 HDR Len:68

request:Matched on header name/value - No match
request:Matched on header name/value - Match regex:27,

0x00007f2010264a80:appfw_action:syslogID:5415008
0x00007f2010264a80:Trying to Match on URI
request: Check URI - No match
0x00007f2010264a80:request:>>>Reset!
%ASA-6-302014: Teardown TCP connection 46 for OUTSIDE_1:3.3.3.1/49606 to INSIDE:192.168.10.5/80 duration 0:00:00 bytes 0 Flow closed by inspection
inspectHttp: ======== Closing Connection 10264A80 =======!!

Repeat the same test this time instead of using curl, we shall use Firefox user-agent to browse to www.domain.co.uk. From the output below, we can confirm the User-Agent is Firefox and no match against the user-agent class-map, therefore the connection is allowed.

%ASA-6-302013: Built inbound TCP connection 48 for OUTSIDE_1:3.3.3.11/39018 (3.3.3.11/39018) to INSIDE:192.168.10.5/80 (1.1.1.5/80)
%ASA-5-304001: 3.3.3.11 Accessed URL 192.168.10.5:http://www.domain.co.uk/favicon.ico
sapi_inspect_http: ====== Opening New Connection 10263F40 =====
10263F40:request:before deobfuscation httpState=sHTTP_START saveState=sHTTP_START matchState=0
data|GET /favicon.ico HTTP/1.1..Host: www.domain.co.uk..User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0..Accept: image/webp,*/*..Accept-Language: en-GB,en;q=0.5..Accept-Encoding: gzip, deflate..DNT: 1..Connection: keep-alive..Pragma: no-cache..Cache-Control: no-cache....| Len:307 Req#:0

0x00007f2010263f40:request:Deobfuscated 296 bytes
0x00007f2010263f40:Number of outstanding requests=1
10263F40:request:After deobfuscate httpState=sHTTP_FINAL  matchState=12 meth=2
URI=/favicon.ico
Header=.Host: www.domain.co.uk.User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0.Accept: image/
URI Len:12 ARG Len:0 HDR Len:290

request:Matched on header name/value - No match
request:Matched on header name/value - No match

0x00007f2010263f40:Trying to Match on URI
request: Check URI - No match

0x00007f2010263f40:request:Forwarding - no action

10263F40:response:before deobfuscation httpState=sHTTP_START saveState=sHTTP_START matchState=0
data|HTTP/1.1 404 Not Found..Content-Type: text/html..Server: Microsoft-IIS/7.5..X-Powered-By: ASP.NET..Date: Fri, 03 Jun 2022 09:34:19 GMT..Content-Length: 1245....<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">..<html xmlns="http://www.w3.org/1999/xhtml">..<head>..<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>..<title>404 - File or directory not found.</title>..<style type="text/css">..<!--..body{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}..fieldset{padding:0 15px 10px 15px;} ..h1{font-size:2.4em;margin:0;color:#FFF;}..h2{font-size:1.7em;margin:0;color:#CC0000;} ..h3{font-size:1.2em;margin:10px 0 0 0;color:#000000;} ..#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS", Verdana, sans-serif;color:#FFF;..background-color:#555555;}..#content{margin:0 0 0 2%;position:relative;}...content-container{background:#FFF;width:96%;margin-top:8px;pad| Len:1368 Rsp#:0

0x00007f2010263f40:response:Deobfuscated 1361 bytes

10263F40:Seeing response corresponding to request: 0   Outstanding requests:0
10263F40:response:after deobfuscation httpState=sHTTP_BODY matchState=42

0x00007f2010263f40:response:Searching Header
0x00007f2010263f40:response:Forwarding - no action
0x00007f2010263f40:response:Forwarding - no body processing
0x00007f2010264a80:response:Forwarding - no body processing
0x00007f2010264a80:response:Forwarding - no body processing
0x00007f2010264a80:response:Forwarding - no body processing
0x00007f2010264a80:response:Forwarding - no body processing
0x00007f2010264a80:response:Forwarding - no body processing
0x00007f2010264a80:response:Forwarding - no body processing
%ASA-6-302014: Teardown TCP connection 48 for OUTSIDE_1:3.3.3.11/39018 to INSIDE:192.168.10.5/80 duration 0:00:03 bytes 1712 TCP FINs from OUTSIDE_1
inspectHttp: ======== Closing Connection 10263F40 =======!!

SNMP

SNMP application inspection lets you restrict specific SNMP versions, denying less secure versions such as v1, v2 and v2c, whilst permitting SNMPv3.

Define an SNMP map and specify which version to deny

snmp-map SNMP-MAP
 deny version 1
 deny version 2c
 deny version 2

Create a L3/L4 class-map to match SNMP traffic (udp/161).

class-map SNMP
 match port udp eq snmp

Create a L3/L4 policy-map to reference the L3/L4 class-map and inspect snmp traffic, referencing the SNMP map.

policy-map INSIDE
 class SNMP
  inspect snmp SNMP-MAP

Enable the service-policy on the INSIDE interface.

service-policy INSIDE interface INSIDE

Verification

For SNMP testing we can use an SNMP MIB Walker application such as AdREM SNMP Walker.

Generate traffic through the ASA and use SNMP walker to test SNMPv1 and/or v2.

With the service policy configured to drop SNMP v1 and v2, the test will fail.

From the ASA CLI, run the command show service-policy interface INSIDE. From the output below we can confirm 3 packets and 3 drops.

Repeat the test using SNMPv3, testing will succeed with the SNMP walker able to scan the OIDs.

The output of the command show service-policy interface INSIDE confirms 2259 packets and no additional drops (the 3 drops are from the previous testing).

Templates

The FTP and HTTP Inspection configuration commands can be found in the templates section of this website.

References

https://www.cisco.com/c/en/us/support/docs/security/asa-5500-x-series-next-generation-firewalls/100535-asa-8x-regex-config.html

https://www.cisco.com/c/en/us/support/docs/security/adaptive-security-appliance-asa-software/115998-asa-http-product-configuration-example-00.html

https://docs.pexip.com/admin/regex_reference.htm