[代码审计]云ec电商系统代码审计
0x00 前言
看了一下博客内最新的文章,竟然是3月28号的,一个多月没写文章了,博客都长草了。
主要是临近毕业,事情繁多,也没有啥时间和心情静下来写。。
不过现在的话,毕业的东西告一段落了,几乎没啥事了,总算能静下来好好学习。
发了篇文章在t00ls,不过是精简版的,有些地方没有细讲。之前也有伙伴留言说,文章放到t00ls,有些没账号的朋友看不到。这里我搬运一下。
0x01 基础环境
审计版本为V1.2
最后更新时间:2018-04-20
用到的工具:vscode,phpstudy
0x02 前台注入漏洞分析
漏洞其实很简单,就是我们常见的获取ip没过滤的问题的,但这里需要点条件。
看到inc\funciton\functions_admin.php getip()函数
function getip(){
static $ip = null;
if($ip)
return $ip; // 不需要计算第二次.
$ip=false;
if($_SERVER['HTTP_VIA']){ //使用了代理
if(!empty($_SERVER["HTTP_CLIENT_IP"])){ //设置client_ip头
$ip = $_SERVER["HTTP_CLIENT_IP"];
}else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
$ips = explode (", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
if ($ip){
array_unshift($ips, $ip); $ip = '';
}
$ipss = count($ips);
for ($i = 0; $i < $ipss; $i++){
if (!preg_match('/^(10|172\.16|192\.168)\./', $ips[$i])){
$ip = $ips[$i];
break;
}
}
}
}else{
$ip = $_SERVER['REMOTE_ADDR'];
} # 更兼容的获取.
if(!$ip)//if $ip为false
if(!$ip = getenv("REMOTE_ADDR"))
if (!$ip = getenv("HTTP_CLIENT_IP"))
if(!$ip = getenv("HTTP_X_FORWARDED_FOR"))
$ip = '';
return $ip;
}
看到几个判断语句,先是判断是否使用了代理访问,如果没有使用直接用$_SERVER['REMOTE_ADDR']来获取ip,这个我们是没办法控制的。
如果使用了代理访问的话,进到判断$_SERVER['HTTP_CLIENT_IP']是否为空,不为空,直接设置$ip=$_SERVER['HTTP_CLIENT_IP'],而这个头我们是可以通过Client-Ip进行控制。
因为这里是SERVER变量,绕过了对GPC的过滤,看到过滤文件inc\function\global.php
$getfilter="\\b(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
$postfilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
$cookiefilter="\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)"; function StopAttack($StrFiltKey,$StrFiltValue,$ArrFiltReq){
if(is_array($StrFiltValue))
{
$StrFiltValue=implode($StrFiltValue);
}
if (preg_match("/".$ArrFiltReq."/is",urldecode($StrFiltValue))){
print "网址有误~";
exit();
}
} foreach($_GET as $key=>$value){
StopAttack($key,$value,$getfilter);
}
if ($_GET["p"]!=='admin'){
foreach($_POST as $key=>$value){
StopAttack($key,$value,$postfilter);
}
} foreach($_COOKIE as $key=>$value){
StopAttack($key,$value,$cookiefilter);
}
unset($_GET['_SESSION']);
unset($_POST['_SESSION']);
unset($_COOKIE['_SESSION']);
全局寻找getip()使用的位置。
找到了一处比较好利用的一个点,看到文件inc\module\user.php
elseif ($act == 'add_comment_reply')
{
$content = isset($content) ? trim($content) : '';
$cid = isset($cid) ? intval($cid) : '';
/*if(intval($gid)==0)
{
$res['err'] = '获取商品号失败';
die(json_encode_yec($res));
}*/
if(intval($pid)==0)
{
$res['err'] = '回复的对象错误';
die(json_encode_yec($res));
}
if(!isset($content) || $content == '')
{
$res['err'] = '请输入回复内容';
die(json_encode_yec($res));
}
elseif(mb_strlen($content,'utf-8')>120) {
$res['err'] = '字数请控制在120个以内';
die(json_encode_yec($res));
}
if($ym_uid==0) //需要登录
{
$ym_uid =check_login(1);
if($ym_uid==0)
{
$res['url'] = 'login.html';
die(json_encode_yec($res));
}
}
dbc();
if(check_comment_reply($ym_uid, getip())==false)
{
$res['err'] = '您评论的有点频繁了,请休息一小时再来吧~';
die(json_encode_yec($res));
}
$reply_id = get_comment_uid(intval($pid), intval($ptype));
$id = add_comment_reply($cid,$ym_uid, $reply_id, intval($pid), intval($ptype), role_user, $content);
$res['res'] = $id;
}
这里是用户评论的逻辑代码,看到最后一个if判断中,使用到了getip()函数,跟进check_comment_reply函数,inc\lib\user.php
function check_comment_reply($uid, $ip='')
{
global $db;
$where ='';
$row_uid = $db->query("select count(*) count from ".$db->table('comment_reply')." where addtime>=".strtotime(date('Y-m-d H:i:s',strtotime("-1 hour")))." and uid=".$uid);
$row_ip = $db->query("select count(*) count from ".$db->table('comment_reply')." where addtime>=".strtotime(date('Y-m-d H:i:s',strtotime("-1 hour")))." and ip='".$ip."'"); if( (!$row_uid || count($row_uid)==0 || intval($row_uid['count']) < 10) && (!$row_ip || count($row_ip)==0 || intval($row_ip['count']) < 10))
{
return true;
} return false;
}
没有过滤带进去了,那么就可以注入了。getip()有很多地方用到,但是仅限于使用query,查询的。insert,update方法都在底层做了过滤,不展开讲。而且这个站默认是开启报错的,可以直接利用报错获取数据。
那么整理一下漏洞利用条件:
1,需要开启会员注册,因为注册要发送验证码,很多商城可能已经废了。
2,需要代理访问。
妈的,不知道谁改了demo站演示账号的密码,找了个站演示:
文字表达一下利用:
请求URL:/user.html?act=add_comment_reply&content=1&cid=1&pid=1
header:Client-Ip:注入payload
获取管理账号
获取密码,分两段获取,最后一个字符获取不出来。
最后的密码为:f9c8c87e0a1f9d085b1008010fbd7781
这个系统密码的加密方式是这样的:
//加密字符串
function encryptStr($val, $salt='')
{
return md5(md5(trim($val)).$salt);
}
加了盐,我们需要把盐也注出来:
之后就是拉去解一下md5,md5解不出也没有关系。
因为这个系统底层用的是pdo,支持多语句执行。
那么可以直接插入一个管理员,或者修改已有管理员的密码,搞完之后修改回来就好了。这里以修改管理员密码为例:
进入后台
0x03 后台任意文件包含
后台有一个任意文件包含,上传图片马,访问URL
http://example.com/admin.html?do=express_track&oauth_code=1&sp_file=图片马路径
这里主要是因为sp_file没有定义,系统存在全局变量注册,可直接定义变量,看到inc\admin_inc\page\express_track.php
<?php
if (!defined('in_mx')) {exit('Access Denied');} checkAuth($login_id, 'system');//权限检测 //$sp_file = plugin."oauth/".$code.'/'.$code.'.php';
$path = plugin."express/";
$dirs =get_dir($path); if($oauth_code)
{
if(file_exists($sp_file)==false){message("获取不到文件 ".$code.'.php');}
require($sp_file);//任意文件包含
$row = $db->fetch('express_track', '*', array('code' => $code));
} $row = $db->fetchall('express_track', '*'); //die("a".$p); ?>
$sp_file未定义,无过滤,直接require,造成了文件包含。这个利用前台的头像+后台的csrf可以直接getshell。
这个系统还有一个session固定的漏洞,结合组合拳直接进后台。
还有之前和Adog师傅聊,他说有xss,我也没找,这里就不细说了。
上面的两个利用无须xss,只有一个img标签的请求即可。利用原理参考我的这篇文章([代码审计]yxcms从伪xss到getshell,https://www.cnblogs.com/r00tuser/p/8419300.html)
img请求+csrf+get请求任意文件包含=getshell
img请求+csrf+get请求session固定=进后台
0x04 总结
这个系统还有很多问题,不一一细讲,抛砖引玉。
[代码审计]云ec电商系统代码审计的更多相关文章
- B2B电商系统开发建设的价格费用取决于哪些要素
B2B电子商务系统平台建设开发怎么做?如何搭建一个电商系统网站平台?相信我们的企业商家在搭建电子商务系统的时候都会进行前期的系统策划,但是对于电子商务系统的构建绝大多数人都有一个误区,那就是对于电子商 ...
- 电商系统架构总结1(EF)
最近主导了一个电商系统的设计开发过程,包括前期分析设计,框架搭建,功能模块的具体开发(主要负责在线支付部分),成功上线后的部署维护,运维策略等等全过程. 虽然这个系统不是什么超大型的电商系统 数亿计的 ...
- 免费领CRMEB移动社交电商系统源码与授权
移动电商风起云涌,直播带货重塑销售模式,传统商业更是举步维艰,各行各业转型移动电商迫在眉睫,拥有一款好的移动社群社交电商系统成为众多企业与商家的心病! 你曾是否被那些劣质的移动电商系统搞得心力憔悴? ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统
本来想在Dpar 1.0GA时发布这篇文章,由于其他事情耽搁了放到现在.时下微服务和云原生技术如何如荼,微软也不甘示弱的和阿里一起适时推出了Dapr(https://dapr.io/),园子里关于da ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(二)——通讯框架讲解
首先感谢张队@geffzhang公众号转发了上一篇文章,希望广大.neter多多推广dapr,让云原生更快更好的在.net这片土地上落地生根. 目录:一.通过Dapr实现一个简单的基于.net的微服务 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(十)——一步一步教你如何撸Dapr之绑定
如果说Actor是dapr有状态服务的内部体现的话,那绑定应该是dapr对serverless这部分的体现了.我们可以通过绑定极大的扩展应用的能力,甚至未来会成为serverless的基础.最开始接触 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(十一)——一步一步教你如何撸Dapr之自动扩/缩容
上一篇我们讲到了dapr提供的bindings,通过绑定可以让我们的程序轻装上阵,在极端情况下几乎不需要集成任何sdk,仅需要通过httpclient+text.json即可完成对外部组件的调用,这样 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(十三)——istio+dapr构建多运行时服务网格之生产环境部署
之前所有的演示都是在docker for windows上进行部署的,没有真正模拟生产环境,今天我们模拟真实环境在公有云上用linux操作如何实现istio+dapr+电商demo的部署. 目录:一. ...
- 电商系统中的商品模型的分析与设计—续
前言 在<电商系统中的商品模型的分析与设计>中,对电商系统商品模型有一个粗浅的描述,后来有博友对货品和商品的区别以及属性有一些疑问.我也对此做一些研究,再次简单的对商品模型做一个介 ...
随机推荐
- java回顾(项目前期的基本准备)
一. 基础回顾 1 集合 1.1 集合的类型与各自的特性 ---|Collection: 单列集合 ---|List: 有存储顺序, 可重复 ---|ArrayList: 数组实现, 查 ...
- 【CSS】clear清除浮动
clear清除浮动1.作用: 规定元素的某一侧不允许存在浮动元素 2.值: 3.应用: 清除其他浮动元素对其产生的影响 <!DOCTYPE html> <html lang=&quo ...
- ThinkPHP框架学习(二)
在上一节中,我主要讲到了如何获取ThinkPHP框架,以及虚拟目录和虚拟主机的配置.准备工作完成之后,就可以利用ThinkPHP去部署项目了. 先在工作目录(D:/zend/workspace)下新建 ...
- 就for循环VS for-in循环
这种模式的问题在于每次循环迭代的时候都要访问数据的长度.这样会使代码变慢,特别是当myarray不是数据,而是HTML容器对象时. HTML容器是DOM方法返回的对象,如: document.getE ...
- 求矩形的周长(线段树+扫描线) Picture POJ - 1177
题目链接:https://cn.vjudge.net/problem/POJ-1177 题目大意:求矩形外部的周长 具体思路:借用一下bin巨的一张图片. 我们按照y周从下往上的扫描线进行扫描,第一下 ...
- linux的内存文件系统tmpfs
在centos系统上自带的内存文件系统.这个tmpfs是temporary file system的意思. 一. 使用命令 df -h 查看tmpfs是否正在运行. Filesystem Size U ...
- HDU 6395 Sequence 杜教板子题
题目意思非常明确,就是叫你求第n项,据我们学校一个大佬说他推出了矩阵,但是我是菜鸡,那么肯定是用简单的方法水过啦!我们先p^(1/2)的复杂度处理出i=[i,p]范围内的所有种类的(int)(p/i) ...
- eclipse中可以导入其它工具编写的RobotFramework脚本吗?
在Robotframework的官方网站中,提供了非常多的编辑RF的工具.比如Ride,eclipse,sublime,notepad++等. 网上查到的资料,大部分都是Ride这个编辑工具的使用.在 ...
- 20165230 《Java程序设计》实验五《网络编程与安全》实验报告
20165230 <Java程序设计>实验五<网络编程与安全>实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:田坤烨 学号:20165230 成绩: ...
- EM算法原理详解
1.引言 以前我们讨论的概率模型都是只含观测变量(observable variable), 即这些变量都是可以观测出来的,那么给定数据,可以直接使用极大似然估计的方法或者贝叶斯估计的方法:但是当模型 ...