38 lines
1.8 KiB
Python
38 lines
1.8 KiB
Python
"""Private auth detection must not change attacker-visible responses."""
|
|||
|
|
import http.client
|
||
|
|
import threading
|
||
|
|
from honeypot import Engine, Server
|
||
|
|
|
||
|
|
rows = []
|
||
|
|
engine = Engine(lambda event, **data: rows.append(dict(event=event, **data)))
|
||
|
|
server = Server(('127.0.0.1', 0), engine, serve_guest_files=False)
|
||
|
|
thread = threading.Thread(target=server.serve_forever, daemon=True)
|
||
|
|
thread.start()
|
||
|
|
responses = []
|
||
|
|
try:
|
||
|
|
for _ in range(12):
|
||
|
|
conn = http.client.HTTPConnection('127.0.0.1', server.server_port, timeout=3)
|
||
|
|
conn.request('POST', '/nf/auth/doAuthentication.do', 'login=fixture&passwd=synthetic',
|
||
|
|
{'Content-Type': 'application/x-www-form-urlencoded', 'X-Forwarded-For': '203.0.113.9'})
|
||
|
|
response = conn.getresponse()
|
||
|
|
responses.append((response.status, response.read()))
|
||
|
|
assert not any('brute' in k.lower() or 'rate' in k.lower() for k, _ in response.getheaders())
|
||
|
|
conn.close()
|
||
|
|
assert len(set(responses)) == 1
|
||
|
|
attempts = [r for r in rows if r['event'] == 'auth_attempt']
|
||
|
|
assert [r['attempts_in_window'] for r in attempts] == list(range(1,13))
|
||
|
|
assert all(r['peer'] == '127.0.0.1' and r['request_id'] for r in attempts)
|
||
|
|
alerts = [r for r in rows if r['event'] == 'brute_force_suspected']
|
||
|
|
assert len(alerts) == 1 and alerts[0]['attempts_in_window'] == 10
|
||
|
|
state = engine.session('127.0.0.1')
|
||
|
|
state.auth_started -= 301
|
||
|
|
engine.auth_attempt(state, {'peer': '127.0.0.1'}, '/nf/auth/doAuthentication.do')
|
||
|
|
assert rows[-1]['attempts_in_window'] == 1
|
||
|
|
other = engine.session('192.0.2.1')
|
||
|
|
engine.auth_attempt(other, {'peer': '192.0.2.1'}, '/nf/auth/doAuthentication.do')
|
||
|
|
assert rows[-1]['attempts_in_window'] == 1
|
||
|
|
finally:
|
||
|
|
server.shutdown()
|
||
|
|
server.server_close()
|
||
|
|
thread.join(3)
|
||
|
|
print('PASS: private per-IP auth detection, spoof rejection, fixed-window reset, unchanged responses')
|