看题目提示,应该是一道文件包含的题目,打开环境后直接告诉我flag在flag.php里
但是因为不知道绝对路径,不能直接利用file读取
查看源码后,发现里面嵌入了一段php代码
代码审计
首先,通过if( !ini_get('display_errors') )判断当前PHP环境是否已设置display_errors配置参数。如果没有设置,则通过ini_set('display_errors', 'On')设置为打开错误显示功能。
使用error_reporting(E_ALL)设置错误报告级别为显示所有错误。
然后,从$_COOKIE数组中获取名为language的值,并将其赋值给$lan变量。
如果$lan不存在或为空,使用setcookie函数设置一个名为language的cookie,值为"english",并包含"english.php"文件。
如果$lan有值,根据该值包含相应的语言文件。
使用file_get_contents函数获取名为index.php的文件的内容,并将其赋值给变量$x。
最后,使用echo语句将变量$x的内容输出。
分析到这里方法就明确了,通过cookie传入文件包含的payload,就会执行
display_errors
display_errors是PHP配置选项之一,用于控制是否在页面上显示错误信息。
当display_errors配置参数被设置为On时,PHP会在页面上显示运行时错误信息。这对于开发和调试阶段非常有用,可以实时查看代码中的错误,并及时进行修复。
当display_errors配置参数被设置为Off时(或者未设置),PHP将禁止在页面上显示错误信息。这在生产环境中是一种常见的配置,以防止敏感信息暴露给用户或潜在的安全风险。
解题步骤
首先我们通过burp抓包,修改cookie值传入payload,这里尝试传入filter伪协议读取源码
发现可以读取,抓包后是没有Cookie字段的,记得插入Cookie的位置不要处于数据包最后,反正我会请求超时
解密后直接获得了flag
fileclude
代码审计
依旧很简单的哦
<?php
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET["file1"]) && isset($_GET["file2"]))
{
$file1 = $_GET["file1"];
$file2 = $_GET["file2"];
if(!empty($file1) && !empty($file2))
{
if(file_get_contents($file2) === "hello ctf")
{
include($file1);
}
}
else
die("NONONO");
}
首先包含flag文件
然后检测GET传参的file和fil2是否存在
如果存在就分别对变量进行赋值
如果变量都不为空,并且打开file2后的值等于hello ctf,就包含file1
直接这样构造file2,触发报错说没有找到目录或文件,有点傻的
突然想要file_get_contents函数是打开文件读取的,所以我们这里需要利用php的data伪协议写入数据
不行,虽然没有报错,但是没有回显数据,我语句没错吧
那就使用input方法写入文件吧
也不行,无语了没有报错说明其实写入了呀,为啥读不出来,检查了很多遍filter命令也没错
最后是因为,第一次传参的时候加了引号闭合,导致传入不成功
?file1=php://filter/convert.base64-encode/resource=flag.php&file2=data://text//plain,hello ctf
解码后获得flag
file_include
打开环境是一串源代码,这个题看着就可以直接利用filter伪协议进行查看check.php的数据
<?php
highlight_file(__FILE__);
include("./check.php");
if(isset($_GET['filename'])){
$filename = $_GET['filename'];
include($filename);
}
?>
本来以为都做完了,结果给我来个报错回显
看来有过滤,因为我没有对应字典,所以我是一段一段测试的
最终测试下来对read、base、encode等其他没测出来的字符进行了过滤
起码从先在看来传统的filter伪协议是不能使用了
在查看wp的时候得知了filter方法有两种在这可用的转换器:string和我们这里的convert
官方解释
可惜string也被过滤掉了,所以我们可以使用convert
convert转换过滤器
主要含有三类,分别是base64的编码转换、quoted-printable的编码转换以及iconv字符编码的转换。该类过滤器以convert开头。
我们这里可以已使用iconv方式(方式的含义是:将一个字符编码转换为另外一个字符编码)
语法:
convert.iconv.<input-encoding>.<output-encoding>
或者
convert.iconv.<input-encoding>/<output-encoding>
以下的copy的字符,原文链接
该 PHP 扩展支持的字符编码有以下几种:
UCS-4*
UCS-4BE
UCS-4LE*
UCS-2
UCS-2BE
UCS-2LE
UTF-32*
UTF-32BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*
EUC-JP*
SJIS*
eucJP-win*
SJIS-win*
ISO-2022-JP
ISO-2022-JP-MS
CP932
CP51932
SJIS-mac(别名:MacJapanese)
SJIS-Mobile#DOCOMO(别名:SJIS-DOCOMO)
SJIS-Mobile#KDDI(别名:SJIS-KDDI)
SJIS-Mobile#SOFTBANK(别名:SJIS-SOFTBANK)
UTF-8-Mobile#DOCOMO(别名:UTF-8-DOCOMO)
UTF-8-Mobile#KDDI-A
UTF-8-Mobile#KDDI-B(别名:UTF-8-KDDI)
UTF-8-Mobile#SOFTBANK(别名:UTF-8-SOFTBANK)
ISO-2022-JP-MOBILE#KDDI(别名:ISO-2022-JP-KDDI)
JIS
JIS-ms
CP50220
CP50220raw
CP50221
CP50222
ISO-8859-1*
ISO-8859-2*
ISO-8859-3*
ISO-8859-4*
ISO-8859-5*
ISO-8859-6*
ISO-8859-7*
ISO-8859-8*
ISO-8859-9*
ISO-8859-10*
ISO-8859-13*
ISO-8859-14*
ISO-8859-15*
ISO-8859-16*
byte2be
byte2le
byte4be
byte4le
BASE64
HTML-ENTITIES(别名:HTML)
7bit
8bit
EUC-CN*
CP936
GB18030
HZ
EUC-TW*
CP950
BIG-5*
EUC-KR*
UHC(别名:CP949)
ISO-2022-KR
Windows-1251(别名:CP1251)
Windows-1252(别名:CP1252)
CP866(别名:IBM866)
KOI8-R*
KOI8-U*
ArmSCII-8(别名:ArmSCII8)
那很显然我们可以直接利用burp抓包进行爆破
最终发现length为2216的基本都可以回显数据
显示的是一串源码,里面记录了注入的正则限制,就没了
<?php
if($_GET["filename"]){
$preg_match_username = 'return preg_match("/base|be|encode|print|zlib|quoted|write|rot13|read|string/i", $_GET["filename"]);';
if (eval($preg_match_username)) {
die("do not hack!");
}
}
可以尝试一下flag.php
成功回显flag字段