note 93502 deleted from function.eval by danbrown
| From: | danbrown@php.net | Date: | Mon, 14 Sep 2009 02:01:14 +0000 |
| Subject: | note 93502 deleted from function.eval by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-160528@lists.php.net to get a copy of this message | ||
Note Submitter: Crypton - blackcrypton at gmail dot com
----
I like the way (udo dot schroeter at gmail dot com's) script works so I have adapted it to
include blacklisting of vars. Of course, you will want to adjust it to your environment. I use it so
I can allow echo, print_r etc.. for example, but prevent access to vars that might be included on
the page of execution and used in the site (such as common things like $db, $sql, etc..).
<?php
class SaferScript {
var $source, $allowedCalls;
function SaferScript($scriptText) {
$this->source = $scriptText;
$this->allowedCalls = array();
$this->blacklistVars = array();
}
function allowHarmlessCalls() {
// Whitelist overrides case switch below.
$this->allowedCalls = explode(',', '
explode,implode,date,time,round,trunc,rand,ceil,
floor,srand,strtolower,strtoupper,substr,stristr,
strpos,print,print_r,echo'
);
$this->blacklistVars = explode(',',
'db,sql,username,password,GLOBALS,_SERVER,_GET,_POST,
_FILES_REQUEST,_SESSION,_ENV,_COOKIE,php_errormsg,
HTTP_RAW_POST_DATA,http_response_header'
);
}
function parse() {
$this->parseErrors = array();
$tokens = token_get_all('<?'.'php '.$this->source.'
?'.'>');
$vcall = '';
foreach ($tokens as $token) {
if (is_array($token)) {
$id = $token[0];
switch ($id) {
case(T_VARIABLE): {
$vcall .= 'v';
break;
}
case(T_STRING): {
$vcall .= 's';
}
case(T_NEW): case(T_RETURN): case(T_BREAK): case(T_EXIT):
case(T_TRY): case(T_CATCH): case(T_CLONE): case(T_PRINT):
case(T_ECHO): case(T_GLOBAL): case(T_INCLUDE): case(T_INCLUDE_ONCE):
case(T_REQUIRE): case(T_REQUIRE_ONCE): case(T_FOR): case(T_WHILE):
case(T_EVAL): case(T_FUNCTION):
{
if (array_search($token[1], $this->allowedCalls) === false) {
$this->parseErrors[] = 'illegal call: '. $token[1];
}
}
}
} else {
$vcall .= $token;
}
if (stristr($vcall, 'v(') != '') {
$this->parseErrors[] = array('Illegal Dynamic Function Call');
}
foreach($this->blacklistVars as $blacklisted) {
if (strpos($this->source, $blacklisted) !== false) {
$this->parseErrors[] = 'Blacklisted Var: '. $blacklisted;
}
}
if (sizeof($this->parseErrors) > 0) {
return($this->parseErrors);
}
}
}
function execute($parameters = array()) {
foreach ($parameters as $k => $v) {
$k = $v;
}
if (sizeof($this->parseErrors) == 0) {
eval($this->source);
}
}
}
?>
Examples:
$testvars = array(
'$GLOBALS',
'$_SERVER'
);
for ($i = 0; $i < count($testvars); $i++) {
$mycode = 'print_r(' . $testvars[$i] . ');';
$test = new SaferScript($mycode);
$test->allowHarmlessCalls();
print_r($test->parse());
$test->execute();
}
Outputs:
Array ( [0] => Blacklisted Var: GLOBALS ) Array ( [0] => Blacklisted Var: _SERVER )
include('"class.safeeval.php");
$mycode = '$hello = "Hello World!"; echo $hello;';
$test = new SaferScript($mycode);
$test->allowHarmlessCalls();
print_r($test->parse());
$test->execute();
Outputs:
Hello World!