Overwrite std::cin read-buffer after reading password - c++

After reading a password from std::cin
std::cout << "Password: ";
SecureString pw{}; // secure string, wipes automatically on destruction
SetConsoleEcho(false); // hide input in terminal
std::getline(std::cin, pw); // input the password
SetConsoleEcho(true); // switch echo back on
the password stays stored in the read buffer of cin (heap memory) until it is overwritten with new input and can easily be sniffed with tools like Process Hacker or would be written to disk in case of a memory dump.
Does anyone know how the std::cin.rdbuf() can be cleared/overwritten, ideally in a cross-platform way? Or is there a way how to avoid using the buffer in the first place?
The above code uses SecureString which is implemented using Crypto++'s AllocatorWithCleanup which wipes memory at destruction. SetConsoleEcho switches the console echo on/off in order to avoid seeing the plain text password on screen.
I realize this question is very similar to this one but it's been over 10 years and the accepted answer actually does not answer the question.

The linked post has all the answers you need and unfortunately there isn't a way to securely read and then clear the password with 0 risk of it being exposed. See
Even if you scribble over the buffer immediately, it's still possible the password is written to disk. A system i/o buffer might be paged to disk, as might the working memory which std::cin is in. I used to develop forensic software which sniffed out exactly these conditions.
Furthermore if a malicious actor has access to the PC a keylogger can just be used to extract the password.

Or is there a way how to avoid using the buffer in the first place?
I found a cross-platform way (Linux, Mac, Windows) how to avoid the read buffer of cin using a readline replacement library. I used replxx but other readline replacement libraries will likely do as well.
I created a simple wrapper class PasswordInput around replxx that clears its input buffer on every key stroke and stores the entered password in a secure string using Crypto++'s AllocatorWithCleanup. The secure string is automatically wiped after a password digest is created, thus leaving no copy of the plain password in process memory.
All this achieves is to avoid having the plain password in process memory for longer than needed. It does not guard against keyloggers nor against the possibility of leaking the password if the process crashes while calculating the digest nor against well timed sniffing attacks nor against any other possible attack vectors.
So far I've only tested on Windows and I only did basic memory sniffing tests using Process Hacker. These showed no trace of the plain password (contrary to using std::cin)
Header file:
using SecureString =
std::basic_string<char, std::char_traits<char>, CryptoPP::AllocatorWithCleanup<char>>;
class PasswordInput {
public:
PasswordInput();
void Read(const std::string& prompt);
inline const SecureString& Secret() const { return secret_; }
private:
void RxPwModifyCb(std::string& line, int& pos);
Replxx rx_;
SecureString secret_;
};
Implementation:
namespace ph = std::placeholders;
PasswordInput::PasswordInput() :
rx_{}
{
rx_.set_modify_callback(std::bind(&PasswordInput::RxPwModifyCb, this, ph::_1, ph::_2));
}
void PasswordInput::Read(const std::string& prompt)
{
char const* cinput{nullptr};
do
{
cinput = rx_.input(prompt);
} while ((cinput == nullptr) && (errno == EAGAIN));
}
void PasswordInput::RxPwModifyCb(std::string& line, int& pos)
{
if (!line.empty())
{
secret_.append(1, line[0]);
line.clear();
}
}
Usage:
PasswordInput pwi{}; // create password input handler
pwi.Read("Password: "); // read the password
std::cout << "\x1b[A" << "\33[2K\r"; // go one line up, delete line and go to beginning (does nothing in terms of security but looks cool)
CalculatePassphrase(pwi.Secret().c_str(), pwi.Secret().size()); // Scrypt, pbkdf2, etc..
Please note this is not complete code and it needs replxx and Crypto++ libraries linked

Related

c++ password storage .txt file + masking input

