2

I am keeping record of every request made to my website. I am very aware of the security measurements that need to be taken before executing any MySQL query that contains data coming from query strings. I clean it as much as possible from injections and so far all tests have been successful using:

htmlspecialchars, strip_tags, mysqli_real_escape_string.

But on the logs of pages visited I find query strings of failed hack attempts that contain a lot of php code:

?1=%40ini_set%28"display_errors"%2C"0"%29%3B%40set_time_limit%280%29%3B%40set_magic_quotes_runtime%280%29%3Becho%20%27->%7C%27%3Bfile_put_contents%28%24_SERVER%5B%27DOCUMENT_ROOT%27%5D.%27/webconfig.txt.php%27%2Cbase64_decode%28%27PD9waHAgZXZhb

In the previous example we can see:

display_errors, set_time_limit, set_magic_quotes_runtime, file_put_contents

Another example:

/?s=/index/%5Cthink%5Capp/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=ctlpy.php&vars[1][]=<?php @assert($_REQUEST["ysy"]);?>ysydjsjxbei37$

This one is worst, there is even some <?php and $_REQUEST["ysy"] stuff in there. Although I am able to sanitize it, strip tags and encode < or > when I decode the string I can see the type of requests that are being sent.

Is there any way to detect a string that contains php code like:

filter_var($var, FILTER_SANITIZE_PHP); 

FYI: This is not a real function, I am trying to give an idea of what I am looking for.

or some sort of function:

function findCode($var){
   return ($var contains PHP) ? true : false
}

Again, not real

No need to sanitize, that has been taken care of, just to detect PHP code in a string. I need this because I want to detect them and save them in other logs.

NOTE: NEVER EXECUTE OR EVAL CODE COMING FROM QUERY STRINGS

24
  • 4
    First of all, just don't eval Commented Apr 16, 2019 at 7:47
  • 3
    Please don't suggest him to use an api for each query. Security is even more of a reason here than performance. The Query could contain sensitive data you really DON'T wan't to send to 3rd parties on the internet.
    – Jonathan
    Commented Apr 16, 2019 at 7:53
  • 1
    Visiters can submit any query with a request. It could contain PHP, but also Javascript (think: XSS) and possibly other harmful stuff (language, pictures, etc). It's a fact of live. It is up to you to only accept those parameters you actually need, and then only those values that are permissible for those parameters. Storing every request doesn't make your site safer. Making sure you don't do anything stupid, with stuff that shouldn't be permitted, does. Commented Apr 16, 2019 at 8:01
  • 1
    What's the harm in having this stuff in log files? By itself it's just text. Unless you explicitly try to execute it as PHP code, it won't do anything. That's pretty much what all attacks boil down to: don't try to execute user input as PHP/SQL/HTML etc., and you'll be fine.
    – deceze
    Commented Apr 16, 2019 at 8:04
  • 1
    OK, I understand. The answer is: No, not reliably (this is the short answer...). You also say: "I am very aware of the security measurements that need to be taken before executing any MySQL query that contains data coming from query strings.". However sanatizing with htmlspecialchars(), strip_tags() and mysqli_real_escape_string() is not the right method. Better use prepared statements. Here's an explanation. Commented Apr 16, 2019 at 8:16

1 Answer 1

0

After reading lots of comments @KIKO Software came up with an ingenious idea by using PHP tokenizer, but it ended up being extremely difficult because the string that is to be analyzed needed to have almost prefect syntax or it would fail.

So the best solution that I came up with is a simple function that tries to find commonly used PHP statements, In my case, especially on query strings with code injection. Another advantage of this solution is that we can modify and add to the list as many PHP statements as we want. Keep in mind that making the list bigger will considerably slow down your script. this functions uses strpos instead of preg_match (regex ) as its proven to perform faster.

This will not find 100% PHP code inside a string, but you can customize it to find as much as is required, never include terms that could be used in regular English, like 'echo' or 'if'

function findInStr($string, $findarray){
    $found=false;   
    for($i=0;$i<sizeof($findarray);$i++){
        $res=strpos($string,$findarray[$i]);
        if($res !== false){
            $found=true;
            break;
        }
    }
    return $found;
}

Simply use:

$search_line=array(
            'file_put_contents',
            '<?=',
            '<?php',
            '?>',
            'eval(',
            '$_REQUEST',
            '$_POST',
            '$_GET',
            '$_SESSION',
            '$_SERVER',
            'exec(',
            'shell_exec(',
            'invokefunction',
            'call_user_func_array',
            'display_errors',
            'ini_set',
            'set_time_limit',
            'set_magic_quotes_runtime',
            'DOCUMENT_ROOT',
            'include(',
            'include_once(',
            'require(',
            'require_once(',
            'base64_decode',
            'file_get_contents',
            'sizeof',
            'array('
        );

if(findInStr("this has some <?php echo 'PHP CODE' ?>",$search_line)){
  echo "PHP found";
}
1
  • 1
    You could broaden it with a regex instead: /[a-z_]{1,}\(|\$_[a-z]{3,7}/i. Tiny bit less secure, but it catches the function calls and super globals. For a simple check, this should be enough.
    – Martijn
    Commented Apr 20, 2019 at 23:20

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.