Skip to content

Commit

Permalink
Add new plugin to detect Nginx version disclosure and enhance add_hea…
Browse files Browse the repository at this point in the history
…der_redefinition

Introduced a new plugin that checks if the Nginx version is being disclosed which is a security vulnerability. At the same time, the previous "add_header_redefinition" plugin has been enhanced to check if any secure headers were dropped. Severity level of this issue is now determined based on whether a secure header was dropped or not.
  • Loading branch information
dvershinin committed Jan 7, 2024
1 parent 65e612a commit 3bfcda4
Show file tree
Hide file tree
Showing 16 changed files with 292 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# These are supported funding model platforms

github: GetPageSpeed
github: dvershinin
patreon: getpagespeed
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
max-parallel: 4
matrix:
python-version: [2.7, 3.6, 3.7, 3.8, 3.9]
python-version: [3.6, 3.7, 3.8, 3.9]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -30,4 +30,3 @@ jobs:
nosetests --with-coverage --cover-package gixy -v
env:
GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}

9 changes: 9 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: 2

mkdocs:
configuration: mkdocs.yml

python:
version: 3.7
install:
- requirements: docs/requirements.txt
28 changes: 15 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,26 @@ GIXY
Gixy is a tool to analyze Nginx configuration.
The main goal of Gixy is to prevent security misconfiguration and automate flaw detection.

