-
Notifications
You must be signed in to change notification settings - Fork 9
AIK-6314 Attack Wave Detection & Stats #474
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 33 commits
ce729d6
7e610ca
0915ab7
9477744
cfce8ee
7f9a4ff
0e19cf2
8a0f52c
35036ff
bf524d1
d69ae55
2dbd697
8d48fae
ea347c6
6a667ed
5ff3886
a28d2be
b2839e3
15b7ccc
19039c7
1260b9f
456da70
ef52fcc
c6bc1c6
28a2c13
6907302
4a2106b
26580b3
17be2f3
76ef4c2
ddd8fd3
afac85b
5d762f8
a28516b
541c655
d6cf778
ea201eb
aeb4878
35c14fc
2901ef3
b6fbd3f
6c67704
7714c5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| from aikido_zen.background_process.routes import Routes | ||
| from aikido_zen.ratelimiting.rate_limiter import RateLimiter | ||
| from aikido_zen.helpers.logging import logger | ||
| from .on_detected_attack_wave import on_detected_attack_wave | ||
| from .update_firewall_lists import update_firewall_lists | ||
| from ..api.http_api import ReportingApiHTTP | ||
| from ..service_config import ServiceConfig | ||
|
|
@@ -20,6 +21,10 @@ | |
| from .update_service_config import update_service_config | ||
| from .on_start import on_start | ||
| from .send_heartbeat import send_heartbeat | ||
| from aikido_zen.vulnerabilities.attack_wave_detection.attack_wave_detector import ( | ||
| AttackWaveDetector, | ||
| ) | ||
| from aikido_zen.context import Context | ||
|
|
||
|
|
||
| class CloudConnectionManager: | ||
|
|
@@ -51,6 +56,7 @@ def __init__(self, block, api, token, serverless): | |
| self.statistics = Statistics() | ||
| self.ai_stats = AIStatistics() | ||
| self.middleware_installed = False | ||
| self.attack_wave_detector = AttackWaveDetector() | ||
|
|
||
| if isinstance(serverless, str) and len(serverless) == 0: | ||
| raise ValueError("Serverless cannot be an empty string") | ||
|
|
@@ -86,6 +92,9 @@ def on_detected_attack(self, attack, context, blocked, stack): | |
| """This will send something to the API when an attack is detected""" | ||
| return on_detected_attack(self, attack, context, blocked, stack) | ||
|
|
||
| def on_detected_attack_wave(self, context: Context, metadata): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CloudConnectionManager class handles too many unrelated concerns: API communication, configuration, statistics, rate limiting, user management, and attack detection. FeedbackPost a comment with the following structure to provide feedback on this finding: Aikido will process this feedback into learnings to give better review comments in the future. |
||
| return on_detected_attack_wave(self, context, metadata) | ||
|
|
||
| def on_start(self): | ||
| """This will send out an Event signalling the start to the server""" | ||
| return on_start(self) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| from aikido_zen.context import Context | ||
| from aikido_zen.helpers.get_current_unixtime_ms import get_unixtime_ms | ||
| from aikido_zen.helpers.logging import logger | ||
| from aikido_zen.helpers.serialize_to_json import serialize_to_json | ||
|
|
||
|
|
||
| def on_detected_attack_wave(connection_manager, context: Context, metadata): | ||
bitterpanda63 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if not connection_manager.token: | ||
| return | ||
| try: | ||
| payload = { | ||
| "type": "detected_attack_wave", | ||
| "time": get_unixtime_ms(), | ||
| "agent": connection_manager.get_manager_info(), | ||
| "attack": {"metadata": metadata, "user": context.user}, | ||
| "request": { | ||
| "ipAddress": context.remote_address, | ||
| "userAgent": context.get_user_agent(), | ||
| "source": context.source, | ||
| }, | ||
| } | ||
| logger.debug(serialize_to_json(payload)) | ||
| connection_manager.api.report( | ||
| connection_manager.token, | ||
| payload, | ||
| connection_manager.timeout_in_sec, | ||
| ) | ||
| except Exception as e: | ||
| logger.debug(e) | ||
| logger.info("Failed to report an attack wave") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| from aikido_zen.context import Context | ||
|
|
||
|
|
||
| class ReportingQueueAttackWaveEvent: | ||
| def __init__(self, context: Context, metadata): | ||
| self.context = context | ||
| self.metadata = metadata |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,8 +96,9 @@ def __reduce__(self): | |
|
|
||
| def set_as_current_context(self): | ||
| """ | ||
| Set the current context | ||
| Set the current context, called every time we change the context. | ||
| """ | ||
| self.reset_cache() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unrelated change?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. best to extract |
||
| current_context.set(self) | ||
|
|
||
| def set_cookies(self, cookies): | ||
|
|
@@ -109,6 +110,9 @@ def set_body(self, body): | |
| except Exception as e: | ||
| logger.debug("Exception occurred whilst setting body: %s", e) | ||
|
|
||
| def reset_cache(self): | ||
| self.parsed_userinput = {} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unrelated change? |
||
|
|
||
| def set_body_internal(self, body): | ||
| """Sets the body and checks if it's possibly JSON""" | ||
| self.body = body | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,7 @@ | |
| """ | ||
|
|
||
| from collections import OrderedDict | ||
| from aikido_zen.helpers.get_current_unixtime_ms import get_unixtime_ms | ||
| import aikido_zen.helpers.get_current_unixtime_ms as internal_time | ||
|
|
||
|
|
||
| class LRUCache: | ||
|
|
@@ -24,7 +24,8 @@ def get(self, key): | |
| if key in self.cache: | ||
| # Check if the item is still valid based on TTL | ||
| if ( | ||
| get_unixtime_ms(monotonic=True) - self.cache[key]["startTime"] | ||
| internal_time.get_unixtime_ms(monotonic=True) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extract this to another PR?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is so we kan monkeypatch, doesnt change anything about the behaviour |
||
| - self.cache[key]["startTime"] | ||
| < self.time_to_live_in_ms | ||
| ): | ||
| return self.cache[key]["value"] # Return the actual value | ||
|
|
@@ -41,7 +42,7 @@ def set(self, key, value): | |
| self.cache.popitem(last=False) # Remove the oldest item | ||
| self.cache[key] = { | ||
| "value": value, | ||
| "startTime": get_unixtime_ms(monotonic=True), | ||
| "startTime": internal_time.get_unixtime_ms(monotonic=True), | ||
| } # Store value and timestamp | ||
|
|
||
| def clear(self): | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.