{"id":19864187,"url":"https://github.com/sr-lab/gspider","last_synced_at":"2026-03-19T12:05:14.724Z","repository":{"id":75386293,"uuid":"184877550","full_name":"sr-lab/gspider","owner":"sr-lab","description":"Guess success probability slider, for plotting the evolution of password guessing attacks.","archived":false,"fork":false,"pushed_at":"2023-12-30T21:48:38.000Z","size":411,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-04T21:30:15.000Z","etag":null,"topics":["data-structure","dependent-types","password-guessers","probabilistic-models","risk-assessment"],"latest_commit_sha":null,"homepage":"https://sr-lab.github.io/gspider/","language":"Idris","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/sr-lab.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-05-04T09:49:20.000Z","updated_at":"2024-04-28T18:35:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"28b65df1-992f-41c2-a1b4-d53633920d80","html_url":"https://github.com/sr-lab/gspider","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/sr-lab/gspider","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sr-lab%2Fgspider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sr-lab%2Fgspider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sr-lab%2Fgspider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sr-lab%2Fgspider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sr-lab","download_url":"https://codeload.github.com/sr-lab/gspider/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sr-lab%2Fgspider/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29381773,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T20:34:40.886Z","status":"ssl_error","status_checked_at":"2026-02-12T20:23:00.490Z","response_time":55,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["data-structure","dependent-types","password-guessers","probabilistic-models","risk-assessment"],"created_at":"2024-11-12T15:17:44.030Z","updated_at":"2026-02-12T21:32:19.751Z","avatar_url":"https://github.com/sr-lab.png","language":"Idris","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GSPIDER\nGuess success probability slider, for plotting the evolution of password guessing attacks.\n\n![Logo](assets/logo-text-h.svg)\n\n## Overview\nGSPIDER (**g**uess **s**uccess **p**robability sl**ider**) is a utility, written in the dependently-typed programming language [Idris](https://www.idris-lang.org/) that plots the evolution of a password guessing attack against a password dataset. At the moment, it's a proof-of-concept, but it's still usable for small-scale models.\n\n## Building\nYou'll need [Idris](https://www.idris-lang.org/download/) installed to build the project. From the root of the repo:\n\n```bash\ncd ./src\nidris Main.idr -p contrib -o gspider.exe\n```\n\n## Usage\nCall the program like this, from the root of the repo:\n\n```bash\n./src/gspider.exe ./systems/\u003csystem\u003e.sys ./dists/\u003cdistribution\u003e.freqs ./attacks/\u003cattack\u003e.att \u003e ./results.log\n```\n\nHere's an overview of what those options mean:\n\n| Position | Name         | Description                                                                                                                                                                 |\n|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| 1        | System       | This specifies the supported character set of the system you're modelling. Two sample system files come with the software, which you can find in `/systems`.                |\n| 2        | Distribution | This specifies the distribution of passwords on the system you're modelling. Four sample distribution files come with the software, which you can find in `/distributions`. |\n| 3        | Attack       | This specifies the password guessing attack you're modelling. A sample attack comes with this software, which you can find in `/attacks`.                                   |\n\nAs a quick example, from the root of the repo, run the following:\n\n```bash\n./src/gspider.exe ./systems/ascii.sys ./dists/faithwriters.freqs ./attacks/top10k.att \u003e ./results.log\n```\n\nThis will leave you with a file called `results.log` in the repo root, that will contain the guess success probability of the attack after each guess (or at every *frame*). The file will look something like this:\n\n```\nFrame is initial.\n0.005458852610979503\n0.007003810897105778\n0.007621794211556288\n0.007827788649706457\n0.008342774745081882\n0.008342774745081882\n...\n0.2126892573900505\n0.2126892573900505\n0.2126892573900505\n0.2126892573900505\n0.2126892573900505\n0.2126892573900505\nFrame is terminal.\n```\n\nPlotting this data as a line graph makes for some interesting visualisations! The following graph was generated by running the output of the `/attacks/top10k.att` attack on each distribution in `/distributions` through a plotting script based on [Matplotlib](https://matplotlib.org/).\n\n![Graph](docs/svg/paf-dataset-graph.svg)\n\n## Dependent Types\nDependent types are employed for type-safe reasoning across systems in the GSPIDER model:\n\n### Restricted Character-Set String\nAt the core of the probabilistic attack frame type is the restricted character-set string, which is a string type restricted to containing some specific set of characters. It's encoded as below.\n\n```idris\n||| Returns true if the given list of characters `str` contains only characters specified in `chars`.\n|||\n||| @chars the list of permitted characters\n||| @str the string to check\nmadeOf' : (chars : List Char) -\u003e (str : List Char) -\u003e Bool\nmadeOf' chars [] = True\nmadeOf' chars (x :: xs) = elem x chars \u0026\u0026 madeOf' chars xs\n\n\n||| Returns true if the given string `str` contains only characters specified in `chars`.\n|||\n||| @chars the list of permitted characters\n||| @str the string to check\nexport\nmadeOf : (chars : List Char) -\u003e (str : String) -\u003e Bool\nmadeOf chars str = madeOf' chars (unpack str)\n\n\n||| Strings that are restricted to only a specific set of characters.\n|||\n||| @allowed the list of characters allowed in the string\npublic export\ndata RestrictedCharString : (allowed : List Char) -\u003e Type where\n  ||| Constructs a restricted character set string with the specified value.\n  |||\n  ||| @val the value of the string\n  MkRestrictedCharString : (val : String) -\u003e\n                           {auto prf : So (madeOf allowed val)} -\u003e\n                           RestrictedCharString allowed\n```\n\n### Distributions\nA distribution is just a function that maps restricted character-set strings to floating-point values. With `RestrictedCharString` defined, we can go ahead and define the `Distribution` dependent type as below.\n\n```idris\n||| Represents a password probability distribution for a system.\n|||\n||| @s the system\npublic export\nDistribution : (s : System) -\u003e Type\nDistribution s = (RestrictedCharString s) -\u003e Double\n```\n\nProbability distributions themselves are calculated from real-world password frequency distributions using the [Idris probability package](https://github.com/fieldstrength/probability) which draws heavily on the work of Erwig and Kollmansberger in [_Probabilisitic Functional Programming in Haskell_](https://web.engr.oregonstate.edu/~erwig/pfp/).\n\n### Probabilistic Attack Frames\nProbabilistic attack frames are a new datatype, used by GSPIDER, to model guessing attack evolution in a type-safe way. They make use of restricted character-set strings to ensure that both the password distribution and guessing attack relate to passwords containing the same specific subset of characters. It wouldn't make sense, for example, to attempt to input the password `hunter2` on an ATM, which only supports numeric passwords. This is one of the problems that dependently-typed PAFs address (see below).\n\n```idris\n||| Represents a probabilistic attack frame.\n|||\n||| @ n the number of pending guesses at this frame\n||| @ m the number of made guesses at this frame\npublic export\ndata AttackFrame : (s : System) -\u003e (n : Nat) -\u003e (m : Nat) -\u003e Type where\n  -- Included for completeness.\n  Empty : (d : Distribution s) -\u003e\n          AttackFrame s Z Z\n  Initial : (p : Vect (S n) (RestrictedCharString s)) -\u003e\n            (d : Distribution s) -\u003e\n            AttackFrame s (S n) Z\n  Ongoing : (p : Vect (S n) (RestrictedCharString s)) -\u003e\n            (g : Vect (S m) (RestrictedCharString s)) -\u003e\n            (d : Distribution s) -\u003e\n            (q : Double) -\u003e\n            AttackFrame s (S n) (S m)\n  Terminal : (g : Vect (S m) (RestrictedCharString s)) -\u003e\n             (d : Distribution s) -\u003e\n             (q : Double) -\u003e\n             AttackFrame s Z (S m)\n```\n\n## Computing Lockout Policies\nThis utility comes with a file `/scripts/lockout.py` which allows you to compute a _lockout policy_ for a system based on the output yielded by GSPIDER. A lockout policy is just the minimum number of guesses we can allow a user to make while keeping the probability of a guessing attack being successful against a randomly-chosen account on our system below a certain acceptable threshold. Try it out like this (must be from the `/scripts` directory):\n\n```bash\npython lockout.py ../systems/ascii.sys ../dists/elitehacker.freqs ../attacks/top10k.att 0.05\n```\n\nYou'll get some nice friendly output that looks like this:\n\n```\nA maximum of 14 guesses can be made by this attack in order for guess success probability to remain below 0.05.\n```\n\n## Limitations\nGSPIDER is still very much in the proof-of-concept stage. With this in mind, there are a few limitations:\n\n* Frequency file/attack size are limited to a few thousand entries each. I this this might be stack space related, but more digging is required.\n\n## Acknowledgements\nI would like to thank the following people for making this project possible:\n\n* [Daniel Miessler](https://github.com/danielmiessler) and all the contributors and maintainers of [SecLists](https://github.com/danielmiessler/SecLists) which contains password datasets used to create the example distribution files in this repository.\n* [Cliff Harvey](https://github.com/fieldstrength) and all the contributors and maintainers of [the probability library](https://github.com/fieldstrength/probability) which this project makes use of.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsr-lab%2Fgspider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsr-lab%2Fgspider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsr-lab%2Fgspider/lists"}