Skip to content

Commit

Permalink
added compatibility with GLPI 10 + added new CVE (#8)
Browse files Browse the repository at this point in the history
* add compatibility with glpi 10 + update cves

* Update GLPIScan.py

* Update Files.py

* Update Files.py

* Update Infos.py

* Delete inc/__pycache__ directory
  • Loading branch information
Edr4 authored Feb 6, 2023
1 parent bb57607 commit 0fd1499
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 11 deletions.
5 changes: 2 additions & 3 deletions GLPIScan.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def parsing():
parser = argparse.ArgumentParser(description='GLPI Vulnerability Scanner.')
parser.add_argument('-u', dest='url', metavar="url", required=True, help='URL of GLPI application')
parser.add_argument('-a', dest='allcheck', action='store_true', default=False, help='Perform allcheck')
parser.add_argument('-e', dest='exploit', action='store_true', default=False, help='Perform vunerability Check')
parser.add_argument('-c', dest='credscheck', action='store_true', default=False, help='Perform Credential Check')
parser.add_argument('-C', dest='credsfile', metavar='credsfile', help='Perform Credential Check with specific wordlist file (user:password)')
parser.add_argument('-f', dest='filescheck', action='store_true', default=False, help='Perform Files Check')
Expand All @@ -26,6 +27,7 @@ def parsing():
Config.DEBUG = args.debug
Config.GLPI_URL = args.url
Config.ALLCHECK = args.allcheck
Config.EXPLOIT = args.exploit
Config.CREDSCHECK = args.credscheck
Config.CREDSFILE = args.credsfile
Config.FILESCHECK = args.filescheck
Expand All @@ -46,11 +48,8 @@ def main():
if (Infos.UrlCheck().getInfo()):
if (Config.ALLCHECK or Config.CREDSCHECK or Config.CREDSFILE):
Credentials.CredentialsCheck().credentials()

if (Config.ALLCHECK or Config.FILESCHECK):
Files.FilesCheck().files()

if (Config.ALLCHECK or Config.PLUGINSCHECK):
Plugins.PluginsCheck().plugins()

main()
46 changes: 45 additions & 1 deletion inc/Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
COOKIE = ""

SERVER = ['/phpmyadmin',
'/adminer',
'/ocsreport',
]

Expand All @@ -51,10 +52,13 @@
'/files/_log/php-errors.log',
'/files/_log/mail.log',
'/files/_log/sql-errors.log',
'/vendor/htmlawed/htmlawed/htmLawedTest.php'

]

FOLDERS = ['/files',
'/files/_dumps',
'/files/_uploads',
'/plugins',
'/plugins_old',
]
Expand All @@ -64,6 +68,7 @@
['post-only','postonly'],
['tech','tech'],
['normal', 'normal'],
['admin', 'admin']
]

