Code security audit: When file_exists encounters eval
Last night, someone asked a QQ group how a vulnerability in lcms (a website CMS system) was formed. He is incomplete, so he is asked to pass the code. The code snippet of router. php is as follows:
protected function getInputString($name, $default_value = "", $format = "GPCS") { //order of retrieve default GPCS (get, post, cookie, session); $format_defines = array ( 'G'=>'_GET', 'P'=>'_POST', 'C'=>'_COOKIE', 'S'=>'_SESSION', 'R'=>'_REQUEST', 'F'=>'_FILES', ); preg_match_all("/[G|P|C|S|R|F]/", $format, $matches); //splitting to globals order foreach ($matches[0] as $k=>$glb) { if ( isset ($GLOBALS[$format_defines[$glb]][$name])) { return $GLOBALS[$format_defines[$glb]][$name]; } } return $default_value; }
Here we will first look at getInputString ().
Preg_matach_all: Execute the search in $ format to match/[G | P | C | S | R | F]/. Then, an array $ matches is returned, which means GPCS are returned by default.
Then loop through this array. $ GLOBALS refers to referencing a global variable,
In this way, $ GLOBALS [$ format_defines [$ glb] [$ name]
This code first obtains a value in the $ format_defines array, such as _ GET, and then obtains the name value using the get method. Here, the Code itself does not have a problem. But the best addslashes, addslashes please refer to: http://www.bkjia.com/kf/201302/191294.html
public function Router(){ //Get page request (if any) $page = $this->getInputString("page", "index"); //Get plugin request (if any) $plugin = $this->getInputString("system", "Page"); //If there is a request for a plugin if(file_exists("core/plugs/".$plugin."Starter.php")){ //Include Page fetcher include("core/plugs/".$plugin."Starter.php"); //Fetch the page and get over loading cache etc... eval("new ".$plugin."Starter('".$page."');"); }else if(file_exists("data/modules/".$plugin."/starter.dat")){ //Include Module Fetching System include("core/lib/ModuleLoader.php"); //Load Module new ModuleLoader($plugin, $this->getInputString("page", null)); }else{ //Otherwise load a page from the standard system. //Include Page fetcher include("core/plugs/PageStarter.php"); //Fetch the page and get over loading cache etc... new PageStarter($page); } }
The following code shows that code 2 calls the getInputString function, but this function does not perform any filtering,
It is determined that the core/plugs/". $ plugin." Starter. php file is not stored. If it is stored, the eval is included.
Referencing a comment from a Daniel, "it is harmful for all variables entering the function ".
And the $ page here is controllable, that is, when a request is submitted? Page = '); phpinfo ();//
The statement becomes eval ("new". $ plugin. "starter (''); phpinfo ();//')")
In eval, the double slash represents the meaning of the comment, which means that phpinfo () is executed, so this vulnerability exists.
Important
Next, let's talk about the key points. A guy in the group said that $ plugin can also be phpinfo I 've been studying for a long time, so I have to think about it ......
After a long time, the ox will be released ,(? A = echo 1 ;//.. /1) the tragedy is only found in one step. I am very grateful to the Daniel for his guidance. Now I want to analyze the meaning of this sentence, so I wrote a 1.php code, as shown below:
<?php $act=$_GET['a'];if (file_exists('test/'.$act.'2.php')) {eval("echo ('2');".$act);}?>
Create an empty file named 12. php under the test file, which means that the file_exists meets eval. First, let's analyze the Code. If there is * 2. php under test, execute the following code. What should be submitted normally? A = 1 to execute the following. Output 1
However, what we submit is 1.php? A = echo 1 ;//../
Http: // localhost/1.php? A = echo % 201; // ../1
More than the normal commit, one output is 1, that is, the submitted echo 1 is executed. Write the submitted content into the code, that is, if (file_exists ('test/echo 1; // ../12. php'). Why does it execute the following eval? It may be the file_exists processing method. Process echo 1;/as a directory, and then /.. /is replaced with the upper-level directory, that is, if (file_exists ('test/12. php ') However, We have 12.php under the test directory. Therefore, this judgment is replaced with true, that is, it enters eval.
This code of Eval becomes the code after the annotation, which is called "echo ('2'); echo 1; // ../1,
Therefore, 21 is output.
Summary
Use eval as few as possible and filter controllable variables. The CMS system is patched by writing a function to filter out/in $ plugin and filter $ page. If you do not write the csm example above, you may think that the mentioned file_exists is not very practical in the case of eval.