Skip to content

Commit

Permalink
Swapped the user and global (#27)
Browse files Browse the repository at this point in the history
* Swapped the user and global
run order per issue #21 intent.

* Forgot to pull main becore starting.
Updated version, changelog, spelling
pass on all files, and linted with clang-tidy.

* Removed dockerfile inadvertently comitted to repo.

* Fixed a minor grammar issue and
nit-picked line lengths.
  • Loading branch information
nuvious authored Apr 4, 2022
1 parent 051d00e commit 04e607f
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 99 deletions.
62 changes: 36 additions & 26 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
# Changelog
- 1.0.0
- Initial commit of prototype tested on Debian 10.
- 1.0.1
- Fixed some potential memory leaks, linted, and adjusted documentation.
- 1.1.0
- Fixed privilege escalation vulnerability that could allow an unprivileged user to run commands as root.
- 1.1.1
- OSX support and makefile improvements contributed by [cormacrelf](https://github.com/cormacrelf).
- 1.1.2
- Fixed issue #11; error when running scripts under /etc/duress.d resulting in account unavailable error.
- Fixed issue #10; documentation or pushover script.
- Added link to demo video.
- Removed unnecessary casts for malloc calls.
- Created dbg_log wrapper function to clean up DEBUG compile flag use.
- 1.1.3
- Fixed privilege escalation issue #16 [reported by wowaname](https://news.ycombinator.com/item?id=28276200) from Hacker News.
- Redirected output of all scripts/binaries to /dev/null by convention.
- 1.1.4
- Memory leak resolved by [Jürgen Hötzel on github](https://github.com/juergenhoetzel).
- 1.1.5
- Makefile improvements by [Prateek Ganguli on github](https://github.com/pganguli). Debug build path now added.
- 1.1.6
- Removal of unnecessary intermediate shell. Contribution by [Jürgen Hötzel on github](https://github.com/juergenhoetzel).
- Debug builds will not redirect output of stderr and stdout to /dev/null by default to support testing/debugging.
- 1.1.7
- Removal of exit statements; replaced with NULL to preven the PAM application exiting. Contribution by [Jürgen Hötzel on github](https://github.com/juergenhoetzel).

- 2.0.0
- **BREAKING CHANGE:** Changed run order of scripts to run user scripts first and system scripts after. This enables
the possibility of uninstalling pam-duress as a system level operation.
- Linted with clang-tidy. No linter errors in files.
- Changed outputs of errno to strerror(errno).
- General spelling pass.
- 1.1.7
- Removal of exit statements; replaced with NULL to prevent the PAM application exiting. Contribution by
[Jürgen Hötzel on github](https://github.com/juergenhoetzel).
- 1.1.6
- Removal of unnecessary intermediate shell. Contribution by
[Jürgen Hötzel on github](https://github.com/juergenhoetzel).
- Debug builds will not redirect output of stderr and stdout to /dev/null by default to support testing/debugging.
- 1.1.5
- Makefile improvements by [Prateek Ganguli on github](https://github.com/pganguli). Debug build path now added.
- 1.1.4
- Memory leak resolved by [Jürgen Hötzel on github](https://github.com/juergenhoetzel).
- 1.1.3
- Fixed privilege escalation issue #16 [reported by wowaname](https://news.ycombinator.com/item?id=28276200) from
Hacker News.
- Redirected output of all scripts/binaries to /dev/null by convention.
- 1.1.2
- Fixed issue #11; error when running scripts under /etc/duress.d resulting in account unavailable error.
- Fixed issue #10; documentation or pushover script.
- Added link to demo video.
- Removed unnecessary casts for malloc calls.
- Created dbg_log wrapper function to clean up DEBUG compile flag use.
- 1.1.1
- OSX support and makefile improvements contributed by [cormacrelf](https://github.com/cormacrelf).
- 1.1.0
- Fixed privilege escalation vulnerability that could allow an unprivileged user to run commands as root.
- 1.0.1
- Fixed some potential memory leaks, linted, and adjusted documentation.
- 1.0.0
- Initial commit of prototype tested on Debian 10.
77 changes: 50 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
# Intro

The PAM Duress is a module designed to allow users to generate 'duress' passwords that when used in place of their normal password will execute arbitrary scripts.
The PAM Duress is a module designed to allow users to generate 'duress' passwords that when used in place of their
normal password will execute arbitrary scripts.

This functionality could be used to allow someone pressed to give a password under coercion to provide a password that grants access but in the background runs scripts to clean up sensitive data, close connections to other networks to limit lateral movement, and/or to send off a notification or alert (potentially one with detailed information like location, visible wifi hotspots, a picture from the camera, a link to a stream from the microphone, etc). You could even spawn a process to remove the pam_duress module so the threat actor won't be able to see if the duress module was available.
This functionality could be used to allow someone pressed to give a password under coercion to provide a password that
grants access but in the background runs scripts to clean up sensitive data, close connections to other networks to
limit lateral movement, and/or to send off a notification or alert (potentially one with detailed information like
location, visible wifi hot-spots, a picture from the camera, a link to a stream from the microphone, etc). You could
even spawn a process to remove the pam_duress module so the threat actor won't be able to see if the duress module was
available.

This is transparent to the person coercing the password from the user as the duress password will grant authentication and drop to the user's shell.
This is transparent to the person coercing the password from the user as the duress password will grant authentication
and drop to the user's shell.

Duress scripts can be generated on an individual user basis or generated globally. Users can also re-use global duress passwords to sign their own duress scripts (rare instance where this could actually be useful from a security perspective).
Duress scripts can be generated on an individual user basis or generated globally. Users can also re-use global duress
passwords to sign their own duress scripts (rare instance where this could actually be useful from a security
perspective).

Contributions to this project are more than welcome; refer to our guidance on making contributions [here](docs/Contributing.md).
Contributions to this project are more than welcome; refer to our guidance on making contributions
[here](docs/Contributing.md).

## Demo

Expand Down Expand Up @@ -44,14 +54,16 @@ sudo make install

## Configuration

Configuration of the duress module is split into two different configuration directories. After installation, you'll need to manually create both of them.
Configuration of the duress module is split into two different configuration directories. After installation, you'll
need to manually create both of them.

```bash
mkdir -p ~/.duress # Local duress scripts.
sudo mkdir -p /etc/duress.d # Global Duress scripts.
```

After creating the directories you can create script and put them in these directories. To assign a password to execute a particular script you use the duress_sign to create a combination password hash and integrity hash for the script.
After creating the directories you can create script and put them in these directories. To assign a password to execute
a particular script you use the duress_sign to create a combination password hash and integrity hash for the script.

```bash
$> duress_sign ~/.duress/delete_workspace.sh
Expand All @@ -70,11 +82,15 @@ drwxr-xr-x 8 user user 4096 Aug 20 15:11 ..

**NOTE:** Scripts will only execute with permission masks of 500, 540, or 550

**NOTE:** User generated duress scripts are only run when they attempt to log in AND use a duress password that one of their scripts is signed with. If user Jill signs their scripts with the same password as a global script, when they use it the global scripts will run, followed by Jill's duress scripts, but Bob, Jane, or Dan's scripts will not be run even if they also re-used the same duress scripts.
**NOTE:** User generated duress scripts are only run when they attempt to log in AND use a duress password that one of
their scripts is signed with. If user Jill signs their scripts with the same password as a global script, when they use
it the global scripts will run, followed by Jill's duress scripts, but Bob, Jane, or Dan's scripts will not be run even
if they also re-used the same duress scripts.

## PAM Configuration

Modify /etc/pam.d/common-auth from the following defaults:

```bash
auth [success=1 default=ignore] pam_unix.so

Expand All @@ -92,24 +108,30 @@ auth requisite pam_deny.so
```

### Order of Operations Normal Password
- User enters their standard username and password.
- pam_unix.o confirms them and returns PAM_SUCESS and skips 2 past pam_deny.o.

- User enters their standard username and password.
- pam_unix.o confirms them and returns PAM_SUCESS and skips 2 past pam_deny.o.

### Order of Operations Duress Password
- The pam_unix.o module first checks standard username and password, but since the duress password is not the users actual password it fails resulting in a default behavior of 'ignore' per the configuration.
- PAM then applies the username/password to pam_duress.so which:
- Enumerates files in /etc/duress.d/
- Checks for files that have matching .sha256 extensions
- Hashes the provided password salted with the sha256 hash of the file and compares it with the one stored in the .sha256 extension file
- If the hashes match, the script is executed via:
- `export PAMUSER=[USERNAME]; /bin/sh [FILE]` for /etc/duress.d scripts (run as root).
- `export PAMUSER=[USERNAME]; su - [USERNAME] -c "/bin/sh [FILE]"` for ~/.duress scripts (run as the user).
- NOTE: PAMUSER is set so global duress scripts can specify the account flagging duress.
- Process is repeated for all files in ~/.duress/ for the user attempting to log in.
- Finally if ANY script is run, PAM_SUCCESS is return. Otherwise PAM_IGNORE is returned.
- If PAM_SUCESS is returned PAM will skip 1 and move past pam_deny.o to continue the pam module processes, eventually dropping to an authenticated shell. Otherwise the default 'ignore' behavior is honored moving to pam_deny.o, resulting in a failed authentication.

![Simple Flow Diagram](docs/img/diagram.png "Simple Flow Diagra")

- The pam_unix.o module first checks standard username and password, but since the duress password is not the users
actual password it fails resulting in a default behavior of 'ignore' per the configuration.
- PAM then applies the username/password to pam_duress.so which:
- Enumerates files in /etc/duress.d/
- Checks for files that have matching .sha256 extensions
- Hashes the provided password salted with the sha256 hash of the file and compares it with the one stored in the
.sha256 extension file
- If the hashes match, the script is executed via:
- `export PAMUSER=[USERNAME]; /bin/sh [FILE]` for /etc/duress.d scripts (run as root).
- `export PAMUSER=[USERNAME]; su - [USERNAME] -c "/bin/sh [FILE]"` for ~/.duress scripts (run as the user).
- NOTE: PAMUSER is set so global duress scripts can specify the account flagging duress.
- Process is repeated for all files in ~/.duress/ for the user attempting to log in.
- Finally if ANY script is run, PAM_SUCCESS is return. Otherwise PAM_IGNORE is returned.
- If PAM_SUCESS is returned PAM will skip 1 and move past pam_deny.o to continue the pam module processes, eventually
dropping to an authenticated shell. Otherwise the default 'ignore' behavior is honored moving to pam_deny.o,
resulting in a failed authentication.

![Simple Flow Diagram](docs/img/diagram.png "Simple Flow Diagram")

## Testing

Expand Down Expand Up @@ -138,9 +160,10 @@ Authenticated

## Example Implementations

- [Use Pushover to Notify IT You're Under Duress](docs/examples/Pushover.md)
- [Use Pushover to Notify IT You're Under Duress](docs/examples/Pushover.md)

## Reference

- Initial starter code and test code from [beatgammit/simple-pam](https://github.com/beatgammit/simple-pam).
- Contribution guidelines built from template provided by [briandk/CONTRIBUTING.md](https://gist.github.com/briandk/3d2e8b3ec8daf5a27a62).
- Initial starter code and test code from [beatgammit/simple-pam](https://github.com/beatgammit/simple-pam).
- Contribution guidelines built from template provided by
[briandk/CONTRIBUTING.md](https://gist.github.com/briandk/3d2e8b3ec8daf5a27a62).
29 changes: 20 additions & 9 deletions docs/Contributing.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
[<- Back to README.md](../README.md)
# Contributing to PAM-Duress

Continued development on this module is welcome! We want to make contributing to this project as easy and transparent as possible, whether it's:
Continued development on this module is welcome! We want to make contributing to this project as easy and transparent
as possible, whether it's:

- Reporting a bug
- Discussing the current state of the code
- Submitting a fix
- Proposing new features
- Becoming a maintainer

## Development Platform.
## Development Platform

All development will be hosted and maintained in GitHub.

## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests
Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests:
## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html)

Code Changes Happen Through Pull Requests. Pull requests are the best way to propose changes to the codebase. We
actively welcome your pull requests:

1. Fork the repo and create your branch from `main`.
2. If you've added code that should be tested, add tests.
Expand All @@ -24,10 +26,14 @@ Pull requests are the best way to propose changes to the codebase (we use [Githu
6. Issue that pull request!

## Any contributions you make will be under the GNU LESSER GENERAL PUBLIC LICENSE v3
In short, when you submit code changes, your submissions are understood to be under the same [LGPL v3](https://www.gnu.org/licenses/lgpl-3.0.txt) that covers the project.

In short, when you submit code changes, your submissions are understood to be under the same
[LGPL v3](https://www.gnu.org/licenses/lgpl-3.0.txt) that covers the project.

## Report bugs using Github's [issues](https://github.com/briandk/transcriptase-atom/issues)
We use GitHub issues to track public bugs. Report a bug by [opening a new issue]().

We use GitHub issues to track public bugs. Report a bug by
[opening a new issue](https://github.com/nuvious/pam-duress/issues).

**Bug Reports Should Include**:

Expand All @@ -37,12 +43,17 @@ We use GitHub issues to track public bugs. Report a bug by [opening a new issue]
- Give sample code if you can
- What you expected would happen
- What actually happens
- Notes (possibly including why you think this might be happening, or mitigations/resolutions you tried and their effectiveness)
- Notes (possibly including why you think this might be happening or any mitigations/resolutions you tried and their
effectiveness)

## Use a Consistent Coding Style

Follow the [GNU Coding styles guidelines](https://www.gnu.org/prep/standards/standards.html#Formatting) for c/c++ code.

We recommend using clang-tidy for linting.

## License

By contributing, you agree that your contributions will be licensed under the LGPL v3.

[<- Back to README.md](../README.md)
[<- Back to README.md](../README.md)
21 changes: 14 additions & 7 deletions docs/examples/Pushover.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[<- Back to README.md](../../README.md)
# Intro

One simple use case for a duress password is to simply notify IT of the user being in duress. In this demonstration we'll create a script which sends a pushover notification with the username reporting the duress, the hostname, and the current IP.
One simple use case for a duress password is to simply notify IT of the user being in duress. In this demonstration
we'll create a script which sends a pushover notification with the username reporting the duress, the hostname, and the
current IP.

## Requirements

Expand All @@ -13,7 +14,8 @@ sudo apt-get install curl

## The Script

First we'll make a pushover script. The first step for that should be to generate an app in your pushover account for this purpose. Then you'll want to generate an configuration file:
First we'll make a pushover script. The first step for that should be to generate an app in your pushover account for
this purpose. Then you'll want to generate an configuration file:

```bash
# /root/.pushover_creds
Expand Down Expand Up @@ -66,10 +68,15 @@ sudo chmod 500 /etc/duress.d/pushover.sh
sudo chmod 400 /etc/duress.d/pushover.sh.sha256
```

This will produce a pushover.sh.sha256 file. The has is not the direct hash of the file but rather the hash of the password salted with the sha256 hash of the file.
This will produce a pushover.sh.sha256 file. The has is not the direct hash of the file but rather the hash of the
password salted with the sha256 hash of the file.

You can then distribute this global configuration's password to new users you can simply give them the password. Before local configurations are run a password provided to the duress module will be checked against the hashes of the scripts in /etc/duress.d. If the password matches the script wil be run with root privileges.
You can then distribute this global configuration's password to new users you can simply give them the password.
Before local configurations are run a password provided to the duress module will be checked against the hashes of the
scripts in /etc/duress.d. If the password matches the script wil be run with root privileges.

**SECURITY NOTE:** If a person who is granted one of these shared passwords leaves the group/organization/etc, you should immediately re-sign the script. This is in keeping with the best practices of using organizational duress-words; they must be kept secret and need-to-know and if someone leaves the group, they don't need to know anymore so change it.
**SECURITY NOTE:** If a person who is granted one of these shared passwords leaves the group/organization/etc, you
should immediately re-sign the script. This is in keeping with the best practices of using organizational duress-words;
they must be kept secret and need-to-know and if someone leaves the group, they don't need to know anymore so change it.

[<- Back to README.md](../../README.md)
[<- Back to README.md](../../README.md)
Loading

0 comments on commit 04e607f

Please sign in to comment.