I'm pretty new to programming - just starting out with C++. So I wanted to make an application - just for fun - which would mask user input with asterisks. I did some research and found exactly what I was looking for. As you can see inside the code below it works fine but only checks password from a char I put - "correct_password". I thought it'd be more challenging to extend options. The program would write two options out: 1. register - just put your login and password (without asterisks), then store it into a file (fstream I guess), 2. login - after putting login and password (with asterisks just the way it is in getpass) it would check the file for data if user is actually registered. Even thought maybe about encrypting data in that file, although I have no idea how to proceed. Well, it's just made up thing to learn some new stuff, I know it's not really a THING and there's no really a purpose to write such code - just messing around with C++. Maybe you got some ideas how to snap that? After I wrote this asterisk thing i don't really see where I should put those other options, storing in file and so on. Would love to go through some ideas and appreciate the input from more experienced coders :)
I tried using fstream inside getpass but didn't work out. Generally I'd like to extend this program with login and password input, storing them into .txt file and then program would check if user is registered and while logging with this data input would be masked with asterisks - just like my first idea of that program which is only masking password input. I don't really know how to split unmasked input with that inside getpass.
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
string getpass(const char *dat, bool s_asterisk=true)
{
const char BACKSPACE=8;
const char RETURN=13;
string password;
unsigned char ch=0;
cout << dat;
DWORD con_mode;
DWORD dwRead;
HANDLE hIn=GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode( hIn, &con_mode );
SetConsoleMode( hIn, con_mode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT) );
while(ReadConsoleA( hIn, &ch, 1, &dwRead, NULL) && ch !=RETURN)
{
if(ch==BACKSPACE)
{
if(password.length()!=0)
{
if(s_asterisk)
cout <<"\b \b";
password.resize(password.length()-1);
}
}
else
{
password+=ch;
if(s_asterisk)
cout <<'*';
}
}
cout << endl;
return password;
}
int main()
{
const char *correct_password="fdsidfjsijdsf21128321873";
START:
string password=getpass("Enter the password: ",true);
if(password==correct_password){
cout <<"\nCorrect password."<<endl;
exit(1);
}else{
cout <<"\nIncorrect password. Try again.\n"<<endl;
goto START;
}
return 0;
}
Usually you don't want to store actual passwords in a file. Although encrypting them would help security (to at least some degree), it's still generally pretty insecure and better avoided.
What you usually want to do instead is salt the password, then hash the salted password with a cryptographic hash. Then you store the salt and the hash, rather than the password itself.
Then (for the simplest case) when the user wants to log in, you repeat the same process: retrieve the salt for their password, apply the salt to the password they enter, hash the result, and finally compare that result to the value you stored. If they match, you assume the user entered the correct password. If they don't match, you know they didn't.
Note that this is only reasonable for the user logging into your application locally (or at least over a secure connection). If they might log in over an insecure connection, you need to get considerably more sophisticated still.
Another major point though: nearly all of this should happen outside getpass. getpass should do exactly one thing: read in a password from the user. Salting, hashing, storing, and so on, should all happen separately from that.

Trying to reread redirected file using seekg()

