DCE/RPC 2 Preprocessor

The main purpose of the preprocessor is to perform SMB desegmentation and DCE/RPC defragmentation to avoid rule evasion using these techniques. SMB desegmentation is p"/>

Snort FAQ

README.dcerpc2

DCE/RPC 2 Preprocessor

The main purpose of the preprocessor is to perform SMB desegmentation and DCE/RPC defragmentation to avoid rule evasion using these techniques. SMB desegmentation is performed for the following commands that can be used to transport DCE/RPC requests and responses: Write, Write Block Raw, Write and Close, Write AndX, Transaction, Transaction Secondary, Read, Read Block Raw and Read AndX. The following transports are supported for DCE/RPC: SMB, TCP, UDP and RPC over HTTP v.1 proxy and server. New rule options have been implemented to improve performance, reduce false positives and reduce the count and complexity of DCE/RPC based rules.

Sections: Dependency Requirements Target Based Configuration Events Rule Options

Dependency Requirements

For proper functioning of the preprocessor: The dcerpc preprocessor (the initial iteration) must be disabled. Stream session tracking must be enabled, i.e. stream5. The preprocessor requires a session tracker to keep its data. Stream reassembly must be performed for TCP sessions. If it is decided that a session is SMB or DCE/RPC, either through configured ports, servers or autodetecting, the dcerpc2 preprocessor will enable stream reassembly for that session if necessary. IP defragmentation should be enabled, i.e. the frag3 preprocessor should be enabled and configured.

Target Based

There are enough important differences between Windows and Samba versions that a target based approach has been implemented. Some important differences:

Named pipe instance tracking A combination of valid login handle or UID, share handle or TID and file/named pipe handle or FID must be used to write data to a named pipe. The binding between these is dependent on OS/software version. Samba 3.0.22 and earlier Any valid UID and TID, along with a valid FID can be used to make a request, however, if the TID used in creating the FID is deleted (via a tree disconnect), the FID that was created using this TID becomes invalid, i.e. no more requests can be written to that named pipe instance. Samba greater than 3.0.22 Any valid TID, along with a valid FID can be used to make a request. However, only the UID used in opening the named pipe can be used to make a request using the FID handle to the named pipe instance. If the TID used to create the FID is deleted (via a Tree Disconnect), the FID that was created using this TID becomes invalid, i.e. no more requests can be written to that named pipe instance. If the UID used to create the named pipe instance is deleted (via a Logoff AndX), since it is necessary in making a request to the named pipe, the FID becomes invalid. Windows 2003 Windows XP Windows Vista These Windows versions require strict binding between the UID, TID and FID used to make a request to a named pipe instance. Both the UID and TID used to open the named pipe instance must be used when writing data to the same named pipe instance. Therefore, deleting either the UID or TID invalidates the FID. Windows 2000 Windows 2000 is interesting in that the first request to a named pipe must use the same binding as that of the other Windows versions. However, requests after that follow the same binding as Samba 3.0.22 and earlier, i.e. no binding. It also follows Samba greater than 3.0.22 in that deleting the UID or TID used to create the named pipe instance also invalidates it. Accepted SMB commands Samba in particular does not recognize certain commands under an IPC$ tree. Samba (all versions) Under an IPC$ tree, does not accept: Open Write And Close Read Read Block Raw Write Block Raw Windows (all versions) Accepts all of the above commands under an IPC$ tree. AndX command chaining Windows is very strict in what command combinations it allows to be chained. Samba, on the other hand, is very lax and allows some nonsensical combinations, e.g. multiple logins and tree connects (only one place to return handles for these), login/logoff and tree connect/tree disconnect. Ultimately, we don’t want to keep track of data that the server won’t accept. An evasion possibility would be accepting a fragment in a request that the server won’t accept that gets sandwiched between an exploit. Transaction tracking The differences between a Transaction request and using one of the Write* commands to write data to a named pipe are that (1) a Transaction performs the operations of a write and a read from the named pipe, whereas in using the Write* commands, the client has to explicitly send one of the Read* requests to tell the server to send the response and (2) a Transaction request is not written to the named pipe until all of the data is received (via potential Transaction Secondary requests) whereas with the Write* commands, data is written to the named pipe as it is received by the server. Multiple Transaction requests can be made simultaneously to the same named pipe. These requests can also be segmented with Transaction Secondary commands. What distinguishes them (when the same named pipe is being written to, i.e. having the same FID) are fields in the SMB header representing a process id (PID) and multiplex id (MID). The PID represents the process this request is a part of. An MID represents different sub-processes within a process (or under a PID). Segments for each “thread” are stored separately and written to the named pipe when all segments are received. It is necessary to track this so as not to munge these requests together (which would be a potential evasion opportunity). Windows (all versions) Uses a combination of PID and MID to define a “thread”. Samba (all versions) Uses just the MID to define a “thread”. Multliple Bind requests A Bind request is the first request that must be made in a connection-oriented DCE/RPC session in order to specify the interface/interfaces that one wants to communicate with. Windows (all versions) For all of the Windows versions, only one Bind can ever be made on a session whether or not it succeeds or fails. Any binding after that must use the Alter Context request. If another Bind is made, all previous interface bindings are invalidated. Samba 3.0.20 and earlier Any amount of Bind requests can be made. Samba later than 3.0.20 Another Bind request can be made if the first failed and no interfaces were successfully bound to. If a Bind after a successful Bind is made, all previous interface bindings are invalidated. DCE/RPC Fragmented requests - Context ID Each fragment in a fragmented request carries the context id of the bound interface it wants to make the request to. Windows (all versions) The context id that is ultimately used for the request is contained in the first fragment. The context id field in any other fragment can contain any value. Samba (all versions) The context id that is ultimately used for the request is contained in the last fragment. The context id field in any other fragment can contain any value. DCE/RPC Fragmented requests - Operation number Each fragment in a fragmented request carries an operation number (opnum) which is more or less a handle to a function offered by the interface. Samba (all versions) Windows 2000 Windows 2003 Windows XP The opnum that is ultimately used for the request is contained in the last fragment. The opnum field in any other fragment can contain any value. Windows Vista The opnum that is ultimately used for the request is contained in the first fragment. The opnum field in any other fragment can contain any value. DCE/RPC Stub data byte order The byte order of the stub data is determined differently for Windows and Samba. Windows (all versions) The byte order of the stub data is that which was used in the Bind request. Samba (all versions) The byte order of the stub data is that which is used in the request carrying the stub data.

