IoT Hunter Public Release

IoT_hunter: automating CVE rule creation

Hey Hey people,

Tony here, and I’m proud to be writing about IoT_hunter. In a nutshell it’s a rule creation suite to create rules for simple vulnerabilities.

This code is available in the Emerging Threats Github, and is released under the Apache2.0 License.

Some users of the ET ruleset may have noticed the increase in coverage for a wide variety of exploits over the past year. I’ve been involved in those efforts, focusing on coverage for exploits against IoT devices – IP cameras, NAS devices, SOHO routers, networked controllers, etc.

Usually, vulnerabilities in these devices are fairly simple to exploit, and so the rules to write for them are also somewhat simple as the vast majority I’ve covered attack web-based frameworks. Many of these devices re-use these frameworks for device management, and have common URI structures – for example a large variety of TOTOLINK devices use the URI /cgi-bin/cstecgi.cgi for POST requests needed to make configuration changes. This framework typically has a topicurl http body parameter for defining what feature the user wants to configure. Then there are the parameters related to that topicurl/feature. Several manufacturers use the “goform” framework, others use “boafrm”, and still others decide to roll their own.

Process for covering most IoT device CVEs

There’s a process that I follow when I’m working on coverage for IoT device vulnerabilities

  • If the proof of concept is publicly available, ensure it is archived via the Internet Archive/Wayback machine
  • Determine the class of vulnerability
    • Regarding these vulnerabilities, they typically fall into one of these categories:
      • Buffer Overflow
      • Command Injection
      • Cross Site Scripting (XSS)
      • SQL Injection
      • Directory Traversal
  • Determine the http.method (GET, POST, PUT, etc.)
  • Determine the http.uri string of the vulnerable component
  • Determine the vulnerable parameter in the http request, and where its located (http.uri or http.request_body)
  • Determine the formatting for the parameters (JSON key/value pairs or equal sign key/value pairs)
  • Apply a regular expression based on the type of vulnerability the rule needs to cover via the pcre keyword to identify attempts to exploit the vulnerability.
  • Fill out the rule metadata keywords (msg, reference, classtype, sid, rev, and metadata)
  • Create a snort 2.9.x compatible rule that maintains parity with the Suricata rule

IoT_hunter is my attempt at trying to automate some of this process in order to make writing rules of this nature faster and easier. Let’s get into how it works.

Operation

IoT_hunter can be run with a couple of different options. If it is ran with zero arguments, the program begins a menu-based system where it will ask the user a series of questions to determine the type of rule to write. When the process is completed, the program will output three rules:

  • A Suricata rule that should be compatible with Suricata 5 or higher
  • A Snort 2.9.x formatted rule
  • A special snort rule delivered in a format that we use here internally on the ET team, called “proback formatting”
    • our internal rule publishing platform we submit our rules to handles adding metadata to our rules, so “proback format” strips all metadata keywords from the rule so that our internal platform can manage those metadata keywords, instead

Many of the menu choices have a default value defined, to where a user can just hit enter to continue, and in other cases, the program can detect invalid output and prompt the user to try again. Once the rule has been generated, the menu-driven interface automatically loops, ready to fill out details for the next rule. But the menu-driven interface is not the only means of working with IoT_hunter. there are a number of arguments that can be passed to change how IoT_hunter behaves.

Arguments

IoT_hunter supports the following arguments:

  -i INFILE, --infile INFILE
                        The name of the csv file to generate rules from
  -o OUTFILE, --outfile OUTFILE
                        The name of the file to output generated rules to
  -osu OUTFILE_SURICATA_ONLY, --output-suricata OUTFILE_SURICATA_ONLY
                        Name of the file to output Suricata rules to. Only
                        writes Suricata rules to this file
  -osn OUTFILE_SNORT_ONLY, --output-snort OUTFILE_SNORT_ONLY
                        Name of the file to output Completed Snort rules to.
                        Only writes Snort rules to this file
  -opb OUTFILE_PROBACK_ONLY, --output-proback OUTFILE_PROBACK_ONLY
                        Name of the file to output Proback (minimal)
                        formatted Snorted rules to. Only writes proback
                        formatted rules to this file
  -s SID_NUMBER, --sid_number SID_NUMBER
                        The starting sid number to assign to generated rules.
                        If a sid number is not supplied, defaults to 1000000
                        (local rules range)

We’ll cover -i/ –-infile in a moment. For now, let’s talk about the other options here. -o/--outfileallows users to write the Suricata rule, Standard Snort rule, and proback-formatted Snort rule to a single file, while the options -osu/--output-suricata, -osn/--output-snort, and -opb/--output-proback allow users to output a single rule type to individual files. Additionally the -s option allows users to specify a sid number to begin starting from to assign to rules as they are generated. By default IoT_hunter starts at sid 1000000 (range reserved for local rules – see sidallocation.org), and increments from there. This is useful for users who want to integrate these generate rules into their existing local.rules file, or have a specific range they use for rules they create.

Documentation

The README.md included with the project has EXTREMELY detailed documentation. Options are documented, and the purpose of every CSV field in the -i mode are spelled out. Additionally, a sample CSV file, and sample output from that CSV file is available with the project as well.

Features

Below, I’ll talk about some of the features that I haven’t already mentioned that make IoT_hunter a valuable addition to my threat research and IDS rule writing arsenal. Hopefully if you’re a rule writer or security researcher, you’ll feel the same, and be able to make good use of this tool.

Wayback Machine Archive