I am trying to read a redirected file using cin.get(). This is my attemp at using seekg, but it's not working correctly.
int temp;
while(cin.get(temp))
{
//code here
}
cin.seekg(0,ios::beg);
if(cin.fai())
{
cout << "failed";// it fails
}
In general, redirected files do not support seek operations, because the input goes through stdin (or it's equivalent), which doesn't support "move around" operations. This is because although there may be a small internal buffer, the expectation is that "once something has been read, it's no longer available on the input".
If you want to be able to go back and forth, either open the file directly, or create your own buffer (or find a way to read the input just once!)

Password Manager - Continuing / Long-Term Things

Okay, I know very well how everybody feels about homemade password managers, but I would like help with mine. Not for actual use, just for the sake of learning.
I was wondering, in C++ how to have long-term variables. Or really, have anything long-term.
What do I mean by long-term? Something that is saved or continues upon next run of the .exe. In my case, I want where, the first time you run the program it asks you to enter an access password, so next time you launch the program, you will have to type the password chosen when you first launched.
Currently, I just use an if() statement to check if password is equal to my desired password, and if it is, to run. However, that is far from actually effective and isn't very practical.
Something I thought of was to create a text file somewhere containing the access password, and read it, but that kind of defeats the purpose of a password manager.
Every variable in your program is only in memory and lost at exit. You must store it on your disk and later read it from there.
There are many ways to do that directly or indirectly.
A very simple low level way is to use ofstream and ifstream. E.g.:
#include <iostream>
#include <fstream>
int main() {
using namespace std;
int counter = 0;
// try to load counter from file
{
ifstream myfile("mycounter.txt");
if (myfile.is_open())
{
myfile >> counter;
}
myfile.close();
}
cout << "current counter: " << counter << endl;
// save counter to file
{
ofstream myfile;
myfile.open("mycounter.txt");
myfile << counter << endl;
}
}
You might be more comfortable with the C-functions fopen, fread, fwrite, fclose, etc.
Then, there are databases and there are easy libraries to use such databases. Check out sqlite, you can use it from C++.
You could start a database or save/write the data into files.

flock-ing a C++ ifstream on Linux (GCC 4.6)

context
I'm slowly writing a specialized web server application in C++ (using the C onion http server library and the JSONCPP library for JSON serialization, if that matters)., for a Linux system with GCC 4.6 compiler (I don't care about portability to non Linux systems, or to GCC before 4.5 or to Clang before 3.0).
I decided to keep the user "database" (there will be very few users, probably one or two, so performance is not a concern, and O(n) access time is acceptable) in JSON format, probably as a small array of JSON objects like
{ "_user" : "basile" ;
"_crypasswd" : "XYZABC123" ;
"_email" : "basile#starynkevitch.net" ;
"firstname" : "Basile" ;
"lastname" : "Starynkevitch" ;
"privileges" : "all" ;
}
with the convention (à la .htpasswd) that the _crypasswd field is the crypt(3) "encryption" of the user password, salted by the _user name;
The reason I want to describe users by Json objects is that my application might add (not replace) some JSON fields (like e.g. privileges above) in such Json objects describing users. I'm using JsonCpp as a Json parsing library for C++. This library wants an ifstream to be parsed.
So I am reading my password file with
extern char* iaca_passwd_path; // the path of the password file
std::ifstream jsinpass(iaca_passwd_path);
Json::Value jpassarr;
Json::Reader reader;
reader.parse(jsinpass,jpassarr,true);
jsinpass.close();
assert (jpassarr.isArray());
for (int ix=0; ix<nbu; ix++) {
const Json::Value&jcuruser= jpassarr[ix];
assert(jcuruser.isObject());
if (jcuruser["_user"].compare(user) == 0) {
std::string crypasswd = jcuruser["_crypasswd"].asString();
if (crypasswd.compare(crypted_password(user,password)) == 0) {
// good user
}
}
}
question
Obviously, I want to flock or lockf the password file, to ensure that only one process is reading or writing it. To call these functions, I need to get the file descriptor (in Unix parlance) of the ifstream jsinpass. But Google gives me mostly Kreckel's fileno (which I find complete, but a bit insane) to get the file descriptor of an std::ifstream and I am not sure that the constructor won't pre-read some of it. Hence my question:
how can I lock a C++ ifstream (Linux, GCC 4.6) ?
(Or do you find some other way to tackle that issue?)
Thanks
My solution to this problem is derived from this answer: https://stackoverflow.com/a/19749019/5899976
I've only tested it with GCC 4.8.5.
#include <cstring> // for strerror()
#include <iostream> // for std::cerr
#include <fstream>
#include <ext/stdio_filebuf.h>
extern "C" {
#include <errno.h>
#include <sys/file.h> // for flock()
}
// Atomically increments a persistent counter, stored in /tmp/counter.txt
int increment_counter()
{
std::fstream file( "/tmp/counter.txt" );
if (!file) file.open( "/tmp/counter.txt", std::fstream::out );
int fd = static_cast< __gnu_cxx::stdio_filebuf< char > * const >( file.rdbuf() )->fd();
if (flock( fd, LOCK_EX ))
{
std::cerr << "Failed to lock file: " << strerror( errno ) << "\n";
}
int value = 0;
file >> value;
file.clear(); // clear eof bit.
file.seekp( 0 );
file << ++value;
return value;
// When 'file' goes out of scope, it's closed. Moreover, since flock() is
// tied to the file descriptor, it gets released when the file is closed.
}
You might want to use a separate lockfile rather than trying to get the descriptor from the ifstream. It's much easier to implement, and you could probably wrap the ifstream in a class that automates this.
If you want to ensure atomic open/lock, You might want to construct a stream using the method suggested in this SO answer, following open and flock
A deficiency with the filestream API is that you cannot (at least not easily) access the file descriptor of an fstream (see here and here, for example). This is because there is no requirement that fstream is implemented in terms of FILE* or file descriptors (though in practice it always is).
This is also required for using pipes as C++ streams.
Therefore the 'canonical' answer (as implied in the comments to the question) is:
create a stream buffer (derived from std::basic_streambuf) that uses Posix and C stdio I/O functions (i.e open etc) and thus gives access to the file descriptor.
Create your own 'LockableFileStream' (derived from std::basic_iostream) using your stdio based stream buffer instead of std::streambuf.
You may now have a fstream like class from which you may gain access to the file descriptor and thus use fcntl (or lockf) as appropriate.
There are a few libraries which provide this out of the box.
I had thought this was addressed partly now that we've reached C++17 but I can't find the link so I must have dreamed it.
Is the traditional unix-y solution of relying on the atomicity of rename() unacceptable?
I mean, unless your JSON serialization format supports in-place update (with a transaction log or whatever), then updating your password database entails rewriting the entire file, doesn't it? So you might as well write it to a temporary file, then rename it over the real name, thus ensuring that readers read a consistent entry? (Of course, in order for this to work each reader must open() the file each time it wants to access a DB entry, leaving the file open doesn't cut it)

Is it a good idea to use output stream to display text "in-game"?

Let's say I'm making a game where text can be displayed and scrolled/okay'd when ENTER is pressed.
Is it a good idea to use a output stream class and send my "raw" std::string to it? I'm thinking about doing this so it'd be easier to either send the messages to the console or to the actual screen using an fancy display style
thanks
There's nothing stopping you from making your own stream buffer class that can then forward to std::cout or do something more exotic at a later point in time.
I suggest reading this article here http://spec.winprog.org/streams/ about iostreams and rolling your own using what is provided to you. Read this to gain an understanding of what is going on.
The Boost IO stream libraries make it even easier for you to create your own streams:
http://www.boost.org/doc/libs/1_43_0/libs/iostreams/doc/index.html
If you "raw" string consists of printable text, there is nothing wrong with dumping the std::string to std::cout using operator<< to print it, for example:
// Display prompt to user
std::string output("Please press <ENTER>: ");
std::cout << output << std::flush;
// Wait for user to press <Enter>
std::string input;
std::getline(std::cin, input);