javascript.apollo.security.apollo-axios-ssrf.apollo-axios-ssrf

profile photo of semgrepsemgrep
Author
742
Download Count*

User-controllable argument $DATAVAL to $METHOD passed to Axios via internal handler $INNERFUNC. This could be a server-side request forgery. A user could call a restricted API or leak internal headers to an unauthorized party. Validate your user arguments against an allowlist of known URLs, or consider refactoring so that user-controlled data is not necessary.

Run Locally

Run in CI

Defintion

rules:
  - id: apollo-axios-ssrf
    message: User-controllable argument $DATAVAL to $METHOD passed to Axios via
      internal handler $INNERFUNC. This could be a server-side request forgery.
      A user could call a restricted API or leak internal headers to an
      unauthorized party. Validate your user arguments against an allowlist of
      known URLs, or consider refactoring so that user-controlled data is not
      necessary.
    metadata:
      owasp:
        - A10:2021 - Server-Side Request Forgery (SSRF)
      cwe:
        - "CWE-918: Server-Side Request Forgery (SSRF)"
      category: security
      technology:
        - apollo
        - axios
      references:
        - https://www.cvedetails.com/cve/CVE-2020-28168/
        - https://owasp.org/www-community/attacks/Server_Side_Request_Forgery
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - audit
      likelihood: LOW
      impact: MEDIUM
      confidence: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Server-Side Request Forgery (SSRF)
    languages:
      - javascript
    severity: WARNING
    patterns:
      - pattern: const $RESPONSE = await axios.request($INNERARG,...)
      - pattern-inside: |
          Query: {
            $METHOD(parent, args, context, info) {
              ...
              $DATA = args.$DATAVAL
              ...
              async function $INNERFUNC(...,$INNERARG,...){
                ...
              }
              ...
              return $INNERFUNC(...,$DATA,...)
              }
            }

Examples

apollo-axios-ssrf.jsx

module.exports = {
    Query: {
        requestStatus(parent, args, context, info)
        {
            url = args.url
            const axios = require('axios');

            axios({
                method: 'GET'
            })
            console.log(url)
            async function getStatus(url) {
                try {
                  // ruleid: apollo-axios-ssrf
                  const response = await axios.request(url);
                  console.log(response);
                  var s = response.status;
                } catch (error) {
                  console.error(error);
                  var s = error.code;
                }
                return s;
              }
            return getStatus(url);

        },

        requestResponse(parent, args, context, info)
        {
            url = args.url
            verb = args.verb
            payload = args.payload
            const axios = require('axios');
            if (payload !== null || payload !== "") {
                axios({
                    method: verb,
                    data: payload,
                    headers: {
                        'Content-Type': 'application/json'
                    }
                })
            }
            else {
                axios({
                    method: verb
                })
            }

            console.log(url)
            console.log(payload)

            async function getResponse(url) {
                try {
                    // ruleid: apollo-axios-ssrf
                    const response = await axios.request(url);
                    console.log(response);
                    var s = response.status;
                } catch (error) {
                    console.error(error);
                    var s = error.message;
                }
                return s;
            }


            async function getResponseWithPayload(url, payload) {
                try {
                  // ruleid: apollo-axios-ssrf
                  const response = await axios.request(url);
                  console.log(response);
                  var s = response.status;
                } catch (error) {
                  console.error(error);
                  var s = error.message;
                }
                return s;
            }

            if (payload !== null || payload !== "") {
                return getResponse(url);
            }
            else {
                return getResponseWithPayload(url, payload)
            }

        }

      }
  };