In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)05/31 Report--
The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.
Install the 0x01 program to reproduce
1. The first step to install the system
two。 The second step is to create the database here, otherwise it will not be created automatically.
3. The third step is to complete the installation, and then we click to enter the background.
4. Step 4: enter the background-"Program upgrade -" upgrade configuration
5. The fifth step is to build the code on the server, create `index.php` and put it in the root directory of the web page.
6. The sixth step, backstage-"program upgrade -" online upgrade, I change here 1999-09-09 09:09:09 represents the upgrade software of my server
7. Step 7, we click upgrade and use D Shield to monitor whether the directory has uploaded Trojan files successfully.
8.
0x02 code audit
The file where the vulnerability lies:\ framework\ admin\ update_control.php (upgraded in the background program)
Vulnerability file code: (only relevant codes are posted)
First of all, we look at line 369, $file = $this- > get ('file','int'); here we see that he receives the file value in the GET variable, so int converts the received value to the int type.
In line 370, if (! $file) determines whether the $file variable has an assignment, and prompts for a JSON data if it is not copied.
Line 373, $urlext = 'file='.rawurlencode ($file);, the rawurlencode function represents the conversion of spaces to% 20.
On line 374, $rs = $this- > service (5mementurlext); here you can see the service method in the call itself file, so let's go into this method and take a look at line 465 of the article.
Line 465, if (! file_exists ($this- > dir_root.'data/update.php')), the file_exists function checks to see if the file or directory exists.
Line 471, include ($this- > dir_root.'data/update.php');, the include function represents the introduction of a file, and if the file is not found, it will only prompt a warning not to terminate the error.
Line 478, if (file_exists ($this- > dir_root.'data/update.xml')), the file_exists function checks to see if the file or directory exists.
Line 486, if (substr ($url,-1)! ='/'), the substr function represents string segmentation and determines that it is not equal to / then enters the 487 line interval.
Line 489, $url. = 'index.php?version='.rawurlencode (trim ($info [' version'])).'& time='.$this- > time.'&type='.$type;,URL address concatenation, and the rawurlencode function converts spaces to the% 20line trim function that removes white space characters from both sides of the string.
Line 493, if ($type = = 1 | | $type = = 4) to determine whether the incoming $type equals 1 or 4.
Line 494, $onlyid = $uconfig ['onlyid']? $uconfig [' onlyid']: $this- > _ onlyid ();, where the ternary operator is used.
Line 495, $domain = $this- > lib ('server')-> domain ($this- > config [' get_domain_method']);, which represents the URL to get the current visit.
Line 496, $client_ip = $this- > lib ('common')-> ip ();, get the client Ip
Line 497, $url. = "& domain=" .rawurlencode ($domain). "& ip=" .rawurlencode ($client_ip);, URL address concatenation, rawurlencode function converts spaces to% 20.
Line 498, $url. = "& onlyid=". $onlyid. "& phpversion=" .PHP _ VERSION;, is also URL address concatenation.
Line 499, if (function_exists ('php_uname')), the function_exists function stands for determining whether there is a function.
Line 502, $soft = $_ SERVER ['SERVER_SOFTWARE']; to get the server PHP version.
Line 506, $mysqlversion = $this- > db- > version ('server');, get the server mysql version number.
Line 511, $this- > lib ('html')-> setting (' timeout',900);, in this case, set the timeout for CURL requests.
Line 513, $this- > lib ('html')-> ip ($uconfig [' ip']);, set the request IP.
Line 515, $info = $this- > lib ('html')-> get_content ($url);, request the URL address and return the XML content.
Here is the return of the XML data, so let's go back to the first picture.
Line 375, $rs = $this- > lib ('json')-> decode ($rs);, which represents converting the received XML content into JSON data.
Line 376, if ($rs ['status']! =' ok'), determine that $rs ['status'] is not equal to ok.
Line 379, if (! $rs ['content']), determines whether it is empty or not.
Line 382, $info = base64_decode ($rs ['content']);, converts the received $rs [' content'] value from base64 to entity.
Line 383, file_put_contents ($this- > dir_root.'data/tmp.zip',$info);, writes to the current file, with the first parameter representing the path and the second parameter representing the content.
Line 384, $this- > lib ('phpzip')-> unzip ($this- > dir_root.'data/tmp.zip','data/update/'); which we see here means to extract the file to a directory.
Line 386, $this- > lib ('file')-> rm ($this- > dir_root.'data/tmp.zip');, delete the written file.
Line 386, $verinfo = substr ($file,0,1). "." .substr ($file,1,1). ".substr ($file,2);, here is string cutting.
Line 387, $info = $this- > update_load ($verinfo);, where the custom method is called, also on line 152 of this article.
Line 154, $list = array ();, defines an empty array.
Line 155, $this- > lib ('file')-> deep_ls ($this- > dir_root.'data/update/',$list); which probably means traversing all the filenames of the current file, so I'm not looking for the code here, I'll just copy it out.
Then the code path is on lines 297-313 in framework\ libs\ file.php
/ * get a list of multi-tier files such as folders and subfolders (unlimited level, length is limited by the system) * @ parameter $folder folder * @ parameter $list reference variable * / public function deep_ls ($folder,&$list) {$this- > read_count++; $tmplist = $this- > _ dir_list ($folder) Foreach ($tmplist AS $key= > $value) {if (is_dir ($value)) {$this- > deep_ls ($value,$list);} else {$list [] = $value;}
Line 156, if (! $list | | count ($list)
< 1),判断$list是否为空,并且判断他的数据是不是小于1。 第159行,$strlen = strlen($this->Dir_root. "data/update/");, strlen represents the statistical string length.
Line 162, foreach ($list as $key= > $value), foreach loops through the array.
Line 163, $value = trim ($value);, and trim represents the removal of characters from both sides of the string.
Line 165, continue;, here stands for jumping out of the loop.
Line 167, $tmp = substr ($value,$strlen);, substr represents string cutting.
Line 168, if ($tmp = = 'version.txt'), where it is determined whether $tmp equals version.txt.
Line 169, $verinfo = trim (file_get_contents ($value));, trim represents removal of characters on both sides of the string, and file_get_contents represents writing to the file.
Line 183, if (substr ($tmp,0,10) = = 'framework/'), substr represents string cutting, which is judged to be equal to framework/ from 0 to 10.
Line 185, if (is_file ($value)), is_file represents to determine whether the file exists.
Line 187, $this- > lib ('file')-> mv ($value,$this- > dir_phpok.$tmp1);, cut the file to a directory.
Line 189, if (is_dir ($value) & &! is_dir ($this- > dir_phpok.$tmp1)), is_dir stands for determining whether the directory exists and whether the temporary file does not exist.
Line 190, $this- > lib ('file')-> make ($this- > dir_phpok.$tmp1,'folder');, create a directory.
Line 194, if (is_file ($value) & & $tmp! = 'table.sql'), is_file stands for determining whether the file exists and that $tmp is not equal to the entry range of the table.sql file.
Line 194-line 210 are all the same, cut and create directories.
Line 205, $dlist = file ($delfile);, file represents the entire file read into an array.
Line 209, foreach ($dlist AS $key= > $value), foreach represents the array loop.
Line 213, $value = trim ($value);, and trim represents the removal of characters on both sides of the string.
Line 214, if ($value & & is_file ($this- > dir_root.$value)), determines whether $value has a value, and determines whether the file exists.
Line 215, $this- > lib ('file')-> rm ($this- > dir_root.$value); represents the deletion of the file.
Line 218, if ($value & & is_dir ($this- > dir_root.$value)), determines whether $value has a value, and determines whether the directory exists.
Line 225, $this- > update_table (); here you see calling your own method again.
Why there is so much code to analyze.
Let's move on to the next analysis. Here, I'll Copy the code. Too many screenshots don't look good.
Here I pick the important functions to explain, here are sql execution statements, there is nothing to analyze.
Function:
File_exists, which means to check whether a file or directory exists.
File_get_contents, which stands for reading the file, and writing if it takes two parameters.
Str_replace, which represents string substitution.
Strlen, which represents the length of the view string.
Substr, which stands for string cutting.
Unset, which represents the deletion of variables.
Explode, which means cutting a string into an array.
Trim, which represents the removal of characters on both sides of a string.
Private function update_table () {if (! file_exists ($this- > dir_root.'data/update/table.sql')) {return false;} / / create a new table temporary $prefix = 'tmp_'.$this- > db- > prefix; $sqlcontent = file_get_contents ($this- > dir_root.'data/update/table.sql') $sqlcontent = str_replace ('qinggan_',$prefix,$sqlcontent); $this- > sql_run ($sqlcontent); / / compare the new table results $list = $this- > db- > list_tables (); $tblist = array (); $nlength = strlen ($prefix); $olength = strlen ($this- > db- > prefix) Foreach ($list as $key= > $value) {/ / skip the extension table $continue_1 = substr ($value,0,strlen ($prefix.'list_')); $continue_2 = substr ($value,0,strlen ($this- > db- > prefix.'list_')) If ($continue_1== $prefix.'list_' | | $continue_2 = = $this- > db- > prefix. "list_") {continue;} if (substr ($value,0,$nlength) = = $prefix) {$tblid = substr ($value,$nlength) $tblist [$tblid] ['new'] = $value;} if (substr ($value,0,$olength) = = $this- > db- > prefix) {$tblid = substr ($value,strlen ($this- > db- > prefix)); $tblist [$tblid] [' old'] = $value }} foreach ($tblist as $key= > $value) {if (! $value ['new']) {continue;} if (! $value [' old']) {$sql = "SHOW CREATE TABLE". $value ['new'] $rs = $this- > db- > get_one ($sql); if (! $rs ['Create Table']) {continue;} $rs [' Create Table'] = str_replace ($prefix,$this- > db- > prefix,$rs ['Create Table']) $this- > db- > query ($rs ['Create Table']); continue;} / compare the new table $nlist = $this- > db- > list_fields_more ($value [' new']); $olist = $this- > db- > list_fields_more ($value ['old']) Foreach ($nlist as $k = > $v) {if ($olist [$k] & & $olist [$k] ['type'] = = $v [' type']) {continue } if (! $olist [$k]) {$sql = "ALTER TABLE". $value ['old']. " ADD `". $k."`. $v ['type']. "";} else {$sql = "ALTER TABLE `". $value [' old']. "`CHANGE`". $k. "``". $k. "`". $v ['type']. " } if ($v ['null'] = =' NO') {$sql. = "NOT NULL" If ($v ['default']! =') {$sql. = "DEFAULT". $v ['default']. "" }} else {$sql. = "DEFAULT". ($v ['default']! ='? $v ['default']:' NULL'). "" } if ($value ['extra']) {$sql. = ". $v [' extra']." } if ($v ['comment']) {$sql. = "COMMENT'". $v ['comment']. "'";} $this- > db- > query ($sql) } unset ($nlist,$olist);} / delete temporary table operation foreach ($list as $key= > $value) {if (substr ($value,0,$nlength) = = $prefix) {$sql = "DROP TABLE". $value $this- > db- > query ($sql);}} unset ($list,$tbllist); return true;} private function sql_run ($sql='') {$sql= str_replace ("\ r", "\ n", $sql); $ret = array (); $num = 0 Foreach (explode (";\ n", trim ($sql)) as $query) {$queries = explode ("\ n", trim ($query)); foreach ($queries as $query) {$ret [$num]. = $query [0] = ='#'| $query [0]. $query [1] = ='- -'?': $query } $num++;} foreach ($ret as $query) {$query = trim ($query); if ($query) {$this- > db- > query ($query);}} return true;}
All right, let's go back to the previous picture.
Line 231, $info = trim (file_get_contents ($value));, trim represents removal of characters on both sides of the string, and file_get_contents represents writing to the file.
Line 233, $info = str_replace ('qinggan_',$this- > db- > prefix,$info);, and str_replace represents string substitution.
Line 240, if (file_exists ($this- > dir_root. "data/update/run.php"), file_exists stands for checking whether the file or directory exists.
Line 241, include ($this- > dir_root.'data/update/run.php');, include introduces a file.
Line 243, $this- > lib ('file')-> rm ($this- > dir_root.'data/update/');, which represents deleting the file.
Line 244, $list = $this- > lib ('file')-> ls ($this- > dir_root.'data/update/');, which means to remove the directory structure.
Line 245, if ($list & & count ($list) > 0), determine whether the $list value exists, and determine whether its number is less than 0.
Line 247, $this- > lib ('file')-> rm ($value,'folder');, which represents a loop to delete a file.
Line 251, $this- > success_version ($verinfo); here we enter a custom method interval.
As usual, Copy code, I will Copy out if there is not much code.
/ / after the update is successful, the modification record private function success_version ($version='') {if (! $version) {return false;} / / is written to the latest version $html ='. "\ n"; $html.='. "\ n" $html.= "\ t".''.trim ($version). "\ n"; $html.= "\ t".' '.date ("Y-m-d H:i:s", $this- > time).'. "\ n"; $html.=''; file_put_contents ($this- > dir_root.'data/update.xml',$html) If (is_writeable ($this- > dir_root.'version.php') & & file_exists ($this- > dir_data.'version.tpl')) {$info = file_get_contents ($this- > dir_data.'version.tpl'); $info = str_replace ('{version}', trim ($version), $info) $info = str_replace ('{updatetime}', date ("m / d / Y / H / I / s / s, $this- > time), $info); file_put_contents ($this- > dir_root.'version.php',$info);} $this- > lib ('file')-> rm ($this- > dir_root.'data/tpl_admin/') $this- > lib ('file')-> rm ($this- > dir_root.'data/tpl_www/'); $this- > lib (' file')-> rm ($this- > dir_cache); return true;}
So let's make a brief introduction to the important functions.
Trim, which represents the removal of characters on both sides of a string.
Is_writeable to determine whether the file is writable.
File_exists, which means to check whether a file or directory exists.
Str_replace, string substitution.
File_put_contents, write or read the file.
This is the end of the introduction, and the whole audit analysis logic is on it.
0x03 vulnerability repair
Path:\ framework\ admin\ update_control.php
Line 152, add this code to the foreach loop in the method to filter.
$verinfo = str_replace (['eval','assert','system','phpinfo'], [' eval','assert','system','phpinfo'], strtolower (trim (file_get_contents ($value);, here I only write the more harmful keywords.
Thank you for reading! This is the end of the article on "how to use GetShell to upgrade the system". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.