rafket / pam_duress

A pam module written in C for duress codes in linux authentication
GNU General Public License v2.0
146 stars 11 forks source link

Revisiting the hashes/salt database #8

Open UnitedMarsupials-zz opened 7 years ago

UnitedMarsupials-zz commented 7 years ago

After trying the adduser once, I found the following changes on the filesystem:

  1. New file -- presumably, containing the encrypted command to execute: /usr/share/duress/actions/ff3361c77df7a79ccfea11ce7562f54b1010aa9a50cb7f25441df980672f3ca2
  2. New (updated) file /usr/share/duress/hashes with the line: 6qaedptqoJCi4Uoo:ff3361c77df7a79ccfea11ce7562f54b1010aa9a50cb7f25441df980672f3ca2

The flat hashes-file is a nuisance because transactional integrity is difficult to maintain -- changes to the file aren't atomic and a sudden crash may leave the file corrupted and/or "orphaned" records in the actions/ subdirectory. A similar corruption may ensue from two instances of adduser running in parallel.

A multi-user system with each user having multiple actions tied to different passwords may also begin to slow down due to linear searching of the database...

First, I discuss, whether a separate salt-storage is even necessary -- if not, you can get rid of the hashes-database altogether and simply go through the contents of the actions/-directory upon a user's login...

Is additional salt even needed?

The name of the encrypted action-file is currently a cryptographic function of:

  1. Username
  2. Action-specific password
  3. Salt

What additional protection does the salt give in this case? Suppose, an attacker -- suspicious of the user attempting a duress-action -- confiscates the computer, gets in as root and examines the actions/ directory. Does it really help him much, that instead of a randomly-generated salt, the username itself was used to salt the filenames?

This guy argues, that usernames should not be used as salt, because they are predictable, but he also argues, the salt should be at least as big as the output of the hash-function, whereas your current code only uses 12-bytes for salt :-)

But, if we add the numeric uid to the mix -- which is much harder for an attacker to predict -- it will complicates his attempts to use a pre-built lookup-table to the point of defeating a dictionary attack, will it not?

This method will eliminate the linear search through available action-files -- the would be filename can be obtained once (from username + uid + password) and then a single stat(2) call will tell, whether it has an action tied to it or not...

Ok, ok, extra salt is needed -- can we use timestamp?

If simply salting with the username+uid is not good enough, we can add the timestamp to the mix -- the adduser program will open the future actions-file with mkstemp(3), populate it, then read the ctime off of the file descriptor and use the username + uid + ctime combination as salt.

An even stronger -- if somewhat confusing -- variation of the above would be to obtain a fake ctime from a random source and record it with futimes(2).

This method would still require a linear search through the filenames, but no separate database for salts...

A directory is a database

If you don't think, any of the above two approaches are good enough, and remain convinced, that a purely random salt must be recorded separately for each action, how about we recall, that a directory on a filesystem is already a key->value database. Straight away, the hashes file can be replaced with hashes/ subdirectory with symbolic links like this:

ff3361c77df7a79ccfea11ce7562f54b1010aa9a50cb7f25441df980672f3ca2 -> 6qaedptqoJCi4Uoo

Each such link can be added/deleted atomically while the whole collection remains easy to browse/verify/maintain without special tools.

The code would still need to perform a linear search for each login, however, but the transactional integrity will be much easier to ensure. Checking for orphaned actions will be quick too.