Skip to content

Commit

Permalink
Merge pull request #125 from Ostorlab/feature/CVE_2024_9164
Browse files Browse the repository at this point in the history
Add version based detection for CVE-2024-9164
  • Loading branch information
3asm authored Oct 22, 2024
2 parents 3fee5e4 + aa6797b commit a0928a5
Show file tree
Hide file tree
Showing 2 changed files with 253 additions and 0 deletions.
165 changes: 165 additions & 0 deletions agent/exploits/cve_2024_9164.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
"""Agent Asteroid implementation for CVE-2024-9164"""

import datetime
import re
from urllib import parse as urlparse

import requests
from requests import exceptions as requests_exceptions

from agent import definitions
from agent import exploits_registry
from agent.exploits import webexploit

MAX_REDIRECTS = 2
DEFAULT_TIMEOUT = datetime.timedelta(seconds=90)

VULNERABILITY_TITLE = "Gitlab Run pipelines on arbitrary branches."
VULNERABILITY_REFERENCE = "CVE-2024-9164"
VULNERABILITY_DESCRIPTION = (
"An issue was discovered in GitLab EE affecting all versions starting from 12.5 prior to 17.2.9,"
"starting from 17.3, prior to 17.3.5, and starting from 17.4 prior to 17.4.2, which allows running pipelines on arbitrary branches."
)
RISK_RATING = "CRITICAL"

