3SRT has asked for the wisdom of the Perl Monks concerning the following question:

Hello fellow monks! I have written a fairly simple cgi file that generates a temporary password for a given user. I do not want to output the password as text, so I am converting it to a picture, using GD::SecurityImage. I created a second file, dubbed 'secimage.cgi', which will generate the picture. My main file, dubbed 'main.cgi', simply prints the picture using a simple print statement:

print"<img src='https://www.mysite.com/secure/cgi-bin/secimage.cgi'>";

My question is this: How do I send the password generated in my main.cgi to the secimage.cgi? I thought about writing it to a file, and using the secimage.cgi to open and read it in. Isn't there another way? Thanks in advance!

Replies are listed 'Best First'.
Re: Passing variable from one cgi to another
by bigmacbear (Monk) on Jan 10, 2008 at 18:40 UTC

    As olus said, you can get around passing the plaintext password in the filesystem entirely if, instead of producing HTML code that invokes a separate CGI, you have your main CGI program generate the image (into the filesystem) and then produce HTML that points to this temporary file. You're still passing the password around in the filesystem, but using a generated image as a form of encryption.

    Once you have done that, the next question is how to store the password for future comparison against the credentials supplied by the user.

    The Unix password authentication system, which has worked well for many years, actually never stores the password itself, either in plaintext or in a format that can be decrypted. What it stores is a "hash", which is produced by encrypting a fixed plaintext, unrelated to the password, using the password as key. The key is then discarded, so the hash can never be decrypted. However, if the same plaintext is ever encrypted using the same algorithm using the same key, the hash produced is guaranteed identical. So you end up storing and comparing hashes of passwords instead of actual passwords.

    Look at the crypt() function if you're on a Unix or Unix-like system, which works pretty much as I've just described (I've left out some details for simplicity); or look at MD5 digests, which operate similarly and are used in place of crypt() on some Linux distributions.

    One last thing: you will run afoul of accessibility requirements -- which have the force of law in many applications -- using only an image to transmit temporary passwords like this. Visually impaired users will have to be provided their passwords in some other way, probably involving the telephone.

Re: Passing variable from one cgi to another
by moritz (Cardinal) on Jan 10, 2008 at 16:46 UTC
    A database is probably better than a simple file because the DB engine handles the locking for you.

    If you want to verify that password later on you have to have it stored somewhere anyway.

    BTW way do you want to print that password into an image? to fool bots?

      Yeah, fooling bots was one reason. The other reason is to prevent users from copying the passwords directly. The project I am working on doesn't want a user to be able to easily copy the password and save it, or just copy and paste it into the login box.

      I thought about a DB, but I don't know if I like the idea of having the lists of passwords stored, even if they are locked?
        lists of passwords stored, even if they are locked

        Don't store lists of passwords. Store them encrypted. Share a secret between main.cgi and secimage.cgi. Encrypt and store in main; pull and decrypt in secimage.

        The project I am working on doesn't want a user to be able to easily copy the password and save it, or just copy and paste it into the login box

        The project is an ass. This is half-baked at best. Figure out the security controls that are required, and implement them. "Don't make it easy" is not a control. Presumably what you are trying to do is to require positive action to activate the thing this is password protecting, i.e. to force the user to take the protection of password seriously. Generating a password and then sending it to them is going to have the opposite action.

        I would strongly encourage review of the protocols by a security professional.

        --woody

        EDIT:

        Sorry, my tone is bad. One should never call a well meaning project an ass. I work in Fedspace, and recently had an encounter with a web project that went something like this:

        Designer: We need a unique identifier. Lets ask the user for their social security number.
        Reviewer: You can't do that. People are quite sensitive about social security numbers -- as personally identifiable information, there are significant risks, including federal law, such as the privacy act, which forbids it. In addition, it would support "matching", comparing against other databases, so we'd have to publish it in the federal register, and jump a lot of other hoops.
        Designer:Ok, we'll just use their last four digits. They do that with credit cards, so it must be ok.
        Reviewer:(strangles self with tie)
        Designer:Ah, good, no objections, so lets do that!

        Let me restate. Before designing the final solution, determine the actual requirements. Be aware of any unintended consequences of your solution. If your requirement is to 'fool the bots', i.e. to perform a turing test, be aware that this is not easy and that there are no great solutions today. Use of graphical captcha's carries a rather high cost, actually -- in the united states, about one person in ten has a vision defect, with about one in twenty suffering from red/green blindness. Graphical captchas will either disenfranchise large portions of your community or will require deployment of alternative strategies and probably help desk lines.

        Well, at least the advice to not store passwords in the clear is sound. :-)

        I'm a bit puzzled - how do passwords help you if your system doesn't store them anywhere?

        I mean when the user enters the password somewhere you need to verify if his password is correct, so you must have the password stored somewhere.

        If you're worried that your database admin might steal the passwords you could try to encrypt the temporary passwords like this:

        For each generated password you also create a unique key. Then you encrypt the password with key and store it in the DB, and you send the key to the client (print"<img src='https://www.mysite.com/secure/cgi-bin/secimage.cgi?key=$key'>";).

        That way the secret is split into two halves, one is only known in the database and one that is only send the browser (and not stored), so no evil database admin can recover the passwords.

Re: Passing variable from one cgi to another
by leocharre (Priest) on Jan 10, 2008 at 19:12 UTC

    You could use CGI::Session.
    Here's a loose plan for doing it.

    main.cgi would

    • 1) make sure there's a session
    • 2) gen or regen a password
    • 3) save it to the session (maybe call flush(), is it?) parameter 'string_to_render' (?)
    • 4) output html that has
      your pw: 

    secimage.cgi would

    • 1) get remote user's session id
    • 2) look inside the session for 'string_to_render'
    • 3) output to screen.

    The downfall here is that the sessions could be potentially read by third parties, etc. Of course, the sessions are not named after the usernames.

Re: Passing variable from one cgi to another
by olus (Curate) on Jan 10, 2008 at 16:53 UTC
    You could, instead of having two cgi files, create a module that works the images and in your main cgi you simply call that module's methods.
    One of them would return you the name of the file. And then your main.cgi does the print with the image name already there.