DEV Community

Cover image for An AI Agent Hit 600 Firewalls in 55 Countries With No Human
Gabriel Anhaia
Gabriel Anhaia

Posted on

An AI Agent Hit 600 Firewalls in 55 Countries With No Human


Between January 11 and February 18, 2026 (38 days), an AI-driven offensive tool ran credential harvesting and reconnaissance against FortiGate firewall management interfaces in 55 countries. It landed on more than 600 of them. No human in the loop.

Per The Hacker News' reporting on Amazon Threat Intelligence's findings, the operator was a low-skill actor whose capability gap was filled by commercial generative-AI tools (Hacker News writeup). Foresiet's April 2026 review of AI security incidents catalogues this campaign alongside five other documented AI-driven incidents in a 15-day window. Dark Reading's writeup frames the attacker as an AI-armed amateur. Any operator with a credential list and an LLM can now run this.

No FortiGate zero-day was used. The campaign worked by hammering exposed management ports against weak, single-factor credentials. That detail matters because it tells you what the agent automated. Not exploit development. The agent took over the parallelizable work: spraying credentials, parsing responses, deciding when to escalate, and pivoting once inside.

Detection logic built around human attackers misses agent-shaped traffic. The shape is detectable if you instrument for it.

What changes when the attacker is an agent

Four shifts matter for detection.

Pacing flattens. A human attacker runs in bursts: a long session, a coffee break, another session. An agent's session has no coffee break. The request rate per source is more uniform across hours and days. Long-and-flat replaces bursty.

Target selection broadens. A human picks targets that look interesting. An agent's target list is whatever its enumerator produced: the entire IPv4 management-port hit list, sorted by whatever heuristic the agent generated. Reconnaissance against unrelated assets becomes parallel and constant rather than focused and sequential.

The third shift is in evasion. An agent told "do not get rate-limited" implements rate limits with too much mathematical regularity. Sleep intervals come out too regular. Jitter, when added, is usually uniform; human-driven traffic is closer to log-normal. If you plot inter-arrival times for a fingerprint cluster and the histogram looks like a clean rectangle, that is a tell on its own — a human-driven session bunches and gaps in ways no agent loop does without effort.

Retry semantics are the fourth. Failed logins do not trigger frustrated rapid-fire retries. The agent emits backoff curves that look like SDK code: exponential, capped, deterministic, resumed after the interval the agent's own retry policy specifies. The shape of the curve gives the script away even when the requests themselves look benign.

No single signal is conclusive: agents can be tuned to look human, and a tight script can look agent-shaped. Reliable detection comes from clusters of these signals on the same source, or coordinated across sources. ProArch's writeup of the FortiGate campaign reports the same combination — globally distributed sources, near-uniform inter-request timing — which suggests target breadth at a scale no human team would sit through.

Four detection signals worth wiring today

None of the signals below are new. What is new is pointing them at one question: is the source agent-shaped?

The first signal is a cross-IP behavioral fingerprint. When a single tool runs from many IPs (residential proxies, VPS pools), the addresses differ but the request fingerprint collapses: header order, TLS JA4, retry timing, body shape. Cluster on the fingerprint and ignore the IP. A fingerprint cluster spanning fifty ASNs tells you more than any single IP's reputation score.

The second is low-and-slow pacing. Agents under instruction to avoid rate limits produce inter-request intervals with abnormally low variance. A coefficient of variation under roughly 0.2 on inter-arrival times across a sustained window (minutes to hours) is uncommon in human traffic. Compute it per fingerprint and calibrate against your own logs before you trust the threshold.

The third is parallel reconnaissance against unrelated assets. Track reconnaissance touches across asset boundaries. A source touching firewall-mgmt.foo.example, crm.bar.example, and legacy-app.baz.example within minutes is doing breadth-first enumeration at agent speed, even though those three orgs share no infrastructure. This is the cheapest signal to surface and the one most often missed; per-org SOCs do not see across boundaries. ISACs and managed-detection providers do.

The fourth is agent-shaped retry patterns. After a 401, the next request lands at exactly N seconds, then 2N, then 4N, with sub-millisecond consistency on the deltas. Humans do not produce this. Naive scripts produce it. Agents produce it consistently because the agent's own retry-policy code is deterministic.

A note on confidence. Each signal alone has false-positive rates that make it useless for blocking. With two or more of the four firing on the same fingerprint within a window, the false-positive rate drops fast. Put this logic upstream of any blocking decision. A labeling pipeline scores sources; a policy engine decides what to do with the scores.

