skipfish/doc/signatures.txt

194 lines
6.8 KiB
Plaintext

-----------------
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:[!]"<string>"
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:<int>
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 <title> 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".