Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mttjohnson/3ed0ec32e4b45e4c154686ec3276474a to your computer and use it in GitHub Desktop.
Save mttjohnson/3ed0ec32e4b45e4c154686ec3276474a to your computer and use it in GitHub Desktop.
Test File or Folder for Dangerous PHP Functions
<?php
/**
* dangerous_functions.php
* Perry Holden <perry.holden@gmail.com>
*
* Usage: php dangerous_functions.php [type: folder|file] [folder_or_filename]
* Example: php dangerous_functions.php folder vendor/businessname/module-name
*/
if (!isset($argv[1])) {
echo "Missing action ('folder' or 'file')\n";
die();
}
if (!isset($argv[2])) {
echo "Missing folder name or file name\n";
die();
}
$dangerousFunctions = new DangerousFunctions($argv[1], $argv[2]);
$dangerousFunctions->execute();
class DangerousFunctions
{
/**
* Complete list of dangerous functions for which we will scan
*
* @var array
*/
protected $functions = [
'apache_child_terminate',
'apache_get_modules',
'apache_note',
'apache_setenv',
'define_syslog_variables',
'disk_free_space',
'disk_total_space',
'diskfreespace',
'dl',
'escapeshellarg',
'escapeshellcmd',
'exec',
'extract',
'get_cfg_var',
'get_current_user',
'getcwd',
'getenv',
'getlastmo',
'getmygid',
'getmyinode',
'getmypid',
'getmyuid',
'ini_restore',
'ini_set',
'passthru',
'pcntl_alarm',
'pcntl_exec',
'pcntl_fork',
'pcntl_get_last_error',
'pcntl_getpriority',
'pcntl_setpriority',
'pcntl_signal',
'pcntl_signal_dispatch',
'pcntl_sigprocmask',
'pcntl_sigtimedwait',
'pcntl_sigwaitinfo',
'pcntl_strerrorp',
'pcntl_wait',
'pcntl_waitpid',
'pcntl_wexitstatus',
'pcntl_wifexited',
'pcntl_wifsignaled',
'pcntl_wifstopped',
'pcntl_wstopsig',
'pcntl_wtermsig',
'php_uname',
'phpinfo',
'popen',
'posix_getlogin',
'posix_getpwuid',
'posix_kill',
'posix_mkfifo',
'posix_setpgid',
'posix_setsid',
'posix_setuid',
'posix_ttyname',
'posix_uname',
'posixc',
'proc_close',
'proc_get_status',
'proc_nice',
'proc_open',
'proc_terminate',
'ps_aux',
'putenv',
'readlink',
'runkit_function_rename',
'shell_exec',
'show_source',
'symlink',
'syslog',
'system',
];
/**
* Folders that this script will ignore and not process
*
* @var array
*/
protected $foldersToIgnore = [
'.',
'..',
'.git',
'.idea'
];
/**
* Action: either 'folder' or 'file'
*
* @var string
*/
protected $action;
/**
* Name of the folder or file
*
* @var string
*/
protected $name;
/**
* @param string $action
* @param string $name
*/
public function __construct($action, $name)
{
$this->action = $action;
$this->name = $name;
}
/**
* Main action of script
*/
public function execute()
{
if ($this->action == 'folder') {
// If folder, loop through files in folder and test individually
if ($allFiles = $this->getAllFiles($this->name)) {
foreach ($allFiles as $fileToCheck) {
if (substr($fileToCheck, -3) === 'php') {
$this->outputFileInfo($fileToCheck);
}
}
} else {
echo "Folder is empty\n";
}
// If file, test directly
} else if ($this->action == 'file') {
$this->outputFileInfo($this->name);
} else {
echo "Invalid action: $this->action\n";
}
}
/**
* Outputs all dangerous methods in the specified file
*
* @param string $filename
*/
protected function outputFileInfo($filename)
{
if ($file = fopen($filename, 'r')) {
$count = 1;
while (($line = fgets($file)) !== false) {
foreach ($this->functions as $function) {
if (preg_match("/$function\(/", $line)) {
echo "$filename($count): $function\n";
}
}
$count++;
}
fclose($file);
} else {
echo "Invalid filename: $file\n";
}
}
/**
* Gets all the files in the folder and returns them as an array (this is a recursive method)
*
* @param string $folder
* @param array $results
* @return array
*/
protected function getAllFiles($folder, &$results = []) {
$files = scandir($folder);
// Ignore directories that are not needed
foreach ($this->foldersToIgnore as $folderToIgnore) {
unset($files[array_search($folderToIgnore, $files, true)]);
}
// Loop through files and add to array. If directory, recursively call again.
foreach($files as $key => $value){
$path = $folder . DIRECTORY_SEPARATOR . $value;
if (!is_dir($path)) {
$results[] = $path;
} else {
$this->getAllFiles($path, $results);
}
}
return $results;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment