{"id":13845661,"url":"https://github.com/AvalZ/WAF-A-MoLE","last_synced_at":"2025-07-12T03:31:42.799Z","repository":{"id":38318124,"uuid":"210328720","full_name":"AvalZ/WAF-A-MoLE","owner":"AvalZ","description":"A guided mutation-based fuzzer for ML-based Web Application Firewalls","archived":false,"fork":false,"pushed_at":"2024-03-06T13:38:21.000Z","size":4652,"stargazers_count":171,"open_issues_count":1,"forks_count":31,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-11-21T19:38:41.413Z","etag":null,"topics":["adversarial-machine-learning","machine-learning","web","web-application-firewall","web-security"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AvalZ.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-23T10:35:18.000Z","updated_at":"2024-11-18T04:35:44.000Z","dependencies_parsed_at":"2024-11-21T19:31:17.406Z","dependency_job_id":"28edf8a7-a06b-4752-920c-f462d8865360","html_url":"https://github.com/AvalZ/WAF-A-MoLE","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AvalZ/WAF-A-MoLE","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AvalZ%2FWAF-A-MoLE","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AvalZ%2FWAF-A-MoLE/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AvalZ%2FWAF-A-MoLE/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AvalZ%2FWAF-A-MoLE/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AvalZ","download_url":"https://codeload.github.com/AvalZ/WAF-A-MoLE/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AvalZ%2FWAF-A-MoLE/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264930715,"owners_count":23684916,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adversarial-machine-learning","machine-learning","web","web-application-firewall","web-security"],"created_at":"2024-08-04T17:03:32.208Z","updated_at":"2025-07-12T03:31:41.806Z","avatar_url":"https://github.com/AvalZ.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# WAF-A-MoLE\n\nA *guided mutation-based fuzzer* for ML-based Web Application Firewalls, inspired by AFL and based on the [FuzzingBook](https://www.fuzzingbook.org) by Andreas Zeller et al.\n\nGiven an input SQL injection query, it tries to produce a *semantic invariant* query that is able to bypass the target WAF.\nYou can use this tool for assessing the robustness of your product by letting WAF-A-MoLE explore the solution space to find dangerous \"blind spots\" left uncovered by the target classifier.\n\n\n[![Python Version](https://img.shields.io/badge/Python-3.7-green.svg)](https://www.python.org/downloads/release/python-374/)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/AvalZ/WAF-A-MoLE/blob/master/LICENSE)\n[![Documentation Status](https://readthedocs.org/projects/waf-a-mole/badge/?version=latest)](https://waf-a-mole.readthedocs.io/en/latest/?badge=latest)\n\n# Architecture\n\n![WAF-A-MoLE Architecture](docs/fig/WAF-A-MoLE.png)\n\nWAF-A-MoLE takes an initial payload and inserts it in the payload **Pool**, which manages a priority queue ordered by the WAF confidence score over each payload.\n\nDuring each iteration, the head of the payload Pool is passed to the **Fuzzer**, where it gets randomly mutated, by applying one of the available mutation operators.\n\n\n## Mutation operators\n\nMutations operators are all *semantics-preserving* and they leverage the high expressive power of the SQL language (in this version, MySQL).\n\nBelow are the mutation operators available in the current version of WAF-A-MoLE.\n\n| Mutation | Example |\n| --- | --- |\n|  Case Swapping | `admin' OR 1=1#` ⇒ `admin' oR 1=1#` |\n| Whitespace Substitution | `admin' OR 1=1#` ⇒ `admin'\\t\\rOR\\n1=1#`|\n| Comment Injection | `admin' OR 1=1#` ⇒ `admin'/**/OR 1=1#`|\n| Comment Rewriting | `admin'/**/OR 1=1#` ⇒ `admin'/*xyz*/OR 1=1#abc`|\n| Integer Encoding | `admin' OR 1=1#` ⇒ `admin' OR 0x1=(SELECT 1)#`|\n| Operator Swapping | `admin' OR 1=1#` ⇒ `admin' OR 1 LIKE 1#`|\n| Logical Invariant | `admin' OR 1=1#` ⇒ `admin' OR 1=1 AND 0\u003c1#`|\n| Number Shuffling | `admin' OR 1=1#` ⇒ `admin' OR 2=2#`|\n\n# How to cite us\n\nWAF-A-MoLE implements the methodology presented in [\"WAF-A-MoLE: Evading Web Application Firewalls through Adversarial Machine Learning\"](https://dl.acm.org/doi/abs/10.1145/3341105.3373962).\nA pre-print of our article can also be found on [arXiv](https://arxiv.org/abs/2001.01952).\n\nIf you want to cite us, please use the following (BibTeX) reference:\n```\n@inproceedings{demetrio20wafamole,\n  title={WAF-A-MoLE: evading web application firewalls through adversarial machine learning},\n  author={Demetrio, Luca and Valenza, Andrea and Costa, Gabriele and Lagorio, Giovanni},\n  booktitle={Proceedings of the 35th Annual ACM Symposium on Applied Computing},\n  pages={1745--1752},\n  year={2020}\n}\n```\n\n# Running WAF-A-MoLE\n\n## Prerequisites\n\n* [numpy](https://numpy.org/)\n* [keras](https://keras.io/)\n* [scikit-learn](https://scikit-learn.org/stable/)\n* [joblib](https://github.com/joblib/joblib)\n* [sqlparse](https://github.com/andialbrecht/sqlparse)\n* [networkx](https://networkx.github.io/)\n* [Click](https://click.palletsprojects.com/en/7.x/)\n\n## Setup\n\n`pip install -r requirements.txt`\n\n## Sample Usage\n\nYou can evaluate the robustness of your own WAF, or try WAF-A-MoLE against some example classifiers.\nIn the first case, have a look at the [Model](https://github.com/AvalZ/waf-a-mole/blob/master/wafamole/models/model.py) class. Your custom model needs to implement this class in order to be evaluated by WAF-A-MoLE.\nWe already provide wrappers for *sci-kit learn* and *keras* classifiers that can be extend to fit your feature extraction phase (if any).\n\n### Help\n\n`wafamole --help`\n```\nUsage: wafamole [OPTIONS] COMMAND [ARGS]...\n\nOptions:\n  --help  Show this message and exit.\n\nCommands:\n  evade  Launch WAF-A-MoLE against a target classifier.\n```\n\n\n`wafamole evade --help`\n```\nUsage: wafamole evade [OPTIONS] MODEL_PATH PAYLOAD\n\n  Launch WAF-A-MoLE against a target classifier.\n\nOptions:\n  -T, --model-type TEXT     Type of classifier to load\n  -t, --timeout INTEGER     Timeout when evading the model\n  -r, --max-rounds INTEGER  Maximum number of fuzzing rounds\n  -s, --round-size INTEGER  Fuzzing step size for each round (parallel fuzzing\n                            steps)\n  --threshold FLOAT         Classification threshold of the target WAF [0.5]\n  --random-engine TEXT      Use random transformations instead of evolution\n                            engine. Set the number of trials\n  --output-path TEXT        Location were to save the results of the random\n                            engine. NOT USED WITH REGULAR EVOLUTION ENGINE\n  --help                    Show this message and exit.\n\n```\n\n### Evading example models\n\nWe provide some pre-trained models you can have fun with, located in [wafamole/models/custom/example_models](https://github.com/AvalZ/waf-a-mole/tree/master/wafamole/models/custom/example_models).\nThe classifiers we used are listed in the table below.\n\n| Classifier name| Algorithm\n| --- | --- |\n| [WafBrain](https://github.com/BBVA/waf-brain) | Recurrent Neural Network |\n| [ML-Based-WAF](https://github.com/vladan-stojnic/ML-based-WAF) | Non-Linear SVM |\n| [ML-Based-WAF](https://github.com/vladan-stojnic/ML-based-WAF) | Stochastic Gradient Descent |\n| [ML-Based-WAF](https://github.com/vladan-stojnic/ML-based-WAF) | AdaBoost |\n| Token-based | Naive Bayes |\n| Token-based | Random Forest |\n| Token-based | Linear SVM |\n| Token-based | Gaussian SVM |\n| [SQLiGoT](https://www.sciencedirect.com/science/article/pii/S0167404816300451) - Directed Proportional | Gaussian SVM |\n| [SQLiGoT](https://www.sciencedirect.com/science/article/pii/S0167404816300451) - Directed Unproportional | Gaussian SVM |\n| [SQLiGoT](https://www.sciencedirect.com/science/article/pii/S0167404816300451) - Undirected Proportional | Gaussian SVM |\n| [SQLiGoT](https://www.sciencedirect.com/science/article/pii/S0167404816300451) - Undirected Unproportional | Gaussian SVM |\n\nIn addition to ML-based WAF, WAF-a-MoLE supports also rule-based WAFs.\nSpecifically, it provides a wrapper for the ModSecurity WAF equipped with the [OWASP Core Rule Set (CRS)](https://coreruleset.org), based on the [pymodsecurity](https://github.com/pymodsecurity/pymodsecurity) project.\n\n#### WAF-BRAIN - Recurrent Neural Newtork\n\nBypass the pre-trained WAF-Brain classifier using a `admin' OR 1=1#` equivalent.\n\n```bash\nwafamole evade --model-type waf-brain wafamole/models/custom/example_models/waf-brain.h5  \"admin' OR 1=1#\"\n```\n\n#### ML-Based-WAF - Non-Linear SVM (with original WAF-A-MoLE dataset)\nBypass the pre-trained ML-Based-WAF SVM classifier using a `admin' OR 1=1#` equivalent. \n\n```bash\nwafamole evade --model-type mlbasedwaf wafamole/models/custom/example_models/mlbasedwaf_svc.dump  \"admin' OR 1=1#\"\n```\n\n#### ML-Based-WAF - Non-Linear SVM (with SQLiV5/SQLiV3 datasets)\nBypass the pre-trained ML-Based-WAF SVM classifier using a `admin' OR 1=1#` equivalent. Note that SQLiV5 is a dataset sourced from [Kaggle](https://www.kaggle.com/datasets/syedsaqlainhussain/sql-injection-dataset) expanded with a series of queries generated by WAF-A-MoLE itself, as a proof of concept that WAF-A-MoLE queries can enhance the robustness of a WAF with retraining. Use `mlbasedwaf_svc_sqliv3.dump` to bypass the WAF trained with the original Kaggle dataset (SQLiV3).\n\n```bash\nwafamole evade --model-type mlbasedwaf wafamole/models/custom/example_models/mlbasedwaf_svc_sqliv5.dump  \"admin' OR 1=1#\"\n```\n\n#### ML-Based-WAF - Stochastic Gradient Descent (SGD)\nBypass the pre-trained ML-Based-WAF SGD classifier using a `admin' OR 1=1#` equivalent. \n\n```bash\nwafamole evade --model-type mlbasedwaf wafamole/models/custom/example_models/mlbasedwaf_sgd.dump  \"admin' OR 1=1#\"\n```\n\n#### ML-Based-WAF - AdaBoost\nBypass the pre-trained ML-Based-WAF AdaBoost classifier using a `admin' OR 1=1#` equivalent (takes longer than other models, at around 2 to 5 minutes of runtime). \n\n```bash\nwafamole evade --model-type mlbasedwaf wafamole/models/custom/example_models/mlbasedwaf_ada.dump  \"admin' OR 1=1#\"\n```\n#### Token-based - Naive Bayes\n\nBypass the pre-trained token-based Naive Bayes classifier using a `admin' OR 1=1#` equivalent.\n\n```bash\nwafamole evade --model-type token wafamole/models/custom/example_models/naive_bayes_trained.dump  \"admin' OR 1=1#\"\n```\n\n#### Token-based - Random Forest\n\nBypass the pre-trained token-based Random Forest classifier using a `admin' OR 1=1#` equivalent.\n\n```bash\nwafamole evade --model-type token wafamole/models/custom/example_models/random_forest_trained.dump  \"admin' OR 1=1#\"\n```\n\n#### Token-based - Linear SVM\n\nBypass the pre-trained token-based Linear SVM classifier using a `admin' OR 1=1#` equivalent.\n\n```bash\nwafamole evade --model-type token wafamole/models/custom/example_models/lin_svm_trained.dump  \"admin' OR 1=1#\"\n```\n\n#### Token-based - Gaussian SVM\n\nBypass the pre-trained token-based Gaussian SVM classifier using a `admin' OR 1=1#` equivalent.\n\n```bash\nwafamole evade --model-type token wafamole/models/custom/example_models/gauss_svm_trained.dump  \"admin' OR 1=1#\"\n```\n\n#### SQLiGoT\n\nBypass the pre-trained SQLiGOT classifier using a `admin' OR 1=1#` equivalent.\nUse **DP**, **UP**, **DU**, or **UU** for (respectivly) Directed Proportional, Undirected Proportional, Directed Unproportional and Undirected Unproportional.\n\n```bash\nwafamole evade --model-type DP wafamole/models/custom/example_models/graph_directed_proportional_sqligot \"admin' OR 1=1#\"\n```\n\n#### OWASP ModSecurity CRS - Rule-based WAF\n\nBypass the OWASP ModSecurity CRS using a `admin' OR 1=1#` equivalent.\nThe user also need to specify the [Paranoia Level](https://coreruleset.org/docs/concepts/paranoia_levels/) as well as the path to locate the CRS rules (e.g., `/etc/coreruleset`).\n\n```bash\nwafamole evade --model-type modsecurity_pl[1-4] /etc/coreruleset \"admin' OR 1=1#\"\n```\n\n**BEFORE LAUNCHING EVALUATION ON SQLiGoT**\n\nThese classifiers are more robust than the others, as the feature extraction phase produces vectors with a more complex structure, and all pre-trained classifiers have been strongly regularized.\nIt may take hours for some variants to produce a payload that achieves evasion (see Benchmark section).\n\n**Note on newer ML-Based-WAF models**\n\nSome models based on a slightly modified version of vladan-stojnic's [ML-Based-WAF](https://github.com/vladan-stojnic/ML-based-WAF) have been recently added, from an extension of WAF-A-MoLE entitled [wafamole++](https://github.com/nidnogg/wafamole-plusplus) by [nidnogg](https://github.com/nidnogg). Testing the AdaBoost model might take a longer time than usual (usually 2 to 5 minutes).\n\nThere are variants trained with the [SQLiV5.json](https://github.com/nidnogg/sqliv5-dataset) dataset, while most use the original SQL injection from WAF-A-MoLE dataset by default. \n\nA Google Colaboratory [notebook](https://colab.research.google.com/drive/1YPHb8lrbxN6RjJWjwvM1upvsVoV7de8r?usp=sharing) is provided with the training routines for some of these models, using the original WAF-A-MoLE dataset (modified to the SQLiV5 format). Any dataset can be used as long as they're in the same format as SQLiV5.json.\n\n### Custom adapters\n\nFirst, create a custom Model class that implements the `extract_features` and `classify` methods.\n\n```python\nclass YourCustomModel(Model):\n    def extract_features(self, value: str):\n    \t# TODO: extract features\n        feature_vector = your_custom_feature_function(value)\n        return feature_vector\n\n    def classify(self, value):\n    \t# TODO: compute confidence\n        confidence = your_confidence_eval(value)\n        return confidence\n```\n\nThen, create an object from the model and instantiate an `engine` object that uses your model class.\n\n```python\nmodel = YourCustomModel() #your init\nengine = EvasionEngine(model)\nresult = engine.evaluate(payload, max_rounds, round_size, timeout, threshold)\n```\n\n# Benchmark\n\nWe evaluated WAF-A-MoLE against all our example models.\n\nThe plot below shows the time it took for WAF-A-MoLE to mutate the `admin' OR 1=1#` payload until it was accepted by each classifier as benign.\n\nOn the *x* axis we have time (in seconds, logarithmic scale).\nOn the *y* axis we have the *confidence* value, i.e., how sure a classifier is that a given payload is a SQL injection (in percentage).\n\nNotice that being \"50% sure\" that a payload is a SQL injection is equivalent to flipping a coin.\nThis is the usual classification threshold: if the confidence is lower, the payload is classified as benign.\n\n![Benchmark over time](docs/fig/benchmark_over_time.png)\n\nExperiments were performed on [DigitalOcean *Standard* Droplets](https://www.digitalocean.com/products/droplets/).\n\n# Contribute\n\nQuestions, bug reports and pull requests are welcome.\n\nIn particular, if you are interested in expanding this project, we look for the following contributions:\n\n1. New WAF adapters\n1. New mutation operators\n1. New search algorithms\n\n# Team\n\n* [Luca Demetrio](http://csec.it/people/luca_demetrio/) - [CSecLab](https://csec.it/), DIBRIS, University of Genova\n* [Andrea Valenza](https://avalz.it/) - [CSecLab](https://csec.it/), DIBRIS, University of Genova\n* [Gabriele Costa](https://www.imtlucca.it/it/gabriele.costa) - [SysMA](http://sysma.imtlucca.it/), IMT Lucca\n* [Giovanni Lagorio](https://csec.it/people/giovanni_lagorio/) - [CSecLab](https://csec.it/), DIBRIS, University of Genova\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAvalZ%2FWAF-A-MoLE","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAvalZ%2FWAF-A-MoLE","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAvalZ%2FWAF-A-MoLE/lists"}