Best security questions in February 2011

PHP 2-way encryption: I need to store passwords that can be retrieved

41 votes

I am creating an application that will store passwords, which the user can retrieve and see. The passwords are for a hardware device, so checking against hashes are out of the question.

What I need to know is:

  1. How do I encrypt and decrypt a password in PHP?

  2. What is the safest algorithm to encrypt the passwords with?

  3. Where do I store the private key?

  4. Instead of storing the private key, is it a good idea to require users to enter the private key any time they need a password decrypted? (Users of this application can be trusted)

  5. In what ways can the password be stolen and decrypted? What do I need to be aware of?

Personally, I would use mcrypt like others posted. But there is much more to note...

  1. How do I encrypt and decrypt a password in PHP?

    See below for a strong class that takes care of everything for you:

  2. What is the safest algorithm to encrypt the passwords with?

    safest? any of them. The safest method if you're going to encrypt is to protect against information disclosure vulnerabilities (XSS, remote inclusion, etc). If it gets out, the attacker can eventually crack the encryption (no encryption is 100% un-reversible without the key - As @NullUserException points out this is not entirely true. There are some encryption schemes that are impossible to crack such as OneTimePad).

  3. Where do I store the private key?

    What I would do is use 3 keys. One is user supplied, one is application specific and the other is user specific (like a salt). The application specific key can be stored anywhere (in a config file outside of the web-root, in an environmental variable, etc). The user specific one would be stored in a column in the db next to the encrypted password. The user supplied one would not be stored. Then, you'd do something like this:

    $key = $userKey . $serverKey . $userSuppliedKey;
    

    The benefit there, is that any 2 of the keys can be compromised without the data being compromised. If there's a SQL Injection attack, they can get the $userKey, but not the other 2. If there's a local server exploit, they can get $userKey and $serverKey, but not the third $userSuppliedKey. If they go beat the user with a wrench, they can get the $userSuppliedKey, but not the other 2 (but then again, if the user is beaten with a wrench, you're too late anyway).

  4. Instead of storing the private key, is it a good idea to require users to enter the private key any time they need a password decrypted? (Users of this application can be trusted)

    Absolutely. In fact, that's the only way I would do it. Otherwise you'd need to store an unencrypted version in a durable storage format (shared memory such as APC or memcached, or in a session file). That's exposing yourself to additional compromises. Never store the unencrypted version of the password in anything except a local variable.

  5. In what ways can the password be stolen and decrypted? What do I need to be aware of?

    Any form of compromise of your systems will let them view encrypted data. If they can inject code or get to your filesystem, they can view decrypted data (since they can edit the files that decrypt the data). Any form of Replay or MITM attack will also give them full access to the keys involved. Sniffing the raw HTTP traffic will also give them the keys.

    Use SSL for all traffic. And make sure nothing on the server has any kind of vulnerabilities (CSRF, XSS, SQL Injection, Privilege Escalation, Remote Code Execution, etc).

Edit: Here's a PHP class implementation of a strong encryption method:

/**
 * A class to handle secure encryption and decryption of arbitrary data
 *
 * Note that this is not just straight encryption.  It also has a few other
 *  features in it to make the encrypted data far more secure.  Note that any
 *  other implementations used to decrypt data will have to do the same exact
 *  operations.  
 *
 * Security Benefits:
 *
 * - Uses Key stretching
 * - Hides the Initialization Vector
 * - Does HMAC verification of source data
 *
 */
class Encryption {

    /**
     * @var string $cipher The mcrypt cipher to use for this instance
     */
    protected $cipher = '';

    /**
     * @var int $mode The mcrypt cipher mode to use
     */
    protected $mode = '';

    /**
     * Constructor!
     *
     * @param string $cipher The MCRYPT_* cypher to use for this instance
     * @param int    $mode   The MCRYPT_MODE_* mode to use for this instance
     */
    public function __construct($cipher, $mode) {
        $this->cipher = $cipher;
        $this->mode = $mode;
    }

    /**
     * Decrypt the data with the provided key
     *
     * @param string $data The encrypted datat to decrypt
     * @param string $key  The key to use for decryption
     * 
     * @returns string|false The returned string if decryption is successful
     *                           false if it is not
     */
    public function decrypt($data, $key) {
        $key = $this->stretch($key);
        $iv = $this->getIv($data, $key);
        if ($iv === false) {
            return false; //Invalid IV, so we can't continue
        }
        $de = mcrypt_decrypt($this->cipher, $key, $data, $this->mode, $iv);
        if (!$de || strpos($de, ':') === false) return false;

        list ($hmac, $data) = explode(':', $de, 2);
        $data = rtrim($data, "\0");

        if ($hmac != hash_hmac('sha1', $data, $key)) {
            return false;
        }
        return $data;
    }

    /**
     * Encrypt the supplied data using the supplied key
     * 
     * @param string $data The data to encrypt
     * @param string $key  The key to encrypt with
     *
     * @returns string The encrypted data
     */
    public function encrypt($data, $key) {
        $key = $this->stretch($key);
        $data = hash_hmac('sha1', $data, $key) . ':' . $data;

        $iv = $this->generateIv();
        $enc = mcrypt_encrypt($this->cipher, $key, $data, $this->mode, $iv);

        return $this->storeIv($enc, $iv, $key);
    }

    /**
     * Generate an Initialization Vector based upon the class's cypher and mode
     *
     * @returns string The initialization vector
     */
    protected function generateIv() {
        $size = mcrypt_get_iv_size($this->cipher, $this->mode);
        return mcrypt_create_iv($size, MCRYPT_RAND);
    }

    /**
     * Extract a stored initialization vector from an encrypted string
     *
     * This will shorten the $data pramater by the removed vector length.
     * 
     * @see Encryption::storeIv()
     *
     * @param string &$data The encrypted string to process.
     * @param string $key   The supplied key to extract the IV with
     *
     * @returns string The initialization vector that was stored
     */
    protected function getIv(&$data, $key) {
        $size = mcrypt_get_iv_size($this->cipher, $this->mode);
        $iv = '';
        for ($i = $size - 1; $i >= 0; $i--) {
            $pos = hexdec($key[$i]);
            $iv = substr($data, $pos, 1) . $iv;
            $data = substr_replace($data, '', $pos, 1);
        }
        if (strlen($iv) != $size) {
            return false;
        }
        return $iv;
    }

    /**
     * Store the Initialization Vector inside the encrypted string.
     *
     * We will need the IV later to decrypt the data, so we need to
     * make it available.  We don't want to just append it, since that
     * could open MITM style attacks on the data.  So we'll hide it 
     * using the key to determine exactly how to hide it.  That way,
     * without knowing the key, it should be impossible to get the IV.
     *
     * @param string $data The data to hide the IV within
     * @param string $iv   The IV to hide
     * @param string $key  The key to use to hide the IV with
     *
     * @returns string The $data parameter with the hidden IV
     */
    protected function storeIv($data, $iv, $key) {
        for ($i = 0; $i < strlen($iv); $i++) {
            $offset = hexdec($key[$i]);
            $data = substr_replace($data, $iv[$i], $offset, 0);
        }
        return $data;
    }

    /**
     * Stretch the key using a simple hmac based stretching algorythm
     *
     * We want to use sha1 here over something stronger since Blowfish
     * expects a key between 4 and 56 bytes.  Sha1 produces a 40 byte
     * hash, so it should be good for these purposes.  This also allows
     * an arbitrary key of any length to be used for encryption.
     *
     * Another benefit of streching the kye is that it actually slows
     * down any potential brute force attacks. 
     *
     * We use 5000 runs for the stretching since it's a good balance
     * between brute force protection and system load.  We could increase
     * this if we were paranoid, but it shouldn't be necessary.
     *
     * @see http://en.wikipedia.org/wiki/Key_stretching
     *
     * @param string $key The key to stretch
     *
     * @returns string A 40 character hex string with the stretched key
     */
    protected function stretch($key) {
        $hash = sha1($key);
        $runs = 0;
        do {
            $hash = hash_hmac('sha1', $hash, $key);
        } while ($runs++ < 5000);
        return $hash;
    }

}

Usage:

$e = new Encryption(MCRYPT_BlOWFISH, MCRYPT_MODE_CBC);
$encryptedData = $e->encrypt($data, 'key');

Then, to decrypt:

$e2 = new Encryption(MCRYPT_BlOWFISH, MCRYPT_MODE_CBC);
$data = $e2->decrypt($encryptedData, 'key');

Note that I used $e2 the second time to show you different instances will still properly decrypt the data.

Now, how does it work/why use it over another solution:

  1. Keys

    • The keys are not directly used. Instead, the key is stretched by a 5000 round hmac cycle.

    • The key is used to store the Initialization Vector. That way, without the proper key, you cannot even get the IV. So MITM attacks should be averted.

  2. Data Integrity

    • All stored data is hmac'd to verify that it has not been tampered with prior to encryption. When it's decrypted, it's hmac'ed again (against the key) to determine if it was tampered with and that the correct result was returned.
  3. Encryption:

    • It uses mcrypt to actually perform the encryption. I would suggest using MCRYPT_BLOWFISH cypher and MCRYPT_MODE_CBC for the mode. It's strong enough, and still fairly fast (an encryption and decryption cycle takes about 1/2 second on my machine).

Now, as to point 3 from the first list, what that would give you is a function like this:

function makeKey($userKey, $serverKey, $userSuppliedKey) {
    $key = hash_hmac('sha512', $userKey, $serverKey);
    $key = hash_hmac('sha512', $key, $userSuppliedKey);
    return $key;
}

You could stretch it in the makeKey() function, but since it's going to be stretched later, there's not really a huge point to doing so.

As far as the storage size, it depends on the plain text. Blowfish uses a 8 byte block size, so you'll have:

  • 8 bytes for the initialization vector
  • 40 bytes for the hmac
  • 1 byte for the hmac separator :
  • data length
  • Padding so that (41 + data length) % 8 == 0

So for a 16 character data source, there will be 41 + 16 (57) characters of data to be encrypted. So that means the actual encrypted data size is 64 bytes due to padding. Then add the 8 bytes for the IV and the total stored size is 72 bytes. So there's at best a 49 character overhead, and at worst a 56 character overhead...

I hope that helps...

Is time() a good salt

23 votes

I'm looking at some code that I have not written myself. The code tries to hash a password with SHA512 and uses just time() as the salt. Is time() too simple a salt for this or is this code safe?

Thanks for the answers and comments. I will sum it up here for the new readers:

  • salt should be different for each user, so if 2 users register at the same time, their salts won't be unique. This is a problem, but not a big one.
  • but salt shouldn't be in any way related to the user, so time() is not a good salt.
  • Use a random, evenly distributed, high entropy salt. That's a mouthful, so what code could possibly generate a random, evenly distributed, high entropy salt?

Ok, so how about I replace time() with a random string 32 char long. The random string could be generated from looping 32 times over a set of alphabet chars. Does that sound good?

Short answer:

No, time() is not a good salt.

Long answer:

copied from my answer to Salt Generation and open source software

What is a salt?

A salt is a random set of bytes of a fixed length that is added to the input of a hash algorithm.


Why is salting (or seeding) a hash useful?

Adding a random salt to a hash ensures that the same password will produce many different hashes. The salt is usually stored in the database, together with the result of the hash function. Salting a hash is good for a number of reasons:

  1. Salting greatly increases the difficulty/cost of precomputated attacks (including rainbow tables)
  2. Salting makes sure that the same password does not result in the same hash. This makes sure you cannot determine if two users have the same password. And, even more important, you cannot determine if the same person uses the same password across different systems.
  3. Salting increases the complexity of passwords, thereby greatly decreasing the effectiveness of both Dictionary- and Birthday attacks. (This is only true if the salt is stored separate from the hash).
  4. Proper salting greatly increases the storage need for precomputation attacks, up to the point where they are no longer practical. (8 character case-sensitive alpha-numeric passwords with 16 bit salt, hashed to a 128 bit value, would take up just under 200 exabytes without rainbow reduction).


There is no need for the salt to be secret.

A salt is not a secret key, instead a salt 'works' by making the hash function specific to each instance. With salted hash, there is not one hash function, but one for every possible salt value. This prevent the attacker from attacking N hashed passwords for less than N times the cost of attacking one password. This is the point of the salt.
A "secret salt" is not a salt, it is called a "key", and it means that you are no longer computing a hash, but a Message Authentication Code (MAC). Computing MAC is tricky business (much trickier than simply slapping together a key and a value into a hash function) and it is a very different subject altogether.

The salt must be random for every instance in which it is used. This ensures that an attacker has to attack every salted hash separately.
If you rely on your salt (or salting algorithm) being secret, you enter the realms of Security Through Obscurity (won't work). Most probably, you do not get additional security from the salt secrecy; you just get the warm fuzzy feeling of security. So instead of making your system more secure, it just distracts you from reality.


So, why does the salt have to be random?

Technically, the salt should be unique. The point of the salt is to be distinct for each hashed password. This is meant worldwide. Since there is no central organization which distributes unique salts on demand, we have to rely on the next best thing, which is random selection with an unpredictable random generator, preferably within a salt space large enough to make collisions improbable (two instances using the same salt value).

It is tempting to try to derive a salt from some data which is "presumably unique", such as the user ID, but such schemes often fail due to some nasty details:

  1. If you use for example the user ID, some bad guys, attacking distinct systems, may just pool their resources and create precomputed tables for user IDs 1 to 50. A user ID is unique system-wide but not worldwide.

  2. The same applies to the username: there is one "root" per Unix system, but there are many roots in the world. A rainbow table for "root" would be worth the effort, since it could be applied to millions of systems. Worse yet, there are also many "bob" out there, and many do not have sysadmin training: their passwords could be quite weak.

  3. Uniqueness is also temporal. Sometimes, users change their password. For each new password, a new salt must be selected. Otherwise, an attacker obtained the hash of the old password and the hash of the new could try to attack both simultaneously.

Using a random salt obtained from a cryptographically secure, unpredictable PRNG may be some kind of overkill, but at least it provably protects you against all those hazards. It's not about preventing the attacker from knowing what an individual salt is, it's about not giving them the big, fat target that will be used on a substantial number of potential targets. Random selection makes the targets as thin as is practical.


In conclusion:

Use a random, evenly distributed, high entropy salt. Use a new salt whenever you create a new password or change a password. Store the salt along with the hashed password. Favor big salts (at least 10 bytes, preferably 16 or more).

A salt does not turn a bad password into a good password. It just makes sure that the attacker will at least pay the dictionary attack price for each bad password he breaks.


Usefull sources:
stackoverflow.com: Non-random salt for password hashes
Bruce Schneier: Practical Cryptography (book)
Matasano Security: Enough with the Rainbow Tables
usenix.org: Unix crypt used salt since 1976
owasp.org: Why add salt
openwall.com: Salts

Disclaimer:
I'm not a security expert. (Although this answer was reviewed by Thomas Pornin)
If any of the security professionals out there find something wrong, please do comment or edit this wiki answer.


As for what seems to be a good source for your random salt
Also read: What is the most secure seed for random number generation?
In the absence of dedicated, hardware based, random generators, the best way of obtaining random data is to ask the operating system (on Linux, this is called /dev/random or /dev/urandom [both have advantages and problems, choose your poison]; on Windows, call CryptGenRandom())

If for some reason you do not have access to the above mentioned sources of random, in PHP you could use the following function:
From the source of phpass v0.3

<?php
/**
 * Generate pseudo random bits
 * @copyright: public domain
 * @link http://www.openwall.com/phpass/
 * @param int $length number of bits to generate
 * @return string A string with the hexadecimal number
 * @note don't try to improve this, you will likely just ruin it
 */
function random_bits($entropy) {
    $entropy /= 8;
    $state = uniqid();
    $str = '';
    for ($i = 0; $i < $entropy; $i += 16) {
        $state = md5(microtime().$state);
        $str .= md5($state, true);
    }
    $str = unpack('H*', substr($str, 0, $entropy));
    // for some weird reason, on some machines 32 bits binary data comes out as 65! hex characters!?
    // so, added the substr
    return substr(str_pad($str[1], $entropy*2, '0'), 0, $entropy*2);
}
?>

Challenge: maximize cost of obfuscation's reverse engineering

13 votes

Disclaimer: Similar questions has been asked a number of times on SO, however this question is much more specific, and has not been adequately addressed so far.

We're developing a new packaged software, which, for business security reasons, must run on our customer's server, in PHP. The software is sold with a per-user end-license; price range is within $20-80 per user, target market is small (and web-savy) consultancies, and IT agencies.

To discourage piracy (eg. removing the user-license enforcement), we'd like to maximize the protection of the PHP code in any means technologically available, which does not inconvenience the user.

Let's break this down:

  • does not inconvenience the user: no additional server-side installs (no zend decoder, or other binaries). Has to run on a plain-vanilla shared PHP host out-of-the-box.

  • Maximize the protection: breaking the protection has to outweigh the cost of buying an additional license. That is, it has to take at least 3-5 working days for a professional hacker to remove the user license protection.

  • Any means technologically available: might call home, might use high-end crypto, might implement a c64 emulator.

To pro-actively address the so far highest-voted non-solutions:

  • NOT looking for perfect obfuscation, just extremely hard ones (defined as: have to take at least 3-5 working days to decrypt), OR other anti-piracy methods

  • NOT looking for "black-box" software packages, which I don't know how they work, and can't determine whether it fits our purpose; looking for algorithmic ,and out-of-the-box ideas.

  • NOT looking for license/law-side protection, we already have that covered.

  • We DO know, that given enough time, and focus, all obfuscation will be hacked sooner or later; we merely want this not to be the economical solution.

Given the above constraints, what methods, or ideas would you use to maximize anti-piracy measures?

Bounty-hunt: point goes for the hardest algorithmic method to reverse-engineer the code, given the constraints above.

Update / Bounty-hunt: I've accepted Ira Baxter's answer, mostly because the rest failed to answer the core question, and attempted to question the underlying assumptions (business, closed source, yadda yadda). Thanks all!

I think what you want to do is to transform the code algorithmically, to obfuscate not only what is executed, but also to obfuscate the data structures. We assume we start with a clean version of the program, produced by the developer. He always works wih the clean version. Obfuscation produces the to-ship version. Good obfuscation will produce a to-ship version with exactly the same functionality as the original, so no further testing is (arguably) needed.

For control flow scrambling, the idea is to take the nicely written code you have at the start, and push it through transformations that make static (and human) analysis of the decisions that control the flow difficult by multiplying the set of assumptions that have to analyzed. For instance, if you have two pointers, and store a value through one, can it affect the value seen by the other? Depending on whether the pointers are aliased on not, you can get two different answers. Now take N pointers, each of which may be aliased; you get 2^N possible aliasing relations. If the reader doesn't know the exact combination, he won't be able to determine if a decision might be true, false or conditional. Of course, the tool that generates this produces conditionals whose outcome it knows, because it designs (generates) the pointer rat's nest to produce a specific outcome.

See Code Obfuscation Literature Survey (not my paper), which discusses a variety of control flow and data flow obfuscation. This is likely not the most recent summary of what is possible, but its pretty instructive. You should note doing this kind of obfuscation has some impact on execution time.

What the papers on this topic make clear is that control and data flow obfuscated programs are extremely hard for static analyzers to "understand"; the papers provide/reference demonstrations of the algorithmic complexity of processing such obfuscated programs.

Now, you might argue that people aren't static analyzers and therefore don't suffer the same limitations. You might be right; Roger Penrose famously argues that people do not have the same constraints as Turing machines; the argument isn't settled by a long shot. But the entire foundation of encryption/hashing technology is built on essentially the same kind of computational complexity arguments. And to date, nobody has proven smart enough to crack these technologies in ways that can be used in daily life by theives (good thing, or your bank accounts would be empty).

To do this to a PHP program, you need tools that can parse the PHP code, and carry out such transformations. Our DMS Software Reengineering Toolkit has robust PHP parsers, and can apply very complex transformations to code. To do this really well, you want to apply the transformations globally across all your code, not just on a file-by-file basis. We don't have this kind of obfuscation transformation implemented on PHP, but if you really wanted to do it, this would be the way. We have applied complex transformations to PHP programs for other commercial products that we sell.

When you are all done, ideally you'd compile this result to machine code, say using the HipHop compiler. (Just compiling would defeat some folks, but not the serious software engineers).

EDIT: Obfuscation != AntiPiracy is a theme in other answers. So how does obfuscation help?

First you need to deal with the anti-piracy issue. The obvious things to do are:

  • Add copyright comments to each file. These serve as warnings to theives. Not good ones.
  • Add copyright strings in various places and print them out occasionally; these will end up in memory and play a roleif a pirate steals the code; he stole this string, too.
  • Add a string to your application saying, "licensed to ". This makes your customer unenthusiastic about letting it be stolen.
  • Add a check to your application that it is running on the intended customer's machine. (Since your app is intended to be very cheap, you'll probably need to automate a registration process)
  • Have the application phone home with its machine ID occasionally.

Now, these steps prevent someone (legally and technically) from stealing your code.
If this is all you have, an unfazed pirate will simply remove the technical checks and its stolen.

It is very hard to prevent somebody from copying the bit stream that makes up your product; computers are far too good at copying. So your goal is to arrange for it to be hard for him to derive value if he does, and that's where obfuscation comes in.

If the code is sufficiently obfuscated, he will have a difficult time locating the license check and phone home mechansisms to disable them. (I suggest several checks, none of them always called, to make it hard for the theif to tell when he is successful.). The obfuscation, well done, should protect the printing of the original owner's name, which means the original owner will have some interest in prevent it from being stolen as you'll name him along with pirate in any lawsuit.

If they defeat the licenses, copyright printing, and phone-home mechanisms, and simply want to run it in the back room without telling you, you might be stuck. (For $80.00, I can't imagine why they'd go to all this trouble just for this effect). But many thieves want to modify the software to "improve" it, especially if they want your market. Serious obfuscation will prevent them for doing this; it will even make it hard for them to add thier own license controls. That limits the value pretty severely.

They may simply steal it and release it to world for free; your hope here is the applicaton is hard to crack. If they succeed, your only good defense is a continuing stream of upgrades that licensed owners get.

Obfuscation is a key to successful piracy defense, IMHO.

The 2011 approach to XSS in PHP?

12 votes

Hi everyone,

I am trying to get updated on available and appropriate counter-measures that actively reduces the chance of being hit by the XSS train during 2011.

I've googled like never before to find out that there's plenty of libraries available online that's supposed to help out with XSS issues, which proudly and boldly states that "the XSS/SQL injection buck stops here".

I have found that these libraries suffer from at least one of the two following symptoms:

  • The library is so huge that it probably has it's own heartbeat.
  • The library is from the times when Beach boys were playing on the radio.

PHP has been around for some time now and the far-from decent strip_tags is accompanied by functions such as filter_var, among others. I am far from an expert in these security issues and really can't tell whether it will ensure good nights of sleep in the future, or not.

What is my best chance of reducing XSS injections during 2011 without bloating my code, with or without dated libraries ?

This: htmlspecialchars()

Correct and secure manner of storing in-app-purchases

9 votes

What is the best way to store an in-app-purchase on the device, so that the purchases can also be accessed offline but, the security off the purchases are not compromised?

Do not store anything valuable on the device as it cannot be trusted and it can easily be compromised by someone motivated.

Now, all of this depends on the type and value of the item that is being purchased and what happens if its compromised.

If its truly valuable then use a remote secure server for managing secure items. In app purchases include a receipt that can be verified by your remote secure server talking to apple's servers directly through a secure connection. See this link to verifying store receipts.

Securely provide a unique secret code to winner of flash game?

8 votes

Here's what I want to do: when a player wins a game (coded in flash/actionscript), they are given a personalized secret key, which they can email to me in exchange for a prize. I can then validate the key on my end using a private algorithm.

I need to design it so that it is practically impossible for hackers to generate a valid prize key without winning the game. Is this even possible?

I assume that any SWF file is basically vulnerable to decompilation, but I don't know exactly how vulnerable they are. Perhaps any algorithm for generating a valid key will be accessible to hackers?

I have at my disposal all the methods in actionscript 3, as well as a PHP/MySQL server, and I control the server where the game will be hosted.

First off, don't give the user a "secret" code to validate.

When delivering the page to the client create a "secret" code. Probably a base64 encoded GUID would work. Record the guid, when it was generated, and the browser fingerprint in your database.

Once the game is over have the action script get their details for prize delivery. Post this back to your server along with the code. Again record the date time of completion and the browser fingerprint.

To validate, check the amount of time that passed between guid generation. Also look at the browser fingerprint.

Cheaters will stand out in three ways. First, the date/time delta will be extremely short. You should know how long it normally takes to play. Second, you might see a host of posts to your page with invalid codes. Third, the browser fingerprint might even tell you who was using automated tools.

UPDATE
I just wanted to point out a couple things you will want to include. First, @aaz had a great idea about asking the player a question about the game at the point they are filling out the winner information. This should be some element that is randomized. Probably not color simply due to the number of people who are color blind; but certainly something you can control and record server side prior to delivering the action script. At the very least this would require some level of human intervention when posting results.

Second, @John Lewis had a good idea about recording their in game actions and submitting those. Perhaps any click coordinates could be saved and immediately sent back to the server and saved with a date/time stamp. You could compare those coordinates across multiple games to look for patterns. Intelligent analysis will be important.

How to create a login-screen replacement for Ubuntu

7 votes

I'm interested in writing a replacement login screen for Ubuntu that would present the user with a puzzle rather than prompt for a password. I'm looking for some advice on how to go about creating this. I'm a programmer by profession with years of experience, but am not familiar enough with Linux application programming to know how to begin this particular project. Thank you!

You could probably do this as an authentication module for PAM (Linux Pluggable Authentication Modules). PAM is configured in configuration files in /etc/pam.d. Each file in this directory defines a PAM service by specifying a set of PAM modules and how they should work together. You could write a new authentication module and replace the current authentication module in the services where you want to use the new login scheme.

How does SQLParameter prevent SQL Injection?

5 votes

What exactly is going on in the background that makes it so SQLParameter prevents SQL Inection attacks in a .NET Parameterized query? Is it just stripping out any suspect characters or is there something more to it?

Has anyone out there checked to see what actually gets to SQL Server when you pass malicious input?

Related: Can you use a SQLParameter in the SQL FROM statement?

Basically, when you perform a SQLCommand using SQLParameters, the parameters are never inserted directly into the statement. Instead, a systrem stored procedure called sp_executesql is called and given the SQL string and the array of parameters. When used as such, the parameters are isolated and treated as data, NOT commands, so what they contain can never be "executed". You'll just get a big fat error that the parameter value is invalid in some way.