Configuration

The dcerpc2 preprocessor has a global configuration and one or more server configurations. The global preprocessor configuration name is dcerpc2 and the server preprocessor configuration name is dcerpc2_server.

Global configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ preprocessor dcerpc2

The global dcerpc2 configuration is required. Only one global dcerpc2 configuration can be specified.

Option syntax Option Argument Required Default —————————————————————————- memcap NO memcap 102400 disable_defrag NONE NO OFF max_frag_len NO OFF events NO OFF reassemble_threshold NO OFF disabled NONE NO OFF smb_fingerprint_policy NO OFF

memcap           = 1024-4194303 (kilobytes)
max-frag-len     = 1514-65535
events           = pseudo-event | event | '[' event-list ']'
pseudo-event     = "none" | "all"
event-list       = event | event ',' event-list
event            = "memcap" | "smb" | "co" | "cl"
re-thresh        = 0-65535
fp-policy        = "server" | "client" | "both"

Option explanations memcap Specifies the maximum amount of run-time memory that can be allocated. Run-time memory includes any memory allocated after configuration. Default is 100 MB. disabled This optional keyword is allowed with any policy to avoid packet processing. This option disables the preprocessor. When the preprocessor is disabled only the memcap option is applied when specified with the configuration. The other options are parsed but not used. Any valid configuration may have “disabled” added to it. disable_defrag Tells the preprocessor not to do DCE/RPC defragmentation. Default is to do defragmentation. max_frag_len Specifies the maximum fragment size that will be added to the defragmentation module. If a fragment is greater than this size, it is truncated before being added to the defragmentation module. The allowed ranges for this option are 1514 - 65535. events Specifies the classes of events to enable. (See Events section for an enumeration and explanation of events.) memcap Only one event. If the memcap is reached or exceeded, alert. smb Alert on events related to SMB processing. co Stands for connection-oriented DCE/RPC. Alert on events related to connection-oriented DCE/RPC processing. cl Stands for connectionless DCE/RPC. Alert on events related to connectionless DCE/RPC processing. reassemble_threshold Specifies a minimum number of bytes in the DCE/RPC desegmentation and defragmentation buffers before creating a reassembly packet to send to the detection engine. This option is useful in inline mode so as to potentially catch an exploit early before full defragmentation is done. A value of 0 supplied as an argument to this option will, in effect, disable this option. Default is disabled. smb_fingerprint_policy In the initial phase of an SMB session, the client needs to authenticate with a SessionSetupAndX. Both the request and response to this command contain OS and version information that can allow the preprocessor to dynamically set the policy for a session which allows for better protection against Windows and Samba specific evasions.

Option examples memcap 30000 max_frag_len 16840 events none events all events smb events co events [co] events [smb, co] events [memcap, smb, co, cl] reassemble_threshold 500 smb_fingerprint_policy both smb_fingerprint_policy client

Configuration examples preprocessor dcerpc2 preprocessor dcerpc2: memcap 500000 preprocessor dcerpc2: max_frag_len 16840, memcap 300000, events smb preprocessor dcerpc2: memcap 50000, events [memcap, smb, co, cl], \ max_frag_len 14440 preprocessor dcerpc2: disable_defrag, events [memcap, smb] preprocessor dcerpc2: reassemble_threshold 500 preprocessor dcerpc2: memcap 50000, events [memcap, smb, co, cl], \ max_frag_len 14440, smb_fingerprint_policy both