A Python detector for low-and-slow agent-shaped traffic

The script below takes a stream of timestamped auth-attempt records and flags sources whose inter-arrival timing is too regular to be human. It is the fourth signal made concrete and the easiest one to deploy as a starting point.

import math
from collections import defaultdict, deque

WINDOW = 50            # last N requests per source
MIN_REQS = 30          # need this many before scoring
CV_THRESHOLD = 0.2     # coefficient of variation cutoff
MIN_SPAN_SEC = 600     # span must cover at least 10 minutes

state: dict[str, deque] = defaultdict(
    lambda: deque(maxlen=WINDOW)
)


def observe(source_id: str, ts: float):
    state[source_id].append(ts)


def score(source_id: str) -> dict | None:
    times = list(state[source_id])
    if len(times) < MIN_REQS:
        return None
    deltas = [b - a for a, b in zip(times, times[1:])]
    span = times[-1] - times[0]
    if span < MIN_SPAN_SEC:
        return None
    mean = sum(deltas) / len(deltas)
    if mean == 0:
        return None
    var = sum((d - mean) ** 2 for d in deltas) / len(deltas)
    cv = math.sqrt(var) / mean
    return {
        "source": source_id,
        "n": len(times),
        "span_sec": span,
        "mean_interval_sec": mean,
        "cv": cv,
        "agent_shaped": cv < CV_THRESHOLD,
    }


def flagged():
    for src in list(state.keys()):
        s = score(src)
        if s and s["agent_shaped"]:
            yield s
Enter fullscreen mode Exit fullscreen mode

Two tuning notes. The window of 50 requests is chosen so a single agent's retry burst does not dominate the variance calculation; raise it for higher-volume sources. The CV threshold of 0.2 is deliberately loose. In practice you may find a tighter cutoff (closer to 0.15) works better once you fold in residential-proxy jitter on the attacker side. Calibrate against your own auth logs by computing CV for known-human and known-bot populations and picking the gap.

The detector runs in O(1) per observation and a few microseconds per score call. Wire it into the auth-log tail, score every minute, push the agent_shaped flag as a label on the source, and let your existing rate-limiter or WAF make the policy decision. Do not block on this — false positives at the network edge are operational pain. Label, and let downstream rules act on the label: require step-up MFA on agent-shaped sources, or raise login-attempt cost via proof-of-work or interactive challenge.

What the FortiGate campaign tells you about defaults

The campaign succeeded on devices that exposed management ports to the public internet with single-factor credentials. The agent did not need a vulnerability. It needed devices configured the way devices have been configured since 2010 and a credential list. According to Insurance Journal's coverage, some compromised victims reportedly appeared to be on a path toward ransomware deployment — a detail that should land with anyone running infrastructure-of-record gear with management interfaces reachable from the internet.

Three configuration changes that would have neutralized this specific campaign:

  • Management interfaces reachable only from a VPN or jump host, never the public internet.
  • Multi-factor authentication on management auth, with hardware keys for high-privilege accounts.
  • Login-failure budgets per source IP and per identity, with automatic lockout below a threshold.

None of those are new advice. The campaign worked because the universe of devices for which that advice has not been followed remains large, and an agent can sweep that universe in days where a human team needed months. The cost-benefit on jump-host placement and MFA on management auth shifted under your feet: those controls were always cheap, and they now block the entire attack class instead of just slowing it down.

How to think about agent attackers from here

The honest framing is that the FortiGate campaign is a low-skill operator with high-skill tooling. The attacker did not need to understand FortiOS internals. The attacker needed an LLM that can write the credential-spraying loop, parse responses, decide when a session is worth escalating, and orchestrate the result across 600 successful landings without losing track. Read together, The Hacker News' coverage and Foresiet's broader 2026 trend piece point to the same conclusion: the historical bottleneck on offensive operations was operator time and skill, and commercial generative-AI tools relax both at once.

The defensive answer is to make existing detection logic agent-aware. Wire signals that fire on uniformity, breadth, and stylized retry alongside the volume and exploit-signature rules you already have. Treat those signals as labels and let policy decide what to do with them. Make the default response a step-up MFA requirement. And put management interfaces behind a jump host while you are at it.

If this was useful

The AI Agents Pocket Guide covers the architecture patterns on both sides of this fence — building agents that are operationally well-behaved, and designing systems that detect when an external agent is operating against them. The detection signals above are the short version. The book is the longer one.

AI Agents Pocket Guide

Top comments (0)