打开题目
题目源码:
<?php
$function = @$_GET['f'];
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
if($_SESSION){
unset($_SESSION);
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
extract($_POST);
if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
我们简单代码审计一下
$function = @$_GET['f']; //从 GET 请求中获取名为 'f' 的参数,并赋值给
$function
变量。使用@
符号来抑制可能的未定义变量警告,function filter($img){ //定义了一个名为
filter
的函数,接受一个参数$img
。
$filter_arr = array('php','flag','php5','php4','fl1g'); //$filter_arr
数组包含了需要过滤掉的关键词列表,如 'php', 'flag', 'php5', 'php4', 'fl1g'。
$filter = '/'.implode('|',$filter_arr).'/i'; //将关键词数组连接成一个以竖线|
分隔的字符串,形成一个正则表达式模式,如(php|flag|php5|php4|fl1g)。
/.../i
是一个正则表达式模式,用于在preg_replace()
函数中替换匹配到的内容。这里的i
标志表示不区分大小写
return preg_replace($filter,'',$img); //将匹配到的字符串替换为空字符串,实现了过滤功能。
if($_SESSION){
unset($_SESSION); //用unset($_SESSION)
将整个会话数据清除
}$_SESSION["user"] = 'guest'; //将
$_SESSION['user']
设置为字符串'guest'
$_SESSION['function'] = $function; //将$_SESSION['function']
设置为从$_GET
或者其他地方获得的值$function
extract($_POST); //使用
extract()
函数将$_POST
数组中的键值对提取到当前的符号表中,使得这些键名变成了当前作用域的变量名,对应的值变成了这些变量的值
if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>'; //如果$function
为空,则输出一个链接到index.php?f=highlight_file
的<a>
标签,显示为 "source_code"
}if(!$_GET['img_path']){ //
$_GET['img_path']
如果为空
$_SESSION['img'] = base64_encode('guest_img.png'); //则将$_SESSION['img']
设置为经 base64 编码后的 'guest_img.png'。
}else{ //如果不为空
$_SESSION['img'] = sha1(base64_encode($_GET['img_path'])); //将$_GET['img_path']
进行 base64 编码,并用 sha1 编码,将结果存储到$_SESSION['img']
中
}$serialize_info = filter(serialize($_SESSION)); //
serialize()
函数将$_SESSION
数组序列化,并将结果传递给filter()
函数进行过滤。
if($function == 'highlight_file'){ //如果
$function
的值为 'highlight_file'
highlight_file('index.php'); //highlight_file()
函数来显示 'index.php' 文件的代码
}else if($function == 'phpinfo'){ //如果$function
的值为 'phpinfo',则使用eval()
函数执行phpinfo()
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){ 如果$function
的值为 'show_image'
$userinfo = unserialize($serialize_info); //通过unserialize()
函数尝试将$serialize_info
字符串反序列化为 PHP 数据结构,并将结果存储在$userinfo
变量
echo file_get_contents(base64_decode($userinfo['img'])); //使用file_get_contents()
读取并输出对应图像文件的内容
}
做题
首先题目给了我们提示
那我们就get传参一个f(就相当于function),让f=phpinfo看看提示
在页面里面看到了flag文件的名字
知识点:
implode函数
implode() 函数,把数组元素组合为字符串。
语法
implode(separator,array)
参数 | 描述 |
---|---|
separator | 可选。规定数组元素之间放置的内容。默认是 ""(空字符串)。 |
array | 必需。要组合为字符串的数组。 |
例子:
<?php
$arr = array('Hello','World!','I','love','Shanghai!');
echo implode(" ",$arr);
?>
运行结果为:
Hello World! I love Shanghai!
extract函数
定义和用法
extract() 函数从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
第二个参数 type 用于指定当某个变量已经存在,而数组中又有同名元素时,extract() 函数如何对待这样的冲突。
该函数返回成功导入到符号表中的变量数目。
语法
extract(array,extract_rules,prefix)
参数 | 描述 |
---|---|
array | 必需。规定要使用的数组。 |
extract_rules | 可选。extract() 函数将检查每个键名是否为合法的变量名,同时也检查和符号表中已存在的变量名是否冲突。对不合法和冲突的键名的处理将根据此参数决定。 可能的值:
|
prefix | 可选。请注意 prefix 仅在 extract_type 的值是 EXTR_PREFIX_SAME,EXTR_PREFIX_ALL,EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS 时需要。如果附加了前缀后的结果不是合法的变量名,将不会导入到符号表中。 前缀和数组键名之间会自动加上一个下划线 |
参考下面这个实例就能很清楚看明白如果变量有冲突,该怎么设置
实例
<?php
$a = "Original";
$my_array = array("a" => "Cat", "b" => "Dog", "c" => "Horse");
extract($my_array, EXTR_PREFIX_SAME, "dup");
echo "\$a = $a; \$b = $b; \$c = $c; \$dup_a = $dup_a";
?>
运行结果为:$a = Original; $b = Dog; $c = Horse; $dup_a = Cat
unset函数
unset() 函数用于销毁给定的变量。
PHP Filter
PHP 过滤器用于对来自非安全来源的数据(比如用户输入)进行验证和过滤。
具体使用见:
PHP Filter 函数 | 菜鸟教程
反序列化字符串逃逸
知识点的参考文章:
PHP extract() 函数
PHP implode() 函数