http://foreversong.cn/archives/963
虽然是复现文章,不过会更详细地来阐释这个漏洞,,因为现在后台getshell花样层出不穷,因此想要复现一波来学习一波getshell姿势~
因为是最新的dedecms版本,因此我们直接在织梦官网上下载即可~
http://www.dedecms.com/products/dedecms/downloads/
发布日期: 2017-04-05
这里我测试的是utf-8版本,,感觉版本这个无所谓~
下载下来然后安装什么的就不说了,,直接进后台,找到漏洞功能以及对应的功能函数
漏洞在”模块”下的”广告管理”处,这里我们点击“添加一个新广告”
跟原文复现的有一点不一样,,不过不影响,,下面我们来抓包看看参数
我们的参数在normbody里,文件为dede/ad_add.php
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
(
"成功增加一个广告!"
,
"ad_main.php"
)
;
exit
(
)
;
|
在这里我们看到了我们的代码已经插入到了数据库,,一般的思路应该是找哪些php文件调用了这个广告代码,但是点击我们的广告代码就出现了地址
/plus/ad_js.php?aid=3,ad_js.php这个文件是专门调用广告代码的。。
下面我们进入这个文件来看看是怎么调用的
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
_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
<
$
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\n"
;
$
fp
=
fopen
(
$
cacheFile
,
'w'
)
;
fwrite
(
$
fp
,
$
adbody
)
;
fclose
(
$
fp
)
;
}
include
$
cacheFile
;
|
这里首先是三个判断条件,nocache不为空,cachefile不为空,这些判断条件我们都可以通过GET或者POST来提交,从而进行伪造~
进入判断条件后往下走,首先是从数据库中select aid,那么这时候我们到数据库中去看看
这里当时在填写广告信息的时候,设置的timeset为0,因此也就直接令$adbody = $row[‘normbody’];
而这里的normbody也就是我们的evil code,下面我们就应该重点看这个adbody参数
首先进行三个replace,这里的replace好像对我们的参数没有影响,因此直接跳过~
接着将adbody参数插入到document.write()代码中,这里如果做过ctf的人都应该有一种感觉,那就是参数闭合的话,将会造成任意代码执行,这里也就是漏洞的成因所在!
最后打开cachefile,将adbody写入到文件中~
这里由于这个文件是html静态文件,,因此没有可利用点,,还是找下文件吧,,
WWW\uploads\data\cache\myad-3.html
如果是动态文件,,因此我们也可以利用前后闭合来实现任意代码,,扯远了。。
总结来说其实就是$adbody = “\r\n”; 这段代码出的问题
下面我们来构造参数进行poc验证~
首先是访问给的广告链接
这里我还没输入参数,,下面输入参数逐步进行循环~
其实也就是两个判断条件和一个代码的执行~
这里url不用说,,就是给的广告链接,,其中GET了aid参数,,因此我们只要加上nocache参数,来实现isset($nocache),至于!file_exists($cacheFile)这个刚才文件都找到了,,肯定存在的。。
最后就是就是代码执行,,这里一开始有强迫症,我一定要闭合参数!(下面就是闭合问题的一个尝试)
这里一开始很不解,,这出现的是啥?
1
2
3
|
<
!
--
document
.
write
(
"-->"
)
;
--
>
|
这是源码,,我们插入了–>这段,,但是双引号没闭合啊!也就是页面语句实际成了下面这样
1
2
|
<
!
--
document
.
write
(
"-->
"
)
;
--
>
|
因此也就出现了上面的情况,,这里不太理解,,这样不闭合竟然可以。。
但是我有强迫症。。
最后强行闭合。。虽然对结果没影响。。
上述如有不当之处,敬请指出~