Currently supported Python versions are 2.7, 3.6, 3.7, 3.8 and 3.9.
Currently supported Python versions are 3.6, 3.7, 3.8 and 3.9.

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/dvershinin/gixy/blob/master/docs/en/plugins/ssrf.md)
* [[http_splitting] HTTP Splitting](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/httpsplitting.md)
* [[origins] Problems with referrer/origin validation](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/origins.md)
* [[add_header_redefinition] Redefining of response headers by "add_header" directive](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/addheaderredefinition.md)
* [[host_spoofing] Request's Host header forgery](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/hostspoofing.md)
* [[valid_referers] none in valid_referers](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/validreferers.md)
* [[add_header_multiline] Multiline response headers](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/addheadermultiline.md)
* [[alias_traversal] Path traversal via misconfigured alias](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/aliastraversal.md)
* [[if_is_evil] If is evil when used in location context](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/if_is_evil.md)
* [[allow_without_deny] Allow specified without deny](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/allow_without_deny.md)
* [[add_header_content_type] Setting Content-Type via add_header](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/add_header_content_type.md)
* [[resolver_external] Using external DNS nameservers](https://blog.zorinaq.com/nginx-resolver-vulns/)

This comment has been minimized.

Copy link
@LeviPesin

LeviPesin Jan 13, 2024

version_disclosure is missing from this list here for some reason?

This comment has been minimized.

Copy link
@dvershinin

dvershinin Jan 14, 2024

Author Owner

Fixed in the new release v0.1.24

* [[ssrf] Server Side Request Forgery](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/ssrf.md)
* [[http_splitting] HTTP Splitting](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/httpsplitting.md)
* [[origins] Problems with referrer/origin validation](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/origins.md)
* [[add_header_redefinition] Redefining of response headers by "add_header" directive](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/addheaderredefinition.md)
* [[host_spoofing] Request's Host header forgery](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/hostspoofing.md)
* [[valid_referers] none in valid_referers](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/validreferers.md)
* [[add_header_multiline] Multiline response headers](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/addheadermultiline.md)
* [[alias_traversal] Path traversal via misconfigured alias](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/aliastraversal.md)
* [[if_is_evil] If is evil when used in location context](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/if_is_evil.md)
* [[allow_without_deny] Allow specified without deny](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/allow_without_deny.md)
* [[add_header_content_type] Setting Content-Type via add_header](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/add_header_content_type.md)
* [[resolver_external] Using external DNS nameservers](https://blog.zorinaq.com/nginx-resolver-vulns/)

You can find things that Gixy is learning to detect at [Issues labeled with "new plugin"](https://github.com/dvershinin/gixy/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+plugin%22)

Expand Down
5 changes: 3 additions & 2 deletions docs/en/plugins/validreferers.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ Typical problems with this module's config:

> Notice: at the moment, Gixy can only detect the use of `none` as a valid referer.
## Why none is bad?
## Why `none` is bad?

According to [docs](http://nginx.org/ru/docs/http/ngx_http_referer_module.html#valid_referers):
> `none` - the “Referer” field is missing in the request header;
Expand All @@ -19,4 +20,4 @@ E.g.:
- 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.
So, by using `none` as a valid referer, you nullify any attemps in refferer validation.
17 changes: 17 additions & 0 deletions docs/en/plugins/version_disclosure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# [version_disclosure] Disclosure of version information

## Problem

Nginx version disclosure.

## Description

Nginx version disclosure is a security vulnerability that allows an attacker to obtain information about the version of Nginx running on the server.

## Recommendation

Disable version disclosure by adding the following directive to your `nginx.conf`:

```nginx
server_tokens off;
```
152 changes: 152 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
GIXY
====
[![Mozilla Public License 2.0](https://img.shields.io/github/license/dvershinin/gixy.svg?style=flat-square)](https://github.com/dvershinin/gixy/blob/master/LICENSE)
[![Python tests](https://github.com/dvershinin/gixy/actions/workflows/pythonpackage.yml/badge.svg)](https://github.com/dvershinin/gixy/actions/workflows/pythonpackage.yml)
[![Your feedback is greatly appreciated](https://img.shields.io/maintenance/yes/2023.svg?style=flat-square)](https://github.com/dvershinin/gixy/issues/new)
[![GitHub issues](https://img.shields.io/github/issues/dvershinin/gixy.svg?style=flat-square)](https://github.com/dvershinin/gixy/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/dvershinin/gixy.svg?style=flat-square)](https://github.com/dvershinin/gixy/pulls)

# Overview
<img align="right" width="192" height="192" src="logo.png">

Gixy is a tool to analyze Nginx configuration.
The main goal of Gixy is to prevent security misconfiguration and automate flaw detection.

Currently supported Python versions are 2.7, 3.6, 3.7, 3.8 and 3.9.

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](en/plugins/ssrf.md)
* [[http_splitting] HTTP Splitting](en/plugins/httpsplitting.md)
* [[origins] Problems with referrer/origin validation](en/plugins/origins.md)
* [[add_header_redefinition] Redefining of response headers by "add_header" directive](en/plugins/addheaderredefinition.md)
* [[host_spoofing] Request's Host header forgery](en/plugins/hostspoofing.md)
* [[valid_referers] none in valid_referers](en/plugins/validreferers.md)
* [[add_header_multiline] Multiline response headers](en/plugins/addheadermultiline.md)
* [[alias_traversal] Path traversal via misconfigured alias](en/plugins/aliastraversal.md)
* [[if_is_evil] If is evil when used in location context](en/plugins/if_is_evil.md)
* [[allow_without_deny] Allow specified without deny](en/plugins/allow_without_deny.md)
* [[add_header_content_type] Setting Content-Type via add_header](en/plugins/add_header_content_type.md)
* [[resolver_external] Using external DNS nameservers](https://blog.zorinaq.com/nginx-resolver-vulns/)
* [[version_disclosure] Using external DNS nameservers](en/plugins/version_disclosure.md)

You can find things that Gixy is learning to detect at [Issues labeled with "new plugin"](https://github.com/dvershinin/gixy/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+plugin%22)

# Installation

## CentOS/RHEL and other RPM-based systems

```bash
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install gixy
```
### Other systems

Gixy is distributed on [PyPI](https://pypi.python.org/pypi/gixy-ng). The best way to install it is with pip:

```bash
pip install gixy-ng
```

Run Gixy and check results:
```bash
gixy
```

# Usage

By default, Gixy will try to analyze Nginx configuration placed in `/etc/nginx/nginx.conf`.

But you can always specify needed path:
```
$ gixy /etc/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/dvershinin/gixy/blob/master/docs/ru/plugins/httpsplitting.md
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
```

Or skip some tests:
```
$ gixy --skips http_splitting /etc/nginx/nginx.conf
==================== Results ===================
No issues found.
==================== Summary ===================
Total issues:
Unspecified: 0
Low: 0
Medium: 0
High: 0
```

Or something else, you can find all other `gixy` arguments with the help command: `gixy --help`

You can also make `gixy` use pipes (stdin), like so:

```bash
echo "resolver 1.1.1.1;" | gixy -
```

## Docker usage

Gixy is available as a Docker image [from the Docker hub](https://hub.docker.com/r/getpagespeed/gixy/). To
use it, mount the configuration that you want to analyse as a volume and provide the path to the
configuration file when running the Gixy image.
```
$ docker run --rm -v `pwd`/nginx.conf:/etc/nginx/conf/nginx.conf getpagespeed/gixy /etc/nginx/conf/nginx.conf
```

If you have an image that already contains your nginx configuration, you can share the configuration
with the Gixy container as a volume.
```
$ docker run --rm --name nginx -d -v /etc/nginx
nginx:alpinef68f2833e986ae69c0a5375f9980dc7a70684a6c233a9535c2a837189f14e905
$ docker run --rm --volumes-from nginx dvershinin/gixy /etc/nginx/nginx.conf
==================== Results ===================
No issues found.
==================== Summary ===================
Total issues:
Unspecified: 0
Low: 0
Medium: 0
High: 0
```

# 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.
4 changes: 4 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mkdocs
mkdocs-material
markdown-include
pymdown-extensions
23 changes: 19 additions & 4 deletions gixy/plugins/add_header_redefinition.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class add_header_redefinition(Plugin):
}
"""
summary = 'Nested "add_header" drops parent headers.'
severity = gixy.severity.MEDIUM
severity = gixy.severity.LOW
description = ('"add_header" replaces ALL parent headers. '
'See documentation: http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header')
help_url = 'https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/addheaderredefinition.md'
Expand All @@ -23,6 +23,14 @@ class add_header_redefinition(Plugin):
def __init__(self, config):
super(add_header_redefinition, self).__init__(config)
self.interesting_headers = self.config.get('headers')
# Define secure headers that should escalate severity
self.secure_headers = [
'x-frame-options',
'x-content-type-options',
'x-xss-protection',
'content-security-policy',
'cache-control'
]

def audit(self, directive):
if not directive.is_block:
Expand All @@ -37,7 +45,7 @@ def audit(self, directive):
parent_headers = get_headers(parent)
if not parent_headers:
continue

diff = parent_headers - actual_headers

if len(self.interesting_headers):
Expand All @@ -52,10 +60,17 @@ def _report_issue(self, current, parent, diff):
directives = []
# Add headers from parent level
directives.extend(parent.find('add_header'))
# Add headers from current level
# Add headers from the current level
directives.extend(current.find('add_header'))

# Check if any dropped header is a secure header
is_secure_header_dropped = any(header in self.secure_headers for header in diff)

# Set severity based on whether a secure header was dropped
issue_severity = gixy.severity.MEDIUM if is_secure_header_dropped else self.severity

reason = 'Parent headers "{headers}" was dropped in current level'.format(headers='", "'.join(diff))
self.add_issue(directive=directives, reason=reason)
self.add_issue(directive=directives, reason=reason, severity=issue_severity)


def get_headers(directive):
Expand Down
22 changes: 22 additions & 0 deletions gixy/plugins/version_disclosure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import gixy
from gixy.plugins.plugin import Plugin


class version_disclosure(Plugin):
"""
Syntax for the directive: resolver 127.0.0.1 [::1]:5353 valid=30s;

This comment has been minimized.

Copy link
@LeviPesin

LeviPesin Jan 13, 2024

The description for resolver_external is used here instead of the correct one for some reason?

This comment has been minimized.

Copy link
@dvershinin

dvershinin Jan 14, 2024

Author Owner

Fixed in the new release v0.1.24

"""
summary = 'Do not use external nameservers for "resolver"'
severity = gixy.severity.HIGH
description = 'Using external nameservers allows someone to send spoofed DNS replies to poison the resolver ' \
'cache, causing NGINX to proxy HTTP requests to an arbitrary upstream server.'
help_url = 'https://blog.zorinaq.com/nginx-resolver-vulns/'
directives = ['server_tokens']

def audit(self, directive):
if directive.args[0] in ['on', 'build']:
self.add_issue(
severity=gixy.severity.HIGH,
directive=[directive, directive.parent],
reason="User server_tokens off to hide nginx version"
)
45 changes: 45 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
site_name: Gixy docs
site_description: "Automatic documentation from sources, for Gixy."
site_url: https://gixy.getpagespeed.com/
repo_url: https://github.com/dvershinin/gixy
theme:
name: "material"
palette:
scheme: slate
primary: teal
accent: purple
features:
- navigation.expand
plugins:
- search
nav:
- Overview: index.md
- Plugins:
- Server Side Request Forgery: en/plugins/ssrf.md
- HTTP Splitting: en/plugins/httpsplitting.md
- Problems with referrer/origin validation: en/plugins/origins.md
- Redefining of response headers by "add_header" directive: en/plugins/addheaderredefinition.md
- Request's Host header forgery: en/plugins/hostspoofing.md
- none in valid_referers: en/plugins/validreferers.md
- Multiline response headers: en/plugins/addheadermultiline.md
- Path traversal via misconfigured alias: en/plugins/aliastraversal.md
- If is evil when used in location context: en/plugins/if_is_evil.md
- Allow specified without deny: en/plugins/allow_without_deny.md
- Setting Content-Type via add_header: en/plugins/add_header_content_type.md
- Using external DNS nameservers: https://blog.zorinaq.com/nginx-resolver-vulns/
- Version Disclosure: en/plugins/version_disclosure.md
- 'Blog': 'https://www.getpagespeed.com/posts'
markdown_extensions:
- admonition
- markdown_include.include
- pymdownx.emoji
- pymdownx.magiclink
- pymdownx.superfences
- pymdownx.tabbed
- pymdownx.tasklist
- pymdownx.snippets:
check_paths: true
- toc:
permalink: "¤"
extra:
generator: false
4 changes: 2 additions & 2 deletions tests/plugins/simply/add_header_redefinition/config.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"severity": "MEDIUM"
}
"severity": ["LOW", "MEDIUM"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
server_tokens off;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
server_tokens on;

0 comments on commit 3bfcda4

Please sign in to comment.