<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hashir Saud Khan</title>
    <description>The latest articles on DEV Community by Hashir Saud Khan (@hashirsaudkhan).</description>
    <link>https://dev.to/hashirsaudkhan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1256353%2F88066382-91b2-4814-a05e-284da6bed06b.jpeg</url>
      <title>DEV Community: Hashir Saud Khan</title>
      <link>https://dev.to/hashirsaudkhan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hashirsaudkhan"/>
    <language>en</language>
    <item>
      <title>Blocking Malware with AWS Network Firewall (Bump-in-the-wire Design) 🛑🛡️</title>
      <dc:creator>Hashir Saud Khan</dc:creator>
      <pubDate>Fri, 17 Jul 2026 06:59:35 +0000</pubDate>
      <link>https://dev.to/hashirsaudkhan/blocking-malware-with-aws-network-firewall-bump-in-the-wire-design-1l6</link>
      <guid>https://dev.to/hashirsaudkhan/blocking-malware-with-aws-network-firewall-bump-in-the-wire-design-1l6</guid>
      <description>&lt;p&gt;Blocking Malware Downloads with AWS Network Firewall (Stateful Suricata Rules)&lt;/p&gt;

&lt;h2&gt;
  
  
  INTRO
&lt;/h2&gt;

&lt;p&gt;Ran a hands-on lab that simulates a real-world security incident: end users at a&lt;br&gt;
company kept accidentally downloading malware after visiting a specific website.&lt;br&gt;
IT had already identified the malicious URLs. My job was to harden the network&lt;br&gt;
perimeter using AWS Network Firewall so those files could never reach an internal&lt;br&gt;
host again. Here's a full walkthrough of what I did and why each step matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  SCENARIO
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Company: AnyCompany (lab scenario)&lt;/li&gt;
&lt;li&gt;Role: Security Engineer&lt;/li&gt;
&lt;li&gt;Problem: Users downloading malware from a known-bad site&lt;/li&gt;
&lt;li&gt;Given: Exact URLs hosting the malicious files&lt;/li&gt;
&lt;li&gt;Goal: Block access to those files at the network layer, without touching
every single endpoint individually&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ARCHITECTURE
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A pre-configured EC2 instance (TestInstance) sits in an isolated perimeter
subnet — used purely to simulate an end user's browser/download behavior&lt;/li&gt;
&lt;li&gt;An AWS Network Firewall (LabFirewall) sits between the VPC and the internet&lt;/li&gt;
&lt;li&gt;The firewall is driven by a Firewall Policy (LabFirewallPolicy), which
determines stateless vs. stateful packet handling&lt;/li&gt;
&lt;li&gt;A Stateful Rule Group written in Suricata syntax is attached to the policy
to do the actual content-based blocking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flow: TestInstance -&amp;gt; Network Firewall (stateless check -&amp;gt; stateful rule&lt;br&gt;
group) -&amp;gt; Internet -&amp;gt; malicious site (now blocked)&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 1: CONFIRM THE PROBLEM IS REAL
&lt;/h2&gt;

&lt;p&gt;Before touching any config, I logged into TestInstance via Systems Manager&lt;br&gt;
Session Manager and reproduced the issue:&lt;/p&gt;

&lt;p&gt;wget &lt;a href="http://malware.wicar.org/data/js_crypto_miner.html" rel="noopener noreferrer"&gt;http://malware.wicar.org/data/js_crypto_miner.html&lt;/a&gt;&lt;br&gt;
  wget &lt;a href="http://malware.wicar.org/data/java_jre17_exec.html" rel="noopener noreferrer"&gt;http://malware.wicar.org/data/java_jre17_exec.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both returned HTTP 200 OK and downloaded successfully. This confirms the&lt;br&gt;
malicious files are currently reachable and the firewall isn't inspecting&lt;br&gt;
or blocking this traffic yet. Never skip this step in real environments —&lt;br&gt;
you need a documented "before" state to prove the fix worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 2: SWITCH THE FIREWALL POLICY TO STATEFUL INSPECTION
&lt;/h2&gt;

&lt;p&gt;By default, a lot of basic firewall configs only do stateless filtering&lt;br&gt;
(rules based on IP/port only, no context, no content awareness). To block&lt;br&gt;
based on URI content, traffic needs to go through the stateful rules engine.&lt;/p&gt;

&lt;p&gt;In the Firewall Policy (LabFirewallPolicy):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateless default actions -&amp;gt; Edit&lt;/li&gt;
&lt;li&gt;Fragmented packets: "Use the same actions for all packets"&lt;/li&gt;
&lt;li&gt;Action: "Forward to stateful rule groups"&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stateless engine = fast, no context, evaluates each packet in isolation&lt;br&gt;
Stateful engine = slower, but understands traffic flow/direction and lets&lt;br&gt;
you write much more precise rules (and log everything)&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 3: WRITE A STATEFUL RULE GROUP (SURICATA SYNTAX)
&lt;/h2&gt;

