虽然到目前为止还不是很理解这一题,但是记录下便于以后回溯
这一关主要就是要会看PHP
代码,理解PHP
的一些函数
来人,上代码! 原题地址
(注释部分是我的个人理解,如果有误,希望大佬点出指导,蟹蟹!)
<?php
header("Content-type: text/html; charset=utf-8");
// 这一部分应该是在网页上使php代码高亮,与解题无关
if (isset($_GET['view-source'])) { // 表单域的名称会自动成为 $_GET 数组中的键
show_source(__FILE__);
exit();
}
// 插入文件
include('flag.php');
// 设置$smile的初始值
$smile = 1;
// 下面是一些正则表达式,用于判断$_GET['^_^']是否符合标准
// 格式:preg_match('/pattern/',subject)
if (!isset ($_GET['^_^'])) $smile = 0;
if (preg_match ('/\./', $_GET['^_^'])) $smile = 0;
if (preg_match ('/%/', $_GET['^_^'])) $smile = 0;
if (preg_match ('/[0-9]/', $_GET['^_^'])) $smile = 0;
if (preg_match ('/http/', $_GET['^_^']) ) $smile = 0;
if (preg_match ('/https/', $_GET['^_^']) ) $smile = 0;
if (preg_match ('/ftp/', $_GET['^_^'])) $smile = 0;
if (preg_match ('/telnet/', $_GET['^_^'])) $smile = 0;
if (preg_match ('/_/', $_SERVER['QUERY_STRING'])) $smile = 0;
// 当$_GET['^_^']和$_SERVER['QUERY_STRING']都满足正则表达式
// 进行以下的操作
// 确定$_GET['^_^']不是一个文件,类似file:///C:\Users\huawei\Desktop\002.txt
if ($smile) {
if (@file_exists ($_GET['^_^'])) $smile = 0;
}
// 我的理解是到这里就基本上排除了file、http、https、telnet、ftp的伪协议
// 下面为本题的关键
// 获取变量"^_^"的值,赋给$smile
// 如果$smile的值等于"(●'◡'●)",则会显示flag
// 就要使用data://text/plain;charset=unicode,<data>的为协议类型
if ($smile) {
$smile = @file_get_contents ($_GET['^_^']);
if ($smile === "(●'◡'●)") die($flag);
}
?>
最后的flag网址为
(●'◡'●)
的URL编码为(%E2%97%8F%27%E2%97%A1%27%E2%97%8F)
就是在原先的网址后面添加一个变量代码
我纳闷为什么不能直接写一个^.^=(%E2%97%8F%27%E2%97%A1%27%E2%97%8F)
变量,而要多加data://
的伪协议形式
直到我看到了这一行代码
file_get_contents ($_GET['^_^']);
- file_get_contents()用于将整个文件读入一个字符串
- 也就导致要使用伪协议
- file://不能使用,就使用data://形式
贴出一些非常好的参考文章供阅读:
最后,本人处于入门级别,难免会有一些理解错的地方,希望读者能指点出本文的不足之处
(我相信过一两年我再看这篇文章时,会发现这篇文章的不足之处)