http://foreversong.cn/archives/963
Although it is a recurring article, but will be more detailed to explain the loophole, because now backstage getshell pattern endless, so want to reproduce a wave to learn a wave of Getshell posture ~
Because it is the newest version of Dedecms, we can download it directly from the Dream website.
http://www.dedecms.com/products/dedecms/downloads/ dedecms V5.7 SP2 Official edition
Release Date: 2017-04-05
Here I test is utf-8 version,, feel the version of this doesn't matter ~
Download down and then install what do not say, directly into the background, to find the vulnerability function and corresponding function function
Vulnerability in the "Ads Management" section under "Modules", here we click "Add a new ad"
It's a little different from the original, but it doesn't affect, let's grab the packet and see the parameters.
Our parameters are in Normbody, the file is dede/ad_add.php $query = "INSERT into #@__myad (Clsid,typeid,tagname,adname,timeset,starttime, Endtime,normbody,expbody) VALUES (' $clsid ', ' $typeid ', ' $tagname ', ' $adname ', ' $timeset ', ' $starttime ', ' $endtime ', ' $ Normbody ', ' $expbody '); "; $dsql->executenonequery ($query); ShowMsg ("successfully added an ad. "," ad_main.php "); Exit ();
| 1 2 3 4 5 6 7 |
$ query = "INSERT into #@__myad (clsid,typeid,tagname,adname,timeset,starttime,endtime,normbody,expbody) VALUES ( ' $clsid ', ' $typeid ', ' $tagname ', ' $adname ', ' $timeset ', ' $starttime ', ' $endtime ', ' $normbody ', ' $expbody '); " ; $ dsql-executenonequery ($ query); ShowMsg ("successfully added an ad. "," ad_main.php "); Exit (); |
Here we see that our code has been inserted into the database, the general idea is to find which PHP files to call this ad code, but click on our ad code to appear the address
/plus/ad_js.php?aid=3,ad_js.php This file is specifically called AD code:
Let's go into this file to see how it's called $cacheFile = Dededata. ' /cache/myad-'. $aid. HTM '; if (Isset ($nocache) | |!file_exists ($cacheFile) | | time ()-Filemtime ($cacheFile) > $cfg _puccache_time) {$row = $dsql ->getone ("Select * from ' #@__myad ' WHERE aid= ' $aid '"); $adbody = "; if ($row [' Timeset ']==0) {$adbody = $row [' Normbody '];} else {$ntime = time (); if ($ntime > $row [' endtime '] | | $ntime &L T $row [' StartTime ']) {$adbody = $row [' Expbody '];} else {$adbody = $row [' Normbody '];}} $adbody = Str_replace (' ' ', ' \ ' ', $adbody); $adbody = Str_replace ("\ R", "\\r", $adbody); $adbody = Str_replace ("\ n", "\\n", $adbody); $adbody = "<!--\r\ndocument.write (\" {$adbody}\ "); \r\n-->\r\n"; $fp = fopen ($cacheFile, ' w '); Fwrite ($fp, $adbody); Fclose ($FP); } include $cacheFile;
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
$ cachefile = Dededata. '/cache/myad-'. $ aid. '. htm '; if (Isset ($ nocache) | |! file_exists ($ cachefile) | | time ()-Filemtime ($ cachefile) > $ cfg_puccache _tim E) { $ row = $ dsql-GetOne ("SELECT * from ' #@__myad ' WHERE aid= ' $aid '"); $ adbody = '; if ($ row [' timeset '] = = 0) {&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&N bsp; $ adbody = $ row [' normbody ']; } Else { $ ntime = time (); if ($ ntime > $ row [' Endtime '] | | $ ntime < $ row [' StartTime ' ]) { $ adbody = $ row [' Expbody ']; &nb sp; } else { $ adbody = $ row [' normbody ']; } } $ adbody = str_ Replace (' "', ' \ ' ', $ adbody); $ adbody = Str_replace ("\ R", "\\r", $ adbody); $ adbody = str_replace ("\ n", "\\n", $ adbody); $ adbody = "<!--\r\ndocument.write (\" {$adbody}\ "); \r\n-->\r\n"; $ fp = fopen ($ cachefile, ' W '); fwrite ($ fp, $ adbody); fclose ($ fp); } include $ cachefile; |
Here is the first three conditions, NoCache is not empty, cachefile is not empty, these conditions of judgment we can be submitted by get or post, so as to forge ~
Enter the judging condition and go down, first of all from the database select aid, then we go to the database to see
Here at that time when filling in the advertisement information, the setting Timeset is 0, therefore also directly makes $adbody = $row [' Normbody '];
And here's normbody is our evil code, below we should focus on this adbody parameter
Start with three replace, where replace seems to have no effect on our parameters, so skip directly ~
Then insert the Adbody parameter into the document.write () code, here if the person who has been a CTF should have a feeling that the argument is closed, will cause arbitrary code execution, here is the cause of the vulnerability.
Finally open the Cachefile and write the adbody to the file ~
Here because this file is an HTML static file, so there is no point to use, or to find the file it,
Www\uploads\data\cache\myad-3.html
If it is a dynamic file, so we can also use the front and back closure to implement arbitrary code, and pulled away.
Summing up is actually $adbody = "<!–\r\ndocument.write (\" {$adbody}\ "); \r\n–>\r\n"; The problem with this piece of code
Let's construct parameters for POC verification ~
The first is the access to the ad link
Here I have not input parameters, the following input parameters are gradually looping ~
In fact, it is two judgment conditions and a code execution ~
Here the URL needless to say, is to give the ad link, where get the aid parameters, so we just add the NoCache parameter, to implement Isset ($nocache), As for!file_exists ($cacheFile) This file has been found,, There must be.
The end is code execution, where there is obsessive compulsive disorder, I must close the parameters. (Here is an attempt to close the problem)
It was very confusing at first, and that was what happened. <!--document.write ("--"); -
| 1 2 3 |
<! --document. Write ("--"); --> |
This is the source, we inserted the –> this paragraph, but the double quotation marks are not closed ah. That is, the page statement actually became the following <!--document.write ("--"); -
| 1 2 |
<! --document. Write ( |