Skip to content

Commit 4a5cbf6

Browse files
authored
Merge pull request Pennyw0rth#1172 from A3-N/fix/connection-thread-safety
fix: add thread-safety to failed login counters
2 parents 08ad1cc + 623e6aa commit 4a5cbf6

1 file changed

Lines changed: 18 additions & 15 deletions

File tree

nxc/connection.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import contextlib
66

77
from os.path import isfile
8-
from threading import BoundedSemaphore
8+
from threading import BoundedSemaphore, Lock
99
from functools import wraps
1010
from time import sleep
1111
from ipaddress import ip_address
@@ -25,6 +25,7 @@
2525
from impacket.krb5.ccache import CCache
2626

2727
sem = BoundedSemaphore(1)
28+
fail_lock = Lock()
2829
global_failed_logins = 0
2930
user_failed_logins = {}
3031

@@ -315,26 +316,28 @@ def call_modules(self):
315316
def inc_failed_login(self, username):
316317
global global_failed_logins, user_failed_logins
317318

318-
if username not in user_failed_logins:
319-
user_failed_logins[username] = 0
319+
with fail_lock:
320+
if username not in user_failed_logins:
321+
user_failed_logins[username] = 0
320322

321-
user_failed_logins[username] += 1
322-
global_failed_logins += 1
323-
self.failed_logins += 1
323+
user_failed_logins[username] += 1
324+
global_failed_logins += 1
325+
self.failed_logins += 1
324326

325327
def over_fail_limit(self, username):
326328
global global_failed_logins, user_failed_logins
327329

328-
if global_failed_logins == self.args.gfail_limit:
329-
return True
330+
with fail_lock:
331+
if global_failed_logins == self.args.gfail_limit:
332+
return True
330333

331-
if self.failed_logins == self.args.fail_limit:
332-
return True
334+
if self.failed_logins == self.args.fail_limit:
335+
return True
333336

334-
if username in user_failed_logins and self.args.ufail_limit == user_failed_logins[username]: # noqa: SIM103
335-
return True
337+
if username in user_failed_logins and self.args.ufail_limit == user_failed_logins[username]: # noqa: SIM103
338+
return True
336339

337-
return False
340+
return False
338341

339342
def query_db_creds(self):
340343
"""Queries the database for credentials to be used for authentication.
@@ -481,8 +484,6 @@ def try_credentials(self, domain, username, owned, secret, cred_type, data=None)
481484
- NTLM-hash (/kerberos)
482485
- AES-key
483486
"""
484-
if self.over_fail_limit(username):
485-
return False
486487
if self.args.continue_on_success and owned:
487488
return False
488489

@@ -498,6 +499,8 @@ def try_credentials(self, domain, username, owned, secret, cred_type, data=None)
498499
sleep(value)
499500

500501
with sem:
502+
if self.over_fail_limit(username):
503+
return False
501504
if cred_type == "plaintext":
502505
if self.kerberos:
503506
self.logger.debug("Trying to authenticate using Kerberos")

0 commit comments

Comments
 (0)