Form validation with in_array in PHP
I was looking at my web stats the other day, and noticed that my die roller page on the Biblyon Broadsheet had been accessed as “/Game/Dice/?dice=1&die=20+”. That “plus” sign was invalid, so I went to make sure I hadn’t put in a bad link somehow, and in the process noticed that the image of the d20 failed to load.
It was including the “+” in the HTML. That woke me up. I tried a couple of tests, and sure enough, I was able to inject code into the web page by including it after the die number.
Time to panic.
Thing is, I went into the code and it didn’t make sense. I was doing what I always do: validate against an array of valid options.
[toggle code]
- $allowedDice = array(4, 6, 8, 10, 12, 20, 100, 'ability');
- $formDie = $_GET['die'];
-
if (!in_array($formDie,$allowedDice)) {
- $formDie = 20;
- }
If the form data is in the array of allowed dice, it uses it, otherwise, it sets the die to d20.
What I first noticed is that this is not exactly what I prefer to do when validating against an array: I prefer to use the form data only to pull the real value from the array. Often, I will do this with keys, so that the form data is not the data I use in the code. In this case, it would look something like this:
[toggle code]
-
$allowedDice = array(
- 'four'=>4,
- 'six'=>6,
- 'eight'=>8,
- 'ten'=>10,
- 'twelve'=>12,
- 'twenty'=>20,
- 'percent'=>100,
- 'ability=>'ability',
- );
- $formDie = $allowedDice[$_GET['die']];
-
if (!$formDie) {
- $formDie = 20;
- }
But so what? Why would I want to use that more verbose and complicated form just for a bunch of dice? They’re either valid dice or they’re not!
Well, in this case, it turns out not. The reason is PHP’s type juggling. All form values come in as strings. By setting the dice in the array as integers, I was triggering automatic type conversion. The string “20HELLO”, or worse, “20” followed by HTML code will convert to the integer 20. This meant that it was in the array, because the integer 20 was in the array, even though the string “20HELLO” was not.
There are three solutions; the best is probably to use keys, as in the example above. Also a very good idea, when creating an array to validate form input, make sure every value in the array is a string, because that’s what the form value will be:
- $allowedDice = array('4', '6', '8', '10', '12', '20', '100', 'ability');
Finally, when you’re expecting integer values, always convert to an integer as soon as you get it, using “intval”, for example, and use the converted variable rather than the value directly from the form.
- Die Roller
- Gods & Monsters uses d4, d6, d8, d10, d12, d20, and d100. What is a d4? a d20? What is a d100? What do these dice look like, and how do you read them?
- PHP: Type Juggling
- “PHP does not require (or support) explicit type definition in variable declaration; a variable’s type is determined by the context in which the variable is used.”
More security
- On education, the left is mired in the fifties
- Why don’t schools have locked doors? Because when it comes to education, especially K-12, the left, as in so many things, is mired in the distant industrialized assembly-line past.
- How does Apple’s supposed anti-conservative bias matter?
- If you think Apple has a bias against conservatives or Christians, you definitely don’t want Apple to build a tool its employees can use to help guess an iPhone’s password.
- Should Apple enable exes to access their ex-spouse’s iPad?
- Chris Matyszczyk wants Apple to just believe someone who says their spouse died, and give access to their iPad, then claims that this is how everything else, from house titles to bank accounts work. Unfortunately, he’s not far off there.
- The last four digits of your social security number
- The last four digits of your social security number are the least guessable part of your SSN.