[Subject Prev][Subject Next][Thread Prev][Thread Next][Subject Index][Thread Index]

Implementing security in CGI


Sometime back we had asked questions on how to implement a secure system
under CGI, which did not draw response from this group.
Meanwhile there was a hot discussion on this issue in the mod_perl news
One person has come up with a brilliant note on the same, which I thot will
be most useful for any CGI programmer.
Please read on if you are interested.


-----Original Message-----
From: DeWitt Clinton <dclinton@xxxxxxxxxx>
To: Differentiated Software Solutions Pvt. Ltd. <diffs@xxxxxxxx>
Cc: modperl@xxxxxxxxxx <modperl@xxxxxxxxxx>
Date: 21 April 2000 11:20
Subject: Re: Implementing security in CGI

>Interesting thread and interesting question.   
>It makes sense to start with the requirements for what it means to 
>implement those secure features.  My requirements have an obvious 
>e-commerce bias, and should probably be heavily reviewed by anyone 
>thinking of using this design for online banking or government work. 
>First, I'd like to introduce the notion of a secure session.  Secure
>sessions have some subtle differences from the traditional notion of
>the session, and I'll point those out when they appear.
>The secure session has the following properties:
>*) The user is able to initiate a secure session by providing proper
>credentials (i.e., a username and password pair) via a login process.
>*) The user is able to terminate the secure session via a logout
>*) Secure sessions must be able to time out automatically.
>*) Secure sessions must *never* transmit sensitive data (such as the
>password) over insecure channels.
>*) The secure session, while it requires the use of a secure protocol
>(such as HTTPS), should not require the use of cookies.  Cookies,
>however, can be employed to extend the functionality of the system.  
>Additionally, I feel that one of the essential requirements to any
>enterprise quality, highly scalable, and fault-tolerant system is the
>ability to store session state on a tier other than the front-end.
>This usually means storing state in a shared database, but there are
>other options.
>A very effective method of meeting the requirements above is to use a
>two token architecture.  The first token is a user identifier, which
>can be passed over insecure channels.  This user identification token
>can be used to restore state that isn't particularly sensitive, such
>as a shopping cart or user preferences.  The second token is a secure
>identifier, which is never passed over insecure channels.  The secure
>identifier is required to access sensitive data, such as credit card
>data. (It is possible to create an architecture that uses *only* the
>secure token, but there are significant benefits in terms of
>flexibility afforded by using two tokens, so I won't go into the one
>token model here.)
>The fundamental goal of the secure token is to a) keep it safe from
>prying eyes, and b) use it is a requirement for accessing secure data.
>Tokens can be passed in one of two ways.  First, the token can be
>passed as part of the URL.  Second, the token can be passed in a
>cookie.  I've found it very useful to create an initialization
>procedure inside applications that check both places for these tokens,
>and abstract the particular mechanism used to pass them.  Note,
>however, that is important to remember how the token was passed -- if
>it came from a cookie, it is cosmetic to not pass it around in the
>URL.  I also recommend creating a library used in your templates that
>has a function to build URLs that automatically append the tokens if
>necessary.  Since it is critical that secure tokens are never passed
>in the clear, it really helps to have that function, because it can
>prevent the secure token from being sent via an insecure page in a URL
>(i.e., only setting secure tokens in URLs that contain "https").
>The user identification token is typically used to restore state from
>the database.  It is created whenever a page is viewed and the client 
>has either not provided one (via the URL or a cookie), or the token
>they provide doesn't exist in the database.  This token should then be 
>set in both the URL and in a cookie.  On the subsequent page request,
>if the user identification token is found in a cookie, it is probably
>safe to stop putting it in the URL.  However, if the token is found
>only in the URL (probably meaning the client does not use cookies) the 
>server should not try writing the cookie again.  
>The advantage of the cookie is such that the user can insecurely
>identify themselves across browser sessions.  This is perfectly
>acceptable when used to restore some insensitive state data (such as a
>name or shopping cart).  However, the system still functions without
>the cookie.  The user can now login to associate their client with
>particular stored user information.
>The login process is as follows:
>1) The client connects to a secure page that presents a form
>requesting a username and password.  (There has been much discussion
>about whether a HTTP form that POSTS to a secure page will encrypt the 
>posted data.  There is too much ambiguity here -- I recommend using
>HTTPS on the login form as well.)  The ACTION of the form must also
>be a secure page.
>2) On receiving the username and password, the server compares an
>encrypted version of the password with the stored encrypted password
>associated with that customer.  If the passwords do not match, the
>user is returned to the login page. (For highly secure sites, storing
>a count of the number of failed logins may be desirable.)
>3) The server compares the client supplied user identification token
>with the one associated with that username in the database.  If they
>are different, the server should use the procedure outline above to set
>the new user identification token in the URL and cookie.  
>4) The server now generates a unique secure token.  Using the
>techniques I mentioned, this should be appended to all links from the
>page that use HTTPS, as well as set in the cookie.  *Important* --
>when setting this in the cookie, use the "secure" flag in the cookie
>string.  This will tell the browser never to send the cookie over
>insecure channels.  (I don't know whether to trust the browser here,
>but it seems there is little choice if you want to use cookies.)
>5) The secure token is associated on the server side (preferably on
>another tier, such as a database) with the user identification token.
>Additionally, to support secure session timeouts, the current time
>must be recorded.
>The customer is now technically logged in, and will be able to access
>sensitive pages, providing they provide the proper tokens, and certain 
>other requirements are met.  When a sensitive page is accessed, the
>following requirements must be met:
>1) The page must be viewed over a secure protocol (i.e., HTTPS).  
>2) The client must present a valid user identification token.  
>3) The client must present a valid secure token that matches secure
>token that is stored associated with that user identification token.  
>4) To implement secure session timeouts, the last access time of the
>stored secure token is compared with the current time.  The delta must 
>be less than some predetermined value (such as 15 minutes or one
>5) The current time must be stored as the last access time for the
>stored secure token.
>6) If the secure token was not found in a cookie, then all the exit
>links for that sensitive page should contain the secure token, if and
>only if they point at another secured page (similar to the login
>If any of these requirements are not met, the user can *not* access
>the sensitive page.  The server can then display the login page
>instead (or redirect to it over a secure protocol, in the case that
>requirement #1 was not met).
>Obviously, it helps to encapsulate all of those steps inside a simple
>routine that each page or module can call at the beginning of the
>process.  Even better, enforce some external control that won't even
>let the particular page's code run unless those requirements are met.
>To explicitly logout, the user should simple be presented with a URL
>that requests that the secure session end.  When this happens:
>1) The server then erases the stored secure token identified with the
>user identification token.  (Now, step #3 of the sensitive page view
>requirements will fail on future requests.)
>2) As a courtesy, the server should set the secure token in a cookie
>to null.  (This isn't required for security, but it makes the user
>feel they have logged out.  Do this even if you think the client isn't 
>accepting cookies -- some users are manually accepting/declining
>cookies to test your system.)
>3) Optionally, generate a new user identification token and set this
>in the cookie and URL.  (I prefer this approach, because it is very
>useful for someone accessing your site from a shared computer.)
>There are occasions in which it makes sense to clear the secure cookie
>without being asked to.  For example, after a customer on an
>e-commerce site makes a purchase, you may want to assume that the
>secure session is over.  You  can leave the user identification token
>in effect, however.  Additionally, you can clear the stored secure
>token after a secure session timeout.
>Briefly, the advantage to using cookies is that:
>a) The user identification token can persist between browser sessions,
>provided they don't explicitly log out.  
>b) The user can move between viewing secured and insecured pages.
>Recall that if the user access an insecure page, the secure token will 
>*not* be passed along in the URL.  When they return to a secure page,
>they will fail check #3, and need to log in again.  Cookies, however,
>will still contain the secure token (which is okay, because they will 
>only be passed to secure pages) and will pass check #3, but perhaps
>not check #4 (if the timeout has occurred). 
>Well, that about sums it up.  Obviously there is a lot of work
>involved in correctly supporting secure authentication in a flexible
>fashion.  I've found that most other approaches, even on high profile
>e-commerce sites, don't come anywhere close to doing it correctly (or
>securely!).   Apologies if I forgot something important here.  I
>welcome any comments on this technique, and how to improve it.
>[OT]  This is the approached used by eZiba.com.  eZiba, the leading
>online provider of handcrafted goods from around the world, recently
>closed a $70M round of financial, with about $20M of that coming from
>Amazon.com.  One of the reasons eZiba has attracted so much attention
>is that we elected to build the e-commerce platform from the ground
>up.  When evaluating e-commerce platforms, such as Microsoft's or
>OpenMarket's, we found that nothing currently available provided a
>foundation extensible enough to meet our needs.  And the open source
>alternatives, such as OpenSales and MiniVend, while certainly
>interesting, don't have the enterprise features we required.  
>The mod_perl side of the eZiba platform is actually just the
>presentation layer for the customer.  The actual business logic has
>been developed in a stand-alone, threaded, Java server that consists
>of modules that interface with external clients (such as the mod_perl
>StoreFront application, or the database) via an high-level abstraction
>layer (TCP/IP and XML based, obviously).   Other clients include a
>product and content management suite and customer support tools.  The
>architecture was designed from the start to be flexible, extensible,
>and highly scalable and fault tolerant.
>Over the past six months, eZiba was overwhelmed by requests to use
>this technology.  I'm happy to say that we are spinning of a new
>venture, Avacet, Inc., to make this platform available to the
>community.  And here's the best part -- everything Avacet does will be 
>available open source and free via the GPL.   Currently, there are no
>GPL'd e-commerce platforms that come close to providing the
>functionality and enterprise quality of the IBM's and OpenMarket's of
>the world.  Avacet, in the next few months, will provide that
>alternative.   Additionally, Avacet will be providing consulting
>services to qualified e-commerce companies that seek to lead their
>industry category.
>The reason I mention it here, other than to give people some hope that 
>they won't be stuck on WinNT for the rest of their e-commerce lives,
>is to spread the word, and perhaps attract some mod_perl talent to
>Avacet.  We are recruiting experienced developers and program managers 
>for the team.  Since we are moving very quickly, and already have a
>rather accomplished team, I am particularly interested in developers
>that have a rich background in internet application work.  If you are
>interested in hearing more about Avacet, please don't hesitate to
>send me a mail at dclinton@xxxxxxxxxxx
>Okay, obligatory apologies for the off-topic job pitch.  :)  
>Take care,