# ['URL_VERIFY', 'PLUGIN_NAME', 'PLUGIN_URL', 'PLUGIN_CLASS']
Expand Down Expand Up @@ -218,6 +223,45 @@
['GLPI', [['>=', '9.2'], ['<', '9.5.6']], 'Disclosure of GLPI and server informations in telemetry endpoint', 'https://github.com/glpi-project/glpi/releases/tag/9.5.6', 'CVE-2021-39211'],
['GLPI', [['>=', '9.1'],['<', '9.5.6']], 'Bypassable IP restriction on GLPI API using custom header injection', 'https://github.com/glpi-project/glpi/releases/tag/9.5.6', 'CVE-2021-39213'],
['Ramo', [['=', '9.4.6']], 'SQL Injection in Ramo Plugin', 'https://packetstormsecurity.com/files/166285/Baixar-GLPI-Project-9.4.6-SQL-Injection.html', 'CVE-2021-44617'],
['GLPI', [['<', '9.5.7']], 'Reflected XSS using reload button', 'https://github.com/glpi-project/glpi/commit/e9b16bc8e9b61ebb2d35b96b9c71cd25c5af9e48', 'CVE-2022-21719'],
['GLPI', [['<', '9.5.7']], 'SQL injection using custom CSS administration form', 'https://github.com/glpi-project/glpi/commit/5c3eee696b503fdf502f506b00d15cf5b324b326', 'CVE-2022-21720'],
['GLPI', [['<=', '9.5.7']], 'Reflected XSS using reload button', 'https://github.com/glpi-project/glpi/commit/e9b16bc8e9b61ebb2d35b96b9c71cd25c5af9e48', 'CVE-2022-21719'],
['GLPI', [['<', '10.0.0']], 'LDAP password exposed on source code', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-4r49-52q9-5fgr', 'CVE-2022-24867'],
['GLPI', [['>=', '0.90'],['<', '10.0.0']], 'Cross Site CSS Injection', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-p94c-8qp5-gfpx', 'CVE-2022-24869'],
['GLPI', [['<', '10.0.0']], 'XSS / open redirect via SVG file upload', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-9hg4-fpwv-gx78', 'CVE-2022-24868'],
['GLPI', [['=', '10.0.0'],['<', '10.0.1']], 'Stored XSS on Kanban', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-33g2-m556-gccr', 'CVE-2022-24876'],
['GLPI', [['=', '10.0.0'],['<', '10.0.1']], 'SQL injection on search pages', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-5w33-4wrx-8hvw', 'CVE-2022-29250'],
['GLPI', [['=', '10.0.0'],['<', '10.0.2']], 'SQL injection on login page', 'https://www.swascan.com/security-advisory-teclib-glpi/', 'CVE-2022-31061'],
['GLPI', [['<', '9.5.8']], 'SQL injection on login page', 'https://www.swascan.com/security-advisory-teclib-glpi/', 'CVE-2022-31061'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.2']], 'SQL injection with _actor parameter in assistance objects', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-9q9x-7xxh-w4cg', 'CVE-2022-31056'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.2']], 'Unauthenticated Sensitive Data Exposure on Refused Inventory Files', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-g4hm-6vfr-q3wg', 'CVE-2022-31068'],
['GLPI', [['>=', '9.5.0'],['<', '10.0.3']], 'XSS through registration API', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-jrgw-cx24-56x5', 'CVE-2022-35945'],
['GLPI', [['>=', '9.5.0'],['<','10.0.3']], 'Leak of sensitive informations through login page error', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-6mmq-x3j2-677j', 'CVE-2022-31143'],
['GLPI', [['=', '10.0.0'],['<', '10.0.3']], 'Stored XSS through global search', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-43j5-xhvj-9236', 'CVE-2022-31187'],
['GLPI', [['<', '10.0.0'],['<', '10.0.3']], 'Command injection using a third-party library script', 'https://mayfly277.github.io/posts/GLPI-htmlawed-CVE-2022-35914/', 'CVE-2022-35914'],
['GLPI', [['<', '9.5.4']], 'Command injection using a third-party library script', 'https://mayfly277.github.io/posts/GLPI-htmlawed-CVE-2022-35914/', 'CVE-2022-35914'],
['GLPI', [['>=', '0.72'],['<', '10.0.3']], 'SQL injection through plugin controller', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-92q5-pfr8-r9r2', 'CVE-2022-35946'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.03']], 'Authentication via SQL injection', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-7p3q-cffg-c8xh', 'CVE-2022-35947'],
['GLPI', [['<', '9.5.9']], 'Authentication via SQL injection', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-7p3q-cffg-c8xh', 'CVE-2022-35947'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.3']], 'Blind Server-Side Request Forgery (SSRF) in RSS feeds and planning', 'https://huntr.dev/bounties/a0788aa8-212f-4624-9086-8b7f391dddac/', 'CVE-2022-36112'],
['GLPI', [['>=', '0.70'],['<', '10.0.4']], 'Improper access to debug panel', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-6c2p-wgx9-vrjc', 'CVE-2022-39370'],
['GLPI', [['<', '10.0.4']], 'User\'s session persist after permanently deleting his account', 'https://huntr.dev/bounties/62096b15-2b7b-4de3-96d1-32754c5f9d44/', 'CVE-2022-39234'],
['GLPI', [['>=', '0.65'],['<', '10.0.4']], 'Stored XSS on login page', 'https://huntr.dev/bounties/54fc907e-6983-4c24-b249-1440aac1643c/', 'CVE-2022-39262'],
['GLPI', [['>=', '9.1'],['<', '10.0.4']], 'SQL Injection on REST API', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-cp6q-9p4x-8hr9', 'CVE-2022-39323'],
['GLPI', [['<', '10.0.4']], 'Blind Server-Side Request Forgery (SSRF) in RSS feeds and planning', 'https://huntr.dev/bounties/7a88f92b-1ee2-4ca8-9cf8-05fcf6cfe73f/', 'CVE-2022-39276'],
['GLPI', [['>=', '0.60'],['<', '10.0.4']], 'XSS in external links', 'https://huntr.dev/bounties/8e047ae1-7a7c-48e0-bee3-d1c36e52ff42/', 'CVE-2022-39277'],
['GLPI', [['>=', '0.70'],['<', '10.0.4']], 'Stored XSS in user information', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-5rj7-95qc-89h2', 'CVE-2022-39372'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.4']], 'Stored XSS through asset inventory', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-w7wc-728f-6mm8', 'CVE-2022-39371'],
['GLPI', [['>= ', '10.0.0'],['<', '10.0.4']], 'Stored XSS in entity name', 'https://huntr.dev/bounties/d3c269fc-a865-425f-89e1-15fb32e85e96/', 'CVE-2022-39373'],
['GLPI', [['>=', '0.84'],['<', '10.0.4']], 'XSS through public RSS feed', 'https://huntr.dev/bounties/b45146ef-0f1a-4de9-90be-5c4d78b34fdf/', 'CVE-2022-39375'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.6']], 'Improper input validation on emails links', 'https://huntr.dev/bounties/3557ccc4-9325-41e8-ae01-18685adcd888/', 'CVE-2022-39376'],
['GLPI', [['>=', '0.70'],['<', '9.5.12']], 'Improper input validation on emails links', 'https://huntr.dev/bounties/3557ccc4-9325-41e8-ae01-18685adcd888/', 'CVE-2022-39376'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.6']], 'XSS Stored inside Standard Interface Help Link href attribute', 'https://huntr.dev/bounties/67f2f5da-5316-4bae-96b6-b0f0d719c4bf/', 'CVE-2022-41941'],
['GLPI', [['>=', '0.70'],['<', '9.5.12']], 'XSS Stored inside Standard Interface Help Link href attribute', 'https://huntr.dev/bounties/67f2f5da-5316-4bae-96b6-b0f0d719c4bf/', 'CVE-2022-41941'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.6']], 'XSS in RSS Description Link', 'https://huntr.dev/bounties/dda8bb6d-c556-4a21-9308-43c5bf968003/', 'CVE-2023-22724'],
['GLPI', [['>=', '0.60'],['<', '9.5.12']], 'XSS on external links', 'https://huntr.dev/bounties/9976a2ed-b105-453c-8af8-2768eb1bbb87/', 'CVE-2023-22725'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.6']], 'XSS on external links', 'https://huntr.dev/bounties/9976a2ed-b105-453c-8af8-2768eb1bbb87/', 'CVE-2023-22725'],
['GLPI', [['>=', '9.4.0'],['<', '9.5.12']], 'XSS on browse views', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-352j-wr38-493c', 'CVE-2023-22722'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.6']], 'XSS on browse views', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-352j-wr38-493c', 'CVE-2023-22722'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.6']], 'Unauthorized access to inventory files', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-3ghv-p34r-5ghx', 'CVE-2023-22500'],
['GLPI', [['>=', '10.0.0'],['<', '10.0.6']], 'Unauthorized access to data export', 'https://github.com/glpi-project/glpi/security/advisories/GHSA-6565-hm87-24hf', 'CVE-2023-23610'],
]
21 changes: 15 additions & 6 deletions inc/Credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,24 @@ def checkAuthent(self, request, user):
print(chalk.white('[+] Valid user account found : ', bold=True) + chalk.red(user[0] + ':' + user[1], bold=True))

def getLoginField(self, content):
content = re.findall(r'name=\".*id=\"login_name\"', content)[0]
login = content[content.find('name="')+len('name="'):]
login = login[:login.find('"')]
firstversion = Config.VERSION.split(".")

if(int(firstversion[0]) == 0):
login = "login_name"
else:
content = re.findall(r'name="(field[a-z0-9]{14})', content)
login = content[0]
return login


def getPasswordField(self, content):
content = re.findall(r'type="password" name=\".*.id=\"login_password\"', content)[0]
password = content[content.find('name="')+len('name="'):]
password = password[:password.find('"')]
firstversion = Config.VERSION.split(".")

if(int(firstversion[0]) == 0):
password = "login_password"
else:
content = re.findall(r'name="(field[a-z0-9]{14})', content)
password = content[1]
return password

def getCSRFField(self, content):
Expand Down
20 changes: 20 additions & 0 deletions inc/Exploits.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,28 @@ def getCVE(self, CVE):
if CVE[4]:
print("\t[+] CVE: " + CVE[4])

def CVE_2022_35914(self):
if Config.DEBUG:
print("[DEBUG] GET : " + Config.SERVER_ROOT + "/vendor/htmlawed/htmlawed/htmLawedTest.php")
# data = {'sid': 'foo', 'hhook': 'exec', 'text': 'id'}
# headers = Config.HEADERS.update({"Content-Type":"application/x-www-form-urlencoded"})
# cookies = {"sid": "foo"}
r = requests.get(Config.SERVER_ROOT + "/vendor/htmlawed/htmlawed/htmLawedTest.php", verify=False, proxies=Config.PROXY, allow_redirects=False)
if (r.status_code == 200):
print(chalk.white('[+] GLPI is vulnerable to CVE-2022-35914', bold=True))
# content = r.content.decode('utf-8')
# match = re.search(r'100%;">(.*)</textarea></div><button', content)
# if match:
# print(chalk.white("[+] Result :", bold=True), match.group(1))
# else:
# print(chalk.white("[-] No result", bold=True))

def verifExploit(self, module, version):
print(chalk.white('\t[+] Looking for [', bold=True) + chalk.yellow(module, bold=True) + chalk.white('] exploits depending on version [', bold=True) + chalk.yellow(version, bold=True) + chalk.white(']', bold=True))
for CVE in Config.CVE:
if CVE[0] == module and self.verifVersion(version, CVE[1]):
self.getCVE(CVE)
if(Config.EXPLOIT or Config.ALLCHECK):
print(chalk.green('\n[+] Performing CVE-2022-35914 check', bold=True))
print(chalk.green('===================================\n', bold=True))
self.CVE_2022_35914()
3 changes: 2 additions & 1 deletion inc/Files.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def listFolder(self, folder):
for content in contents[1:]:
content = content[content.find('"')+len('"'):]
content = content[:content.find("\"")]
print(chalk.white('\t[+] : ', bold=True) + chalk.yellow(folder + content, bold=True))
print(chalk.white('\t[+] : ', bold=True) + chalk.yellow(folder + "/" + content, bold=True))

def getFile(self, file):
if Config.DEBUG:
Expand All @@ -36,6 +36,7 @@ def getServer(self, url):
if (r.status_code == 301):
print(chalk.white('[+] Interesting URL found : ', bold=True) + chalk.red(Config.SERVER_ROOT + url, bold=True))


def files(self):
print(chalk.green('\n[+] Performing default files check', bold=True))
print(chalk.green('==================================\n', bold=True))
Expand Down
27 changes: 27 additions & 0 deletions inc/Infos.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ def tryTelemetry(self):
if Config.DEBUG:
print("[DEBUG] GET : " + Config.GLPI_URL + "/ajax/telemetry.php")
r = requests.get(Config.GLPI_URL + "/ajax/telemetry.php", verify=False, proxies=Config.PROXY, headers=Config.HEADERS)

if (r.status_code == 200):
try:
content = r.content.decode('utf-8')
Config.AJAX_TELEMETRY = json.loads(content[content.find('{'):content.find('</code></pre>')])
except:
return False


def tryGetVersion(self):
if Config.DEBUG:
print("[DEBUG] GET : " + Config.GLPI_URL + "/ajax/telemetry.php")
r = requests.get(Config.GLPI_URL + "/ajax/telemetry.php", verify=False, proxies=Config.PROXY, headers=Config.HEADERS)
if (r.status_code == 200):
content = r.content.decode('utf-8')
Config.AJAX_TELEMETRY = json.loads(content[content.find('{'):content.find('</code></pre>')])
Expand All @@ -34,6 +47,18 @@ def getVersion(self, content):
version = version[:version.find(' Copyright')]
Version(version)
return version
except:
pass
try:
# Find GLPI version V10.XX.XX
r = requests.get(Config.GLPI_URL + "/public/lib/photoswipe.js.map", verify=False, proxies=Config.PROXY, headers=Config.HEADERS)
if (r.status_code == 200):
content = r.content.decode('utf-8')

first_index = content.find('glpi-')
second_index = content.find('/glpi/node_modules/', first_index)
version = content[first_index+5:second_index]
return version
except:
return False

Expand Down Expand Up @@ -61,6 +86,8 @@ def checkServer(self):
self.checkVersion()
return True
except Exception as e:
if Config.DEBUG:
print(e)
print(chalk.red('[-] ' + Config.GLPI_URL + ' seems not accessible', bold=True))
return False

Expand Down

0 comments on commit 0fd1499

Please sign in to comment.