CVE-2024-1522

A Cross-Site Request Forgery (CSRF) vulnerability in the parisneo/lollms-webui project allows remote attackers to execute arbitrary code on a victim's system. The vulnerability stems from the `/execute_code` API endpoint, which does not properly validate requests, enabling an attacker to craft a malicious webpage that, when visited by a victim, submits a form to the victim's local lollms-webui instance to execute arbitrary OS commands. This issue allows attackers to take full control of the victim's system without requiring direct network access to the vulnerable application.
Configurations

No configuration.

History

16 Apr 2024, 12:15

Type Values Removed Values Added
Summary (en) The parisneo/lollms-webui does not have CSRF protections. As a result, an attacker is able to execute arbitrary OS commands via the `/execute_code` API endpoint by tricking a user into visiting a specially crafted webpage. (en) A Cross-Site Request Forgery (CSRF) vulnerability in the parisneo/lollms-webui project allows remote attackers to execute arbitrary code on a victim's system. The vulnerability stems from the `/execute_code` API endpoint, which does not properly validate requests, enabling an attacker to craft a malicious webpage that, when visited by a victim, submits a form to the victim's local lollms-webui instance to execute arbitrary OS commands. This issue allows attackers to take full control of the victim's system without requiring direct network access to the vulnerable application.

02 Apr 2024, 19:15

Type Values Removed Values Added
Summary
  • (es) Activé CORS porque tenía una interfaz de usuario de desarrollo que usa otro número de puerto y luego olvidé eliminarla. Entonces, lo que acabo de hacer es: - Primero eliminé la configuración de cors que permite a todos acceder a ella: antes: ```python sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*", ping_timeout=1200, ping_interval= 30) # Habilite CORS para cada ``` después de: ```python cert_file_path = lollms_paths.personal_certificates/"cert.pem" key_file_path = lollms_paths.personal_certificates/"key.pem" si os.path.exists(cert_file_path) y os .path.exists(key_file_path): is_https = True else: is_https = False # Crear un servidor Socket.IO sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins=config.allowed_origins+[f"https://localhost:{ config['port']}" if is_https else f"http://localhost:{config['port']}"], ping_timeout=1200, ping_interval=30) # Habilitar CORS para orígenes seleccionados ``` - Segundo, He actualizado lollms para que tenga dos modos (un modo sin cabeza y un modo ui). Y actualizó /execute_code para bloquear si el servidor no tiene cabeza o está expuesto ```python @router.post("/execute_code") async def ejecutar_code(request: Request): """ Ejecuta el código Python y devuelve la salida. : solicitud de parámetro: el objeto de solicitud HTTP. :return: una respuesta JSON con el estado de la operación. """ if lollmsElfServer.config.headless_server_mode: return {"status":False,"error":"La ejecución del código está bloqueada cuando está en ¡modo sin cabeza por razones obvias de seguridad!"} if lollmsElfServer.config.host=="0.0.0.0": return {"status":False,"error":"La ejecución del código se bloquea cuando el servidor está expuesto al exterior por razones muy obvias !"} intente: datos = (espera solicitud.json()) código = datos["código"] id_discusión = int(data.get("id_discusión","discusión_desconocida")) id_mensaje = int(data.get("id_mensaje) ","unknown_message")) language = data.get("language","python") if language=="python": ASCIIColors.info("Ejecutando código python:") ASCIIColors.amarillo(código) return ejecutar_python(código) , id_discusión, id_mensaje) if idioma=="javascript": ASCIIColors.info("Ejecutando código javascript:") ASCIIColors.amarillo(código) devuelve ejecutar_javascript(código, id_discusión, id_mensaje) si el idioma está en ["html","html5" ,"svg"]: ASCIIColors.info("Ejecutando código javascript:") ASCIIColors.amarillo(código) return ejecutar_html(código, id_discusión, id_mensaje) elif language=="latex": ASCIIColors.info("Ejecutando código latex:" ) ASCIIColors.amarillo(código) devuelve ejecutar_latex(código, id_discusión, id_mensaje) lenguaje elif en ["bash","shell","cmd","powershell"]: ASCIIColors.info("Ejecutando código de shell:") ASCIIColors. amarillo(código) devuelve ejecutar_bash(código, id_discusión, id_mensaje) idioma elif en ["sirena"]: ASCIIColors.info("Ejecutando código de sirena:") ASCIIColors.amarillo(código) devuelve ejecutar_mermaid(código, id_discusión, id_mensaje) idioma elif en ["graphviz","punto"]: ASCIIColors.info("Ejecutando código Graphviz:") ASCIIColors.amarillo(código) return ejecutar_graphviz(código, id_discusión, id_mensaje) return {"status": False, "error": " Idioma no admitido", "execution_time": 0} excepto excepción como por ejemplo: trace_exception(ex) lollmsElfServer.error(ex) return {"status":False,"error":str(ex)} ``` También agregué un opcional modo https y esperamos agregar una autenticación completa con cookies y una sesión personal, etc. Todas las actualizaciones estarán en la versión 9.1 nuevamente, muchas gracias por su trabajo. Lo haré más difícil la próxima vez, pero si encuentras más errores, sé mi invitado :)
