0x00 前言
决定写这篇文章是我解决了所有问题以后决定记录一下这个过程所写的,因此可能会忽略很多细节上的东西。
- 问题一:打点的时候经常会被WAF封禁IP怎么办?
- 问题二:内网的时候只想代理部分目的地址怎么办?
我想大部分人解决问题一的方案就是不断切换出口IP,使得出口地址一直改变,避免被封,而解决问题二的方案可能就是Proxifier或者Proxycap。
Proxifier是一款能够实现系统全局代理的软件,它支持的代理类型有:Http、Https、Socks4a、Socks5.
在使用Windows渗透的过程中,我经常使用Proxifier来实现进程单位的代理进行内网渗透,利用好rules就能避免系统全局流量被导入代理,流量流入内网从而暴露自己的一些信息。
以上两个问题在Windows下不是问题,我之前经常使用Kali Linux来进行渗透,自从更新版本以后,它设置系统代理需要自己写PAC文件,这一点增加了一点点学习门槛,并且好像不是那么好用。最近我使用Arch Linux已经有段时间了,并且把它安装在了我的工作机、家庭电脑上,我非常喜欢这个操作系统和这个操作系统的生态。
因此我不得不开始完全适应更多在Linux上渗透的场景,这也让我收获颇多,这篇文章就记录一下我如何学习自己搭建透明代理实现愉快的工作环境。
0x01 透明代理
什么是透明代理?
透明代理的意思是客户端根本不需要知道有代理服务器的存在,它改变你的request fields(报文),并会传送真实IP,多用于路由器的NAT转发中。
为什么要用到透明代理?
因为这样能够让我的机器“身处”在内网中,也能让我的机器在“世界上的任何角落里”。
大家都知道,在Linux下常规的内网渗透需要使用一些如:proxychains的工具实现指定的进程访问内网的资源,相当于给程序套了一层代理。
它的实现原理如下:
ProxyChains is a UNIX program, that hooks network-related libc functions in dynamically linked programs via a preloaded DLL and redirects the connections through SOCKS4a/5 or HTTP proxies.
关于LD_PRELOAD
之前有写过相关文章:Linux权限维持之LD_PRELOAD
它的缺点却是每个命令必须要在前面加上proxychains
,这样Bash shell
有时候可能不会正常工作给我们进行参数提示。
我要做的就是使用iptables
实现透明代理,让我的机器所有与目标地址相关的流量都导入socks5
代理端口。
题外话一,关闭proxychains
的输出信息可以将/etc/proxychains.conf
文件中的quiet_mode
前面的#
去除。
题外话二,设置metasploit全局代理的方法:
可以将metasploit全局变量proxies
的值进行设置来使得后续所有的流量都经过代理发出,这样能够达到内网穿透的效果。
图中演示了2层代理的设置
0x02 Linux下的iptables防火墙
iptables
是一个用户空间实用程序,它允许系统管理员配置Linux内核防火墙的IP数据包过滤器规则,这些规则实现为不同的Netfilter
模块。筛选器组织在不同的表中,这些表包含有关如何处理网络流量数据包的规则链。当前,不同的内核模块和程序用于不同的协议。iptables
适用于IPv4,ip6tables
适用于IPv6,arptables
适用于ARP,而ebtables
适用于以太网帧。
学习iptables
有一点门槛,需要对表、规则链、动作等关系有一定的了解,这里不继续铺垫,可以自行搜索关于iptables
的文章。
流量导入Socks代理
通过将规则插入到NAT
表的PREROUTING
链中,可以轻松地重定向传入流量。
例如:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
所有访问eth0网卡80端口的流量,都会被重定向到8080端口。
它不同于端口转发,REDIRECT
的--dport
端口并不会被iptables
进行监听。
0x03 实现简单的透明代理
redsocks是一个能够重定向socks代理的一款开源软件,它允许我们在系统上监听一个端口,与远程socks端口进行转换,并且支持socks5认证,这一点非常赞。后来发现还有新的redsocks一些还在维护,但旧版已经足够满足我的需要了,就没有下载。
redsocks安装
安装必备库:
- ArchLinux :
yaourt -S --noconfirm redsocks-git
- Debian :
apt install gcc libevent-dev
- CentOS :
yum install libevent-devel git gcc
编译代码:
git clone https://github.com/darkk/redsocks
cd redsocks
make
-
安装完毕后,当前目录会生成
redsocks
二进制可执行文件,把它拷贝到环境变量目录下即可,例如:/usr/bin/redsocks
-
将配置文件
redsocks.conf
拷贝至/etc/redsocks.conf
配置redsocks代理服务器
在/etc/redsocks.conf
第61行-62行是设置Socks5服务器IP和端口的:
// `ip' and `port' are IP and tcp-port of proxy-server
// You can also use hostname instead of IP, only one (random)
// address of multihomed host will be used.
ip=***;
port=***;
配置redsocks启动身份
为了避免启用端口流量重定向后数据发生回环问题,需要用iptables根据UID进行过滤redsocks
的出口流量。
添加redsocks
组与redsocks
用户:
groupadd redsocks
useradd -g redsocks redsocks
将/etc/redsocks.conf
的启动用户名和用户组进行更改:
user = redsocks;
group = redsocks;
对应的防火墙规则:
iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner redsocks -j REDSOCKS
这么做是为了把除了redsocks用户产生的流量全部经过REDSOCKS链。
0x04 打点模式-配置代理链
创建自定义规则链
iptables -t nat -N REDSOCKS
# 建立REDSOCKS链
iptables -t nat -A PREROUTING -p tcp -j REDSOCKS
# 将所有的TCP流量经过REDSOCKS链
iptables -t nat -A REDSOCKS -d <SOCKS_API_SERVER> -j RETURN
# 放行获取Socks代理的API服务器
iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
# 放行内网地址
iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
# 放行内网地址
iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
# 放行内网地址
iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
# 放行内网地址
iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
# 放行内网地址
iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-port 31338
# 将所有的TCP流量在经过REDSOCKS链后,全部重定向到31338端口。
iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner redsocks -j REDSOCKS
# 将准备流出的流量除了redsocks产生的以外,全部经过REDSOCKS链
建立一个独立的链是为了方便的清空和新建,并且还不会污染内置链的规则。
31338是redsocks的默认端口。
启动redsocks
sudo /usr/bin/redsocks -c /etc/redsocks.conf
启动redsocks后,进程的所属者会被自动更改为redsocks。
这时访问公网查看出口IP,会变成Socks5代理服务器的出口IP,实现打点模式的透明代理。
0x05 内网模式-配置代理链
内网与打点模式不同,主要是实现指定IP地址范围的代理,打点是“放哪些”,内网是“要哪些”。
iptables -t nat -N REDSOCKS
iptables -t nat -F REDSOCKS # 清空
iptables -t nat -A PREROUTING -p tcp -j REDSOCKS
iptables -t nat -A REDSOCKS -p tcp -d 10.0.0.0/8 -j REDIRECT --to-port 31338
iptables -t nat -A REDSOCKS -p tcp -d 172.0.0.0/8 -j REDIRECT --to-port 31338
iptables -t nat -A REDSOCKS -p tcp -d 192.168.0.0/16 -j REDIRECT --to-port 31338
iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner $redsocks_user -j REDSOCKS
以上防火墙规则是将以下目的地址的流量全部导入redsoks:
- 10.0.0.0/8
- 172.0.0.0/8
- 192.168.0.0/16
如果要添加专网的地址,可以手动添加:
iptables -t nat -A REDSOCKS -p tcp -d XXX.XXX.XX.XX/XX -j REDIRECT --to-port 31338
启用以上防火墙规则后,我可以不需要使用proxychains,直接可以用nmap探测端口,自定义的工具也能够像在内网一样工作,本机开的虚拟机切换到NAT模式也能够“身处”内网。
0x06 自动化实现
#!/bin/bash
redsocks_bin_path="/usr/bin/redsocks"
redsocks_config_file_path="/etc/redsocks.conf"
socks_api_url='*****'
shell_log_path="/tmp/socks-switch.log"
# ssh port
ssh_port="22"
redsocks_user="redsocks"
socks_loging(){
current_time=$(date +"%Y-%m-%d %H:%M:%S");
echo "[*] "$current_time ": " $1 >> $shell_log_path
echo "[*] "$current_time ": " $1
}
change_socks(){
local socks_ip=$1;
local socks_port=$2;
socks_loging "Change Socks: $1, Port: $2";
# 61行是Socks IP
sed -i '61d' $redsocks_config_file_path
sed -i "61i\ ip=$socks_ip;" $redsocks_config_file_path
# 62行是Socks Port
sed -i '62d' $redsocks_config_file_path
sed -i "62i\ port=$socks_port;" $redsocks_config_file_path
pkill redsocks
socks_loging "Run redsocks...."
$redsocks_bin_path -c $redsocks_config_file_path
}
start_pentest(){
uninstall_iptables
iptables -t nat -N REDSOCKS
iptables -t nat -F REDSOCKS # 清空
iptables -t nat -A PREROUTING -p tcp -j REDSOCKS
iptables -t nat -A REDSOCKS -p tcp -d 10.0.0.0/8 -j REDIRECT --to-port 31338
iptables -t nat -A REDSOCKS -p tcp -d 172.0.0.0/8 -j REDIRECT --to-port 31338
iptables -t nat -A REDSOCKS -p tcp -d 192.168.0.0/16 -j REDIRECT --to-port 31338
unset_iptables
set_iptables
local socks_ip=$1;
local socks_port=$2;
change_socks $socks_ip $socks_port
socks_loging "Change Socks: $1, Port: $2";
}
install_iptables(){
iptables -t nat -F OUTPUT
iptables -t nat -F PREROUTING
# 如果没有就新建一个
local is_redsocks=`iptables -t nat -nL --line-number |grep REDSOCKS`
if [ -z "$is_redsocks" ]; then
iptables -t nat -N REDSOCKS
fi
iptables -t nat -F REDSOCKS # 清空
iptables -t nat -A PREROUTING -p tcp -j REDSOCKS
iptables -t nat -A REDSOCKS -p tcp --dport $ssh_port -j RETURN
iptables -t nat -A REDSOCKS -d <SOCKS API Server> -j RETURN
iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-port 31338
socks_loging "Install Success!"
}
uninstall_iptables(){
iptables -t nat -F OUTPUT
iptables -t nat -F PREROUTING
socks_loging "Uninstall iptables ..."
is_redsocks=`iptables -t nat -nvL REDSOCKS |wc -l`
if [ "$is_redsocks"!="0" ]; then
iptables -t nat -F REDSOCKS
iptables -t nat -X REDSOCKS
fi
}
set_iptables(){
iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner $redsocks_user -j REDSOCKS
}
unset_iptables(){
ids=`iptables -t nat -nL OUTPUT --line-number | grep REDSOCKS | awk '{print $1}'`
if [ -z "$ids" ]; then
socks_loging "No Set Iptables ..."
return
fi
id_array=(${ids//\n/ })
socks_loging "REDSOCKS OUTPUT Chian ID : $id_array"
for id in ${id_array[@]}
do
id=`echo $id|egrep -o "[0-9]{1,4}"`
if [ $id!="" ]; then
iptables -t nat -D OUTPUT $id
fi
done
}
if [ -z "$1" ]; then
echo "[*] Usage : $0 <start | stop | clean | install | uninstall | change IP PORT | pentest IP PORT>
$0 start : 启动redsocks,自动设置iptables
$0 stop : 停止redsocks,自动清空iptables
$0 clean : 清空iptables所有规则
$0 install : 安装iptables规则
$0 uninstall : 卸载iptables规则
$0 change : 改变Socks的IP和端口
$0 pentest : 开始内网渗透,传入Socks的IP和端口
"
exit 0
fi
if [ "$1" = "install" ]; then
install_iptables
exit 0
fi
if [ "$1" = "pentest" ]; then
start_pentest $2 $3
exit 0
使用方式:
- 打点模式简单使用(每执行一次,向API拉取新的代理):
sudo ./socks-switch.sh install
sudo ./socks-switch.sh start
- 切换至内网模式使用:
sudo ./socks-switch.sh uninstall
sudo ./socks-switch.sh pentest <Socks IP> <Socks Port>
- 手动指定Socks的IP和端口(打点模式与内网模式兼容):
sudo ./socks-switch.sh change <Socks IP> <Socks Port>
0x06 树莓派实现6小时切换一次出口的WiFi
这个是我在熟悉透明代理后产生的想法,适合“团队作战”,尤其是Web渗透这块最消耗IP了,实验室的小伙伴大多也都是笔记本,因此想出了用树莓派实现6小时切换一次出口的WiFi,当然了,也能把穿透内网的Socks变成一个WiFi :)
更改redsocks监听地址
如果是多网卡需要把redsocks配置文件/etc/redsocks.conf
的监听IP地址改为:0.0.0.0,不然在wlan0
的流量转向eth0
的时候,会找不到31338端口。
local_ip = 0.0.0.0;
local_port = 31338;
安装创建AP的工具
sudo apt-get install util-linux procps hostapd iproute2 iw haveged dnsmasq
sudo git clone https://github.com/oblique/create_ap
cd create_ap
sudo make install
创建WiFi:/usr/bin/create_ap -w 2 wlan0 eth0 <WiFi Name> <WiFi Pass>
-w 为启用WPA2
编写AP服务脚本
在 /usr/lib/systemd/system/
创建wifi.service
[Unit]
Description=Create AP Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/create_ap -w 2 wlan0 eth0 <WiFi Name> <WiFi Pass>
KillSignal=SIGINT
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
编写计划任务脚本
random-wifi.sh:
#!/bin/bash
cd /home/pi/socks-switch
systemctl stop wifi # 先停止WiFi
./socks-switch.sh clean # 清空规则
./socks-switch.sh install # 安装规则
./socks-switch.sh start # 启用规则
systemctl start wifi # 创建WiFi
sudo crontab -e
进入root用户的计划任务编写:
* */6 * * * /home/pi/socks-switch/random-wifi.sh # 每隔六小时重置一次,并获取新的出口代理
待完善的缺点
比如在切换新的出口时,WiFi是关闭的,现在的客户端一般都是会自动寻找下一个WiFi自动连接的,如果工具正在扫描会导致真实出口IP被发现。
思路:在切换WiFi前,将wlan0
网卡的流量全部DROP
,这样WiFi也不需要重启。
放两张喜爱的桌面:
0x07 总结
通过动手实践,解决了工作痛点,让技术的价值发挥出来更能收获成就感。
期间还实现了科学上网的透明代理,但是与工作无关,网络上已经大把帖子了,收获颇多,关于渗透还需要研究更多,看问题的角度也要多变,就如上一篇Web正向代理的思考 ,虽说不是一个通用技术,但是能够解决一些场景的问题,提升效率。