Default configuration preprocessor dcerpc2: memcap 102400

Server Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ preprocessor dcerpc2_server

The dcerpc2_server configuration is optional. A dcerpc2_server configuration must start with default or net options. The default and net options are mutually exclusive. At most one default configuration can be specified. If no default configuration is specified, default values will be used for the default configuration. Zero or more net configurations can be specified. For any dcerpc2_server configuration, if non-required options are not specified, the defaults will be used. When processing DCE/RPC traffic, the default configuration is used if no net configurations match. If a net configuration matches, it will override the default configuration. A net configuration matches if the packet’s server IP address matches an IP address or net specified in the net configuration. The net option supports IPv6 addresses. Note that port and ip variables defined in snort.conf CANNOT be used.

Option syntax Option Argument Required Default —————————————————————————- default NONE YES NONE net YES NONE policy NO policy WinXP detect NO detect \ [smb [139,445], \ tcp 135, udp 135, \ rpc-over-http-server 593] autodetect NO autodetect \ [tcp 1025:, udp 1025:, \ rpc-over-http-server 1025:] no_autodetect_http_proxy_ports NONE NO DISABLED (The preprocessor autodetects on all proxy ports by default) smb_invalid_shares NO NONE smb_max_chain NO smb_max_chain 3 smb_file_inspection NO smb_file_inspection off

net          = ip | '[' ip-list ']'
ip-list      = ip | ip ',' ip-list
ip           = ip-addr | ip-addr '/' prefix | ip4-addr '/' netmask
ip-addr      = ip4-addr | ip6-addr
ip4-addr     = a valid IPv4 address
ip6-addr     = a valid IPv6 address (can be compressed)
prefix       = a valid CIDR
netmask      = a valid netmask
policy       = "Win2000" | "Win2003" | "WinXP" | "WinVista" |
               "Samba" | "Samba-3.0.22" | "Samba-3.0.20"
detect       = "none" | detect-opt | '[' detect-list ']'
detect-list  = detect-opt | detect-opt ',' detect-list
detect-opt   = transport | transport port-item | 
               transport '[' port-list ']'
transport    = "smb" | "tcp" | "udp" | "rpc-over-http-proxy" | 
               "rpc-over-http-server"
port-list    = port-item | port-item ',' port-list
port-item    = port | port-range
port-range   = ':' port | port ':' | port ':' port
port         = 0-65535
shares       = share | '[' share-list ']'
share-list   = share | share ',' share-list
share        = word | '"' word '"' | '"' var-word '"'
word         = graphical ascii characters except ',' '"' ']' '[' '$'
var-word     = graphical ascii characters except ',' '"' ']' '['

Because the Snort main parser treats '$' as the start of a variable and
tries to expand it, shares with '$' must be enclosed quotes.

max-chain    = 0-255
file-inspect = file-arg | '[' file-list ']'
file-arg     = "off" | "on" | "only" 
file-list    = file-arg [ ',' "file-depth" <int64_t> ]

Option explanations default Specifies that this configuration is for the default server configuration. net Specifies that this configuration is an IP or net specific configuration. The configuration will only apply to the IP addresses and nets supplied as an argument. policy Specifies the target-based policy to use when processing. Default is “WinXP”. detect Specifies the DCE/RPC transport and server ports that should be detected on for the transport. Defaults are ports 139 and 445 for SMB, 135 for TCP and UDP, 593 for RPC over HTTP server and 80 for RPC over HTTP proxy. autodetect Specifies the DCE/RPC transport and server ports that the preprocessor should attempt to autodetect on for the transport. The autodetect ports are only queried if no detect transport/ports match the packet. The order in which the preprocessor will attempt to autodetect will be - TCP/UDP, RPC over HTTP server, RPC over HTTP proxy and lastly SMB. Note that most dynamic DCE/RPC ports are above 1024 and ride directly over TCP or UDP. It would be very uncommon to see SMB on anything other than ports 139 and 445. Defaults are 1025-65535 for TCP, UDP and RPC over HTTP server. no_autodetect_http_proxy_ports By default, the preprocessor will always attempt to autodetect for ports specified in the detect configuration for rpc-over-http-proxy. This is because the proxy is likely a web server and the preprocessor should not look at all web traffic. This option is useful if the RPC over HTTP proxy configured with the detect option is only used to proxy DCE/RPC traffic. Default is to autodetect on RPC over HTTP proxy detect ports. smb_invalid_shares Specifies SMB shares that the preprocessor should alert on if an attempt is made to connect to them via a Tree Connect or Tree Connect AndX. Default is empty. smb_max_chain Specifies the maximum amount of AndX command chaining that is allowed before an alert is generated. Default maximum is 3 chained commands. A value of 0 disables this option. smb_file_inspection Instructs the preprocessor to do inspection of normal SMB file transfers. This includes doing file type and signature through the file API as well as setting a pointer for the “file_data” rule option. Note that the “file-depth” option only applies to the maximum amount of file data for which it will set the pointer for the “file_data” rule option. For file type and signature it will use the value configured for the file API. If “only” is specified, the preprocessor will only do SMB file inspection, i.e. it will not do any DCE/RPC tracking or inspection. If “on” is specified with no arguments, the default file depth is 16384 bytes. An argument of -1 to “file-depth” disables setting the pointer for “file_data”, effectively disabling SMB file inspection in rules. An argument of 0 to “file-depth” means unlimited. Default is “off”, i.e. no SMB file inspection is done in the preprocessor.

