java.lang.security.audit.crlf-injection-logs.crlf-injection-logs

Community Favorite
profile photo of semgrepsemgrep
Author
50,751
Download Count*

When data from an untrusted source is put into a logger and not neutralized correctly, an attacker could forge log entries or include malicious content.

Run Locally

Run in CI

Defintion

rules:
  - id: crlf-injection-logs
    message: When data from an untrusted source is put into a logger and not
      neutralized correctly, an attacker could forge log entries or include
      malicious content.
    metadata:
      cwe:
        - "CWE-93: Improper Neutralization of CRLF Sequences ('CRLF Injection')"
      owasp:
        - A03:2021 - Injection
      source-rule-url: https://find-sec-bugs.github.io/bugs.htm#CRLF_INJECTION_LOGS
      category: security
      technology:
        - java
      references:
        - https://owasp.org/Top10/A03_2021-Injection
      subcategory:
        - vuln
      likelihood: LOW
      impact: MEDIUM
      confidence: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Improper Validation
    severity: WARNING
    languages:
      - java
    patterns:
      - pattern-either:
          - patterns:
              - pattern-inside: |
                  class $CLASS {
                    ...
                    Logger $LOG = ...;
                    ...
                  }
              - pattern-either:
                  - pattern-inside: |
                      $X $METHOD(...,HttpServletRequest $REQ,...) {
                        ...
                      }
                  - pattern-inside: |
                      $X $METHOD(...,ServletRequest $REQ,...) {
                        ...
                      }
                  - pattern-inside: |
                      $X $METHOD(...) {
                        ...
                        HttpServletRequest $REQ = ...;
                        ...
                      }
                  - pattern-inside: |
                      $X $METHOD(...) {
                        ...
                        ServletRequest $REQ = ...;
                        ...
                      }
          - pattern-inside: |
              $X $METHOD(...) {
                ...
                Logger $LOG = ...;
                ...
                HttpServletRequest $REQ = ...;
                ...
              }
          - pattern-inside: |
              $X $METHOD(...) {
                ...
                Logger $LOG = ...;
                ...
                ServletRequest $REQ = ...;
                ...
              }
      - pattern-either:
          - pattern: |
              String $VAL = $REQ.getParameter(...);
              ...
              $LOG.$LEVEL(<... $VAL ...>);
          - pattern: |
              String $VAL = $REQ.getParameter(...);
              ...
              $LOG.log($LEVEL,<... $VAL ...>);
          - pattern: |
              $LOG.$LEVEL(<... $REQ.getParameter(...) ...>);
          - pattern: |
              $LOG.log($LEVEL,<... $REQ.getParameter(...) ...>);

Examples

crlf-injection-logs.java

package com.vogella.logger.test;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.vogella.logger.MyLogger;

public class TestLog1 {
  private final static Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // ruleid: crlf-injection-logs
        String param = request.getParameter("param");
        log.info("foo"+param+"bar");
        response.getWriter().append("Served at: ").append(request.getContextPath());
    }
}

public class TestLog2 {
  private final static Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);

  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {
      HttpServletResponse httpServletResponse = (HttpServletResponse) response;
      // ruleid: crlf-injection-logs
      String param = request.getParameter("param");
      log.log(log.getLevel(), "foo"+param);
  }
}

public class TestLog3 {
  private final static Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // ruleid: crlf-injection-logs
      log.info("foo"+request.getParameter("param"));
      response.getWriter().append("Served at: ").append(request.getContextPath());
  }
}

public class TestLog4 {
  private final static Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);

  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {
      HttpServletRequest httpServletReq = (HttpServletRequest) request;
      // ruleid: crlf-injection-logs
      String param = httpServletReq.getParameter("param");
      log.log(log.getLevel(), param);
  }
}

public class TestLog5 {

  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {
      Logger  log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
      HttpServletRequest httpServletReq = (HttpServletRequest) request;
      // ruleid: crlf-injection-logs
      String param = httpServletReq.getParameter("foo");
      log.log(log.getLevel(), param+"bar");
  }
}

public class OkTestLog1 {
  private final static NotLogger log = new NorLogger();

  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {
      HttpServletRequest httpServletReq = (HttpServletRequest) request;
      // ok: crlf-injection-logs
      String param = httpServletReq.getParameter("param");
      log.info(param);
  }
}

public class OkTestLog2 {
  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) throws IOException, ServletException {
      Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
      HttpServletRequest httpServletReq = (HttpServletRequest) request;
      // ok: crlf-injection-logs
      String param = "foobar";
      log.log(log.getLevel(), param);
  }
}