Skip to content

Commit

Permalink
Add protection against HTTP header fingerprinting
Browse files Browse the repository at this point in the history
This forces clients to send only the required headers to perform the
request and no additional headers. If additional headers are sent, the
request will be rejected with the HTTP status code 500 (Bad Request).

Of course the P-Service could still perform HTTP header fingerprinting
attacks, even if it is rejecting the request (which can be validated
externally). But the intention is to force clients to avoid sending
superfluous HTTP headers in the first place, as the requests will fail
else which would render using the service meaningless.
  • Loading branch information
blochberger committed Feb 8, 2017
1 parent aea141e commit fdb53ac
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ https://services.app-pets.org.test/storage/v1/<key>

To upload data use `POST` and attach the asset in binary format to the HTTP body of the request. To download data use `GET` and the value will be attached in binary form to the HTTP body of the response.

An example request for getting a default test vector can be issued with the following command:

```sh
curl 'https://privacyservice.test:8080/storage/v1/fcb6471961829d28270462a2d5cba7fd141d80c608d6df074f8e2e213c187471' --header 'User-Agent:' --header 'Accept:' --cacert 'crt.pem' --raw --silent | base64
```

This should print `IdW1+TjJj3KaW79XN1FaFRJoU2Y5T79IkI7zi/vGkh25lFRU2Of+/2mKR58=` to the terminal output.

Please note that in order to prevent HTTP header fingerprinting attacks, requests containing superfluous HTTP header are rejected. This behaviour can be disabled by passing `--allow-superfluous-headers` to `pservice`.

#### Upload

##### Request
Expand Down
33 changes: 33 additions & 0 deletions pservice
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class TestVectors:
Value = b64decode(b'IdW1+TjJj3KaW79XN1FaFRJoU2Y5T79IkI7zi/vGkh25lFRU2Of+/2mKR58=') # Nonce + Mac + Ciphertext

class HttpHeader:
Host = 'Host'
ContentLength = 'Content-Length'
ContentType = 'Content-Type'

Expand Down Expand Up @@ -79,11 +80,29 @@ def insert_or_replace_key_value(key: bin, value: bin):
db.commit()
db.close()

class Settings:
AllowSuperfluousHeaders = False

class PServiceRequestHandler(http.server.BaseHTTPRequestHandler):

def sanitize_request_headers(self, allowed_headers):
if not Settings.AllowSuperfluousHeaders:
superfluous_headers = set(self.headers) - allowed_headers
if superfluous_headers:
self.send_error(
HttpStatus.BadRequest,
message = HttpStatusString(HttpStatus.BadRequest),
explain = 'Superfluous headers are not allowed, they could be used for fingerprinting attacks: "%s"' %
'", "'.join(sorted(list(superfluous_headers))),
)
return False
return True

def do_GET(self):
m = STORAGE_V1_RX.match(self.path)
if m:
if not self.sanitize_request_headers({HttpHeader.Host}):
return
key = str(m.group(STORAGE_V1_RX_KEY_IDX))
db = open_db()
cursor = db.cursor()
Expand Down Expand Up @@ -114,6 +133,12 @@ class PServiceRequestHandler(http.server.BaseHTTPRequestHandler):
def do_POST(self):
m = STORAGE_V1_RX.match(self.path)
if m:
if not self.sanitize_request_headers({
HttpHeader.Host,
HttpHeader.ContentType,
HttpHeader.ContentLength,
}):
return
key = m.group(STORAGE_V1_RX_KEY_IDX)
try:
contentLength = int(self.headers[HttpHeader.ContentLength])
Expand Down Expand Up @@ -174,6 +199,12 @@ def main():
type = str,
default = crtfile,
)
parser.add_argument(
'--allow-superfluous-headers',
help = 'When set additional HTTP headers will be ignored. A request with additional headers will be rejected else.',
action = 'store_true',
default = Settings.AllowSuperfluousHeaders,
)
args = parser.parse_args()

if args.test:
Expand All @@ -185,6 +216,8 @@ def main():

serverAddress = (args.address, args.port)

Settings.AllowSuperfluousHeaders = args.allow_superfluous_headers

if not os.path.isfile(keyfile):
fatal('Missing file: %s' % keyfile)
if not os.path.isfile(crtfile):
Expand Down

0 comments on commit fdb53ac

Please sign in to comment.