VULN_VERSIONS_HASHES = [
"eb078ffe61726e3898dc9d01ea7955809778bde5be3677d907cbd3b48854e687",
"1626b2999241b5a658bddd1446648ed0b9cc289de4cc6e10f60b39681a0683c4",
"70ce56efa7e602d4b127087b0eca064681ecdd49b57d86665da8b081da39408b",
"40d8ac21e0e120f517fbc9a798ecb5caeef5182e01b7e7997aac30213ef367b3",
"ed4780bb05c30e3c145419d06ad0ab3f48bd3004a90fb99601f40c5b6e1d90fd",
"1084266bd81c697b5268b47c76565aa86b821126a6b9fe6ea7b50f64971fc96f",
"7310c45f08c5414036292b0c4026f281a73cf8a01af82a81257dd343f378bbb5",
"473ef436c59830298a2424616d002865f17bb5a6e0334d3627affa352a4fc117",
"4448d19024d3be03b5ba550b5b02d27f41c4bdba4db950f6f0e7136d820cd9e1",
"ae0edd232df6f579e19ea52115d35977f8bdbfa9958e0aef2221d62f3a39e7d8",
"bf1c397958ee5114e8f1dadc98fa9c9d7ddb031a4c3c030fa00c315384456218",
"c923fa3e71e104d50615978c1ab9fcfccfcbada9e8df638fc27bf4d4eb72d78c",
"655ad8aea57bdaaad10ff208c7f7aa88c9af89a834c0041ffc18c928cc3eab1f",
"81c5f2c7b2c0b0abaeb59585f36904031c21b1702c24349404df52834fbd7ad3",
"30a9dffe86b597151eff49443097496f0d1014bb6695a2f69a7c97dc1c27828f",
"b50bfeb87fe7bb245b31a0423ccfd866ca974bc5943e568ce47efb4cd221d711",
"ac9b38e86b6c87bf8db038ae23da3a5f17a6c391b3a54ad1e727136141a7d4f5",
"e2578590390a9eb10cd65d130e36503fccb40b3921c65c160bb06943b2e3751a",
"015d088713b23c749d8be0118caeb21039491d9812c75c913f48d53559ab09df",
"0993beabc8d2bb9e3b8d12d24989426b909921e20e9c6a704de7a5f1dfa93c59",
"62e4cc014d9d96f9cbf443186289ffd9c41bdfe951565324891dcf38bcca5a51",
"d0850f616c5b4f09a7ff319701bce0460ffc17ca0349ad2cf7808b868688cf71",
"08858ced0ff83694fb12cf155f6d6bf450dcaae7192ea3de8383966993724290",
"4990bb27037f3d5f1bffc0625162173ad8043166a1ae5c8505aabe6384935ce2",
"6ae610d783ba9a520b82263f49d2907a52090fecb3ac37819cea12b67e6d94fb",
"27d2c4c4e2fcf6e589e3e1fe85723537333b087003aa4c1d2abcf74d5c899959",
"e355f614211d036d0b3ffac4cd76da00d89e05717df61629e82571e20ac27488",
"a624c11e908db556820e9b07de96e0a465e9be5d5e6b68cdafe6d5c95c99798b",
"515dc29796a763b500d37ec0c765957a136c9e1f1972bb52c3d7edcf4b6b8bbe",
"c91127b2698c0a2ae0103be3accffe01995b8531bf1027ae4f0a8ad099e7a209",
"383b8952f0627703ada7774dd42f3b901ea2e499fd556fce3ae0c6d604ad72b7",
"e539e07c389f60596c92b06467c735073788196fa51331255d66ff7afde5dfee",
"2ea7e9be931f24ebc2a67091b0f0ff95ba18e386f3d312545bb5caaac6c1a8be",
"5df2cb13ec314995ea43d698e888ddb240dbc7ccb6e635434dc8919eced3e25f",
"a4333a9de660b9fc4d227403f57d46ec275d6a6349a6f5bda0c9557001f87e5d",
"ff058b10a8dce9956247adba2e410a7f80010a236b2269fb53e0df5cd091e61d",
"1d765038b21c5c76ff8492561c29984f3fa5c4b8cfb3a6c7b216ac8ab18b78c7",
"301b60d2c71a595adfb65b22edee9023961c5190e1807f6db7c597675b0a61f0",
"6fa9fec63ba24ec06fcae0ec30d1369619c2c3323fe9ddc4849af86457d59eef",
"f8ba2470fbf1e30f2ce64d34705b8e6615ac964ea84163c8a6adaaf8a91f9eac",
"6eb5eaa5726150b8135a4fd09118cfd6b29f128586b7fa5019a04f1c740e9193",
"6a58066d1bde4b6e661fbd5bde83d2dd90615ab409b8c8c36e04954fbd923424",
"1ae98447c220181b7bd2dfe88018cb6e1b1e4d12d7b8c224d651a48ed2d95dfe",
"a6d68fb0380bece011b0180b2926142630414c1d7a3e268fb461c51523b63778",
"95ae8966ec1e6021f2553c7d275217fcfecd5a7f0b206151c5fb701beb7baf1e",
"1e3d7f89df5b5446401d669796adf858c6742cb23a3d41b53f51a3c312c798cc",
"1caf2b894e48f649fcfd6b20de756e07ce64c1a756b9a20ff4505caeffa1a361",
"5a73588c1bf39ca7421dff5d8a03b887f0ebcb4897d6c136dfe03fa63a11b1ad",
"0ac028d3833c573c3e7cd054219213d6b36474cb4531a251238d9fa25831d97a",
"badd1d1762b624e5c7d251e045a3b2a3693054edbcb0115eb3cc64758fa62e92",
"7ac3b54e2ee2a129462d6702c9857a04f1a405f7254b89a2b3dfc7e73e80a489",
"dac7d8befc64f632fac344ebdca56066e013a4e260c3bdfb375fcf6dd30c3c56",
"f6b592d2e7570ce5d28f3dbf7170c0b3aa19dcb951f8c9e9ebe6cd5ec44691e8",
"c19a43b56f2b869d14e8b8865f2673e99e95a3f9912c95776e2aa44d0de56416",
"e7b1efce983de69e755cecf958ad52fe9c578fee502ec2046fbe4d418e12c237",
"a727ffdf1055442288d2fbc8b2ab23c38185697594725ea899f9faa653fad748",
"fb3d9b8e0a1937690eb35bd8b7a8686b51f36226bc9c29f0ea1621d568030c1a",
"ad779fabb121ac9d0c594b996d2fddb1fee9ce36c886c73c3d0e6fe10233819b",
"106174ae025caa47e54ebda6fb32a305a86857c1a808ab1a76a697e8a286166c",
"198963a1fcb2babf24b04c7c3a57fe439f453a90e1820ef7228d23a420b137ec",
"6687cea99d08705f41c22ba6c0f625668940d80a47e99488bf0d3d4bafa9d398",
"1d30846db8d63a25cb7d1a54a8ef11af9382c4d5e95fcc6ba7c8f34f9581d51d",
"c10b409df4222d166bfe9b34b787e05a671f9116b47ee10265029bfda6c5305b",
"f79ed5a6b0dfecf39281aeefcdd5b15d7cc6d871a3ae20e60c40d6a718377704",
"7649badc780fc4e44c1b7063c6153b3c216a5f6f0d7907eed714fac2a39ede73",
"47ec6054e1998d4cb2623b09faa02993de5f7cc92d34ba60dad2646b3b92a83e",
"e357f1b1a6812a8e72a4aec06b3761062a281129d621bf2e580806a8fca6302d",
"aecafb937628c9745dc285b2cb2c41d8a57846c934c2168b0cfec35b3d44e51f",
"73616daa0479bf77369c603146e745cc4cb9874b3b38f81fb2993818049dbf1a",
"58ebcd8f96ecc2ebf7f29122395e38ee28dc833dfc6d08fb667d2655da971df6",
"05a4322b27a3352f9638610b6a2528a03f90070a19fdb9e0499bb0412aad92fb",
"1b91aa4fc5e5ae49577087b2b42821ac87b863ba4de61cdccdd6b3620f587608",
"64ec030272495820a69a90e76affc1d0c47377c80f267ed21fa039c40404d4c9",
"22918e5e48d718e0977422d6c63347ce3199ac16206c958518b968c239529900",
]

POTENTIALLY_VULN_VERSIONS_HASHES = [
"6479d7d7b19cce99a8971e85a3756ea6f1debe89b68d0a86e69cc9c6e7414d7d",
"b52d3dd3b307bb936ad862671cae67163327a698f3dc2c4f232173d621af2a87",
"6a54b783019af16f39492a7c048d885d232d3940d8e5528940d70b6a6d2d0eb0",
]


