194 lines
6.8 KiB
Plaintext
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".
|
|
|