&lt;p&gt;Created a new Stateful Rule Group:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rule group type: Stateful&lt;/li&gt;
&lt;li&gt;Format: Suricata compatible rule string&lt;/li&gt;
&lt;li&gt;Evaluation order: Action order&lt;/li&gt;
&lt;li&gt;Name: StatefulRuleGroup&lt;/li&gt;
&lt;li&gt;Capacity: 100&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rules used:&lt;/p&gt;

&lt;p&gt;drop http $HOME_NET any -&amp;gt; $EXTERNAL_NET 80 (msg:"MALWARE custom solution"; flow: to_server,established; classtype:trojan-activity; sid:2002001; content:"/data/js_crypto_miner.html"; http_uri; rev:1;)&lt;/p&gt;

&lt;p&gt;drop http $HOME_NET any -&amp;gt; $EXTERNAL_NET 80 (msg:"MALWARE custom solution"; flow: to_server,established; classtype:trojan-activity; sid:2002002; content:"/data/java_jre17_exec.html"; http_uri; rev:1;)&lt;/p&gt;

&lt;p&gt;What this actually does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;drop        -&amp;gt; silently block the packet (no reset sent back)&lt;/li&gt;
&lt;li&gt;http        -&amp;gt; only inspect HTTP traffic&lt;/li&gt;
&lt;li&gt;$HOME_NET -&amp;gt; $EXTERNAL_NET -&amp;gt; traffic leaving your VPC toward the internet&lt;/li&gt;
&lt;li&gt;flow: to_server, established -&amp;gt; only match on established outbound requests&lt;/li&gt;
&lt;li&gt;content: "..."; http_uri -&amp;gt; match specifically on the URI path, not
just the domain or IP — this is the key advantage over basic
IP/domain blocklists&lt;/li&gt;
&lt;li&gt;sid -&amp;gt; unique rule ID (required by Suricata)&lt;/li&gt;
&lt;li&gt;classtype: trojan-activity -&amp;gt; categorizes the threat for logging/alerting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  STEP 4: ATTACH THE RULE GROUP TO THE FIREWALL
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Firewalls -&amp;gt; LabFirewall -&amp;gt; Associated firewall policy -&amp;gt; LabFirewallPolicy&lt;/li&gt;
&lt;li&gt;Stateful rule groups -&amp;gt; Add unmanaged stateful rule groups&lt;/li&gt;
&lt;li&gt;Select StatefulRuleGroup -&amp;gt; Add stateful rule group&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the step that actually activates the rules — until this point, the&lt;br&gt;
rule group existed but had zero effect on real traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 5: VALIDATE
&lt;/h2&gt;

&lt;p&gt;Back on TestInstance, re-ran the exact same commands:&lt;/p&gt;

&lt;p&gt;wget &lt;a href="http://malware.wicar.org/data/js_crypto_miner.html" rel="noopener noreferrer"&gt;http://malware.wicar.org/data/js_crypto_miner.html&lt;/a&gt;&lt;br&gt;
  wget &lt;a href="http://malware.wicar.org/data/java_jre17_exec.html" rel="noopener noreferrer"&gt;http://malware.wicar.org/data/java_jre17_exec.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This time: "HTTP request sent, awaiting response..." and then it just hangs&lt;br&gt;
(had to Ctrl+C out of it) — no 200 OK, no file downloaded. The firewall is&lt;br&gt;
silently dropping matching requests before they ever complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  WHY THIS MATTERS (KEY TAKEAWAYS)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;URI-level blocking beats plain IP/domain blocklists. Attackers can move
files to a new path on the same domain — a rule matching http_uri content
catches the actual malicious payload path, not just the host&lt;/li&gt;
&lt;li&gt;Stateless vs. stateful matters. If your firewall policy defaults to
stateless-only, none of your Suricata content rules will ever fire&lt;/li&gt;
&lt;li&gt;This is a form of IDS/IPS at the network edge without needing a separate
third-party appliance — useful as one layer in a defense-in-depth strategy&lt;/li&gt;
&lt;li&gt;Always validate with a "before" and "after" test. Screenshots/logs of
both states are what actually prove the fix to stakeholders/auditors&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  TOOLS/SERVICES USED
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AWS Network Firewall&lt;/li&gt;
&lt;li&gt;AWS VPC&lt;/li&gt;
&lt;li&gt;Amazon EC2&lt;/li&gt;
&lt;li&gt;Suricata rule syntax (IDS/IPS)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  AWS #CyberSecurity #NetworkFirewall #CloudSecurity #InfoSec #Suricata
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>networking</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