Option examples net 192.168.0.10 net 192.168.0.0/24 net [192.168.0.0/24] net 192.168.0.0/255.255.255.0 net feab:45b3:ab92:8ac4:d322:007f:e5aa:7845 net feab:45b3:ab92:8ac4:d322:007f:e5aa:7845/128 net feab:45b3::/32 net [192.168.0.10, feab:45b3::/32] net [192.168.0.0/24, feab:45b3:ab92:8ac4:d322:007f:e5aa:7845] policy Win2000 policy Samba-3.0.22 detect none detect smb detect [smb] detect smb 445 detect [smb 445] detect smb [139,445] detect [smb [139,445]] detect [smb, tcp] detect [smb 139, tcp [135,2103]] detect [smb [139,445], tcp 135, udp 135, \ rpc-over-http-server [593,6002:6004]] autodetect none autodetect tcp autodetect [tcp] autodetect tcp 2025: autodetect [tcp 2025:] autodetect tcp [2025:3001,3003:] autodetect [tcp [2025:3001,3003:]] autodetect [tcp, udp] autodetect [tcp 2025:, udp 2025:] autodetect [tcp 2025:, udp, rpc-over-http-server [1025:6001,6005:]] smb_invalid_shares private smb_invalid_shares “private” smb_invalid_shares “C$” smb_invalid_shares [private, “C$”] smb_invalid_shares [“private”, “C$”] smb_max_chain 1 smb_file_inspection on smb_file_inspection off smb_file_inspection [ on, file-depth -1 ] smb_file_inspection [ on, file-depth 0 ] smb_file_inspection [ on, file-depth 4294967296 ] smb_file_inspection [ only, file-depth -1 ]

Configuration examples preprocessor dcerpc2_server: default preprocessor dcerpc2_server: default, policy Win2000 preprocessor dcerpc2_server: default, policy Win2000, detect [smb, tcp], \ autodetect tcp 1025:, smb_invalid_shares [“C$”, “D$”, “ADMIN$”] preprocessor dcerpc2_server: net 10.4.10.0/24, policy Win2000 preprocessor dcerpc2_server: net [10.4.10.0/24,feab:45b3::/126], \ policy WinVista, smb_max_chain 1 preprocessor dcerpc2_server: net [10.4.10.0/24,feab:45b3::/126], \ policy WinVista, detect [smb, tcp, rpc-over-http-proxy 8081], \ autodetect [tcp, rpc-over-http-proxy [1025:6001,6005:]], \ smb_invalid_shares [“C$”, “ADMIN$”], no_autodetect_http_proxy_ports preprocessor dcerpc2_server: net [10.4.11.56,10.4.11.57], policy Samba, \ detect smb, autodetect none preprocessor dcerpc2_server: default, policy WinXP, \ smb_file_inspection [ on, file-depth 0 ]

Default configuration preprocessor dcerpc2_server: default, policy WinXP, \ detect [smb [139,445], tcp 135, udp 135, rpc-over-http-server 593], \ autodetect [tcp 1025:, udp 1025:, rpc-over-http-server 1025:], \ smb_max_chain 3, smb_file_inspection off

Complete dcerpc2 default configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ preprocessor dcerpc2: memcap 102400 preprocessor dcerpc2_server: default, policy WinXP, \ detect [smb [139,445], tcp 135, udp 135, rpc-over-http-server 593], \ autodetect [tcp 1025:, udp 1025:, rpc-over-http-server 1025:], \ smb_max_chain 3, smb_file_inspection off

Events

The preprocessor uses GID 133 to register events.

Memcap events SID Description ——————————————————————————– 1 If the memory cap is reached and the preprocessor is configured to alert.

