### 简要描述: PHP云人才系统任意刷钱漏洞,演示详细过程,利用难度低0-0! ### 详细说明: 起因在member\model\com.class.php文件中: ``` function dingdan_action(){ if($_POST['price']){ if($_POST['comvip']){ $comvip=(int)$_POST['comvip']; $ratinginfo = $this->obj->DB_select_once("company_rating","`id`='".$comvip."'"); $price = $ratinginfo['service_price']; $data['type']='1'; }elseif($_POST['price_int']){ $price = $_POST['price_int']/$this->config['integral_proportion']; //integral_proportion = 20 只是简单的相除,没有判断正负。 $data['type']='2'; }elseif($_POST['price_msg']){ $price = $_POST['price_msg']/$this->config['integral_msg_proportion']; $data['type']='5'; }else{ $this->obj->ACT_layer_msg("参数不正确,请正确填写!",8,$_SERVER['HTTP_REFERER']); } $dingdan=mktime().rand(10000,99999); //订单生产的订单号,使用时间戳加上随机数。 $data['order_id']=$dingdan; $data['order_price']=$price; $data['order_time']=mktime(); $data['order_state']="1"; $data['order_remark']=trim($_POST['remark']); $data['uid']=$this->uid; $data['rating']=$_POST['comvip'];...
### 简要描述: PHP云人才系统任意刷钱漏洞,演示详细过程,利用难度低0-0! ### 详细说明: 起因在member\model\com.class.php文件中: ``` function dingdan_action(){ if($_POST['price']){ if($_POST['comvip']){ $comvip=(int)$_POST['comvip']; $ratinginfo = $this->obj->DB_select_once("company_rating","`id`='".$comvip."'"); $price = $ratinginfo['service_price']; $data['type']='1'; }elseif($_POST['price_int']){ $price = $_POST['price_int']/$this->config['integral_proportion']; //integral_proportion = 20 只是简单的相除,没有判断正负。 $data['type']='2'; }elseif($_POST['price_msg']){ $price = $_POST['price_msg']/$this->config['integral_msg_proportion']; $data['type']='5'; }else{ $this->obj->ACT_layer_msg("参数不正确,请正确填写!",8,$_SERVER['HTTP_REFERER']); } $dingdan=mktime().rand(10000,99999); //订单生产的订单号,使用时间戳加上随机数。 $data['order_id']=$dingdan; $data['order_price']=$price; $data['order_time']=mktime(); $data['order_state']="1"; $data['order_remark']=trim($_POST['remark']); $data['uid']=$this->uid; $data['rating']=$_POST['comvip']; $data['integral']=$_POST['price_int']; $id=$this->obj->insert_into("company_order",$data); //成功插入了数据库 if($id){ $this->obj->ACT_layer_msg("下单成功,请付款!",9,"index.php?c=payment&id=".$id); }else{ $this->obj->ACT_layer_msg("提交失败,请重新提交订单!",8,$_SERVER['HTTP_REFERER']); } }else{ $this->obj->ACT_layer_msg("参数不正确,请正确填写!",8,$_SERVER['HTTP_REFERER']); } } ``` 此处可以插入$_POST['price_int']=-20000 相当于 -1000元 接下来看api\tenpay\index.php文件中的逻辑: ``` if(!is_numeric($_POST['dingdan'])) //判断了是否为数字 { die; } $userid=(int)$_COOKIE['uid']; $_POST['is_invoice']=(int)$_POST['is_invoice']; //无用 $_POST['balance']=(int)$_POST['balance']; //化为整数了,此参数只要存在就行了,随便提交 $member_sql=$db->query("SELECT * FROM `".$db_config["def"]."member` WHERE `uid`='".$userid."' limit 1"); $member=mysql_fetch_array($member_sql); if($member['username'] != $_COOKIE['username'] || $member['usertype'] != $_COOKIE['usertype']||md5($member['username'].$member['password'].$member['salt'])!=$_COOKIE['shell']){ echo '登录信息验证错误,请重新登录!';die; } $sql=$db->query("select * from `".$db_config["def"]."company_order` where `order_id`='$_POST[dingdan]'"); //根据订单号查询order $row=mysql_fetch_array($sql); if($_POST['balance']&&$userid){ //正常登陆用户,随便提交balance参数即可 $c_sql=$db->query("select `pay` from `".$db_config["def"]."company_statis` where `uid`='".$userid."'"); $company_statis=mysql_fetch_array($c_sql); if($company_statis['pay']>=$row['order_price']){ //关键来了,判断用户余额是否大于订单,因为order_price 是负数,一定为true $up_sql=$db->query("update `".$db_config["def"]."company_statis` set `pay`=`pay`-'".$row['order_price']."' where `uid`='".$userid."'"); //此处直接相减了,负负得正!金钱增加。漏洞触发。 mysql_fetch_array($up_sql); $up_order=$db->query("update `".$db_config["def"]."company_order` set `order_price`='0'".$invoice_title." where `order_id`='".$row['order_id']."'"); //这里不影响,后面都不影响。 mysql_fetch_array($up_order); $price=$row['order_price']; }else{ $price=$company_statis['pay']; $up_sql=$db->query("update `".$db_config["def"]."company_statis` set `pay`='0' where `uid`='".$userid."'"); $up_sql_status=mysql_fetch_array($up_sql); $up_order=$db->query("update `".$db_config["def"]."company_order` set `order_price`=`order_price`-'".$price."'".$invoice_title." where `order_id`='".$row['order_id']."'"); mysql_fetch_array($up_order); } $insert_company_pay=$db->query("insert into `".$db_config["def"]."company_pay`(order_id,order_price,pay_time,pay_state,com_id,pay_remark,type) values('".$row['order_id']."','-".$price."','".time()."','2','".$userid."','".$row['order_remark']."','2')"); mysql_fetch_array($insert_company_pay); $new_sql=$db->query("select * from `".$db_config["def"]."company_order` where `order_id`='".$row['order_id']."'"); $row=mysql_fetch_array($new_sql); } ``` 大致成因是这样的,利用起来也相当的简单。 ``` 在文件member\model\com.class.php中: function paylog_action(){ include(CONFIG_PATH."db.data.php"); $this->yunset("arr_data",$arr_data); $this->public_action(); /* 省略 */ }else{ $urlarr=array("c"=>"paylog","page"=>"{{page}}"); $pageurl=$this->url("index","index",$urlarr); $where="`uid`='".$this->uid."'"; $where.=" and `order_price`>0 order by order_time desc"; //根据这个逻辑只显示了订单额大于0的项目,因此订单号需要我们去猜测。 $this->get_page("company_order",$where,$pageurl,"10"); } /* 省略 */ } ``` [<img src="https://images.seebug.org/upload/201409/26134602aa20bcfc0c5bc90f9aa3162f63bc3c34.png" alt="1111.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/26134602aa20bcfc0c5bc90f9aa3162f63bc3c34.png) 默认只显示正数订单,但是其实订单都是存在在数据库中的。 ### 漏洞证明: 利用方法: 只要在短时间多次重放订单数据包,就能在一秒内拥有最多的订单数,然后跑一遍10000-99999的后缀即可了。 重发使用burpsuite,可以设置大线程。这里有个技巧就是第一个提交一定是一个正常的数据,这样就可以找到mktime前缀了。 演示一遍。 1、多线程提交订单 [<img src="https://images.seebug.org/upload/201409/261346376204358a6e25f09eb7986c6235cb974b.png" alt="2222.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/261346376204358a6e25f09eb7986c6235cb974b.png) 2、只会显示第一个正常的订单 [<img src="https://images.seebug.org/upload/201409/26134656cdb7306aa1580d6692300e7bff0fb28a.png" alt="3333.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/26134656cdb7306aa1580d6692300e7bff0fb28a.png) 3、数据库中显示订单存在 [<img src="https://images.seebug.org/upload/201409/26134725e86b709d42fafeb3a808032315e3af2e.png" alt="4444.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/26134725e86b709d42fafeb3a808032315e3af2e.png) 开始遍历1411709332这个段的订单。订单前缀是在列表中直接显示的- -。 4、其中blance字段一定要有,值随意 [<img src="https://images.seebug.org/upload/201409/26134855bf99e8d97cfaa3831621b123867b74ad.png" alt="6666.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/26134855bf99e8d97cfaa3831621b123867b74ad.png) 坐等跑完 [<img src="https://images.seebug.org/upload/201409/26134931a0627f5f53372f54e164509289c4b675.png" alt="7777.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/26134931a0627f5f53372f54e164509289c4b675.png) 查看余额 [<img src="https://images.seebug.org/upload/201409/26134950c3327cc3d9995d0e470e650e05e6f2d9.png" alt="9999.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201409/26134950c3327cc3d9995d0e470e650e05e6f2d9.png) 试过这样就可以使用了,可以买会员,比如上图的铜牌会员。