Something I had noticed as a part of my efforts to write rules to cover IoT device vulnerabilities is that there are a number of incidents where I will initially find a blog post or a github repo with a proof of concept, or other details that describe how to exploit the vulnerability, then at some point later either the blog post is gone, or the code repository has been deleted. What’s even worse is that there are a wide variety of websites, such as cve.org itself, that will gladly provide reference links to write-ups and/or github code repositories for a given CVE that are dead or otherwise no longer available.

As a countermeasure, I’ve been submitting proof of concept code and/or blog posts to the Internet Archive’s “wayback machine” as I work on them, in an attempt to archive them if they’re deleted. This way if I get busy and have to switch gears and focus on another research topic or task, I don’t have to risk having the proof of concept code disappear from the internet.

This is also something I’ve automated with IoT_hunter. If a user creates an account on archive.org, and configures IoT_hunter with their S3 access key and secret key, the program can automatically make an archive request through their API. Do bear in mind, that there are several sites that use methods meant to counteract bot activity (robots.txt, noindex and nofollow HTML meta tags, proof of work, “turnstiles”, etc.) that will prevent internet archive’s scraper from mirroring the site correctly. Understand that IoT_hunter makes a best-effort attempt to archive the requested URL.

Custom regex, classtype, and vulnerability in msg keyword

Most of the rules that this tool is meant to automate fall in a handful of categories, and apply a pre-canned regular expression. However, if none of the documented regular expressions suit the user’s needs, they can submit their own, or choose to create a rule that doesn’t use one at all. Additionally, when submitting a custom regular expression for the vulnerability, the classtype and a portion of the msg keyword can be customized.

Metadata Enrichment

The original templates for IoT_hunter did not initially include a metadata tag. This is kind of an oversight of mine because we have an internal rule management suite we submit our daily rules to that includes loads of options and drop-downs for generating all of the metadata tags you see in suricata rules released in the ET rulesets.

So, all of this stuff you see in a complete rule in the ET ruleset:

metadata:attack_target Client_Endpoint, created_at 2025_08_11, cve CVE_2025_8088, deployment Perimeter, performance_impact Moderate, confidence High, signature_severity Major, tag Exploit, updated_at 2025_08_11, mitre_tactic_id TA0001, mitre_tactic_name Initial_Access mitre_technique_id T1189, mitre_technique_name Drive_by_Compromise; target:dest_ip;

Was handled by our rule management tool. I’ve since fixed this lack of metadata in rules generated by IoT_hunter, and have taken the liberty of automatically filling out some metadata fields when generating Suricata and Snort (full) rules. Note that if uses choose to enter custom PCRE/classtype/msg, that the amount of metadata will be slightly limited.

Automated/CSV input mode

in addition to the menu-driven interface, IoT_hunter can be fully automated via CSV file input, with the -i/–-infile argument. The git repo has a sample CSV file, and detailed instructions on which columns/values are which, and which ones must be filled in if other options are selected. In total, there are 19 columns, but one of them is just a column for note-taking that isn’t parsed by the program. Depending on the type of rule being generated, and/or depending on whether or not default values are utilized, users can get away with filling out as few as 4 of these fields to generate a functional rule.

Demo

Below is a demo where I just run IoT_hunter with no arguments. In this demo, I’m covering CVE-2025-9938, a buffer overflow against D-Link DI-8400 SOHO routers.

asciicast

Please note that since the rules that are generated are considerably large blocks of text, the output for the suricata version of the generated rule scrolls by very rapidly in this playback. Notice that many of the menu input options include a default value. If the user hits the enter key, then the default option for that menu is chosen. Note that in the recording the default choice of “No” for wayback machine archiving was chosen, and for the PCRE selection, the default value of 1, Buffer Overflow attack was selected.

Now, let’s demonstrate the csv input mode, and the various file output modes:

asciicast

In the demo above there are several vulnerabilities whose details are filled out in the CSV file, IoT_hunter.csv. We then run IoT_hunter in -i mode, use the CSV file, and output the resulting rules in the variety of different output formats (-o, -osu (suricata), -osn (snort), and -opb (snort - proback)). Note that IoT_hunter writes rule files in “append” mode, meaning that if the file name users specify already exists, the program will append to the existing file, instead of overwriting it.

For handling CSV files, I recommend Microsoft Excel, LibreOffice Calc, Modern CSV, cryptpad sheets, there’s even a Visual Studio Code CSV editor plugin available. Of course, you can always use generic text editors, but I would not recommend that.

Future plans

While nothing is set in stone right now, my personal github account has a couple of very simple python scripts that can convert DNS and/or TLS SNI text fields into either suricata DNS or TLS SNI rules. Maybe with a little bit of time, and some elbow grease, I’d like to expand IoT_hunter into a larger automated rule creation suite.

Conclusions

I hope to encourage security researchers, and rule writers to make use of IoT_hunter. The Emerging Threats team, while fairly significant, consists of only 8 rule writers. As such, there is only so much that we can cover in a single day. My hope is, that by providing this tool to the community, that it will act as a massive force multiplier.

As many of you well know, our community acts as our eyes and ears very frequently. The ETOPEN ruleset is an endeavor between us in the ET team, and most of the cybersecurity community. We rely on ETOPEN users to tell us what is working, what is not working, and in many cases, what we may be missing coverage for.

With IoT_hunter, researchers will be able to submit their own rules to the ET ruleset, or generate rules for private use with less friction. Additionally, releasing it as an open-source project allows the community to submit improvements, recommendations, etc. to make it the best it can be. If you find any problems, I encourage you to submit issues. If you have feature requests or other ideas, I also recommend submitting issues for me to see them and maybe integrate them in the future.

As always, happy hunting,

Tony Robinson