mohawk
mohawk copied to clipboard
`seen_nonce` warning in `Sender.accept_response`
I'm using v0.3.4 on python 3.6 and I'm seeing the following warning being logged during Sender.accept_response calls: seen_nonce was None; not checking nonce. You may be vulnerable to replay attacks
I'm confused since there is no nonce in the server's Server-Authorization response header. Is this possibly a bug or am I just misunderstanding?
Hi. Thanks for taking time to file an issue.
This message is warning you that that the request did not contain a nonce and that your receiver is not configured to check a nonce. This message is expected. By not handling nonces, an attacker may be able to intercept a request and replay it without altering the content. This might not do any damage, though. It depends on how your app processes repeat requests. More info: https://mohawk.readthedocs.io/en/latest/usage.html#using-a-nonce-to-prevent-replay-attacks
If I am misunderstanding, maybe you can provide me with the sender / receiver code (or at least the receiver part) as an example.
Feel free to re-open the issue!
Thanks for responding @kumar303.
Here is a reproducer that may help:
from mohawk import Receiver, Sender
from mohawk.util import parse_authorization_header
credentials = {'id': 'abc123', 'key': 'superSecr3t!', 'algorithm': 'sha256'}
url = 'https://example.com/test?id=1'
method = 'GET'
request_data = ''
request_content_type = ''
sender = Sender(credentials, url, method, request_data, request_content_type)
request_auth_header = sender.request_header
if not parse_authorization_header(request_auth_header).get('nonce'):
raise Exception('missing nonce!')
receiver = Receiver(
lambda id: credentials,
request_auth_header,
url,
method,
content=request_data,
content_type=request_content_type,
seen_nonce=lambda id, nonce, ts: False
)
response_content = '{"ok":true}'
response_content_type = 'application/json'
response_header = receiver.respond(content=response_content, content_type=response_content_type)
# this line prints: 'seen_nonce was None; not checking nonce. You may be vulnerable to replay attacks'
sender.accept_response(
response_header,
content=response_content,
content_type=response_content_type,
)
As you can see, the client / sender is causing the warning, not the server / receiver.
Thanks for the code sample. I haven't tried to run this but I think it's because your Sender is not configured for nonce checking. When you run sender.accept_response(), the sender is verifying the signature of the server's response. It is a pretty wild edge case but it is theoretically possible that an attacker could replay server responses. If you were to add Sender(seen_nonce=lambda ...) then the warning would go away.
@kumar303 There is no nonce returned in the server's response (see https://github.com/hueniverse/hawk#response-payload-validation). Just to be sure, I also checked the reference client and it doesn't have any reference to a nonce (see https://github.com/hueniverse/hawk/blob/b117bce695bc6b531a5afda8dbbc46267759efdb/lib/client.js#L141).
Maybe I'm just misunderstanding but I don't think it makes sense to have a seen_nonce check on the client / sender.
Sample code which demonstrates my statement above:
from mohawk import Receiver, Sender
from mohawk.util import parse_authorization_header
credentials = {'id': 'abc123', 'key': 'superSecr3t!', 'algorithm': 'sha256'}
url = 'https://example.com/test?id=1'
method = 'GET'
request_data = ''
request_content_type = ''
def seen_nonce(id, nonce, ts):
print(nonce)
return False
sender = Sender(credentials, url, method, request_data, request_content_type, seen_nonce=seen_nonce)
request_auth_header = sender.request_header
if not parse_authorization_header(request_auth_header).get('nonce'):
raise Exception('missing nonce!')
receiver = Receiver(
lambda id: credentials,
request_auth_header,
url,
method,
content=request_data,
content_type=request_content_type,
seen_nonce=seen_nonce
)
response_content = '{"ok":true}'
response_content_type = 'application/json'
response_header = receiver.respond(content=response_content, content_type=response_content_type)
# this line raises `KeyError: 'nonce'` because there is no nonce in the response
sender.accept_response(
response_header,
content=response_content,
content_type=response_content_type,
)
Oh, whoops! That definitely looks like a bug in mohawk. Thanks for all the detailed info.