Minor documentation refactoring

pull/24/head
Andrew Krasichkov 2017-05-11 00:36:07 +03:00
parent 7255ea610f
commit b643cf3160
13 changed files with 92 additions and 166 deletions

View File

@ -1,4 +1,17 @@
Gixy — это утилита для анализа конфигурации Nginx. Большей частью служит для обнаружения проблем безопасности, но может искать и иные ошибки.
GIXY
====
[![Mozilla Public License 2.0](https://img.shields.io/github/license/yandex/gixy.svg?style=flat-square)](https://github.com/yandex/gixy/blob/master/LICENSE)
[![Build Status](https://img.shields.io/travis/yandex/gixy.svg?style=flat-square)](https://travis-ci.org/yandex/gixy)
[![Your feedback is greatly appreciated](https://img.shields.io/maintenance/yes/2017.svg?style=flat-square)](https://github.com/yandex/gixy/issues/new)
[![GitHub issues](https://img.shields.io/github/issues/yandex/gixy.svg?style=flat-square)](https://github.com/yandex/gixy/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/yandex/gixy.svg?style=flat-square)](https://github.com/yandex/gixy/pulls)
<img align="right" width="192" height="192" src="/docs/logo.png">
Gixy — это утилита для анализа конфигурации Nginx.
Большей частью служит для обнаружения проблем безопасности, но может искать и иные ошибки.
Официально поддерживаются версии Python 2.7, 3.5 и 3.6
## Что умеет
На текущий момент Gixy способна обнаружить:
@ -12,12 +25,11 @@ Gixy — это утилита для анализа конфигурации Ng
Проблемы, которым Gixy только учится можно найти в [Issues с меткой "new plugin"](https://github.com/yandex/gixy/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+plugin%22)
## Установка
Наиболее простой способ установки Gixy - воспользоваться pip для установки из Pypi:
# Установка
Наиболее простой способ установки Gixy - воспользоваться pip для установки из [PyPI](https://pypi.python.org/pypi/gixy):
```bash
pip install gixy
```
Официально поддерживаются версии Python 2.7, 3.5 и 3.6
## Использование
После установки должна стать доступна консольная утилита `gixy`.
@ -107,3 +119,12 @@ available plugins:
ssrf
```
# Contributing
Contributions to Gixy are always welcome! You can help us in different ways:
* Open an issue with suggestions for improvements and errors you're facing;
* Fork this repository and submit a pull request;
* Improve the documentation.
Code guidelines:
* Python code style should follow [pep8](https://www.python.org/dev/peps/pep-0008/) standards whenever possible;
* Pull requests with new plugins must have unit tests for it.

View File

@ -10,12 +10,24 @@ GIXY
<img align="right" width="192" height="192" src="/docs/logo.png">
Gixy is a tool to analyze Nginx configuration.
The main goal of Gixy is to prevent misconfiguration and automate flaw detection.
The main goal of Gixy is to prevent security misconfiguration and automate flaw detection.
Currently supported Python versions are 2.7 and 3.5+.
Disclaimer: Gixy is well tested only on GNU/Linux, other OSs may have some issues.
## What it can do
Right now Gixy can find:
* [[ssrf] Server Side Request Forgery](https://github.com/yandex/gixy/blob/master/docs/en/plugins/ssrf.md)
* [[http_splitting] HTTP Splitting](https://github.com/yandex/gixy/blob/master/docs/en/plugins/httpsplitting.md)
* [[origins] Problems with referrer/origin validation](https://github.com/yandex/gixy/blob/master/docs/en/plugins/origins.md)
* [[add_header_redefinition] Redefining of upstream response headers with directive "add_header"](https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md)
* [[host_spoofing] Request's Host header forgery](https://github.com/yandex/gixy/blob/master/docs/en/plugins/hostspoofing.md)
* [[valid_referers] none in valid_referers](https://github.com/yandex/gixy/blob/master/docs/en/plugins/validreferers.md)
* [[add_header_multiline] Multiline response headers](https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheadermultiline.md)
You can find things that Gixy is learning to detect at [Issues labeled with "new plugin"](https://github.com/yandex/gixy/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+plugin%22)
# Installation
Gixy is distributed on [PyPI](https://pypi.python.org/pypi/gixy). The best way to install it is with pip:
```bash
@ -76,9 +88,6 @@ Total issues:
Or something else, you can find all other `gixy` arguments with the help command: `gixy --help`
# Documentation
Full documentation and recommendations can be found [here](https://github.com/yandex/gixy/blob/master/docs/ru/README.md) (sorry, but Russian language only so far)
# Contributing
Contributions to Gixy are always welcome! You can help us in different ways:
* Open an issue with suggestions for improvements and errors you're facing;

View File

@ -1,109 +0,0 @@
Gixy is a static analysis tool for Ngix config files. It is best at finding security misconfigurations, but can be also used to detect general errors.
## What it can do
Right now Gixy can find:
* [[ssrf] Server Side Request Forgery](https://github.com/yandex/gixy/blob/master/docs/en/plugins/ssrf.md)
* [[http_splitting] HTTP Splitting](https://github.com/yandex/gixy/blob/master/docs/en/plugins/httpsplitting.md)
* [[origins] Problems with referrer/origin validation](https://github.com/yandex/gixy/blob/master/docs/en/plugins/origins.md)
* [[add_header_redefinition] Redefining of upstream response headers with directive "add_header"](https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheaderredefinition.md)
* [[host_spoofing] Request's Host header forgery](https://github.com/yandex/gixy/blob/master/docs/en/plugins/hostspoofing.md)
* [[valid_referers] none in valid_referers](https://github.com/yandex/gixy/blob/master/docs/en/plugins/validreferers.md)
* [[add_header_multiline] Multiline response headers](https://github.com/yandex/gixy/blob/master/docs/en/plugins/addheadermultiline.md)
You can find things that Gixy is learning to detect at [Issues labeled with "new plugin"](https://github.com/yandex/gixy/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+plugin%22)
##Installation
The easiest way to install Gixy is to use pip:
```bash
pip install gixy
```
The tool is compatible with Python 2.7/3.5/3.6
## Using Gixy
After installation you can find `gixy` in your command line. Buy default Gixy is working with `/etc/nginx/nginx.conf` folder, which is standart for Nginx installations, but you can provide a custom path as an argument:
```
$ gixy /www/configs/nginx/nginx.conf
```
==================== Results ===================
Problem: [http_splitting] Possible HTTP-Splitting vulnerability.
Description: Using variables that can contain "\n" may lead to http injection.
Additional info: https://github.com/yandex/gixy/wiki/ru/httpsplitting
Reason: At least variable "$action" can contain "\n"
Pseudo config:
include /etc/nginx/sites/default.conf;
server {
location ~ /v1/((?<action>[^.]*)\.json)?$ {
add_header X-Action $action;
}
}
==================== Summary ===================
Total issues:
Unspecified: 0
Low: 0
Medium: 0
High: 1
```
Gixy can process `include` directive and tries to handle all the dependencies. If something went wrong, you can launch Gixy with the `d` flag, which enables debug mode for extra information.
To view all options:
```
$ gixy -h
usage: gixy [-h] [-c CONFIG_FILE] [--write-config CONFIG_OUTPUT_PATH]
[-v] [-l] [-f {console,text,json}] [-o OUTPUT_FILE] [-d]
[--tests TESTS] [--skips SKIPS] [--disable-includes]
[--origins-domains domains]
[--origins-https-only https_only]
[--add-header-redefinition-headers headers]
[nginx.conf]
Gixy - a Nginx configuration [sec]analyzer
positional arguments:
nginx.conf Path to nginx.conf, e.g. /etc/nginx/nginx.conf
optional arguments:
-h, --help show this help message and exit
-c CONFIG_FILE, --config CONFIG_FILE
config file path
--write-config CONFIG_OUTPUT_PATH
takes the current command line args and writes them
out to a config file at the given path, then exits
-v, --version show program's version number and exit
-l, --level Report issues of a given severity level or higher (-l
for LOW, -ll for MEDIUM, -lll for HIGH)
-f {console,text,json}, --format {console,text,json}
Specify output format
-o OUTPUT_FILE, --output OUTPUT_FILE
Write report to file
-d, --debug Turn on debug mode
--tests TESTS Comma-separated list of tests to run
--skips SKIPS Comma-separated list of tests to skip
--disable-includes Disable "include" directive processing
plugins options:
--origins-domains domains
Default: *
--origins-https-only https_only
Default: False
--add-header-redefinition-headers headers
Default: content-security-policy,x-xss-
protection,x-frame-options,x-content-type-
options,strict-transport-security,cache-control
available plugins:
host_spoofing
add_header_multiline
http_splitting
valid_referers
origins
add_header_redefinition
ssrf
```

View File

@ -1,13 +1,13 @@
# [add_header_multiline] Multiline response headers
You should avoid using multiline response headers, because:
* they sre considered depricated (см. [RFC 7230](https://tools.ietf.org/html/rfc7230#section-3.2.4));
* Some HTTP-clients and web browser never supported them (e.g. IE/Edge/Nginx).
* they are depricated (see [RFC 7230](https://tools.ietf.org/html/rfc7230#section-3.2.4));
* some HTTP-clients and web browser never supported them (e.g. IE/Edge/Nginx).
## How can I find it?
Misconfiguration example:
```nginx
# http://nginx.org/ru/docs/http/ngx_http_headers_module.html#add_header
# http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header
add_header Content-Security-Policy "
default-src: 'none';
script-src data: https://yastatic.net;

View File

@ -1,12 +1,12 @@
# [add_header_redefinition] Redefining of upstream response headers with directive "add_header"
Unfortunately, many people consider the use of `add_header` directive for headers redefining a good practice.
This approach is flawed, which is discussed in Nginx [docs](http://nginx.org/ru/docs/http/ngx_http_headers_module.html#add_header):
This approach is flawed, which is discussed in Nginx [docs](http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header):
> There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.
The logic is quite simple: if you set headers at one level (for example, in `server` section) and then at a lower level (let's say `location`) you set some other headers, then the first group won't apply.
It's easy to observe:
It's easy to check:
- Configuration:
```nginx
server {
@ -25,7 +25,7 @@ server {
}
}
```
- Location request `/` (`X-Frame-Options` header is in server response):
- Request to location `/` (`X-Frame-Options` header is in server response):
```http
GET / HTTP/1.0
@ -39,7 +39,7 @@ X-Frame-Options: DENY
index
```
- Location request `/new-headers` (headers `Cache-Control` and `Pragma` are present, but there's no `X-Frame-Options`):
- Request to location `/new-headers` (headers `Cache-Control` and `Pragma` are present, but there's no `X-Frame-Options`):
```http
GET /new-headers HTTP/1.0
@ -58,8 +58,6 @@ new-headers
## What can I do?
There are several ways to solve this problem:
- dublicate important headers;
- duplicate important headers;
- set all headers at one level (`server` section is a good choice)
- use [ngx_headers_more](https://www.nginx.com/resources/wiki/modules/headers_more/) module.
No solution is perfect, so choose one based on your needs.

View File

@ -1,15 +1,16 @@
# [host_spoofing] Request's Host header forgery
Often, an application located behind Nginx needs a correct `Host` header for URL generation (redirects, resources, links in emails etc.).
An attacker can spoof this header, which leads to a variety of problems, from phishing to SSRF. To prevent this, avoid:
> Relience on `X-Forwarded-Host` request header;
> In this case you have to ensure the header is set correctly at proxies;
Spoofing of this header, may leads to a variety of problems, from phishing to SSRF.
> Notice: your application may also use the `X-Forwarded-Host` request header for this functionality.
> In this case you have to ensure the header is set correctly;
## How can I find it?
Most of the time it's a result of using `$http_host` variable instead of `$host`.
And they are quite different:
* `$http` - host in order of priority: host name from request string, host name form `Host` request header, or a server name, compliant to the request;
* `$http` - host in this order of precedence: host name from the request line, or host name from the “Host” request header field, or the server name matching a request;
* `$http_host` - "Host" request header.
Config sample:
@ -22,7 +23,7 @@ location @app {
```
## What can I do?
Luckly, all is quite obvious:
Luckily, all is quite obvious:
* list all the correct server names in `server name` directive;
* always use `$host` instead of `$http_host`.

View File

@ -2,16 +2,16 @@
HTTP Splitting - attack that use improper input validation. It usually targets web application located behind Nginx (HTTP Request Splitting) or its users (HTTP Response Splitting).
Vulnerability is created when an attacker can insert new line symbol "\n" into request or into response, created by Nginx server.
Vulnerability is created when an attacker can insert newline character `\n` into request or into response, created by Nginx.
## How can I find it?
You should always pay attention to:
- variables that are used in directives, responsible for the request creation (for they may contain CRLF), e.g. `rewrite`, `return`, `add_header`, `proxy_set_header` or `proxy_pass`;
- `$uri` and `$document_uri` variables, and the directive that process them, because these variables contain url-encoded value;
- `$uri` and `$document_uri` variables, and in which directives they are used, because these variables contain decoded URL-encoded value;
- variables, that are selected from an exclusive range, e.g. `(?P<myvar>[^.]+)`.
An example of configuration that contains vriable, selected from an exclusive range:
An example of configuration that contains variable, selected from an exclusive range:
```nginx
server {
listen 80 default;
@ -23,7 +23,7 @@ server {
}
```
Explotation:
Exploitation:
```http
GET /v1/see%20below%0d%0ax-crlf-header:injected.json HTTP/1.0
Host: localhost
@ -39,11 +39,12 @@ x-crlf-header:injected
OK
```
As you can see, an attacker could add `x-crlf-header: injected` response header. This was possible because:
- `add_header` doesn't encode or validate input value on suggestion that author knows about the consiquences;
- the path value is normalized before processing of the location;
- `add_header` doesn't encode or validate input value on suggestion that author knows about the consequences;
- the path value is normalize before location processing;
- `$action` value was given from a regexp with an exclusive range: `[^.]*`;
- as the result, `$action` value is equal to that of `see below\r\nx-crlf-header:injected` and on its use the header was added to the response.
- as the result, `$action` value is equal to `see below\r\nx-crlf-header:injected` and on its use the response header was added.
## What can I do?
- try to use safe variables, e.g. `$request_uri` instead of `$uri`;

View File

@ -1,20 +1,21 @@
# [origins] Problems with referrer/origin validation
It's not unusual to use regexp for `Referer` or `Origin` headers validation.
It's not unusual to use regex for `Referer` or `Origin` headers validation.
Often it is needed for setting the `X-Frame-Options` header (ClickJacking protection) or Cross-Origin Resource Sharing.
The most common errors with this configuration are:
- regexp errors;
- 3rd-party domain permissions.
- regex errors;
- allow 3rd-party origins.
> By default Gixy doesn't check regexps for 3rd-party domains matching, cause it's unclear wether you can should them. You can pass a list of trusted domains by using the option `--origins-domains example.com,foo.bar`
> Notice: by default Gixy doesn't check regexes for 3rd-party origins matching.
> You can pass a list of trusted domains by using the option `--origins-domains example.com,foo.bar`
## How can I find it?
"Eazy"-breezy:
- you have to find all the `if` directives that are in charge of `$http_origin` or `$http_referer` check;
- make sure your regexps are a-ok.
- make sure your regexes are a-ok.
Misconfig example:
Misconfiguration example:
```nginx
if ($http_origin ~* ((^https://www\.yandex\.ru)|(^https://ya\.ru)/)) {
add_header 'Access-Control-Allow-Origin' "$http_origin";
@ -22,9 +23,11 @@ if ($http_origin ~* ((^https://www\.yandex\.ru)|(^https://ya\.ru)/)) {
}
```
TODO(buglloc): cover typical regexp-writing problems
TODO(buglloc): cover typical regex-writing problems
TODO(buglloc): Regex Ninja?
## What can I do?
Fix your regexp or toss it away.
If you use regexp validation for `Referer` request header, then, possibly (not 100%), you could use [ngx_http_referer_module](http://nginx.org/ru/docs/http/ngx_http_referer_module.html).
- fix your regex or toss it away :)
- if you use regex validation for `Referer` request header, then, possibly (not 100%), you could use [ngx_http_referer_module](http://nginx.org/en/docs/http/ngx_http_referer_module.htmll);
- sometimes is much better to use `map` directive without any regex at all.

View File

@ -1,21 +1,22 @@
# [ssrf] Server Side Request Forgery
Server Side Request Forgery - attack that forces a server to perform requests on behalf of an attacker (Nginx in our case).
Server Side Request Forgery - attack that forces a server to perform arbitrary requests (from Nginx in our case).
It's possible when an attacker controls the address of a proxied server (second argument of the `proxy_pass` directive).
## How can I find it?
There are two types of errors that make a server vulnerable:
- lack of the [internal](http://nginx.org/ru/docs/http/ngx_http_core_module.html#internal) directive. It is used to point out a location that can be used for internal requests only;
- lack of the [internal](http://nginx.org/en/docs/http/ngx_http_core_module.html#internal) directive. It is used to point out a location that can be used for internal requests only;
- unsafe internal redirection.
### Lack of the internal directive
Classical misconfig, based on lack of the internal directive, that makes SSRF possible:
Classical misconfiguration, based on lack of the `internal` directive, that makes SSRF possible:
```nginx
location ~ /proxy/(.*)/(.*)/(.*)$ {
proxy_pass $1://$2/$3;
}
```
An attacker has complete control over the proxied address, that makes sending requests on behalf of Nginx possible.
### Unsafe internal redirection
@ -31,15 +32,15 @@ location ~* ^/internal-proxy/(?<proxy_proto>https?)/(?<proxy_host>.*?)/(?<proxy_
}
```
According to Nginx docs, internal requests are:
> - requests redirected by the **error_page**, **index**, **random_index**, and **try_files** directives;
According to Nginx docs, internal requests are the following:
> - requests redirected by the **error_page**, index, random_index, and **try_files** directives;
> - requests redirected by the “X-Accel-Redirect” response header field from an upstream server;
> - subrequests formed by the “include virtual” command of the ngx_http_ssi_module module and by the ngx_http_addition_module module directives;
> - requests changed by the **rewrite** directive.]>
> - requests changed by the **rewrite** directive
Accordingly, any unsafe rewrite allows an attacker to make an internal request and control a proxied server's address.
Misconfig example:
Misconfiguration example:
```nginx
rewrite ^/(.*)/some$ /$1/ last;
@ -52,8 +53,8 @@ location ~* ^/internal-proxy/(?<proxy_proto>https?)/(?<proxy_host>.*?)/(?<proxy_
```
## What can I do?
There are everal rules you better follow when writing such configurations:
- use only `internal location` for proxying;
There are several rules you better follow when writing such configurations:
- use only "internal locations" for proxying;
- if possible, forbid user data transmission;
- protect proxied server's address:
* if the quantity of proxied hosts is limited (when you have S3 or smth), you better hardcode them and choose them with `map` or do it some other way;

View File

@ -1,13 +1,13 @@
# [valid_referers] none in valid_referers
Module [ngx_http_referer_module](http://nginx.org/ru/docs/http/ngx_http_referer_module.html) allows to block the access to service for requests with wrong `Referer~ value.
Module [ngx_http_referer_module](http://nginx.org/en/docs/http/ngx_http_referer_module.html) allows to block the access to service for requests with wrong `Referer` value.
It's often used for setting `X-Frame-Options` header (ClickJacking protection), but there may be other cases.
Typical problems with this module's config:
* use of `server_names` with bad server name (`server_name` directive);
* too broad and/or bad regexps;
* too broad and/or bad regexes;
* use of `none`.
> At the moment, Gixy can only detect the use of `none` as a valid referer.
> Notice: at the moment, Gixy can only detect the use of `none` as a valid referer.
## Why none is bad?
According to [docs](http://nginx.org/ru/docs/http/ngx_http_referer_module.html#valid_referers):
@ -15,8 +15,8 @@ According to [docs](http://nginx.org/ru/docs/http/ngx_http_referer_module.html#v
Still, it's important to remember that any resource can make user's browser to make a request without a `Referer` request header.
E.g.:
- in case of redirect from HTTP to HTTPS;
- by setting up a properc[Referrer Policy](https://www.w3.org/TR/referrer-policy/);
- in case of redirect from HTTPS to HTTP;
- by setting up the [Referrer Policy](https://www.w3.org/TR/referrer-policy/);
- a request with opaque origin, `data:` scheme, for example.
So, by using `none` as a valid referer, you nullify any attemps in refferer validation.

View File

@ -27,5 +27,6 @@ TODO(buglloc): описать типичные проблемы при сост
TODO(buglloc): Regex Ninja?
## Что делать?
Исправить регулярное выражение или отказаться от него вовсе.
Например, если вы используете валидацию на основе регулярного выражения для проверки заголовка запроса `Referer` то, возможно (имеются противопоказания), лучшим решением было бы воспользоваться модулем [ngx_http_referer_module](http://nginx.org/ru/docs/http/ngx_http_referer_module.html)
- исправить регулярное выражение или отказаться от него вовсе :)
- если вы проверяете заголовок запроса `Referer` то, возможно (имеются противопоказания), лучшим решением было бы воспользоваться модулем [ngx_http_referer_module](http://nginx.org/ru/docs/http/ngx_http_referer_module.html);
- если вы проверяете заголовов запроса `Origin` то, зачастую, лучше использовать `map` и отказаться от регулярных выражений.

View File

@ -32,7 +32,7 @@ location ~* ^/internal-proxy/(?<proxy_proto>https?)/(?<proxy_host>.*?)/(?<proxy_
```
Согласно документации Nginx внутренними запросами являются:
> - запросы, перенаправленные директивами **error_page**, **index**, **random_index** и **try_files**;
> - запросы, перенаправленные директивами **error_page**, index, random_index и **try_files**;
> - запросы, перенаправленные с помощью поля “X-Accel-Redirect” заголовка ответа вышестоящего сервера;
> - подзапросы, формируемые командой “include virtual” модуля ngx_http_ssi_module и директивами модуля ngx_http_addition_module;
> - запросы, изменённые директивой **rewrite**.]>

View File

@ -15,7 +15,7 @@
> `none` - поле “Referer” в заголовке запроса отсутствует;
Однако, важно помнить, что любой ресурс может заставить браузер пользователя выполнить запрос без заголовка запроса `Referer`, к примеру:
- в случае редиректа в HTTPS на HTTP;
- в случае редиректа с HTTPS на HTTP;
- указав соответствующую [Referrer Policy](https://www.w3.org/TR/referrer-policy/);
- обращение с opaque origin, например, используя схему `data:`.