Summary (en) I have activated the CORS because I had a development ui that uses another port number then I forgot to remove it. So what I just did is : - First removed the cors configuration that allows everyone to access it : before: ```python sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*", ping_timeout=1200, ping_interval=30) # Enable CORS for every one ``` after: ```python cert_file_path = lollms_paths.personal_certificates/"cert.pem" key_file_path = lollms_paths.personal_certificates/"key.pem" if os.path.exists(cert_file_path) and os.path.exists(key_file_path): is_https = True else: is_https = False # Create a Socket.IO server sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins=config.allowed_origins+[f"https://localhost:{config['port']}" if is_https else f"http://localhost:{config['port']}"], ping_timeout=1200, ping_interval=30) # Enable CORS for selected origins ``` - Second, I have updated lollms to have two modes (a headless mode and a ui mode). And updated the /execute_code to block if the server is headless or is exposed ```python @router.post("/execute_code") async def execute_code(request: Request): """ Executes Python code and returns the output. :param request: The HTTP request object. :return: A JSON response with the status of the operation. """ if lollmsElfServer.config.headless_server_mode: return {"status":False,"error":"Code execution is blocked when in headless mode for obvious security reasons!"} if lollmsElfServer.config.host=="0.0.0.0": return {"status":False,"error":"Code execution is blocked when the server is exposed outside for very obvipous reasons!"} try: data = (await request.json()) code = data["code"] discussion_id = int(data.get("discussion_id","unknown_discussion")) message_id = int(data.get("message_id","unknown_message")) language = data.get("language","python") if language=="python": ASCIIColors.info("Executing python code:") ASCIIColors.yellow(code) return execute_python(code, discussion_id, message_id) if language=="javascript": ASCIIColors.info("Executing javascript code:") ASCIIColors.yellow(code) return execute_javascript(code, discussion_id, message_id) if language in ["html","html5","svg"]: ASCIIColors.info("Executing javascript code:") ASCIIColors.yellow(code) return execute_html(code, discussion_id, message_id) elif language=="latex": ASCIIColors.info("Executing latex code:") ASCIIColors.yellow(code) return execute_latex(code, discussion_id, message_id) elif language in ["bash","shell","cmd","powershell"]: ASCIIColors.info("Executing shell code:") ASCIIColors.yellow(code) return execute_bash(code, discussion_id, message_id) elif language in ["mermaid"]: ASCIIColors.info("Executing mermaid code:") ASCIIColors.yellow(code) return execute_mermaid(code, discussion_id, message_id) elif language in ["graphviz","dot"]: ASCIIColors.info("Executing graphviz code:") ASCIIColors.yellow(code) return execute_graphviz(code, discussion_id, message_id) return {"status": False, "error": "Unsupported language", "execution_time": 0} except Exception as ex: trace_exception(ex) lollmsElfServer.error(ex) return {"status":False,"error":str(ex)} ``` I also added an optional https mode and looking forward to add a full authentication with cookies and a personal session etc. All updates will be in V 9.1 Again, thanks alot for your work. I will make it harder next time, but if you find more bugs, just be my guest :) (en) The parisneo/lollms-webui does not have CSRF protections. As a result, an attacker is able to execute arbitrary OS commands via the `/execute_code` API endpoint by tricking a user into visiting a specially crafted webpage.

30 Mar 2024, 18:15

Type Values Removed Values Added
New CVE

Information

Published : 2024-03-30 18:15

Updated : 2024-04-16 12:15


NVD link : CVE-2024-1522

Mitre link : CVE-2024-1522

CVE.ORG link : CVE-2024-1522


JSON object : View

Products Affected

No product.

CWE
CWE-352

Cross-Site Request Forgery (CSRF)