java.lang.security.audit.tainted-session-from-http-request.tainted-session-from-http-request

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Detected input from a HTTPServletRequest going into a session command, like setAttribute. User input into such a command could lead to an attacker inputting malicious code into your session parameters, blurring the line between what's trusted and untrusted, and therefore leading to a trust boundary violation. This could lead to programmers trusting unvalidated data. Instead, thoroughly sanitize user input before passing it into such function calls.

Run Locally

Run in CI

Defintion

rules:
  - id: tainted-session-from-http-request
    message: Detected input from a HTTPServletRequest going into a session command,
      like `setAttribute`. User input into such a command could lead to an
      attacker inputting malicious code into your session parameters, blurring
      the line between what's trusted and untrusted, and therefore leading to a
      trust boundary violation. This could lead to programmers trusting
      unvalidated data. Instead, thoroughly sanitize user input before passing
      it into such function calls.
    languages:
      - java
    severity: WARNING
    mode: taint
    pattern-sources:
      - patterns:
          - pattern-either:
              - patterns:
                  - pattern: |
                      (HttpServletRequest $REQ).$FUNC(...)
                  - pattern-not: |
                      (HttpServletRequest $REQ).getSession()
              - patterns:
                  - pattern-inside: >
                      (javax.servlet.http.Cookie[] $COOKIES) =
                      (HttpServletRequest $REQ).getCookies(...);

                      ...

                      for (javax.servlet.http.Cookie $COOKIE: $COOKIES) {
                        ...
                      }
                  - pattern: |
                      $COOKIE.getValue(...)
              - patterns:
                  - pattern-inside: |
                      $TYPE[] $VALS = (HttpServletRequest $REQ).$GETFUNC(... );
                      ...
                  - pattern: |
                      $PARAM = $VALS[$INDEX];
              - patterns:
                  - pattern-inside: |
                      $HEADERS = (HttpServletRequest $REQ).getHeaders(...);
                      ...
                      $PARAM = $HEADERS.$FUNC(...);
                      ...
                  - pattern: |
                      java.net.URLDecoder.decode($PARAM, ...)
    pattern-sinks:
      - patterns:
          - pattern: (HttpServletRequest $REQ).getSession().$FUNC($NAME, $VALUE);
          - metavariable-regex:
              metavariable: $FUNC
              regex: ^(putValue|setAttribute)$
          - focus-metavariable: $VALUE
    options:
      interfile: true
    metadata:
      category: security
      technology:
        - java
      cwe:
        - "CWE-501: Trust Boundary Violation"
      owasp:
        - A04:2021 - Insecure Design
      references:
        - https://owasp.org/Top10/A04_2021-Insecure_Design
      subcategory:
        - vuln
      impact: MEDIUM
      likelihood: MEDIUM
      confidence: MEDIUM
      interfile: true
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Other

Examples

tainted-session-from-http-request.java

/**
 * OWASP Benchmark v1.2
 *
 * <p>This file is part of the Open Web Application Security Project (OWASP) Benchmark Project. For
 * details, please see <a
 * href="https://owasp.org/www-project-benchmark/">https://owasp.org/www-project-benchmark/</a>.
 *
 * <p>The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation, version 2.
 *
 * <p>The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE. See the GNU General Public License for more details.
 *
 * @author Dave Wichers
 * @created 2015
 */
package org.owasp.benchmark.testcode;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(value = "/trustbound-00/BenchmarkTest00004")
public class BenchmarkTest00004 extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        javax.servlet.http.Cookie userCookie =
                new javax.servlet.http.Cookie("BenchmarkTest00004", "color");
        userCookie.setMaxAge(60 * 3); // Store cookie for 3 minutes
        userCookie.setSecure(true);
        userCookie.setPath(request.getRequestURI());
        userCookie.setDomain(new java.net.URL(request.getRequestURL().toString()).getHost());
        response.addCookie(userCookie);
        javax.servlet.RequestDispatcher rd =
                request.getRequestDispatcher("/trustbound-00/BenchmarkTest00004.html");
        rd.include(request, response);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // some code
        response.setContentType("text/html;charset=UTF-8");

        javax.servlet.http.Cookie[] theCookies = request.getCookies();

        String param = "noCookieValueSupplied";
        if (theCookies != null) {
            for (javax.servlet.http.Cookie theCookie : theCookies) {
                if (theCookie.getName().equals("BenchmarkTest00004")) {
                    param = java.net.URLDecoder.decode(theCookie.getValue(), "UTF-8");
                    break;
                }
            }
        }

        // javax.servlet.http.HttpSession.setAttribute(java.lang.String^,java.lang.Object)
        // ok: tainted-session-from-http-request
        request.getSession().setAttribute(param, "10340");

        // ruleid: tainted-session-from-http-request
        request.getSession().setAttribute("param", param);

        response.getWriter()
                .println(
                        "Item: '"
                                + org.owasp.benchmark.helpers.Utils.encodeForHTML(param)
                                + "' with value: '10340' saved in session.");
    }
}

@WebServlet(value = "/trustbound-00/BenchmarkTest00321")
public class BenchmarkTest00321 extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        String param = "";
        java.util.Enumeration<String> headers = request.getHeaders("BenchmarkTest00321");

        if (headers != null && headers.hasMoreElements()) {
            param = headers.nextElement(); // just grab first element
        }

        // URL Decode the header value since req.getHeaders() doesn't. Unlike req.getParameters().
        param = java.net.URLDecoder.decode(param, "UTF-8");

        String bar = org.owasp.esapi.ESAPI.encoder().encodeForHTML(param);

        // javax.servlet.http.HttpSession.putValue(java.lang.String^,java.lang.Object)
        // ok: tainted-session-from-http-request
        request.getSession().putValue(bar, "10340");
        // ruleid: tainted-session-from-http-request
        request.getSession().putValue(bar, bar);

        response.getWriter()
                .println(
                        "Item: '"
                                + org.owasp.benchmark.helpers.Utils.encodeForHTML(bar)
                                + "' with value: 10340 saved in session.");
    }
}

@WebServlet(value = "/trustbound-00/BenchmarkTest00004")
public class BenchmarkTest00004 extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        javax.servlet.http.Cookie userCookie =
                new javax.servlet.http.Cookie("BenchmarkTest00004", "color");
        userCookie.setMaxAge(60 * 3); // Store cookie for 3 minutes
        userCookie.setSecure(true);
        userCookie.setPath(request.getRequestURI());
        userCookie.setDomain(new java.net.URL(request.getRequestURL().toString()).getHost());
        response.addCookie(userCookie);
        javax.servlet.RequestDispatcher rd =
                request.getRequestDispatcher("/trustbound-00/BenchmarkTest00004.html");
        rd.include(request, response);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // some code
        response.setContentType("text/html;charset=UTF-8");

        javax.servlet.http.Cookie[] theCookies = request.getCookies();

        String param = "noCookieValueSupplied";
        if (theCookies != null) {
            for (javax.servlet.http.Cookie theCookie : theCookies) {
                if (theCookie.getName().equals("BenchmarkTest00004")) {
                    param = java.net.URLDecoder.decode("hello", "UTF-8");
                    break;
                }
            }
        }

        // javax.servlet.http.HttpSession.setAttribute(java.lang.String^,java.lang.Object)
        // ok: tainted-session-from-http-request
        request.getSession().setAttribute(param, "10340");

        response.getWriter()
                .println(
                        "Item: '"
                                + org.owasp.benchmark.helpers.Utils.encodeForHTML(param)
                                + "' with value: '10340' saved in session.");
    }
}