mctrivia Posted January 30, 2011 Share Posted January 30, 2011 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.) Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/ Share on other sites More sharing options...
kickstart Posted January 30, 2011 Share Posted January 30, 2011 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 Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1167159 Share on other sites More sharing options...
jcbones Posted January 30, 2011 Share Posted January 30, 2011 Without seeing all of your code it is hard to determine. But, it might pass something like: file_put_contents('.htaccess','deny from all'); Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1167161 Share on other sites More sharing options...
.josh Posted January 30, 2011 Share Posted January 30, 2011 Only way to do it is as you have already suspected, make either a whitelist or a blacklist. Whitelist is easier to make and maintain, safer. Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1167163 Share on other sites More sharing options...
phil88 Posted January 30, 2011 Share Posted January 30, 2011 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. Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1167167 Share on other sites More sharing options...
mctrivia Posted January 30, 2011 Author Share Posted January 30, 2011 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? Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1167196 Share on other sites More sharing options...
ignace Posted January 30, 2011 Share Posted January 30, 2011 PHP has a directive to disable certain functions Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1167271 Share on other sites More sharing options...
kickstart Posted January 30, 2011 Share Posted January 30, 2011 Any symbol as long as it is within single quotes Be careful with that, as it would seem that someone could just put the nasty code in a single quote delimited string and then eval that. So make very sure you block eval as well. All the best Keith Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1167289 Share on other sites More sharing options...
mctrivia Posted January 30, 2011 Author Share Posted January 30, 2011 Definitely eval will not be on the list of allowed commands. Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1167321 Share on other sites More sharing options...
mctrivia Posted February 25, 2011 Author Share Posted February 25, 2011 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>'; ?> Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1179361 Share on other sites More sharing options...
mctrivia Posted February 27, 2011 Author Share Posted February 27, 2011 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>'; ?> Quote Link to comment https://forums.phpfreaks.com/topic/226095-how-can-this-code-be-hacked/#findComment-1180318 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.