### 简要描述: sql injection ### 详细说明: sitestar没有做全局的数据转义,很容易出现遗漏的地方。 测试版本sitestar_v2.7_build140505 出现问题的地方在module/mod_order.php 176行开始。 鸡肋的地方在于这是一个普通用户使用的积分兑换功能。需要用户最少有100积分才可以之星下面的逻辑。 ``` public function userjifen_save(){ $integral = ParamHolder::get('exchange'); if (trim(SessionHolder::get('SS_LOCALE')) != '') {// 多语言切换用 $curr_locale = trim(SessionHolder::get('_LOCALE')); } else { $curr_locale = DEFAULT_LOCALE; } $lang_sw = trim(ParamHolder::get('lang_sw', $curr_locale)); SessionHolder::set('mod_site/_LOCALE', $lang_sw); //读取积分总额: $curr_user_id = SessionHolder::get('user/id'); $o_user_ext = new UserExtend(); $curr_user_ext =& $o_user_ext->find("user_id=?", array($curr_user_id)); if (!$curr_user_ext) { $this->assign('json', Toolkit::jsonERR(__('Invalid ID!'))); return '_error'; } if ($curr_user_ext->total_point < 100 ){ echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'; echo '<script type="text/javascript"> alert("'.__('Sorry, membership points can be...
### 简要描述: sql injection ### 详细说明: sitestar没有做全局的数据转义,很容易出现遗漏的地方。 测试版本sitestar_v2.7_build140505 出现问题的地方在module/mod_order.php 176行开始。 鸡肋的地方在于这是一个普通用户使用的积分兑换功能。需要用户最少有100积分才可以之星下面的逻辑。 ``` public function userjifen_save(){ $integral = ParamHolder::get('exchange'); if (trim(SessionHolder::get('SS_LOCALE')) != '') {// 多语言切换用 $curr_locale = trim(SessionHolder::get('_LOCALE')); } else { $curr_locale = DEFAULT_LOCALE; } $lang_sw = trim(ParamHolder::get('lang_sw', $curr_locale)); SessionHolder::set('mod_site/_LOCALE', $lang_sw); //读取积分总额: $curr_user_id = SessionHolder::get('user/id'); $o_user_ext = new UserExtend(); $curr_user_ext =& $o_user_ext->find("user_id=?", array($curr_user_id)); if (!$curr_user_ext) { $this->assign('json', Toolkit::jsonERR(__('Invalid ID!'))); return '_error'; } if ($curr_user_ext->total_point < 100 ){ echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'; echo '<script type="text/javascript"> alert("'.__('Sorry, membership points can be converted more than 100 Member Points').'"); location.href="'.Html::uriquery('mod_order', 'userjifen').'";</script>'; exit; } switch ($integral){ case 100: $cash = 10; echo $integral; break; case 200: $cash = 20; break; case 500: $cash = 50; break; case 1000: $cash = 100; break; default: $cash = 0; break; } echo $cash; if ($cash==0) { $this->assign('json', Toolkit::jsonERR(__('Please select the options you want to exchange'))); echo 'test'; return '_error'; echo 'test'; exit; } //加入会员的账户余额: //读取账户的总额,加上兑换的余额,并更新总额: $curr_user_ext -> total_saving = $curr_user_ext -> total_saving + $cash; $curr_user_ext -> balance = $curr_user_ext -> balance +$cash; $curr_user_ext -> save(); //生成一个交易记录: $o_transaction = new Transaction(); $o_transaction->action_time = time(); $o_transaction->user_id = $curr_user_id; $o_transaction->type = '1'; $o_transaction->amount = $cash; $o_transaction->memo = __('Redeem account balance'); $o_transaction->save(); //记录进积分记录表: $userPoint = array(); $userPoint['userid'] = $curr_user_id; $userPoint['type'] = 'out'; $userPoint['point'] = $integral; $userPoint['momo'] = __('Redeem account balance'); $userPoint['create_time'] = time(); $db =& MySqlConnection::get(); $sql = "insert into ss_users_points(id,userid,orderid,type,point,momo,create_time) values (null,'{$userPoint['userid']}','0','{$userPoint['type']}','{$userPoint['point']}','{$userPoint['momo']}','{$userPoint['create_time']}')"; $db->query($sql); //清零会员的积分 $curr_user_ext->total_point = $curr_user_ext->total_point-$integral; $curr_user_ext -> save(); ``` 问题参数$integral。这里这样一段逻辑: ``` switch ($integral){ case 100: $cash = 10; echo $integral; break; case 200: $cash = 20; break; case 500: $cash = 50; break; case 1000: $cash = 100; break; default: $cash = 0; break; } ``` 看起来像是用白名单的方式限制了$ingegral。其实不然。$integral并没有限制数据类型。这里的一个小trick就是。 当$integral为字符串100asdg时,case 100。结果是true。 可以参考: ``` 如果比较一个整数和字符串,则字符串会被转换为整数。如果比较两个数字字符串,则作为整数比较。此规则也适用于 switch 语句。 <?php var_dump(0 == "a"); // 0 == 0 -> true var_dump("1" == "01"); // 1 == 1 -> true switch ("a") { case 0: echo "0"; break; case "a": // never reached because "a" is already matched with 0 echo "a"; break; } ?> 字符串转换为数值 当一个字符串被当作数字来求值时,根据以下规则来决定结果的类型和值。 如果包括“.”,“e”或“E”其中任何一个字符的话,字符串被当作 float 来求值。否则就被当作整数。 该值由字符串最前面的部分决定。如果字符串以合法的数字数据开始,就用该数字作为其值,否则其值为 0(零)。合法数字数据由可选的正负号开始,后面跟着一个或多个数字(可选地包括十进制分数),后面跟着可选的指数。指数是一个“e”或者“E”后面跟着一个或多个数字。 <?php $foo = 1 + "10.5"; // $foo is float (11.5) $foo = 1 + "-1.3e3"; // $foo is float (-1299) $foo = 1 + "bob-1.3e3"; // $foo is integer (1) $foo = 1 + "bob3"; // $foo is integer (1) $foo = 1 + "10 Small Pigs"; // $foo is integer (11) $foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2) $foo = "10.0 pigs " + 1; // $foo is float (11) $foo = "10.0 pigs " + 1.0; // $foo is float (11) ?> ``` [<img src="https://images.seebug.org/upload/201407/162026407e216568db5af528e197a3050a82ac7b.jpg" alt="sitestar11.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/162026407e216568db5af528e197a3050a82ac7b.jpg) [<img src="https://images.seebug.org/upload/201407/1620320992d9e01fa76755638eb9832fee83dfaa.jpg" alt="site.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/1620320992d9e01fa76755638eb9832fee83dfaa.jpg) ### 漏洞证明: [<img src="https://images.seebug.org/upload/201407/162026407e216568db5af528e197a3050a82ac7b.jpg" alt="sitestar11.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/162026407e216568db5af528e197a3050a82ac7b.jpg) [<img src="https://images.seebug.org/upload/201407/1620320992d9e01fa76755638eb9832fee83dfaa.jpg" alt="site.jpg" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201407/1620320992d9e01fa76755638eb9832fee83dfaa.jpg)