Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ build:
python setup.py bdist_wheel --universal sdist

publish:
twine upload dist/gixy-`grep -oP "(?<=version\s=\s['\"])[^'\"]*(?=['\"])" gixy/__init__.py`*
twine upload dist/gixy_ng-`grep -oP "(?<=version\s=\s['\"])[^'\"]*(?=['\"])" gixy/__init__.py`*

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Right now Gixy can find:
* [[resolver_external] Using external DNS nameservers](https://blog.zorinaq.com/nginx-resolver-vulns/)
* [[version_disclosure] Using insecure values for server_tokens](https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/version_disclosure.md)
* [[try_files_is_evil_too] The try_files directive is evil without open_file_cache](https://www.getpagespeed.com/server-setup/nginx-try_files-is-evil-too)
* [[proxy_pass_normalized] proxy_pass will decode and normalize paths when specified with a path](https://joshua.hu/proxy-pass-nginx-decoding-normalizing-url-path-dangerous#nginx-proxy_pass)

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
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Right now Gixy can find:
* [[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 insecure values for server_tokens](en/plugins/version_disclosure.md)
* [[proxy_pass_normalized] Using proxy_pass with a pathname will normalize and decode the requested path when proxying](https://joshua.hu/proxy-pass-nginx-decoding-normalizing-url-path-dangerous#nginx-proxy_pass)

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
6 changes: 3 additions & 3 deletions gixy/cli/argparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ def parse(self, stream):
continue

white_space = '\\s*'
key = '(?P<key>[^:=;#\s]+?)'
value = white_space + '[:=\s]' + white_space + '(?P<value>.+?)'
comment = white_space + '(?P<comment>\\s[;#].*)?'
key = r'(?P<key>[^:=;#\s]+?)'
value = white_space + r'[:=\s]' + white_space + r'(?P<value>.+?)'
comment = white_space + r'(?P<comment>\s[;#].*)?'

key_only_match = re.match('^' + key + comment + '$', line)
if key_only_match:
Expand Down
44 changes: 44 additions & 0 deletions gixy/plugins/proxy_pass_normalized.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import re
import gixy
from gixy.plugins.plugin import Plugin

class proxy_pass_normalized(Plugin):
r"""
This plugin detects if there is any path component (slash or more)
after the host in a proxy_pass directive.
Example flagged directives:
proxy_pass http://backend/;
proxy_pass http://backend/foo/bar;
"""

summary = 'Detect path after host in proxy_pass (potential URL decoding issue)'
severity = gixy.severity.LOW
description = ("A slash immediately after the host in proxy_pass leads to the path being decoded and normalized before proxying downstream, leading to unexpected behavior related to encoded slashes.")
help_url = 'https://joshua.hu/proxy-pass-nginx-decoding-normalizing-url-path-dangerous#nginx-proxy_pass'
directives = ['proxy_pass']

def __init__(self, config):
super(proxy_pass_normalized, self).__init__(config)
self.parse_uri_re = re.compile(r'(?P<scheme>[^?#/)]+://)?(?P<host>[^?#/)]+)(?P<path>/.*)?')

def audit(self, directive):
proxy_pass_arg = directive.args[0]
if not proxy_pass_arg:
return

parsed = self.parse_uri_re.match(proxy_pass_arg)

if not parsed:
return

if not parsed.group('path'):
return

self.add_issue(
severity=self.severity,
directive=[directive, directive.parent],
reason=(
"Found a slash (and possibly more) after the hostname in proxy_pass. "
"This can lead to path decoding issues."
)
)
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ nav:
- 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/
- Unsafe path decoding with proxy_pass: https://joshua.hu/proxy-pass-nginx-decoding-normalizing-url-path-dangerous#nginx-proxy_pass
- Version Disclosure: en/plugins/version_disclosure.md
- 'Blog': 'https://www.getpagespeed.com/posts'
markdown_extensions:
Expand Down
2 changes: 2 additions & 0 deletions requirements.dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ coverage>=4.3
flake8>=3.2
tox>=2.7.0
pytest-xdist
setuptools
twine
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
location / {
proxy_pass http://server/;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
location / {
proxy_pass http://downstream;
}
Loading