Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safe way to get alpha-numeric string from user input? (without preg_replace)

Tags:

security

php

I have read many other questions regarding how to filter a string to "Alpha-numeric", but all of them suggest the preg_replace() method.

According to OWASP:

Function preg_replace() should not be used with unsanitised user input, because the payload will be eval()’ed13.

preg_replace("/.*/e","system(’echo /etc/passwd’)");

Reflection also could have code injection flaws. Refer to the appropriate reflection documentations, since it is an advanced topic.

So now how do I achieve this without preg_replace?

$result = preg_replace("/[^a-zA-Z0-9]+/", "", $_POST['data']);
// Notice the $_POST['data']
like image 607
Vladimir Avatar asked Nov 11 '16 20:11

Vladimir


4 Answers

There's no problem using preg_replace() to filter user inputs. The OWASP advice you've quoted is talking about the pattern not being user input itself.

However, I'd say that using filtered inputs is a problem by itself - you should validate instead. As in, don't accept invalid inputs.

like image 63
Narf Avatar answered Oct 05 '22 23:10

Narf


  1. As others have pointed out, the OWASP vulnerability you've linked only applies when you're evaluating the expression, which you shouldn't be doing anyway.
  2. In my experience, regular expressions are highly frowned upon for such simple operations where PHP's built-in string functions suffice. The string functions are also faster.
  3. If the data is not valid, then you shouldn't be filtering it, you should be rejecting it.

Example:

$result = ctype_alnum($_POST['data']) ? $_POST['data'] : null;
like image 41
mister martin Avatar answered Oct 05 '22 23:10

mister martin


Well we had similar situation and we use the following:

if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str))
{

//do your stuff
}
like image 32
Just_Do_It Avatar answered Oct 05 '22 23:10

Just_Do_It


You could go for something like this:

<?php
$unsafe_input = 'some"""\'t&%^$@!`hing~~ unsafe \':[]435^%$^%*$^#'; // input from user

$safe_input = ''; // final sanitized string

// we want to allow 0-9 A-Z and a-z
// merge and flip so that we can use isset() later
$allowed_chars = array_flip(array_merge(range(0, 9), range('A', 'Z'), range('a', 'z')));

// loop each byte of the string
for($i = 0; $i < strlen($unsafe_input); ++$i)
{
    // isset() is lightyears faster than in_array()
    if(isset($allowed_chars[$unsafe_input[$i]]))
    {
        // good, sanitized, data
        $safe_input.= $unsafe_input[$i];
    }
}

echo $safe_input;
like image 44
MonkeyZeus Avatar answered Oct 06 '22 01:10

MonkeyZeus