In my Department at the University Of Crete we have a set
of computers where you can login using
ssh(1) and access all your files,
write code, run programs, and in general perform all tasks you may need without
install linux on remove Windows from your computer. For
“Security” reasons, these computers are behind two stripped, chrooted “Gates”.
You cannot ssh into one of the computers directly, you first have to ssh to one
of the gates and then from there ssh into your desired computer. Pretty much
the only thing in the gates is
enable, the second of which does
a port forward to the computer you need.
That means that every time you work on something locally and you need to put it up to one of the computers for submission, you have to first ssh into the gate, then enable the computer, then sftp into the computer, then ssh from the gate to the computer and submit your files. Since it’s so complicated you didn’t understand it the first time you read it, neither do freshmen on their first semester.
I thought I could help them out in this situation and use the feature of the
public_html folder that is supplied. This folder gives you your personal
~username. It supports a stripped-down, basic version of PHP.
For this reason, I created CSD File
Upload, a simple PHP script that
accepts a file and a password and uploads the file in the user directory
without any more hassle.
The way I was handling the user password was to include its SHA-256 hash in a PHP Variable in the beginning of the file. When the user installed the software, she was executing:
printf "My Desired Password" | sha256sum | cut -d" " -f1
and changing the variable content with the output. As simple as it gets. The script, of course, was only accessible through https.
A day after it is announced in the public mailing lists by the System Administrators, I start getting Pull Requests by students. That’s good news because they seem to care and/or know PHP/git, both of which are not in the official curriculum.
I get a Pull Request from a
user making an “improvement”, and that is putting the password in a separate
password.txt and then reading it from there. Now we all know this is
insecure because that way anyone can visit
/password.txt and get the password
The proper way to do this would be to create a file
password.php and put in
$PASSWORD = "sha256-goes-here";
and then simply
require("password.php"); from the
index.php file. That’s
how the configuration is done in popular PHP software.
When you send the password in plain-text, the system performs an equals
operator or a
strcmp() and allows you to get in. If you hash the password in
the client, and then send it to the server for comparison, then it performs the
same operations just as if it was a plain-text input. That means if I send the
password hash, the system will treat it like it was a plain-text password,
which means that the only thing that happens is that your password from
password123 is now
ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f, but if you
send the latter, it will let you in.
This does not mean your password is sent over the internet unencrypted. This page works only with HTTPS, which means we let that layer take care of data encryption.
But truth be told, the code wasn’t just sending the password hash. It also employed the PHP Session ID and did something like:
var phpid = "<?php echo session_id(); ?>"; var stringToSubmit = sha256(password + phpid);
While it seems easy to get software security right, you can never be sure. You have to keep in your head all the possible attack scenarios, even the ones you’re sure won’t happen, and see if your implementation can defend against them (in a reasonable manner). My implementation isn’t perfect, and can be cracked (for example if HTTPS breaks), but in the one hour or two I spent writing the whole I consider this an acceptable risk.
Another conclusion is that by thinking of a better way to do something, making it and submitting it for review, even if it awfully bad or insecure or anything, people are going to see that and they will let you know why so you can learn a lot and benefit from this process. No matter if all your Pull Requests are rejected for various reasons, you should never stop sending them because at least you learn something (new).
At this point I must thank all the people for their contributions to the repository and the time they invested into making the software better.