@exploits_registry.register
class CVE20249164Exploit(webexploit.WebExploit):
accept_request = definitions.Request(method="GET", path="/users/sign_in")
check_request = definitions.Request(method="GET", path="/users/sign_in")
accept_pattern = [re.compile("GitLab")]

metadata = definitions.VulnerabilityMetadata(
title=VULNERABILITY_TITLE,
description=VULNERABILITY_DESCRIPTION,
reference=VULNERABILITY_REFERENCE,
risk_rating=RISK_RATING,
)

def check(self, target: definitions.Target) -> list[definitions.Vulnerability]:
"""Rule to detect specific vulnerability on a specific target.
Args:
target: Target to scan
Returns:
List of identified vulnerabilities.
"""
session = requests.Session()
session.max_redirects = MAX_REDIRECTS
session.verify = False

target_endpoint = urlparse.urljoin(target.origin, self.check_request.path)

try:
req = requests.Request(
method=self.check_request.method,
url=target_endpoint,
data=self.check_request.data,
).prepare()
resp = session.send(req, timeout=DEFAULT_TIMEOUT.seconds, verify=False)
except requests_exceptions.RequestException:
return []

for version_hash in VULN_VERSIONS_HASHES:
pattern = re.compile(version_hash)
if pattern.search(resp.text) is not None:
vulnerability = self._create_vulnerability(target)
return [vulnerability]

for version_hash in POTENTIALLY_VULN_VERSIONS_HASHES:
pattern = re.compile(version_hash)
if pattern.search(resp.text) is not None:
self.metadata = definitions.VulnerabilityMetadata(
title=VULNERABILITY_TITLE,
description=VULNERABILITY_DESCRIPTION,
reference=VULNERABILITY_REFERENCE,
risk_rating="POTENTIALLY",
)
vulnerability = self._create_vulnerability(target)
return [vulnerability]

return []
88 changes: 88 additions & 0 deletions tests/exploits/cve_2024_9164_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""Unit tests for Agent Asteriod: CVE-2024-9164"""

import requests_mock as req_mock

from agent import definitions
from agent.exploits import cve_2024_9164


def testCVE20249164_whenVulnerable_reportFinding(
requests_mock: req_mock.mocker.Mocker,
) -> None:
"""Test exploit report finding when version is vulnerable."""
target = definitions.Target("https", "localhost", 8080)
requests_mock.get(
target.url + "users/sign_in",
status_code=200,
text="<title>Sign in · GitLab</title>"
'<link rel="preload" href="'
'/assets/application-22918e5e48d718e0977422d6c63347ce3199ac16206c958518b968c239529900.css"'
' as="style" type="text/css">',
)

exploit_instance = cve_2024_9164.CVE20249164Exploit()
accept = exploit_instance.accept(target)
vulnerabilities = exploit_instance.check(target)

assert accept is True
assert len(vulnerabilities) > 0
vulnerability = vulnerabilities[0]

assert vulnerability.entry.title == "Gitlab Run pipelines on arbitrary branches."
assert (
vulnerability.technical_detail
== "https://localhost:8080 is vulnerable to CVE-2024-9164, Gitlab Run pipelines on arbitrary branches."
)
assert vulnerability.risk_rating.name == "CRITICAL"


def testCVE20249164_whenPotentiallyVulnerable_reportFinding(
requests_mock: req_mock.mocker.Mocker,
) -> None:
"""Test exploit report finding when version is potentially vulnerable."""
target = definitions.Target("https", "localhost", 8080)
requests_mock.get(
target.url + "users/sign_in",
status_code=200,
text="<title>Sign in · GitLab</title>"
'<link rel="preload" href="'
'/assets/application-b52d3dd3b307bb936ad862671cae67163327a698f3dc2c4f232173d621af2a87.css"'
' as="style" type="text/css">',
)

exploit_instance = cve_2024_9164.CVE20249164Exploit()
accept = exploit_instance.accept(target)
vulnerabilities = exploit_instance.check(target)

assert accept is True
assert len(vulnerabilities) > 0
vulnerability = vulnerabilities[0]

assert vulnerability.entry.title == "Gitlab Run pipelines on arbitrary branches."
assert (
vulnerability.technical_detail
== "https://localhost:8080 is vulnerable to CVE-2024-9164, Gitlab Run pipelines on arbitrary branches."
)
assert vulnerability.risk_rating.name == "POTENTIALLY"


def testCVE20249164_whenNotVulnerable_reportNoFinding(
requests_mock: req_mock.mocker.Mocker,
) -> None:
"""Test exploit don't report finding."""
target = definitions.Target("https", "localhost", 8080)
requests_mock.get(
target.url + "users/sign_in",
status_code=200,
text="<title>Sign in · GitLab</title>"
'<link rel="preload" href="'
'/assets/application-8276cea79ef526c83539dd54f72382f170a49fbe45332e2f2c132a38880e38ff.css"'
' as="style" type="text/css">',
)

exploit_instance = cve_2024_9164.CVE20249164Exploit()
accept = exploit_instance.accept(target)
vulnerabilities = exploit_instance.check(target)

assert accept is True
assert len(vulnerabilities) == 0

0 comments on commit a0928a5

Please sign in to comment.