php 读取cookieid,代码审计:TinyShop网店系统漏洞审计过程分享

* 本文属CE安全网投稿文章  未经允许 不得转载 ! 作者ID:daomeng *

前言

反射XSS

产生原因

疑似cookie产生的SQL注入

上传头像存在DOS风险

产生原因

后台账号充值存在csrf风险

产生原因

前言

审计该 CMS 中的内容只涉及到前台,后台中有存安全问题但对我来说没什么意义,所以没有过多的关注,感兴趣的朋友可以自己动动手。

因为本身已经做了一定的安全加固,本次审计并没挖掘出高危漏洞。但存在几个可以对网站造成危害的安全风险,在此仅做为思路分享给大家参考学习。

框架是这个 CMS 自写的,里面处理接收参数均在 ./framework/lib/util/request_class.php 文件中,比如:

//同时处理$_GET $_POST

public static function args()

{

$num = func_num_args();

$args = func_get_args();

if($num==1)

{

...省略...

}

else if($num>=2)

{

...省略...

}

else

{

return $_POST+$_GET;

}

}

参数及过滤则放在 ./framework/lib/util/filter_class.php 中,所以在阅读代码是可以看到接收参数是这样的:

Filter::int(Req::args('address_id'))

接收参数 address_id,并用正则至获取数字

Filter::text(Req::args('invoice_title'))

接收参数 invoice_title,并用 htmlpurifier 扩展清洗 xss 注入

Filter::sql(Req::post('email'))

接收参数 email,并用正则过滤恶意 sql

碰到这种就可以直接放弃了,可以看看代码:

public static function int($str)

{

$number = preg_replace("/[^\d]/", "", $str);

$number = ($number=='')?0:$number;

return $number;

}

public static function sql($str)