SMB events SID Description ——————————————————————————– 2 An invalid NetBIOS Session Service type was specified in the header. Valid types are: Message, Request (only from client), Positive Response (only from server), Negative Response (only from server), Retarget Response (only from server) and Keep Alive. 3 An SMB message type was specified in the header. Either a request was made by the server or a response was given by the client. 4 The SMB id does not equal “\xffSMB”. Note that since the preprocessor does not yet support SMB2, id of “\xfeSMB” is turned away before an eventable point is reached. 5 The word count of the command header is invalid. SMB commands have pretty specific word counts and if the preprocessor sees a command with a word count that doesn’t jive with that command, the preprocessor will alert. 6 Some commands require a minimum number of bytes after the command header. If a command requires this and the byte count is less than the minimum required byte count for that command, the preprocessor will alert. 7 Some commands, especially the commands from the SMB Core implementation require a data format field that specifies the kind of data that will be coming next. Some commands require a specific format for the data. The preprocessor will alert if the format is not that which is expected for that command. 8 Many SMB commands have a field containing an offset from the beginning of the SMB header to where the data the command is carrying starts. If this offset puts us before data that has already been processed or after the end of payload, the preprocessor will alert. 9 Some SMB commands, such as Transaction, have a field containing the total amount of data to be transmitted. If this field is zero, the preprocessor will alert. 10 The preprocessor will alert if the NetBIOS Session Service length field contains a value less than the size of an SMB header. 11 The preprocessor will alert if the remaining NetBIOS packet length is less than the size of the SMB command header to be decoded. 12 The preprocessor will alert if the remaining NetBIOS packet length is less than the size of the SMB command byte count specified in the command header. 13 The preprocessor will alert if the remaining NetBIOS packet length is less than the size of the SMB command data size specified in the command header. 14 The preprocessor will alert if the total data count specified in the SMB command header is less than the data size specified in the SMB command header. (Total data count must always be greater than or equal to current data size.) 15 The preprocessor will alert if the total amount of data sent in a transaction is greater than the total data count specified in the SMB command header. 16 The preprocessor will alert if the byte count specified in the SMB command header is less than the data size specified in the SMB command. (The byte count must always be greater than or equal to the data size.) 17 Some of the Core Protocol commands (from the initial SMB implementation) require that the byte count be some value greater than the data size exactly. The preprocessor will alert if the byte count minus a predetermined amount based on the SMB command is not equal to the data size. 18 For the Tree Connect command (and not the Tree Connect AndX command), the preprocessor has to queue the requests up and wait for a server response to determine whether or not an IPC share was successfully connected to (which is what the preprocessor is interested in). Unlike the Tree Connect AndX response, there is no indication in the Tree Connect response as to whether the share is IPC or not. There should be under normal circumstances no more than a few pending tree connects at a time and the preprocessor will alert if this number is excessive. 19 After a client is done writing data using the Write* commands, it issues a Read* command to the server to tell it to send a response to the data it has written. In this case the preprocessor is concerned with the server response. The Read* request contains the file id associated with a named pipe instance that the preprocessor will ultimately send the data to. The server response, however, does not contain this file id, so it need to be queued with the request and dequeued with the response. If multiple Read* requests are sent to the server, they are responded to in the order they were sent. There should be under normal circumstances no more than a few pending Read* requests at a time and the preprocessor will alert if this number is excessive. 20 The preprocessor will alert if the number of chained commands in a single request is greater than or equal to the configured amount (default is 3). 21 With AndX command chaining it is possible to chain multiple Session Setup AndX commands within the same request. There is, however, only one place in the SMB header to return a login handle (or Uid). Windows does not allow this behavior, however Samba does. This is anomalous behavior and the preprocessor will alert if it happens. 22 With AndX command chaining it is possible to chain multiple Tree Connect AndX commands within the same request. There is, however, only one place in the SMB header to return a tree handle (or Tid). Windows does not allow this behavior, however Samba does. This is anomalous behavior and the preprocessor will alert if it happens. 23 When a Session Setup AndX request is sent to the server, the server responds (if the client successfully authenticates) which a user id or login handle. This is used by the client in subsequent requests to indicate that it has authenticated. A Logoff AndX request is sent by the client to indicate it wants to end the session and invalidate the login handle. With commands that are chained after a Session Setup AndX request, the login handle returned by the server is used for the subsequent chained commands. The combination of a Session Setup AndX command with a chained Logoff AndX command, essentially logins in and logs off in the same request and is anomalous behavior. The preprocessor will alert if it sees this. 24 A Tree Connect AndX command is used to connect to a share. The Tree Disconnect command is used to disconnect from that share. The combination of a Tree Connect AndX command with a chained Tree Disconnect command, essentially connects to a share and disconnects from the same share in the same request and is anomalous behavior. The preprocessor will alert if it sees this. 25 An Open AndX or Nt Create AndX command is used to open/create a file or named pipe. (The preprocessor is only interested in named pipes as this is where DCE/RPC requests are written to.) The Close command is used to close that file or named pipe. The combination of a Open AndX or Nt Create AndX command with a chained Close command, essentially opens and closes the named pipe in the same request and is anomalous behavior. The preprocessor will alert if it sees this. 26 The preprocessor will alert if it sees any of the invalid SMB shares configured. It looks for a Tree Connect or Tree Connect AndX to the share. 48 The preprocessor will alert if a data count for a Core dialect write command is zero. 49 For some of the Core dialect commands such as Write and Read, there are two data count fields, one in the main command header and one in the data format section. If these aren’t the same, the preprocessor will alert. 50 In the initial negotiation phase of an SMB session, the server in a Negotiate response and the client in a SessionSetupAndX request will advertise the maximum number of outstanding requests supported. The preprocessor will alert if the lesser of the two is exceeded. 51 When a client sends a request it uses a value called the MID (multiplex id) to match a response, which the server is supposed to echo, to a request. If there are multiple outstanding requests with the same MID, the preprocessor will alert. 52 In the Negotiate request a client gives a list of SMB dialects it supports, normally in order from least desirable to most desirable and the server responds with the index of the dialect to be used on the SMB session. Anything less than “NT LM 0.12” would be very odd these days (even Windows 98 supports it) and the preprocessor will alert if the client doesn’t offer it as a supported dialect or the server chooses a lesser dialect. 53 There are a number of commands that are considered deprecated and/or obsolete by Microsoft (see MS-CIFS and MS-SMB). If the preprocessor detects the use of a deprecated/obsolete command used it will alert. 54 There are some commands that can be used that can be considered unusual in the context they are used. These include some of the transaction commands such as: SMB_COM_TRANSACTION / TRANS_READ_NMPIPE SMB_COM_TRANSACTION / TRANS_WRITE_NMPIPE SMB_COM_TRANSACTION2 / TRANS2_OPEN2 SMB_COM_NT_TRANSACT / NT_TRANSACT_CREATE The preprocessor will alert if it detects unusual use of a command. 55 Transaction commands have a setup count field that indicates the number of 16bit words in the transaction setup. The preprocessor will alert if the setup count is invalid for the transaction command / sub command. 56 There can be only one Negotiate transaction per session and it is the first thing a client and server do to determine the SMB dialect each supports. The preprocessor will alert if the client attempts multiple dialect negotiations. 57 Malware will often set a file’s attributes to ReadOnly/Hidden/System if it is successful in installing itself as a Windows service or is able to write an autorun.inf file since it doesn’t want the user to see the file and the default folder options in Windows is not to display Hidden files. The preprocessor will alert if it detects a client attempt to set a file’s attributes to ReadOnly/Hidden/System.

