Coordinated Disclosure Timeline
- 2023-12-06: Sent report to a maintainer’s email.
- 2024-01-04: Sent a follow up email.
- 2024-01-08: Received an answer that the fix was created.
- 2024-02-12: Sent a reminder about creating an advisory and the deadline for this report.
- 2024-02-14: Received an answer that a fix is being worked on.
-
2024-03-11: Sent a follow up email asking about when the new release with the fix will be published.
- 2024-03-13: Received an answer that the affected code will be removed in the upcoming release.
- 2024-04-08: Sent an email asking about the fix and advisory, and informed that GitHub Security Lab would like to requesting a CVE for this vulnerability.
- 2024-04-09: Received a reply with a draft advisory and that a CVE has been requested.
- 2024-04-10: Advisory is published.
Summary
Plane v0.13-dev is vulnerable to authenticated blind server-side request forgery vulnerability.
Project
makeplane/plane
Tested Version
Details
blind SSRF in jira.py (GHSL-2023-257
)
The get
function of the ServiceIssueImportSummaryEndpoint
class in apiserver/plane/api/views/importer.py takes the user-controlled cloud_hostname
GET parameter, and passes it to the jira_project_issue_summary function, which concatenates it unsafely with a URL on lines 11, 16, 21, 26 and 36 and consequently uses the URLs to make GET requests to arbitrary destinations, which leads to blind server side request forgery.
def jira_project_issue_summary(email, api_token, project_key, hostname):
try:
auth = HTTPBasicAuth(email, api_token)
headers = {"Accept": "application/json"}
issue_url = f"https://{hostname}/rest/api/3/search?jql=project={project_key} AND issuetype=Story"
issue_response = requests.request(
"GET", issue_url, headers=headers, auth=auth
).json()["total"]
module_url = f"https://{hostname}/rest/api/3/search?jql=project={project_key} AND issuetype=Epic"
module_response = requests.request(
"GET", module_url, headers=headers, auth=auth
).json()["total"]
status_url = f"https://{hostname}/rest/api/3/status/?jql=project={project_key}"
status_response = requests.request(
"GET", status_url, headers=headers, auth=auth
).json()
labels_url = f"https://{hostname}/rest/api/3/label/?jql=project={project_key}"
labels_response = requests.request(
"GET", labels_url, headers=headers, auth=auth
).json()["total"]
users_url = (
f"https://{hostname}/rest/api/3/users/search?jql=project={project_key}"
)
users_response = requests.request(
"GET", users_url, headers=headers, auth=auth
).json()
This issue was found with help of CodeQL.
Impact
This issue may lead to Information Disclosure
. The vulnerability allows for sending GET requests to arbitrary destinations using the server.
Resources
CVE
- CVE-2024-31461
Credit
This issue was discovered and reported by GHSL team member @sylwia-budzynska (Sylwia Budzynska).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2023-257
in any communication regarding this issue.