----------------- 1. Introduction ----------------- With skipfish signatures it is possible to find interesting content, or even vulnerabilities, in server responses. The signatures follow a Snort-like syntax and most keywords behave similarly as well. Signatures focus on detecting web application vulnerabilities, information leaks and can recognize interesting web applications, such as phpmyadmin or phpinfo() pages. Signatures could also detect vulnerable software packages (e.g. old WordPress instances) but this is a task that fits vulnerability scanners, like Nessus and Nikto, better. ----------------- 2. Contributing ----------------- The current signature list is nice but far from complete. If you have new signatures or can optimize existing ones, please help out by reporting this via our issue tracker: https://code.google.com/p/skipfish/issues/entry?template=Content%20signatures ----------------------- 3. Signature keywords ----------------------- === content:[!]"" The content keyword is used to specify a string that we try to match against the server response. The value can either be a static string or a regular expression (the latter requires the type:regex; modifier). Multiple content strings can be specified per signature and, unless the signature specifies a mime type, there should be at least one. Modifiers can be specified per content keyword to influence how the string is matches against the payload. For example, with the 'depth' keyword you can specify how far in the payload we should look for the string. When ! is specified before the content string, the test is positive when the string is NOT present. This is mainly useful in case your signature has multiple content values. Note: content string modifiers should be specified _after_ the content string to which they apply. === content modifier: depth: With depth you can limit the amount of bytes we should search for the string. Initially the depth is relative to the beginning of the payload. However, when multiple 'content' strings are used, the depth is relative to the first byte after the previous content match. Using the depth keyword has two advantages: increase performance and increase signature accuracy. 1) Performance: A signature that matches on a tag doesn't need to be applied to the whole payload. Instead, a depth of 512 or even 1024 bytes will help to improve performance. 2) Accuracy: In a signature with two 'content' keywords, you can force the second keyword to be searched within a very short depth of the previous content match. === content modifier: offset:<int> The content string searching will start at the given offset value. For the first content string this is relative to the beginning of the payload. For the following content strings, this is relative to the first byte of the last match. === content modifier: type:["regex|static"] Indicates whether the content string should be treated as a regular expression or a static string. Content strings are treated as static by default so you can leave this keyword out unless you're using a regular expression. In a signature that has multiple content strings, static strings can be mixed with regular expressions. You'll likely get the best performance by starting with a static string before applying a regular expression. === content modifier: regex_match:"<string>" Regular expressions can capture substrings and with regex_match, it is possible to compare <string> with the first substring that is returned by the regular expression. Given "Apache/2.2.14" as payload and "Apache\/([\d\.]+)" as regex, you could use regex_match:"2.2.14" to find this specific Apache version. === content modifier: nocase When "nocase" is specified, the content string is matched without case sensitivity. This keyword requires no value. === header:"<string>" By default signature matching is performed on the respose body. By specifying a header name using the "header" keyword, this behavior is changed: the matching will occur on the header value. The header name is not case sensitive and header signatures are treated exactly the same as content signatures meaning that you can use multiple content strings and their modifiers. === mime:"<string>" The given value will be compared with the MIME type specified by the server. This is a "begins with" comparison so a partial MIME string, like "javascript/" will match with a server value of "javascript/foo". === memo:"<string>" The memo message is displayed in the report when the signature matches. The content should be a short but meaningful problem title. === sev:[1-4] The severity with which a signature match should be reported where: - 1 is High - 2 is Medium - 3 is Low - 4 is Info (default) === prob:"<string>" All issue types are defined in database.h and, by default, signature matches are reported with generic (signature) issue types. Using the prob keyword, a signature match can be reported as any other known issue. For example, issue 40401 stands for interesting files and is already used for several signatures. The advantage of using an existing issue ID is that it's severity and description will be used to report the signature match. === check:<int> Injection tests have their own ID which are specified in checks.h. Using the "check" keyword, it is possible to bind a signature to a specific injection test. The idea is to allow context specific signatures to be written. Take the following scenario as an example: During a scan, file disclosure tests might not fully succeed to highlight a vulnerability. Errors thrown during these tests can still reveal that there is more than likely a file disclosure problem. While generic server error detection will highlight these errors, it is more useful if we can detect that these errors are related to our tests and report them as such. === id:<int> The unique signature ID. This is for documentation purpose and for using the depend keyword which allows signature chaining. Note that the signature ID is also included in the report files (e.g. samples.js). === depend:<int> A signature can be made dependent on another signature by specifying it's signature ID as the value of this keyword. This means that the signature will be skipped unless the dependent signature was successfully matched already. One example use case could be a global signature that identifies a framework, say Wordpress, and dependent signatures that detect wordpress specific issues. === proto:"[http|https]" The "proto" keyword can be used to make a signature only applicable for either "http" or "https" type URLs. This changes the default behavior where every signature is applied to both http and https URLs. === report:"[once|always]" Some signatures are to find host specific problems and only need to be reported once. This can be acchieved by using report:"once"; This keywords default value is "always".