Connection-oriented DCE/RPC events SID Description ——————————————————————————– 27 The preprocessor will alert if the connection-oriented DCE/RPC major version contained in the header is not equal to 5. 28 The preprocessor will alert if the connection-oriented DCE/RPC minor version contained in the header is not equal to 0. 29 The preprocessor will alert if the connection-oriented DCE/RPC PDU type contained in the header is not a valid PDU type. 30 The preprocessor will alert if the fragment length defined in the header is less than the size of the header. 31 The preprocessor will alert if the remaining fragment length is less than the remaining packet size. 32 The preprocessor will alert if in a Bind or Alter Context request, there are no context items specified. 33 The preprocessor will alert if in a Bind or Alter Context request, there are no transfer syntaxes to go with the requested interface. 34 The preprocessor will alert if a non-last fragment is less than the size of the negotiated maximum fragment length. Most evasion techniques try to fragment the data as much as possible and usually each fragment comes well below the negotiated transmit size. 35 The preprocessor will alert if a fragment is larger than the maximum negotiated fragment length. 36 The byte order of the request data is determined by the Bind in connection-oriented DCE/RPC for Windows. It is anomalous behavior to attempt to change the byte order mid-session. 37 The call id for a set of fragments in a fragmented request should stay the same (it is incremented for each complete request). The preprocessor will alert if it changes in a fragment mid-request. 38 The operation number specifies which function the request is calling on the bound interface. If a request is fragmented, this number should stay the same for all fragments. The preprocessor will alert if the opnum changes in a fragment mid-request. 39 The context id is a handle to a interface that was bound to. If a request if fragmented, this number should stay the same for all fragments. The preprocessor will alert if the context id changes in a fragment mid-request.

Connectionless DCE/RPC events SID Description ——————————————————————————– 40 The preprocessor will alert if the connectionless DCE/RPC major version is not equal to 4. 41 The preprocessor will alert if the connectionless DCE/RPC pdu type is not a valid pdu type. 42 The preprocessor will alert if the packet data length is less than the size of the connectionless header. 43 The preprocessor will alert if the sequence number uses in a request is the same or less than a previously used sequence number on the session. In testing, wrapping the sequence number space produces strange behavior from the server, so this should be considered anomalous behavior.

Rule Options

New rule options are supported by enabling the dcerpc2 preprocessor:

dce_iface dce_opnum dce_stub_data

New modifiers to existing byte_test and byte_jump rule options:

byte_test: dce byte_jump: dce

