Home | Logout |
Change Password
Create New User Account
Logged in from
An infrastructure for user acount authorization and file access control is available. Each request is matched against a list of URL path patterns. If the request matches, a Session Ticket is required to access the URL. This Session Ticket should be present as a CGI parameter or Cookie, eg:
CGI: SESSIONTICKET=<value>
Cookie: CGIscriptorSESSION=<value>
The example implementation stores Session Tickets as files in a local directory. To create Session Tickets, a Login request must be given with a LOGIN=<value> CGI parameter, a user name and a (doubly hashed) password. The user name and (singly hashed) password are stored in a PASSWORD ticket with the same name as the user account (name cleaned up for security). There is a Tutorial of the authorization application.
The example session model implements 3 functions:
The session authentication mechanism is based on the exchange of ticket identifiers. A ticket identifier is just a string of characters, a name or a random 64 character hexadecimal string. Authentication is based on a (password derived) shared secret and the ability to calculate ticket identifiers from this shared secret. Ticket identifiers should be "safe" filenames (except user names). At the server side, there are four types of tickets:
A Login page should create a LOGIN ticket file locally and send a server specific salt, a Random salt, and a LOGIN ticket identifier. The server side compares the username and hashed password, actually hashed(hashed(password+serversalt)+Random salt) from the client with the values it calculates from the stored Random salt from the LOGIN ticket and the hashed(password+serversalt) from the PASSWORD ticket. If successful, a new SESSION ticket is generated as a (double) hash sum of the LOGIN ticket and the stored password, i.e. LoginTicket = hashed(hashed(password+serversalt)+REMOTE_HOST+Random salt) and SessionTicket = hashed(hashed(LoginTicket).LoginTicket). This SESSION ticket should also be generated by the client and stored as sessionStorage and cookie values as needed. The Username, IP address and Path are available as $LoginUsername, $LoginIPaddress, and $LoginPath, respectively.
The CHALLENGE protocol stores the single hashed version of the SESSION tickets. However, this value is not exchanged, but kept secret in the JavaScript sessionStorage object. Instead, every page returned from the server will contain a one-time Challenge value ($CHALLENGETICKET) which has to be hashed with the stored value to return the current ticket id string.
In the current example implementation, all random values are created as full, 256 bit SHA256 hash values (Hex strings) of 64 bytes read from /dev/urandom.
A limited level of authorization tuning is build into the login system. Each account file (PASSWORD ticket file) can contain a number of Capabilities lines. These control special priveliges. The Capabilities can be checked inside the HTML pages as part of the ticket information. Two privileges are handled internally: CreateUser and VariableREMOTE_ADDR. CreateUser allows the logged in user to create a new user account. With VariableREMOTE_ADDR, the session of the logged in user is not limited to the Remote IP address from which the inital log-in took place. Sessions can hop from one apparant (proxy) IP address to another, e.g., when using Tor. Any IPaddress patterns given in the PASSWORD ticket file remain in effect during the session. For security reasons, the VariableREMOTE_ADDR capability is only effective if the session type is CHALLENGE.
For strong security, please use end-to-end encryption. This can be achieved using a VPN (Virtual Private Network), SSH tunnel, or a HTTPS capable server with OpenSSL. The session ticket system of CGIscriptor.pl is intended to be used as a simple authentication mechanism WITHOUT END-TO-END ENCRYPTION. The authenticating mechanism tries to use some simple means to protect the authentication process from eavesdropping. For this it uses a secure hash function, SHA256. For all practial purposes, it is impossible to "decrypt" a SHA256 sum. But this login scheme is only as secure as your browser. Which, in general, is not very secure.
Humans tend to reuse passwords. A compromise of a site running
CGIscriptor.pl could therefore lead to a compromise of user accounts at
other sites. Therefore, plain text passwords are never stored, used, or
exchanged. Instead, a server site salt value is "encrypted" with
the plain password and user name. Actually, all are concatenated and hashed
with a one-way secure hash function (SHA256) into a single string.
Whenever the word "password" is used, this hash sum is meant. Note that
the salts are generated from /dev/urandom. You should check whether the
implementation of /dev/urandom on your platform is secure before
relying on it. This might be a problem when running CGIscriptor under
Cygwin on MS Windows.
Note: no attempt is made to slow down the password hash, so bad
passwords can be cracked by brute force
As the (hashed) passwords are all that is needed to identify at the site, these should not be stored in this form. A site specific passphrase can be entered as an environment variable ($ENV{'CGIMasterKey'}). This phrase is hashed with the server site salt and the result is hashed with the user name and then XORed with the password when it is stored. Also, to detect changes to the account (PASSWORD) and session tickets, a (HMAC) hash of some of the contents of the ticket with the server salt and CGIMasterKey is stored in each ticket.
Creating a valid (hashed) password, encrypt it with the CGIMasterKey and construct a signature of the ticket are non-trivial. This has to be redone with every change of the ticket file or CGIMasterKey change. CGIscriptor can do this from the command line with the command:
perl CGIscriptor.pl --managelogin salt=Private/.Passwords/SALT \ masterkey='Sherlock investigates oleander curry in Bath' \ password='There is no password like more password' \ adminCGIscriptor will exit after this command with the first option being --managelogin. Options have the form:
For the authentication and a change of password, the (old) password is used to "encrypt" a random one-time token or the new password, respectively. For authentication, decryption is not needed, so a secure hash function (SHA256) is used to create a one-way hash sum "encryption". A new password must be decrypted. New passwords are encryped by XORing them with the old password.
If you only could see what you are typing
Your password might be vulnerable to
brute force guessing. Protections against such attacks are
costly in terms of code complexity, bugs, and execution time.
However, there is a very simple and secure counter measure. See the
XKCD comic. The phrase,
There is no password like more password would
be both much easier to remember, and still stronger than
h4]D%@m:49, at least before this phrase was pasted as an example
on the Internet.
For the procedures used at this site, a basic computer setup can check
in the order of a billion passwords per second. You need a password (or
phrase) strength in the order of 56 bits to be a little secure (one year
on a single computer). One of the largest network in the world, Bitcoin
mining, can check some 12 terahashes per second (June 2012). This
corresponds to checking 6 times 1012 passwords per second.
It would take a passwords strength of ~68 bits to keep the equivalent of
the Bitcoin computer network occupied for around a year before it found
a match.
Please be so kind and add the name of your favorite flower, dish,
fictional character, or small town to your password. Say,
Oleander, Curry, Sherlock, or Bath, UK
(each adds ~12 bits) or even the phrase Sherlock investigates
oleander curry in Bath (adds > 56 bits, note that oleander is
poisonous, so do not try this curry at home). That would be more
effective than adding a thousand rounds of encryption.
Typing long passwords without seeing what you are typing is problematic.
So a button should be included to make password visible.
The example Login page is vulnerable to a Man-in-the-Middle (MITM) attack.
One fundamental weakness of the implemented procedure is that the Client obtains
the code to encrypt the passwords from the server. It is the JavaScript
code in the HTML pages. An attacker who could place herself between Server
and Client, a man in the middle attack (MITM), could change the code to
reveal the plaintext password and other information. There is no real
protection against this attack without end-to-end encryption and
authentication.
A solution for the MITM attack problem to protect at least the password input
would be to run a trusted copy of the web page from local storage to handle password input.
An example of such a solution has been implemented for IPADDRESS sessions and
plain SESSION ticket only. This Login.html page has four comment lines saying:
UNCOMMENT for use in a local version of the Private/Login.html web page.
If you save this Login page and follow the instructions in these comments, you
will be able to load the page from local storage in your browser and
log in at the designated web site. It is not (yet) possible to set the
required session storage inside the browser, so this method only works
for IPADDRESS sessions and plain SESSION tickets, not for the CHALLENGE sessions.