乌云1000个PHP代码审计案例(1)
前两天发现的宝藏网站:https://php.mengsec.com/
在github上面找到了源代码:https://github.com/Xyntax/1000php,可以在自己的服务器上面搭建
跟数据结构学习一样,每天跟着上面前辈们的案例进行审计,打基础+学习思路
1,BlueCMS v1.6 sp1 ad_js.php SQL注入漏洞
使用seay自动审计工具
可以看到第一条可能出现的漏洞点就是ad_js.php
我们跟进去看,
经过getone函数在数据库里面查询出结果并赋值给$ad变量,同时可以看到$ad_id没有包裹引号
getone函数是在数据库里面进行查询的函数
mysqli_fetch_array() 函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有。也就是从数据库中查询。
我们往上看$ad_id变量的输入位置是否有过滤。
可以看到对于GET方法输入的ad_id变量仅仅是使用trim函数去除了输入值两边的空格,此外就没有另外的过滤了,所以该点确实存在SQL注入漏洞。
真实环境下利用很简单,使用union联合注入即可出数据
修复方法:$ad_id = !empty($_GET['ad_id']) ? intval($_GET['ad_id']) : '';
将输入的数据强行转换成整型
2,Discuz!7.2/X1 第三方插件SQL注入及持久型XSS漏洞
这里分析SQL注入漏洞,插件是由Discuz!认证的(http://addons.discuz.com/workroom.php)第三方开发团队“潮流少年工作室 Teen Studio”出品的心情墙插件(http://www.discuz.net/forum.php?mod=viewthread&tid=1632898)
因为去找漏洞插件太麻烦了,我这里直接贴上漏洞源代码吧
elseif($action == 'edit_mood' && moodid) { //moodid未初始化,直接代入sql查询 $check = $db->result_first("SELECT * FROM {$tablepre}moodwall WHERE id='$moodid' AND uid='$discuz_uid'"); if(!$check || !$moodid) { showmessage('moodwall:moodwall_inc_php_2', 'plugin.php?id=moodwall&action=user_mood'); } $sql = "SELECT * FROM {$tablepre}moodwall WHERE id='$moodid'"; $query = $db->query($sql); $moodlist_edit = array(); while($mood_edit = $db->fetch_array($query)) { $moodlist_edit[] = $mood_edit; }
可以看到$moodid变量在单引号包裹下代入$sql语句进行查询
$sql = "SELECT * FROM {$tablepre}moodwall WHERE id='$moodid'";
但是在这里漏洞的发现者也说了,需要网站magic_quotes_gpc=off,在magic_quotes_gpc=On的情况下,如果输入的数据有单引号(’)、双引号(”)、反斜线()与 NULL(NULL 字符)等字符都会被加上反斜线。
不过实际上还可以有宽字节注入等特殊情况对网站进行注入
3,ecshop SQL注射漏洞
因为没有详细的ecshop版本信息,所以同样不进行源码的下载,在wooyun大大的基础上直接进行分析
在include_libcommon.php中存在如下函数,get_package_info函数
function get_package_info($id)
{
global $ecs, $db,$_CFG;
$now = gmtime();
$sql = "SELECT act_id AS id, act_name AS package_name, goods_id , goods_name, start_time, end_time, act_desc, ext_info".
" FROM " . $GLOBALS['ecs']->table('goods_activity') .
" WHERE act_id='$id' AND act_type = " . GAT_PACKAGE;
$package = $db->GetRow($sql);
/* 将时间转成可阅读格式 */
if ($package['start_time'] <= $now && $package['end_time'] >= $now)
{
$package['is_on_sale'] = "1";
}
else
{
$package['is_on_sale'] = "0";
}
$package['start_time'] = local_date('Y-m-d H:i', $package['start_time']);
$package['end_time'] = local_date('Y-m-d H:i', $package['end_time']);
$row = unserialize($package['ext_info']);
unset($package['ext_info']);
if ($row)
{
foreach ($row as $key=>$val)
{
$package[$key] = $val;
}
}
$sql = "SELECT pg.package_id, pg.goods_id, pg.goods_number, pg.admin_id, ".
" g.goods_sn, g.goods_name, g.market_price, g.goods_thumb, g.is_real, ".
" IFNULL(mp.user_price, g.shop_price * '$_SESSION[discount]') AS rank_price " .
" FROM " . $GLOBALS['ecs']->table('package_goods') . " AS pg ".
" LEFT JOIN ". $GLOBALS['ecs']->table('goods') . " AS g ".
" ON g.goods_id = pg.goods_id ".
" LEFT JOIN " . $GLOBALS['ecs']->table('member_price') . " AS mp ".
"ON mp.goods_id = g.goods_id AND mp.user_rank = '$_SESSION[user_rank]' ".
" WHERE pg.package_id = " . $id. " ".
" ORDER BY pg.package_id, pg.goods_id";
$goods_res = $GLOBALS['db']->getAll($sql);
$market_price = 0;
可以看到$sql语句里面代入了输入的$id,我们再定位谁调用了get_package_info函数,在系统的lib_order.php中。
function add_package_to_cart($package_id, $num = 1)
{
$GLOBALS['err']->clean();
/* 取得礼包信息 */
$package = get_package_info($package_id);
if (empty($package))
{
$GLOBALS['err']->add($GLOBALS['_LANG']['goods_not_exists'], ERR_NOT_EXISTS);
return false;
}
可以看到调用get_package_info函数赋值给了$package变量,而$package_id变量是传递给add_package_to_cart函数的,在该函数中也没有看到有对变量的过滤,寻找调用add_package_to_cart函数的文件
在flow.php中存在可控的输入源
$package = $json->decode($_POST['package_info']);
/* 如果是一步购物,先清空购物车 */
if ($_CFG['one_step_buy'] == '1')
{
clear_cart();
}
/* 商品数量是否合法 */
if (!is_numeric($package->number) || intval($package->number) <= 0)
{
$result['error'] = 1;
$result['message'] = $_LANG['invalid_number'];
}
else
{
/* 添加到购物车 */
if (add_package_to_cart($package->package_id, $package->number))
{
if ($_CFG['cart_confirm'] > 2)
而在这里$package->package_id是我们可以控制的输入源,根据刚才函数调用的过程,对于我们的这个输入并没有其余的过滤,可知存在SQL注入漏洞
4,Discuz!漫游插件API本地包含漏洞
先上代码 manyou/api/class/MyBase.php
128: function parseRequest() { 131: $request = $_POST; 132: $module = $request['module']; 133: $method = $request['method']; ... 174: return $this->callback($module, $method, $params); 175: } 177: function callback($module, $method, $params) { ... 191: @include_once DISCUZ_ROOT.'./manyou/api/class/'.$module.'.php';
在parseRequest函数里面,可以看到最后return调用了callback函数,并且传入的三个参数都是我们可以控制的输入,而callback函数里面使用include_once函数包含了当前路径下的传递的$module.php文件
PHP中文件包含函数有以下四种:
require() require_once() include() include_once()
include和require的区别在于include在包含的时候出现错误的时候,会抛出一个警告,然后程序继续运行,而require函数在出现错误的时候,会直接报错并且退出程序的执行
require_once和include_once这两个函数与前两个不同的地方在于,这两个函数只包含一次,适合于脚本执行期间同一个文件可能被包括一次以上的情况时,你想确保它只包含一次以避免函数重定义,变量重新赋值等问题
参考自:https://www.freebuf.com/articles/web/182280.html
在这里我们可以控制$module变量,但是这里是有限制的文件包含,因为在后面加上了.php的后缀,当我们想包含当前文件夹任意文件的时候,如果magic_quotes_gpc = Off php版本<5.3.4,我们可以使用%00截断的方式,当然还有其他很多的方式可以绕过这个限制,如果在这里还存在目录穿越漏洞的话,我们就可以包含服务器任意文件了,而不是限制在这个文件夹下。
5,PHPCMS通杀XSS
这里是一个反射型XSS漏洞,在我要报错功能页下,过滤不严格
http://**.**.**.**/error_report/error_report.php?title=1&contentid=1"><script>alert(/xss/)</script>
反射型XSS漏洞比较容易通过扫描器黑盒直接发现,只需要将尖括号,单双引号等提交到web服务器,检查返回的HTML页面里面有没有保留原来的特殊字符即可判断。
在白盒审计中,我们只需要寻找带有参数输出函数,然后根据输出函数对输出内容回溯输入参数,观察有没有进行经过过滤
6,phpcms 2008 sp4 爆路径及任意文件删除漏洞
漏洞文件是corpandresize/config.inc.php
$tmp = $_COOKIE['tmp']; define("TMP_PATH", $tmp);
在cookie参数中获取tmp,同时定义TMP_PATH等于变量tmp的值
使用到TMP_PATH的位置是corpandresize/process.php
@unlink(TMP_PATH.'/'.$thumbfile);
这里使用unlink函数删除文件,我们可以使用%00截断删除我们想要删除的任意文件
如在cookie中添加tmp=../index.php%00,按照上面的分析过程,就可以删除首页文件
7,phpcms2008本地文件包括及利用(执行任意SQL脚本)
漏洞文件存在于wap/index.php
代码如下:
<?php include '../include/common.inc.php'; include './include/global.func.php'; $lang = include './include/lang.inc.php'; if(preg_match('/(mozilla|m3gate|winwap|openwave)/i', $_SERVER['HTTP_USER_AGENT'])) { header('location:../'); } wmlHeader($PHPCMS['sitename']); $action = isset($action) && !empty($action) ? $action : 'index'; if($action) { include './include/'.$action.'.inc.php'; } $html = CHARSET != 'utf-8' ? iconv(CHARSET, 'utf-8', $html) : $html; echo str_replace('<br/>', "<br/>\n", $html); wmlFooter(); ?>
可以看到在这一段代码里有:
$action = isset($action) && !empty($action) ? $action : 'index';
if($action)
{
include './include/'.$action.'.inc.php';
}
isset() 函数用于检测变量是否已设置并且非 NULL。在这里即检测$action是否设置,同时检测$action是否为空,空的话就赋值为index,非空即传入值,接着就是包含传入的$action.inc.php文件,对于输入的$action没有进行过多的检测
可以包含存在sql语句的php文件,执行任意sql语句来对漏洞进行利用
例如包含目录include\fields\areaid 下任一文件,执行任意SQL脚本。
比如field_add.inc.php文件,我们只需要传入的$action=fields/areaid/field_add,field_add.inc.php文件代码为:
<?php if(!$maxlength) $maxlength = 255; $maxlength = min($maxlength, 255); $sql = "ALTER TABLE `$tablename` ADD `$field` VARCHAR( $maxlength ) NOT NULL DEFAULT '$defaultvalue'"; $db->query($sql); ?>
在这里我们只需要传入$tablename变量就可以执行$sql语句进行查询
最后的payload为:http://www.phpcms.cn/wap/index.php?action=../../include/fields/areaid/field_add&tablename=xx
8,Ecshop2.7.2持久型XSS(可获得管理员帐号)
可以看到当POST传输的数据extend_field_index没有任何的过滤就进入数据库进行更新了。
这里的输入是密码保护问题这一项,我们可以在密码保护问题里输入XSS,但是后台查看会员资料是不显示密码保护问题的,所以这里必须要网站后台添加了新的 “会员注册项”时,后台查看资料就会显示了,显示了之后就可以进行XSS攻击了。
这里不懂的地方是原漏洞作者导入外部js的时候,js文件里面的内容是Ajax:
Ajax.call('privilege.php?act=update','id=1&user_name=heihei&email=10001@**.**.**.**','',"POST","JSON");
而不是写入外部js盗取管理员cookie,以后明白了再补充这里。
乌云1000个PHP代码审计案例(1)的更多相关文章
- 渗透系统虚拟机----win7(渗透工具包)
今天把自己用的win7渗透虚拟机和渗透工具脚本整合到一起备份传网盘了: D:\渗透工具包>dir 驱动器 D 中的卷是 DATA 卷的序列号是 0D74-084B D:\渗透工具包 的目录 // ...
- 74CMS3.0储存型XSS漏洞代码审计
发现一个总结了乌云以前代码审计案例的宝藏网站:https://php.mengsec.com/ 希望自己能成为那个认真复现和学习前辈们思路的那个人,然后准备慢慢开始审计一些新的小型cms了 骑士cms ...
- 关于jquery插件模板的两个案例
/** * jquery tips 提示插件 jquery.tips.js v0.1beta * * 使用方法 * $(selector).tips({ //selector 为jquery选择器 * ...
- 闲谈:乌云上那些 web-based 的 QQ 漏洞
0×00 起始 昨日凌晨,看到爱尖刀团队发布了一条“腾讯客户端XSS,已第一时间提交至TSRC”的微博,心想,腾讯又出此类漏洞了.今日,由于有一位名叫“阿布”的同学将该漏洞发布到了乌云,引来不少争吵甚 ...
- [转]C#编程总结(三)线程同步
本文转自:http://www.cnblogs.com/yank/p/3227324.html 在应用程序中使用多个线程的一个好处是每个线程都可以异步执行.对于 Windows 应用程序,耗时的任务可 ...
- Android(java)学习笔记195:三重for循环的优化(Java面试题)
1.首先我们看一段代码: for(int i=0;i<1000;i++){ for(int j=0;j<100;j++){ for(int k=0;k<10;k++){ testFu ...
- C#线程同步(转)
线程同步 在应用程序中使用多个线程的一个好处是每个线程都可以异步执行.对于 Windows 应用程序,耗时的任务可以在后台执行,而使应用程序窗口和控件保持响应.对于服务器应用程序,多线程处理提供了用不 ...
- 几个例子弄懂JS 的setInterval的运行方式
这篇文章主要介绍了js的setInterval方法的用法以及示例,非常的有用,这里推荐给小伙伴们. setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口 ...
- JSAP106
JSAP106 一.clientX.clientY 点击位置距离当前body可视区域的x,y坐标 二.pageX.pageY 对于整个页面来说,包括了被卷去的body部分的长度 三.screenX.s ...
随机推荐
- 腾讯云对象存储COS新品发布——智能分层存储,自动优化您的存储成本
近日,腾讯云正式发布对象存储新品--智能分层存储,能够根据用户数据的访问模式,自动地转换数据的冷热层级,为用户提供与标准存储一致的低延迟和高吞吐的产品体验,同时具有更低的存储成本. 熟悉数据存储的用户 ...
- Vue常用性能优化
Vue常用性能优化 Vue常用的一些优化方式,主要是在构建项目过程需要注意的方面. 编码优化 避免响应所有数据 不要将所有的数据都放到data中,data中的数据都会增加getter和setter,并 ...
- PHP无限级评论回复功能实现
protected function commentList($aid,$pid = 0,&$result=array()){ $arr = ArticleComment::relation( ...
- 02模板渲染和参数(补充:URL传参到视图)
先抛出代码: @app.route('/') def index(): return render_template('index.html',username ="郑勇") 问题 ...
- 经典c程序100例==31--40
[程序31] 题目:请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续 判断第二个字母. 1.程序分析:用情况语句比较好,如果第一个字母一样,则判断用情况语句或if语句判断第二个字 ...
- [leetcode/lintcode 题解] 微软 面试题:实现 Trie(前缀树)
实现一个 Trie,包含 insert, search, 和 startsWith 这三个方法. 在线评测地址:领扣题库官网 样例 1: 输入: insert(" ...
- c++中的几种函数调用约定(转)
C++中的函数调用约定(调用惯例)主要针对三个问题: 1.参数传递的方式(是否采用寄存器传递参数.采用哪个寄存器传递参数.参数压桟的顺序等): 参数的传递方式,最常见的是通过栈传递.函数的调用方将参数 ...
- 《.NET 5.0 背锅案》第5集-案情大转弯:都是我们的错,让 .NET 5.0 背锅
第1集:验证 .NET 5.0 正式版 docker 镜像问题 第2集:码中的小窟窿,背后的大坑,发现重要嫌犯 EnyimMemcachedCore 第3集-剧情反转:EnyimMemcachedCo ...
- 学习一下 Spring Security
一.Spring Security 1.什么是 Spring Security? (1)基本认识 Spring Security 是基于 Spring 框架,用于解决 Web 应用安全性的 一种方案, ...
- appium-appium的等待时间
#三种appium设置等待时间的方法 #第一种 sleep(): 设置固定休眠时间. python 的 time 包提供了休眠方法 sleep() , 导入 time包后就可以使用 sleep()进行 ...