dce_iface ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For DCE/RPC based rules it has been necessary to set flow-bits based on a client bind to a service to avoid false positives. It is necessary for a client to bind to a service before being able to make a call to it. When a client sendsa bind request to the server, it can, however, specify one or more service interfaces to bind to. Each interface is represented by a UUID. Each interface UUID is paired with a unique index (or context id) that future requests can use to reference the service that the client is making a call to. The server will respond with the interface UUIDs it accepts as valid and will allow the client to make requests to those services. When a client makes a request, it will specify the context id so the server knows what service the client is making a request to. Instead of using flow-bits, a rule can simply ask the preprocessor, using this rule option, whether or not the client has bound to a specific interface UUID and whether or not this client request is making a request to it. This can eliminate false positives where more than one service is bound to successfully since the preprocessor can correlate the bind UUID to the context id used in the request. A DCE/RPC request can specify whether numbers are represented as big endian or little endian. The representation of the interface UUID is different depending on the endianness specified in the DCE/RPC previously requiring two rules - one for big endian and one for little endian. The preprocessor eliminates the need for two rules by normalizing the UUID. An interface contains a version. Some versions of an interface may not be vulnerable to a certain exploit. Also, a DCE/RPC request can be broken up into 1 or more fragments. Flags (and a field in the connectionless header) are set in the DCE/RPC header to indicate whether the fragment is the first, a middle or the last fragment. Many checks for data in the DCE/RPC request are only relevant if the DCE/RPC request is a first fragment (or full request), since subsequent fragments will contain data deeper into the DCE/RPC request. A rule which is looking for data, say 5 bytes into the request (maybe it’s a length field), will be looking at the wrong data on a fragment other than the first, since the beginning of subsequent fragments are already offset some length from the beginning of the request. This can be a source of false positives in fragmented DCE/RPC traffic. By default it is reasonable to only evaluate if the request is a first fragment (or full request). However, if the “any_frag” option is used to specify evaluating on all fragments.

Syntax [ ',' ] [ ',' "any_frag" ]

uuid       = hexlong '-' hexshort '-' hexshort '-' 2hexbyte '-' 6hexbyte
hexlong    = 4hexbyte
hexshort   = 2hexbyte
hexbyte    = 2HEXDIGIT
operator   = '<' | '>' | '=' | '!'
version    = 0-65535

Examples dce_iface: 4b324fc8-1670-01d3-1278-5a47bf6ee188; dce_iface: 4b324fc8-1670-01d3-1278-5a47bf6ee188,<2; dce_iface: 4b324fc8-1670-01d3-1278-5a47bf6ee188,any_frag; dce_iface: 4b324fc8-1670-01d3-1278-5a47bf6ee188,=1,any_frag;

This option is used to specify an interface UUID. Optional arguments are an interface version and operator to specify that the version be less than (‘<’), greater than (‘>’), equal to (‘=’) or not equal to (‘!’) the version specified. Also, by default the rule will only be evaluated for a first fragment (or full request, i.e. not a fragment) since most rules are written to start at the beginning of a request. The “any_frag” argument says to evaluate for middle and last fragments as well. This option requires tracking client Bind and Alter Context requests as well as server Bind Ack and Alter Context responses for connection-oriented DCE/RPC in the preprocessor. For each Bind and Alter Context request, the client specifies a list of interface UUIDs along with a handle (or context id) for each interface UUID that will be used during the DCE/RPC session to reference the interface. The server response indicates which interfaces it will allow the client to make requests to - it either accepts or rejects the client’s wish to bind to a certain interface. This tracking is required so that when a request is processed, the context id used in the request can be correlated with the interface UUID it is a handle for.

hexlong and hexshort will be specified and interpreted to be in big endian order (this is usually the default way an interface UUID will be seen and represented). As an example, the following Messenger interface UUID as taken off the wire from a little endian Bind request: |f8 91 7b 5a 00 ff d0 11 a9 b2 00 c0 4f b6 e6 fc| must be written as: 5a7b91f8-ff00-11d0-a9b2-00c04fb6e6fc The same UUID taken off the wire from a big endian Bind request: |5a 7b 91 f8 ff 00 11 d0 a9 b2 00 c0 4f b6 e6 fc| must be written the same way: 5a7b91f8-ff00-11d0-a9b2-00c04fb6e6fc

This option matches if the specified interface UUID matches the interface UUID (as referred to by the context id) of the DCE/RPC request and if supplied, the version operation is true. This option will not match if the fragment is not a first fragment (or full request) unless the “any_frag” option is supplied in which case only the interface UUID and version need match. Note that a defragmented DCE/RPC request will be considered a full request.

Using this rule option will automatically insert fast pattern contents into the fast pattern matcher. For UDP rules, the interface UUID, in both big and little endian format will be inserted into the fast pattern matcher. For TCP rules, (1) if the rule option “flow:to_server|from_client” is used, |05 00 00| will be inserted into the fast pattern matcher, (2) if the rule option “flow:from_server|to_client” is used, |05 00 02| will be inserted into the fast pattern matcher and (3) if the flow isn’t known, |05 00| will be inserted into the fast pattern matcher. Note that if the rule already has content rule options in it, the best (meaning longest) pattern will be used. If a content in the rule uses the fast_pattern rule option, it will unequivocally be used over the above mentioned patterns.