{

if(class_exists('TPdo') && class_exists('pdo')){

}else{

if (!get_magic_quotes_gpc()){

$str = addslashes($str);

}else{

$str = preg_replace('/(?

}

}

$str = preg_replace('/([^a-z]+)(select|insert|update|delete|union|into|load_file|outfile|and|or|sleep|tiny_)/i', ' $2', $str);

return $str;

}

反射XSS

在官网示例中测试成功

http://shop.tinyrise.org/index.php?con=simple&act=address_save&accept_name=1&mobile=13888888888&phone=13888888888&province=110000&

0fcda4367f11d485deaad2187058683d.gif

产生原因

看代码:

public function address_save($redirect=null){

$rules = array('zip:zip:邮政编码格式不正确!','addr:required:内容不能为空!','accept_name:required:收货人姓名不能为空!,mobile:mobi:手机格式不正确!,phone:phone:电话格式不正确','province:[1-9]\d*:选择地区必需完成','city:[1-9]\d*:选择地区必需完成','county:[1-9]\d*:选择地区必需完成');

$info = Validator::check($rules);

if(!is_array($info) && $info==true) {

...省略...

}

else{

$this->assign("msg",array("error",$info['msg']));

$this->redirect("address_other",false,Req::args());

}

}

问题出在 Req::args() 。当参数校验失败后页面会进行重定向,并将接收到的参数传递至视图中。

视图中原样输出 zip 参数内容:

./runtime/default/simple/address_other.php

邮政编码:" alt="邮政编码错误">

疑似cookie产生的SQL注入

为什么说疑似注入呢,因为通过分析这个方法确实将恶意代码注入进了 SQL 查询。但因为本人注入战5渣,技术比较烂没用找到正确的利用姿势,所以放弃了。

// ./protected/classes/Common.php

//自动登录时的用户信息

static function autoLoginUserInfo()

{

$cookie = new Cookie();

$cookie->setSafeCode(Tiny::app()->getSafeCode());

$autologin = $cookie->get('autologin');

$obj = null;

if($autologin!=null){

...省略...

}else{

$weixin_openid = Cookie::get('weixin_openid');

if($weixin_openid != null){

$model = new Model('oauth_user');

// 关注点 $weixin_openid 参数

$oauth_user = $model->where("oauth_type='WeixinOAuth' and open_id='$weixin_openid'")->find();

if($oauth_user && $oauth_user['user_id']!=''){

...省略...

}

}

}

return $obj;

}

从上面的代码可以看到, $weixin_openid 参数是从 cookie 中获取。我们看看 Cookie::get() 函数:

// ./framework/lib/util/cookie_class.php

// 取得cookie值

public static function get($name)

{

// 这里的if是要 $_COOKIE['safecode'] 中的参数是 1 即可。

if(self::checkSafe()==1)

{

// $per = 'Tiny_';

if(isset($_COOKIE[self::$per.$name]))

{

$cryptCookie = $_COOKIE[self::$per.$name];

$cookie= Crypt::decode($cryptCookie,self::getSafeCode());

$tem = substr($cookie,0,10);

if(preg_match('/^[Oa]:\d+:.*/',$tem)) $cookie = unserialize($cookie);

return $cookie;

}

return null;

}

if(self::checkSafe()==0) self::clear($name);// Tiny::msg('非法窃取COOKIE,系统将终止工作!',0);

else return null;

}

可以看到,这里用到了 Crypt 类对值进行算法解密处理,最终调用反序列化函数后将值传递给 $cookie。

这里只要找到加密方式,并对恶意代码进行一次处理随后传递至 cookie 中的 Tiny_autologin 参数即可。

所以我们构造一段代码,将 Cookie::set() 函数里面的值返回出来即可。

// ./framework/lib/util/cookie_class.php

public static function set($name,$value='',$time='86400',$path='/',$domain=null)

{

if($time<=0) $time = -3600;

else $time = time() + $time;

setCookie('safecode',self::cookieId(),$time,$path,$domain);

if(is_array($value) || is_object($value)) $value=serialize($value);

$value = Crypt::encode($value,self::getSafeCode());

//setCookie(self::$per.$name,$value,$time,$path,$domain); // 注释该行

return $value;

}

// ./protected/classes/Common.php

//自动登录时的用户信息

static function autoLoginUserInfo()

{

$str = '\' or 1=1-- ';

$poc = Cookie::set('weixin_openid',$str);

echo $poc;exit();

/*...后面的代码先注释或忽略...*/

}

0fcda4367f11d485deaad2187058683d.gif

输出加密后的字符串:ddb494c3baUwYICFJVAwJSBVUACQFWB1MGVQcGVlUCAlhUAApaDAUQF1tARQkLU0sVFQ

现在我们用它来测试试试看,是否能被正确解密:

0fcda4367f11d485deaad2187058683d.gif

好了,我们去除调试用的 var_dump($weixin_openid);exit();,看看是否被带入到SQL中:

0fcda4367f11d485deaad2187058683d.gif

至于后面怎么利用,请原来我这个辣鸡水平低~ 咳咳~

你在查看源代码的时候后会发现,这个 cms 大量使用了序列化和反序列函数,如果你登录了后台,并且想留个后面什么的,用序列化蛮方便的。

当然,前台我已基本上分析完了,有反序列化的地方但并不能形成漏洞。

很失望。

上传头像存在DOS风险

该 CMS 对上传已经做了很好的安全限制,但它支持用户上传 gif 文件,结合文章中所述的 POC 测试此处风险确实存在。

/**

* 生成图像

*

* @access private

* @param mixed $type 图片类型

* @param mixed $filename 文件名

* @return mixed

*/

private function createImage($type,$filename)

{

//1 = GIF,2 = JPG,3 = PNG

switch($type)

{

case 1: $im = imageCreateFromGif($filename);break; // 代码运行至此处,存在DOS风险

case 2: $im = imageCreateFromJpeg($filename);break;

case 3: $im = imageCreateFromPng($filename);break;

default:

{

$im = imageCreateFromJpeg($filename);break;

}

}

return $im;

}

0fcda4367f11d485deaad2187058683d.gif

可以看到, poc.gif 图片上传后,导致超出了服务最大等待时间,使页面 504 。

产生原因

不使用 imagecreatefromgif() 处理 .gif 图片,或升级最新版本可以可以防御。

详细参看:http://blog.orange.tw/2018/01/php-cve-2018-5711-hanging-websites-by.html

后台账号充值存在csrf风险

后台里面的问题我就那这一个出来说吧:

0fcda4367f11d485deaad2187058683d.gif

如图中所示,这个用户的金额是 0.00,我们先登录后台管理员账号,并给该账号充值 200。

找出充值成功的请求,生成 csrf 攻击重放页面:

0fcda4367f11d485deaad2187058683d.gif

好,现在我们用浏览器打开保存的HTML页面,打开后点击确认按钮可以看到如下提示:

0fcda4367f11d485deaad2187058683d.gif

回到账号充值页面,看看现在这个账号金额是多少:

0fcda4367f11d485deaad2187058683d.gif

思考一下

单独拿这个问题提出来说,是因为这里可以形成一个组合漏洞。

上面有个反射 XSS 漏洞,如果恶意用户伪造 javascript 脚本对账号进行充值,随后去诱导客服进行点击。

当当当~ 脑补攻击+1。

产生原因

后台对用户进行充值时,没有加入表单来源认证,未区分本次请求是管理点发出,还是恶意用户伪造。

* 本文属CE安全网投稿文章  未经允许 不得转载 ! 作者ID:daomeng *

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值