{"id":13547212,"url":"https://github.com/nuvious/pam-duress","last_synced_at":"2025-05-14T17:06:27.058Z","repository":{"id":39111992,"uuid":"398482261","full_name":"nuvious/pam-duress","owner":"nuvious","description":"A Pluggable Authentication Module (PAM) which allows the establishment of alternate passwords that can be used to perform actions to clear sensitive data, notify IT/Security staff, close off sensitive network connections, etc if a user is coerced into giving a threat actor a password.","archived":false,"fork":false,"pushed_at":"2025-03-24T00:32:17.000Z","size":111,"stargazers_count":1353,"open_issues_count":4,"forks_count":40,"subscribers_count":17,"default_branch":"main","last_synced_at":"2025-05-12T21:10:05.350Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nuvious.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/Contributing.md","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,"zenodo":null}},"created_at":"2021-08-21T06:15:05.000Z","updated_at":"2025-05-12T17:25:40.000Z","dependencies_parsed_at":"2023-01-27T07:01:23.522Z","dependency_job_id":"d71f68a7-e055-423f-acce-b0ef86b3b640","html_url":"https://github.com/nuvious/pam-duress","commit_stats":{"total_commits":39,"total_committers":11,"mean_commits":"3.5454545454545454","dds":0.4871794871794872,"last_synced_commit":"79416748fe4cad33ccdfadacd88cdc193a41089e"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuvious%2Fpam-duress","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuvious%2Fpam-duress/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuvious%2Fpam-duress/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nuvious%2Fpam-duress/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nuvious","download_url":"https://codeload.github.com/nuvious/pam-duress/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254190396,"owners_count":22029632,"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":[],"created_at":"2024-08-01T12:00:52.532Z","updated_at":"2025-05-14T17:06:27.032Z","avatar_url":"https://github.com/nuvious.png","language":"C","funding_links":[],"categories":["C"],"sub_categories":[],"readme":"# Intro\n\nThe PAM Duress is a module designed to allow users to generate 'duress' passwords that when used in place of their\nnormal password will execute arbitrary scripts.\n\nThis functionality could be used to allow someone pressed to give a password under coercion to provide a password that\ngrants access but in the background runs scripts to clean up sensitive data, close connections to other networks to\nlimit lateral movement, and/or to send off a notification or alert (potentially one with detailed information like\nlocation, visible wifi hot-spots, a picture from the camera, a link to a stream from the microphone, etc). You could\neven spawn a process to remove the pam_duress module so the threat actor won't be able to see if the duress module was\navailable.\n\nThis is transparent to the person coercing the password from the user as the duress password will grant authentication\nand drop to the user's shell.\n\nDuress scripts can be generated on an individual user basis or generated globally. Users can also re-use global duress\npasswords to sign their own duress scripts (rare instance where this could actually be useful from a security\nperspective).\n\nContributions to this project are more than welcome; refer to our guidance on making contributions\n[here](docs/Contributing.md).\n\n**Maintainer's Notes:** While this project is primarily developed in Debian\nflavors of linux, the maintainer's will make every attempt to spin up VM's or\ndocker containers to troubleshoot linux specific flavor issues. We also\nwelcome contributions from the community. Below are specific linux variant\ninstallation guides available:\n\n- [Arch Linux](docs/ArchLinux.md)\n\n## Demo\n\n[![Video Demo - https://www.youtube.com/watch?v=ShVYxhHUYdg](https://img.youtube.com/vi/ShVYxhHUYdg/0.jpg)](https://www.youtube.com/watch?v=ShVYxhHUYdg)\n\n## Requirements\n\n```bash\n# Ubuntu/Debian dependencies\nsudo apt-get install build-essential libpam0g-dev libssl-dev\n```\n\n## Build\n\n```bash\nmake\nsudo make install\nmake clean\n# make uninstall\n```\n\n### Debug Build\n\n```bash\n# Debug build provides detailed output to syslog.\\\nsudo make uninstall\nmake clean\nmake debug\nsudo make install\n```\n\n**NOTE**: In debug builds script output IS NOT redirected to /dev/null by default; in non-debug builds it is.\n\n## Configuration\n\nConfiguration of the duress module is split into two different configuration directories. After installation, you'll\nneed to manually create both of them.\n\n```bash\nmkdir -p ~/.duress # Local duress scripts.\nsudo mkdir -p /etc/duress.d  # Global Duress scripts.\n```\n\nAfter creating the directories you can create script and put them in these directories. To assign a password to execute\na particular script you use the duress_sign to create a combination password hash and integrity hash for the script.\n\n```bash\n$\u003e duress_sign ~/.duress/delete_workspace.sh\nPassword: \nConfirm: \nReading /home/user/.duress/delete_workspace.sh, 33...\nDone\n6B8B621EFB8050B83AAC734D56BF9165DC55D709CBAD530C6241E8A352587B3F\n$\u003e chmod -R 500 ~/.duress\n$\u003e ls -al ~/.duress/\ndrwxr-xr-x 2 user user 4096 Aug 20 15:15 .\ndrwxr-xr-x 8 user user 4096 Aug 20 15:11 ..\n-r-x------ 1 user user   33 Aug 20 15:11 delete_workspace.sh\n-r-x------ 1 user user   32 Aug 20 21:49 delete_workspace.sh.sha256\n```\n\n**NOTE:** Scripts will only execute with permission masks of 500, 540, or 550\n\n**NOTE:** User generated duress scripts are only run when they attempt to log in AND use a duress password that one of\ntheir scripts is signed with. If user Jill signs their scripts with the same password as a global script, when they use\nit the global scripts will run, followed by Jill's duress scripts, but Bob, Jane, or Dan's scripts will not be run even\nif they also re-used the same duress scripts.\n\n## PAM Configuration\n\nModify /etc/pam.d/common-auth from the following defaults:\n\n```bash\nauth    [success=1 default=ignore]      pam_unix.so\n\nauth    requisite                       pam_deny.so\n```\n\nTo the below:\n\n```bash\n# Example /etc/pam.d/common-auth\nauth    [success=2 default=ignore]      pam_unix.so\nauth    [success=1 default=ignore]      pam_duress.so\n\nauth    requisite                       pam_deny.so\n```\n\n### Order of Operations Normal Password\n\n- User enters their standard username and password.\n- pam_unix.o confirms them and returns PAM_SUCESS and skips 2 past pam_deny.o.\n\n### Order of Operations Duress Password\n\n- The pam_unix.o module first checks standard username and password, but since the duress password is not the users\n  actual password it fails resulting in a default behavior of 'ignore' per the configuration.\n- PAM then applies the username/password to pam_duress.so which:\n  - Enumerates files in /etc/duress.d/\n  - Checks for files that have matching .sha256 extensions\n  - Hashes the provided password salted with the sha256 hash of the file and compares it with the one stored in the\n    .sha256 extension file\n  - If the hashes match, the script is executed via:\n    - `export PAMUSER=[USERNAME]; /bin/sh [FILE]` for /etc/duress.d scripts (run as root).\n    - `export PAMUSER=[USERNAME]; su - [USERNAME] -c \"/bin/sh [FILE]\"` for ~/.duress scripts (run as the user).\n    - NOTE: PAMUSER is set so global duress scripts can specify the account flagging duress.\n  - Process is repeated for all files in ~/.duress/ for the user attempting to log in.\n  - Finally if ANY script is run, PAM_SUCCESS is return. Otherwise PAM_IGNORE is returned.\n- If PAM_SUCESS is returned PAM will skip 1 and move past pam_deny.o to continue the pam module processes, eventually\n  dropping to an authenticated shell. Otherwise the default 'ignore' behavior is honored moving to pam_deny.o,\n  resulting in a failed authentication.\n\n![Simple Flow Diagram](docs/img/diagram.png \"Simple Flow Diagram\")\n\n## Testing\n\nIt is easy to do a quick test to ensure the duress module is working properly.\n\n```bash\n$\u003e mkdir -p ~/.duress\n$\u003e echo '#!/bin/sh\necho \"Hello World\" \u003e /tmp/test.txt' \u003e ~/.duress/hello.sh\n$\u003e duress_sign ~/.duress/hello.sh\nPassword: # Enter a duress password that is NOT your actual password.\nConfirm: \n$\u003e chmod 500 ~/.duress/hello.sh\n$\u003e chmod 400 ~/.duress/hello.sh.sha256\n$\u003e sudo pam_test $USER\nCredentials accepted.\nPassword: # Enter the password you signed the hello.sh script with.\nAccount is valid. # ...and we still got a valid authentication.\nAuthenticated\n$\u003e cat /tmp/test.txt\nHello World # This shows the test.txt file was created and therefore the script was executed\n$\u003e rm /tmp/test.txt\n$\u003e sudo pam_test $USER\nCredentials accepted.\nPassword: # Now enter your actual password.\nAccount is valid. # Note, Hello World doesn't print.\nAuthenticated\n$\u003e cat /tmp/test.txt\ncat: /tmp/test.txt: No such file or directory # this shows the file wasn't created and therefore the script wasn't executed\n```\n\n## Example Implementations\n\n- [Use Pushover to Notify IT You're Under Duress](docs/examples/Pushover.md)\n\n## Reference\n\n- Initial starter code and test code from [beatgammit/simple-pam](https://github.com/beatgammit/simple-pam).\n- Contribution guidelines built from template provided by\n  [briandk/CONTRIBUTING.md](https://gist.github.com/briandk/3d2e8b3ec8daf5a27a62).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnuvious%2Fpam-duress","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnuvious%2Fpam-duress","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnuvious%2Fpam-duress/lists"}