Jump to content

How can this code be hacked?


mctrivia

Recommended Posts

I know the following line of code is dangerous since the user has control of $query but I do not know any other way to realistically do it.

 

  if (eval('return (' . $query . ');')) {

 

The perpose is to allow the user to type in any valid php statement and see if it evaluates true or false.

 

I.E. 

1==1  is true

substr('cat',1,2)=='at' is true

12<6 is false

 

the problem is I am sure there are ways a hacker could use this code to upload code to my site and take over.  I have 2 options.  1 filter out any possible way a hacker could hack it or 2 only allow the user to enter functions that can't be used to hack it.  I will probably go the later route but either way I need to know what to look for.

 

Please let me know if you can think of any values for $query that would let you hack my site

 

(p.s. this code is not up yet and will not go up until any possible security flaws are fixed.)

Link to comment
Share on other sites

Hi

 

Pretty much anything could be used.

 

Suspect something like this could be used which would be pretty nasty.

 

True==Hack();
function Hack()
{
$dir = "./"; 
if (is_dir($dir)) 
{
if ($dh = opendir($dir)) 
{
while (($file = readdir($dh)) !== false) 
{ 
unlink($file);
}
}
}
return true
}

 

All the best

 

Keith

Link to comment
Share on other sites

Or, depending on resources/budget available - you could run the code in a virtual machine that reverts back to its default state every x runs.

 

 

Given the sheer number of ways you could exploit your code above, a blacklist would be very difficult to create/maintain. A whitelist would be more practical.

Link to comment
Share on other sites

Thanks for the input.  I am going to go with a white list

 

String Comparisons: http://www.w3schools.com/PHP/php_ref_string.asp

Math Functions: http://www.w3schools.com/php/php_ref_math.asp

Math Operators: -,+,/,*,%,&,|

Comparators: <,>,=,!

Symbols: $,0..9,(,),comma

Any symbol as long as it is within single quotes

 

 

would remove echo, and print functions from string list but otherwise this list should give a lot of versatility and I do not believe there is anything on there that is unsafe.  Anyone see anything I have included that would be bad?

Link to comment
Share on other sites

  • 4 weeks later...

The following is my test preprocessing script so far.  Any code before it can be run through the dangerous

 

 if (eval('return (' . $rule . ');')) {

 

will pass.  at the bottom $rules is an array of rules to test.  It will print out the rule and if they pass or fail the test.  Can anyone find a way to get a bad rule to pass this test or use this script itself to hack my server.  If you have an idea how to improve is greatly appreciated also.

 

<?php

      $whitefunc=array(
'abs()','acos()','acosh()','asin()','asinh()','atan()','atan2()','atanh()',
'base_convert()','bindec()',
'ceil()','cos()','cosh()',
'decbin()','dechex()','decoct()','deg2rad()',
'exp()','expm1()',
'floor()','fmod()',
'getrandmax()',
'hexdec()','hypot()',
'is_finite()','is_infinite()','is_nan()',
'lcg_value()','log()','log10()','log1p()',
'max()','min()','mt_getrandmax()','mt_rand()','mt_srand()',
'octdec()',
'pi()','pow()',
'rad2deg()','rand()','round()',
'sin()','sinh()','sqrt()','srand()',
'tan()','tanh()'
      );





function breakBracket($code,$a="(",$b=")") {
  $parts=array();
  $end=strpos($code,$b);
  while (!($end===false)) {

    //find first start bracket before point
    $start=strrpos(substr($code,0,$end),$a);

    //find first end bracket after point
    $end=strpos($code,$b,$start);

    //break inner brackets out
    $parts[]=substr($code,$start+1,$end-$start-1);
    $code=substr($code,0,$start) . '|~-~|' . substr($code,$end+1);

    //find next search point
    $end=strrpos($code,$b);
  }
  $parts[]=$code;

  //replace '|~-~|' with brackets
  foreach ($parts as &$part) {
    $part=preg_replace("/\|~-~\|/", "()", $part);
  }

  return $parts;
}

function check_syntax($code) {
    return @eval('return true;' . $code);
}

function testRule($rule) {    
  //replace $1,$2,$3... in rules with tag code parts
  $rule=preg_replace_callback(
'/\$[0-9]+/',
create_function(
	// single quotes are essential here,
	// or alternative escape all $ as \$
	'$matches',
	'return "53";'
),
$rule
  );

  //check for ilegal characters ;'"
  $good=(!(preg_match("/([;'\"])/",$rule)>0));

  //check for assingments
  if ($good) {
    $temp=preg_replace('/([=!]==)/','',$rule);
    $temp=preg_replace('/([=<>!]=)/','',$temp);
    $good=(!(preg_match("/(=)/",temp)>0));
  }

  //see if rule is valid
  if ($good) {
    $good=check_syntax('(' . $rule . ');');
  }

  //check if rule only contains good functions, numbers, brackets, and math operators
  if ($good) {

    //break inside of () out of outsides
    $ruleparts=breakBracket($rule);

    //combine all parts together into 1 string
    $str='';
    foreach ($ruleparts as $part) {
      $str.=$part . ' ';
    }

    //remove all valid functions
    global $whitefunc; 				//array of lower case functions user may use with () after name
    $str=str_replace($whitefunc,' ',$str); 

    //remove all valid characters
    $str=preg_replace('|([0-9\(\)\+\-\*\/\%])|',' ',$str);

    //if anything left call error
    if (preg_match_all("/([^ ])/",$str,$out)) {
      $good=false;
    }
  }

  return $good;
}







$rules=array(
'acos(56)+(ceil(56)-3+5)',
'sin(45)-35',
'a+$1*4',
);
echo '<table border="1">';
foreach($rules as $rule) {
  echo '<tr><td>' . $rule . '</td><td>';
  if (testRule($rule)) {
    echo ' </td><td>Pass';
  } else {
    echo ' </td><td>Fail';
  }
  echo '</td></tr>';
}
echo '</table>';
?>

Link to comment
Share on other sites

I found a bug in the code where 1==1 would fail the test but shouldn't.  Fixed now.  Please let e know if you have tried to hack but failed.  I think I have made this bulit proof but there are alot smarter people on here then me.

 

<?php

      $whitefunc=array(
'abs()','acos()','acosh()','asin()','asinh()','atan()','atan2()','atanh()',
'base_convert()','bindec()',
'ceil()','cos()','cosh()',
'decbin()','dechex()','decoct()','deg2rad()',
'exp()','expm1()',
'floor()','fmod()',
'getrandmax()',
'hexdec()','hypot()',
'is_finite()','is_infinite()','is_nan()',
'lcg_value()','log()','log10()','log1p()',
'max()','min()','mt_getrandmax()','mt_rand()','mt_srand()',
'octdec()',
'pi()','pow()',
'rad2deg()','rand()','round()',
'sin()','sinh()','sqrt()','srand()',
'tan()','tanh()'
      );





function breakBracket($code,$a="(",$b=")") {
  $parts=array();
  $end=strpos($code,$b);
  while (!($end===false)) {

    //find first start bracket before point
    $start=strrpos(substr($code,0,$end),$a);

    //find first end bracket after point
    $end=strpos($code,$b,$start);

    //break inner brackets out
    $parts[]=substr($code,$start+1,$end-$start-1);
    $code=substr($code,0,$start) . '|~-~|' . substr($code,$end+1);

    //find next search point
    $end=strrpos($code,$b);
  }
  $parts[]=$code;

  //replace '|~-~|' with brackets
  foreach ($parts as &$part) {
    $part=preg_replace("/\|~-~\|/", "()", $part);
  }

  return $parts;
}

function check_syntax($code) {
    return @eval('return true;' . $code);
}

function testRule($rule) {    
  //replace $1,$2,$3... in rules with tag code parts
  $rule=preg_replace_callback(
'/\$[0-9]+/',
create_function(
	// single quotes are essential here,
	// or alternative escape all $ as \$
	'$matches',
	'return "53";'
),
$rule
  );

  //check for ilegal characters ;'"
  $good=(!(preg_match("/([;'\"])/",$rule)>0));

  //check for assingments
  if ($good) {
    $temp=preg_replace('/([=!]==)/','',$rule);
    $temp=preg_replace('/([=<>!]=)/','',$temp);
    $good=(!(preg_match("/(=)/",temp)>0));
  }

  //see if rule is valid
  if ($good) {
    $good=check_syntax('(' . $rule . ');');
  }

  //check if rule only contains good functions, numbers, brackets, and math operators
  if ($good) {

    //break inside of () out of outsides
    $ruleparts=breakBracket($rule);

    //combine all parts together into 1 string
    $str='';
    foreach ($ruleparts as $part) {
      $str.=$part . ' ';
    }

    //remove all valid functions
    global $whitefunc; 				//array of lower case functions user may use with () after name
    $str=str_replace($whitefunc,' ',$str); 

    //remove all valid characters
    $str=preg_replace('|([0-9\(\)\+\-\*\/\%=])|',' ',$str);

    //if anything left call error
    if (preg_match_all("/([^ ])/",$str,$out)) {
      $good=false;
    }
  }

  return $good;
}







$rules=array(
'acos(56)+(ceil(56)-3+5)',
'sin(45)-35',
'a+$1*4',
'1==1',
'hacked=true',
);
echo '<table border="1">';
foreach($rules as $rule) {
  echo '<tr><td>' . $rule . '</td><td>';
  if (testRule($rule)) {
    echo ' </td><td>Pass';
  } else {
    echo ' </td><td>Fail';
  }
  echo '</td></tr>';
}
echo '</table>';
?>

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.