java.lang.security.insecure-jms-deserialization.insecure-jms-deserialization

profile photo of returntocorpreturntocorp
Author
5,552
Download Count*

JMS Object messages depend on Java Serialization for marshalling/unmarshalling of the message payload when ObjectMessage.getObject() is called. Deserialization of untrusted data can lead to security flaws; a remote attacker could via a crafted JMS ObjectMessage to execute arbitrary code with the permissions of the application listening/consuming JMS Messages. In this case, the JMS MessageListener consume an ObjectMessage type received inside the onMessage method, which may lead to arbitrary code execution when calling the $Y.getObject method.

Run Locally

Run in CI

Defintion

rules:
  - id: insecure-jms-deserialization
    severity: WARNING
    languages:
      - java
    metadata:
      cwe:
        - "CWE-502: Deserialization of Untrusted Data"
      owasp:
        - A08:2017 - Insecure Deserialization
        - A08:2021 - Software and Data Integrity Failures
      asvs:
        section: V5 Validation, Sanitization and Encoding
        control_id: 5.5.3 Insecue Deserialization
        control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v55-deserialization-prevention
        version: "4"
      references:
        - https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities-wp.pdf
      category: security
      technology:
        - java
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: LOW
      impact: MEDIUM
      confidence: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    message: JMS Object messages depend on Java Serialization for
      marshalling/unmarshalling of the message payload when
      ObjectMessage.getObject() is called. Deserialization of untrusted data can
      lead to security flaws; a remote attacker could via a crafted JMS
      ObjectMessage to execute arbitrary code with the permissions of the
      application listening/consuming JMS Messages. In this case, the JMS
      MessageListener consume an ObjectMessage type received inside the
      onMessage method, which may lead to arbitrary code execution when calling
      the $Y.getObject method.
    patterns:
      - pattern-inside: |
          public class $JMS_LISTENER implements MessageListener {
            ...
            public void onMessage(Message $JMS_MSG) {
                ...
            }
          }
      - pattern-either:
          - pattern-inside: $X = $Y.getObject(...);
          - pattern-inside: $X = ($Z) $Y.getObject(...);

Examples

insecure-jms-deserialization.java

package com.rands.couponproject.ejb;

import java.util.Date;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;

import org.apache.log4j.Logger;

import com.rands.couponproject.jpa.Income;

/**
 * Message-Driven Bean implementation class for: IncomeConsumerBean
 */
@MessageDriven(activationConfig = {
        @ActivationConfigProperty(
        propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(
        propertyName = "destination", propertyValue = "java:/jms/queue/MyQueue")
        })
public class IncomeConsumerBean implements MessageListener {

    static Logger logger = Logger.getLogger(IncomeConsumerBean.class);

    @EJB
    IncomeServiceBean isb;

    /**
     * Default constructor.
     */
    public IncomeConsumerBean() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see MessageListener#onMessage(Message)
     */
    public void onMessage(Message message) {
        try {
            if (message instanceof TextMessage) {
                logger.info("onMessage received a TextMessage at " + new Date());
                TextMessage msg = (TextMessage) message;
                logger.warn("onMessage ignoring TextMessage : " + msg.getText());
            } else if (message instanceof ObjectMessage) {
                logger.info("onMessage received an ObjectMessage at " + new Date());

                ObjectMessage msg = (ObjectMessage) message;

                // ruleid: insecure-jms-deserialization
                Object o = msg.getObject(); // variant 1 : calling getObject method directly on an ObjectMessage object
                logger.info("o=" + o);

                // ruleid: insecure-jms-deserialization
                Income income = (Income) msg.getObject(); // variant 2 : calling getObject method and casting to a custom class
                logger.info("Message is : " + income);

                isb.StoreIncome(income);
            } else {
                logger.error("onMessage received an invalid message type");
            }

        } catch (JMSException e) {
            logger.error("onMessage failed : " + e.toString());
        }
    }


}