dce_opnum ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The opnum represents a specific function call to an interface. After is has been determined that a client has bound to a specific interface and is making a request to it (see above - dce_iface) usually we want to know what function call it is making to that service. It is likely that an exploit lies in the particular DCE/RPC function call.

Syntax

opnum-list   = opnum-item | opnum-item ',' opnum-list
opnum-item   = opnum | opnum-range
opnum-range  = opnum '-' opnum
opnum        = 0-65535

Examples dce_opnum: 15; dce_opnum: 15-18; dce_opnum: 15,18-20; dce_opnum: 15,17,20-22;

This option is used to specify an opnum (or operation number), opnum range or list containing either or both opnum and/or opnum-range. The opnum of a DCE/RPC request will be matched against the opnums specified with this option. This option matches if any one of the opnums specified match the opnum of the DCE/RPC request.

dce_stub_data ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Since most DCE/RPC based rules had to do protocol decoding only to get to the DCE/RPC stub data, i.e. the remote procedure call or function call data, this option will alleviate this need and place the cursor at the beginning of the DCE/RPC stub data. This reduces the number of rule option checks and the complexity of the rule.

This option takes no arguments.

Example: dce_stub_data;

This option is used to place the cursor (used to walk the packet payload in rules processing) at the beginning of the DCE/RPC stub data, regardless of preceding rule options. There are no arguments to this option. This option matches if there is DCE/RPC stub data.

The cursor is moved to the beginning of the stub data. All ensuing rule options will be considered “sticky” to this buffer. The first rule option following dce_stub_data should use absolute location modifiers if it is position-dependent. Subsequent rule options should use a relative modifier if they are meant to be relative to a previous rule option match in the stub data buffer. Any rule option that does not specify a relative modifier will be evaluated from the start of the stub data buffer. To leave the stub data buffer and return to the main payload buffer, use the “pkt_data” rule option.

byte_test and byte_jump ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A DCE/RPC request can specify whether numbers are represented in big or little endian. These rule options will take as a new argument “dce” and will work basically the same as the normal byte_test/byte_jump, but since the DCE/RPC preprocessor will know the endianness of the request, it will be able to do the correct conversion.

byte_test

Syntax ',' [ '!' ] ',' \ [ ',' [ ',' "relative" ]] ',' "dce"

convert    = 1 | 2 | 4
operator   = '<' | '=' | '>' | '&' | '^'
value      = 0-4294967295
offset     = -65535 to 65535

Examples byte_test: 4,>,35000,0,relative,dce; byte_test: 2,!=,2280,-10,relative,dce;

When using the “dce” argument to a byte_test, the following normal byte_test arguments will not be allowed: “big”, “little”, “string”, “hex”, “dec” and “oct”.

byte_jump

Syntax ',' [ ',' "relative" ] \ [ ',' "multiplier" ] [ ',' "align" ] \ [ ',' "post_offset" ] ',' "dce"

convert           = 1 | 2 | 4
offset            = -65535 to 65535
mult-value        = 0-65535
adjustment-value  = -65535 to 65535

Examples byte_jump:4,-4,relative,align,multiplier 2,post_offset -4,dce;

When using the dce argument to a byte_jump, the following normal byte_jump arguments will not be allowed: “big”, “little”, “string”, “hex”, “dec”, “oct” and “from_beginning”.

Example of rule complexity reduction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following two rules using the new rule options replace 64 (set and isset flowbit) rules that are necessary if the new rule options are not used:

alert tcp $EXTERNAL_NET any -> $HOME_NET [135,139,445,593,1024:] (msg:”dns R_Dnssrv funcs2 overflow attempt”; flow:established,to_server; dce_iface:50abc2a4-574d-40b3-9d66-ee4fd5fba076; dce_opnum:0-11; dce_stub_data; pcre:”/^.{12}(\x00\x00\x00\x00 .{12})/s”; byte_jump:4,-4,relative,align,dce; byte_test:4,>,256,4,relative,dce; reference:bugtraq,23470; reference:cve,2007-1748; classtype:attempted-admin; sid:1000068;)
alert udp $EXTERNAL_NET any -> $HOME_NET [135,1024:] (msg:”dns R_Dnssrv funcs2 overflow attempt”; flow:established,to_server; dce_iface:50abc2a4-574d-40b3-9d66-ee4fd5fba076; dce_opnum:0-11; dce_stub_data; pcre:”/^.{12}(\x00\x00\x00\x00 .{12})/s”; byte_jump:4,-4,relative,align,dce; byte_test:4,>,256,4,relative,dce; reference:bugtraq,23470; reference:cve,2007-1748; classtype:attempted-admin; sid:1000069;)