Merge branch 'master' into stdin-reader

pull/37/head
Andrew Krasichkov 2017-05-13 14:14:40 +03:00 committed by GitHub
commit 885485e7dc
8 changed files with 103 additions and 13 deletions

57
.dockerignore Normal file
View File

@ -0,0 +1,57 @@
# Byte-compiled / optimized / DLL files
**/__pycache__/
**/*.py[cod]
# C extensions
***/*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
cover
# Translations
**/*.mo
**/*.pot
# PyBuilder
target/
venv/
venv3/
.idea/
# 100% unnecessary for docker image
.*
*.md
docs
rpm
Dockerfile

19
.editorconfig Normal file
View File

@ -0,0 +1,19 @@
root = true
[*]
end_of_file = lf
insert_final_newline = true
[*.{py,j2}]
charset = utf-8
[*.py]
indent_style = space
indent_size = 4
[Makefile]
indent_style = tab
[.travis.yml]
indent_style = space
indent_size = 2

9
Dockerfile Normal file
View File

@ -0,0 +1,9 @@
FROM python:2.7-alpine
ADD . /src
WORKDIR /src
RUN python2 setup.py install
ENTRYPOINT ["gixy"]

View File

@ -1,6 +1,6 @@
# [add_header_redefinition] Redefining of response headers by "add_header" directive
Unfortunately, many people doesn't know how the inheritance of directives works. Most often this leads to misuse of the `add_header` directive while trying to add a new response header on the nested level.
Unfortunately, many people don't know how the inheritance of directives works. Most often this leads to misuse of the `add_header` directive while trying to add a new response header on the nested level.
This feature is mentioned 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.

View File

@ -10,7 +10,7 @@ Spoofing of this header, may leads to a variety of problems, from phishing to SS
Most of the time it's a result of using `$http_host` variable instead of `$host`.
And they are quite different:
* `$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;
* `$host` - 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:
@ -29,4 +29,4 @@ Luckily, all is quite obvious:
## Additional info
* [Host of Troubles Vulnerabilities](https://hostoftroubles.com/)
* [Practical HTTP Host header attacks](http://www.skeletonscribe.net/2013/05/practical-http-host-header-attacks.html)
* [Practical HTTP Host header attacks](http://www.skeletonscribe.net/2013/05/practical-http-host-header-attacks.html)

View File

@ -141,7 +141,7 @@ class IfBlock(Block):
# if ($request_method = POST)
self.variable, self.operand, self.value = args
else:
raise Exception('Unknown "if" definition')
raise Exception('Unknown "if" definition, args: {}'.format(repr(args)))
def __str__(self):
return '{} ({}) {{'.format(self.name, ' '.join(self.args))

View File

@ -1,4 +1,3 @@
import re
import logging
from cached_property import cached_property
@ -31,9 +30,7 @@ class RawParser(object):
"""
Returns the parsed tree.
"""
# Temporary, dirty hack :(
content = self._if_fixer.sub('\\1) )\\2', data)
return self.script.parseString(content, parseAll=True)
return self.script.parseString(data, parseAll=True)
@cached_property
def script(self):
@ -59,10 +56,15 @@ class RawParser(object):
Keyword("=") |
Keyword("~*") | Keyword("~") |
(Literal("-") + (Literal("f") | Literal("d") | Literal("e") | Literal("x")))))
condition = (
condition_body = (
(if_modifier + Optional(space) + value) |
(variable + Optional(space + if_modifier + Optional(space) + value))
)
# This ugly workaround needed to parse unquoted regex with nested parentheses
# pyparsing.nestedExpr doesn't work in some rare cases like: ($http_user_agent ~* \( )
# so we capture all content between parentheses and then parse it:)
# TODO(buglloc): may be use something better?
condition = Regex(r'\(.*\)').setParseAction(lambda s, l, t: condition_body.parseString(t[0][1:-1]))
# rules
include = (
@ -112,9 +114,7 @@ class RawParser(object):
if_block << (
Keyword("if") +
Suppress("(") +
Group(condition) +
Suppress(")") +
Group(
left_bracket +
Optional(sub_block) +

View File

@ -225,11 +225,14 @@ if (!-e "/var/data/$dataset") {
return 503;
}
if ($https_or_slb = (by_slb|https)) {
if ($https_or_slb = (by_\(sl\)b|https)) {
}
if ($host ~* (lori|rage2)\.yandex\.(ru|ua|com|com\.tr)) {
set $x_frame_options ALLOW;
}
if ($request_filename ~* ^.*?/(\d+_)([^/]+)$) {
}
'''
@ -253,11 +256,13 @@ if ($host ~* (lori|rage2)\.yandex\.(ru|ua|com|com\.tr)) {
['if', ['!-e', '/var/data/$dataset'], [
['return', '503']
]],
['if', ['$https_or_slb', '=', '(by_slb|https)'], [
['if', ['$https_or_slb', '=', '(by_\(sl\)b|https)'], [
]],
['if', ['$host', '~*', '(lori|rage2)\.yandex\.(ru|ua|com|com\.tr)'], [
['set', '$x_frame_options', 'ALLOW']
]],
['if', ['$request_filename', '~*', '^.*?/(\d+_)([^/]+)$'], [
]]
]
assert_config(config, expected)