attackstr 0.1.0

Grammar-based security payload generation — TOML-driven, composable, encoding-aware
Documentation

attackstr

Grammar-driven security payload generation for scanners, fuzzers, and taint-aware tooling.

attackstr loads TOML grammars, expands contexts and variables deterministically, applies built-in or custom encodings, and returns payloads with source metadata. It is designed for crates.io use, not just the wider Santh workspace.

Features

  • TOML grammar loading from strings or directories
  • Configurable include/exclude/runtime filtering
  • Built-in encoding transforms plus custom encoders
  • Marker injection for taint-tracking payloads
  • Streaming iterator API with iter_payloads
  • Serde support across payload/config/grammar types
  • Mutation helpers for lightweight evasive variants

Installation

[dependencies]
attackstr = "0.1"

Quick Start

use attackstr::{PayloadConfig, PayloadDb};

let mut db = PayloadDb::with_config(
    PayloadConfig::builder()
        .max_per_category(16)
        .deduplicate(true)
        .build(),
);

db.load_toml(
    r#"
[grammar]
name = "basic-xss"
sink_category = "xss"

[[contexts]]
name = "quoted-attr"
prefix = "\""
suffix = "\""

[[techniques]]
name = "svg-onload"
template = "<svg/onload={handler}>"

[[handlers]]
value = "alert(1)"
value = "confirm(1)"

[[encodings]]
name = "raw"
transform = "identity"
"#,
)?;

let payloads = db.payloads("xss");
assert_eq!(payloads.len(), 2);
assert!(payloads[0].text.contains("<svg/onload="));

# Ok::<(), attackstr::PayloadError>(())

Grammar Format

Each grammar defines:

  • [grammar] metadata
  • [[contexts]] for prefix/suffix breakout wrappers
  • [[techniques]] for templates
  • [[encodings]] for final transforms
  • [[variables]]-style arrays for substitution sets

Example:

[grammar]
name = "sql-basic"
sink_category = "sql-injection"
description = "Foundational SQLi payloads"
target_runtime = ["php", "node"]

[[contexts]]
name = "single-quoted"
prefix = "'"
suffix = "-- "

[[techniques]]
name = "boolean-tautology"
template = "{prefix} OR {tautology} {suffix}"
confidence = 0.95
expected_pattern = "(?i)sql|syntax|mysql"

[[tautologies]]
value = "1=1"
value = "'a'='a'"

[[encodings]]
name = "raw"
transform = "identity"

[[encodings]]
name = "url"
transform = "url_encode"

Iterator APIs

Use cached category access when you want slices:

use attackstr::PayloadDb;

let mut db = PayloadDb::new();
db.load_toml(
    r#"
[grammar]
name = "demo"
sink_category = "cmdi"

[[techniques]]
name = "ping"
template = "; ping -c 1 {host}"

[[hosts]]
value = "127.0.0.1"
"#,
)?;

let payloads = db.payloads("cmdi");
assert_eq!(payloads.len(), 1);
# Ok::<(), attackstr::PayloadError>(())

Use streaming iteration when you want to avoid materializing the whole category:

use attackstr::PayloadDb;

let mut db = PayloadDb::new();
db.load_toml(
    r#"
[grammar]
name = "streaming"
sink_category = "xss"

[[techniques]]
name = "basic"
template = "<script>{call}</script>"

[[calls]]
value = "alert(1)"
value = "confirm(1)"
"#,
)?;

let streamed: Vec<_> = db.iter_payloads("xss").map(|payload| payload.text).collect();
assert_eq!(streamed.len(), 2);
# Ok::<(), attackstr::PayloadError>(())

For in-memory payload sets, StaticPayloads supports iter() and iter_category() as well.

TOML Config End To End

PayloadConfigFile can load runtime behavior and grammar directories from TOML:

use attackstr::PayloadDb;

let temp = tempfile::tempdir()?;
let grammar_dir = temp.path().join("grammars");
std::fs::create_dir(&grammar_dir)?;

std::fs::write(
    grammar_dir.join("xss.toml"),
    r#"
[grammar]
name = "xss"
sink_category = "xss"

[[techniques]]
name = "basic"
template = "<script>alert(1)</script>"
"#,
)?;

std::fs::write(
    temp.path().join("attackstr.toml"),
    r#"
deduplicate = true
grammar_dirs = ["./grammars"]
"#,
)?;

let (mut db, errors) = PayloadDb::load_config_and_grammars(temp.path().join("attackstr.toml"))?;
assert!(errors.is_empty());
assert_eq!(db.payloads("xss").len(), 1);
# Ok::<(), attackstr::PayloadError>(())

Custom Encodings

use attackstr::PayloadDb;

let mut db = PayloadDb::new();
db.register_encoding("reverse", |input| input.chars().rev().collect());

db.load_toml(
    r#"
[grammar]
name = "custom-encoding"
sink_category = "demo"

[[techniques]]
name = "one"
template = "abc"

[[encodings]]
name = "reversed"
transform = "reverse"
"#,
)?;

assert_eq!(db.payloads("demo")[0].text, "cba");
# Ok::<(), attackstr::PayloadError>(())

Examples

Run the bundled examples:

cargo run --example basic
cargo run --example toml_config

Development

  • cargo fmt
  • cargo check
  • cargo test

Contribution workflow is documented in CONTRIBUTING.md.

License

MIT