http://qs321.pair.com?node_id=93391


in reply to Web Security for CGI programs

  • Taint Mode
    In addition to some sort of user authentication, nothing beats good 'ol taint mode. If you're dealing with CGI, just use

    #!/usr/bin/perl -wT

    at the top of your Perl scripts. If you're in mod_perl, you need add the following line to your httpd.conf:

    PerlTaintCheck On

    Taint mode forces you to clean up data that was received from an outside source, before you can do anything too damaging with it. To untaint data, you just have to send it through a regex.. if it matches, the resulting $1 will be untainted. Yes, it is possible to write cheesy regexes to get around this, but then that's the programmers fault for not trying.

    You can get all sorts of juicy bits of information on taint mode, and other security measures, with "perldoc perlsec". Additionally, there are two modules, taint and untaint which are utility functions for working in taint mode. You don't need them, but they may prove helpful depending on what you are trying to accomplish.

  • Password Challenge-Response
    It's also possible to keep from sending plaintext passwords when you have no SSL. It's called a challenge-response system. In order to make it work, you need something like a javascript md5 implementation on the client end, and session support and md5 on the server end.

    When the browser connects to the server for the first time, a new session ID is generated for it. Additionally, a hash is generated (made of random characters, much like the session ID). The session ID and Hash are stored on the server, AND given to the browser on it's first request (which is probably the login page).

    Whenever the user types in their name and password, and then clicks submit.. you have the HTML form call a javascript function BEFORE it submits any data to the server. The Javascript function MD5's the password, and appends the result to the Hash that we generated earlier. Then you MD5 the resulting string. This resulting string is what you send to the server as your password. Immediatly replace the plaintext password with this new string you have, you don't want the plaintext password going to the server :-)

    When the form finally submits the info to the server, your server does the same process. It digs the users password out of the database (or whatever you are using), runs it through MD5, appends that to the hash it has associated with your Session ID, and then runs the resulting string through MD5. Now, if that matches what the browser passed you, the password is correct!

    This method isn't the most secure method in the world, by any means. SSL would be better then this. For even better protection SSL could be used in addition to this method. But as you said, SSL isn't always available. If somebody is sniffing your connection and you don't have SSL, they can sniff the hash that the server sent you. Now, they would never ever see the password in plaintext. But with the hash, they might have a better chance at being able to brute force your password. Would it be easy for them to do this? No. But if somebody really wanted to break in, that would be a possible route they could use. Just something to ponder...
    -Eric

    Updated