Category Archives: web application security

Good Read: What Is SAML and How Does It Work? Oauth vs SAML

Abstract

SAML stands for Security Assertion Markup Language, an open standard that passes authorization credentials from identity providers (IdPs) to service providers (SPs). Put simply, it enables secure communication between applications and allows users to gain access with a single set of credentials.

Types of SAML providers

In order for SAML to work, there needs to be an identity provider and a service provider: 

  • Identity providers authenticate users: These systems are responsible for confirming that a user is who they say are, and then sending that data (and the user’s access rights) to a service provider. Okta, Microsoft Active Directory (AD), and Microsoft Azure are all examples of identity providers.
  • Service providers authorize users: These systems use the authentication data from an identity provider to grant access to a service. Examples include Salesforce, Box, and other best-of-breed technology. 

To Read about Oauth2 vs SAML

https://www.ubisecure.com/uncategorized/difference-between-saml-and-oauth/

Read more in

https://www.okta.com/blog/2020/09/what-is-saml/

How to implement activeMQ JMS Producer in Spring-boot application?

Let’s consider a scenario where your application is deployed in clustering environment and application handles thousands of email request to handle it. To solve this problem, You could simple trigger an API endpoints and post the message to the process which sends email. This could solve the problem however when an application received 100’s message per seconds, You have to handle concurrency. You got to have a queue to handle these messages and that’s where you need JMS & ActiveMQ. ActiveMQ is implementation of JMS like any other JMS implementation (RabbitMQ, AmazonMQ etc).

As you know, Spring boot controllers do not provide concurrency.

In this post, I would like to put details how you can implement producer job to sent JMS messages. If you wish to know how to implement JMS Listener.. Read my previous post Follow below each step to implement ActiveMQ Producer JOB in your Spring boot application.

NOTES: In below code, There are a lots of ActiveMQ policies which are configured in the code listed below. These configurations are varies based on your requirement. And, Recommendation is to read actual document to understand more on these configurations.

Sample Configurations: Session.CLIENT_ACKNOWLEDGE and DeliveryMode.PERSISTENT

Maven POM.XML Dependencies

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
#Add dependencies if you have producer too in same environment.
<dependency>
   <groupId>org.apache.activemq</groupId>
   <artifactId>activemq-client</artifactId>
   <version>5.15.8</version>
</dependency>
<dependency>
	<groupId>org.apache.activemq</groupId>
	<artifactId>activemq-pool</artifactId>
	<version>5.15.8</version>
</dependency>

ActiveMQ Configuration: application.properties

activemq.packages.trusted=<Optional but for security you can configure package name where the listener is>
activemq.brokerUrl=<brokenURL>
activemq.connection.pool=5
activemq.prefetch.limit=50
#consumer
producer.user=<userName>
producer.password=<Password>
producer.queues=<Queue Name>

ActiveMQ Java Configuration File mapped with application.properties file.

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

@Service
@Configuration
public class AMQConfig {

    @Value("${activemq.packages.trusted}")
    private String trustedPackages;

    @Value("${activemq.connection.pool}")
    private String noOfConnections;

    @Value("${activemq.brokerUrl}")
    private String brokerUrl;

    @Value("${producer.user}")
    private String consumerUser;

    @Value("${producer.password}")
    private String consumerPassword;

    @Value("${producer.queues}")
    private String queues;

    @Value("${activemq.prefetch.limit}")
    private int prefetchLimit=50;

Springboot Java JMS Listener Service

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.pool.PooledConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Session;

@Component
public class ProducerJob {

    @Autowired
    AMQConfig amqConfig;

    private final Logger LOGGER = LoggerFactory.getLogger(ProducerJob.class);
  // replace with your own producer cron
    @Scheduled(cron = "${PRODUCER_JOB_CRON}")
    public void run(){
            Session producerSession = null;
            try {
                Connection producerConnection = AMQProducer.getActiveMQProducerConnection(amqConfig);
                if (producerConnection != null) {
                    producerSession = producerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
                    LOGGER.info(" Producer Job Starts. sending sample message ");
                    for (int index = 0; index < 10; index++) {
                        AMQProducer.sendMessage(producerSession, amqConfig, "{'orderno': index*100, 'type':'order', 'amount':'202'}");
                    }
                    LOGGER.info(" Job ran and queue size is: {} ",  count * 50);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (producerSession != null) {
                    try {
                        producerSession.close();
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            }
    }
}

AMQProducer.java: This file contains the code which sends message in activeMQ.

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.pool.PooledConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jms.*;

public final class AMQProducer {
    private AMQProducer(){ }

    private static final Logger LOGGER = LoggerFactory.getLogger(AMQProducer.class);

    static PooledConnectionFactory pooledConnectionFactory = null;
    static Connection producerConnection = null;

    private static PooledConnectionFactory getPooledConnectionFactory(final String brokenUrl, String userName, String password, String noOfConnections){
        final ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokenUrl);
        // Pass the username and password.
        connectionFactory.setUserName(userName);
        connectionFactory.setPassword(password);
        // Create a pooled connection factory.
        final PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
        pooledConnectionFactory.setConnectionFactory(connectionFactory);      pooledConnectionFactory.setMaxConnections(Integer.parseInt(noOfConnections));
        return pooledConnectionFactory;
    }
    public static Connection  getActiveMQProducerConnection(AMQConfig amqConfig) {
        if (pooledConnectionFactory == null) {
            LOGGER.info(" pooledConnectionFactory is null ");
            pooledConnectionFactory = getPooledConnectionFactory(amqConfig.getBrokerUrl(), amqConfig.getProducerUser(),
                    amqConfig.getProducerPassword(), amqConfig.getNoOfPooledConnections());
        }
        if (producerConnection == null){
            try {
                LOGGER.info(" producerConnection is null ");
                producerConnection = pooledConnectionFactory.createConnection();
                producerConnection.start();
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
        return producerConnection;
    }

    public static void sendMessage(Session producerSession, AMQConfig amqConfig, final String message) throws Exception{
        if (producerSession != null) {
            final Destination producerDestination = producerSession.createTopic(amqConfig.getTopics());
            final MessageProducer producer = producerSession.createProducer(producerDestination);
            producer.setDeliveryMode(DeliveryMode.PERSISTENT);
            try {
                TextMessage producerMessage = producerSession.createTextMessage(message);
                producer.send(producerMessage);
                LOGGER.info(" ******************* message sent  ******************* ");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Note: This is a working solution however there is a chance that code could throw error due to typing mistake. Reach out to me, will do my best to help you out.

References

https://activemq.apache.org/

https://activemq.apache.org/what-is-the-prefetch-limit-for

https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/getting-started-activemq.html

https://activemq.apache.org/using-apache-activemq

WebApplication Qualys Security Scanning: How to Find XPath query in HTML DOM?

When you do web application security scan, we need to do authentication of application to extend the coverage. In most of the scanning tools (i.e qualys) has chrome extension to write selenium script which could do authentication in the application.

Any login selenium script finds appropriate HTML DOM elements (login or password) and do as per script commands. In authentication security scan, One has to know how to find login form DOM fields via Selenium XPATH Query. Let’s understand basic of XPATH in selenium script.

The basic format of XPath in selenium is explained below with screen shot.

Basic Format of XPath

Syntax for XPath selenium:

XPath contains the path of the element situated at the web page. Standard XPath syntax for creating XPath is.

Xpath=//tagname[@attribute='value']

Some more basic xpath expressions:

Xpath=//input[@type='text']				
Xpath=	//label[@id='message23']
Xpath=	//input[@value='RESET']
Xpath=//*[@class='barone']
Xpath=//a[@href='http://demo.guru99.com/']
Xpath= //img[@src='//cdn.guru99.com/images/home/java.png']

WebSecurity: Importance of HTTP Headers & In-Depth Security

There is a number of HTTP response headers that you should use to increase the security of your web application. They are referred to as HTTP security headers.

Once implemented, HTTP security headers restrict modern browsers from running into easily preventable vulnerabilities. They also provide yet another, additional layer of security by helping to mitigate security vulnerabilities and prevent attacks (like XSSClickjacking, information leakage, etc.). But it is important to mention that HTTP security headers are not intended to replace proper, secure code.

HTTP STRICT TRANSPORT SECURITY

HTTP Strict Transport Security (HSTS) is a mechanism that prevents user-agents (a browser or any kind of program designed for communication with a particular server) from browsing a website via an unencrypted connection in case an encrypted connection can be established, and only using a trusted certificate.

If the request is communicated through an unencrypted channel, it can be captured and tampered with by an attacker. The attacker then can steal or modify any information transmitted between the client and the server or redirect the user to a phishing website. So, the first goal of HSTS is to ensure traffic is encrypted, so it instructs the browser to always use HTTPS instead of HTTP.

Usually, browsers allow users to ignore TLS errors and continue browsing potentially insecure websites. With HSTS enabled, the user will be unable to skip the browser warning and continue. The second important goal of HSTS is to make sure that the traffic is encrypted using a trusted and valid certificate.

When HSTS response header signals the browser that the certain domain must be requested only using HTTPS, the browser saves this domain to the HSTS list and keeps it there for the timeframe specified in max-age directive of the Strict-Transport-Security header.

There are two cases when HSTS doesn’t provide proper protection:

  • when the user hasn’t browsed to the website before and is making his very first request to this website over HTTP,
  • when existing HSTS data has already expired.

X-XSS-PROTECTION

Some modern browsers have built-in XSS protection mechanisms that can be used as an additional layer of security against Reflected XSS. The main problem with that is that all of the browsers implement built-in XSS filtering differently, so to add more control to the process and make sure that the loading of a page with the malicious content will be blocked, the X-XSS-Protection header is needed.

X-XSS-Protection header is an optional HTTP header that performs XSS filtering by defining the anti-XSS mechanism behavior: from sanitizing the page by blocking injected Javascript to preventing page rendering and reporting the violation.

By default, browsers that support XSS filtering have it enabled. Though it can be disabled, this is considered a bad practice; often, if an application requires XSS protection to be disabled in order to function properly, it is an indication that the application is quite likely vulnerable to XSS.

Please note that only using the X-XSS-Protection header will not protect your application from XSS, but this header will make an important input in your defense-in-depth strategy and make it more robust.

CONTENT-SECURITY-POLICY: X-FRAME-OPTIONS

X-Frame-Options header a defines if the webpage can be rendered inside an <iframe><frame><applet><embed> or <object> tags. Depending on the directive, this header either specifies the list of domains that can embed the webpage, or allows the page to be embedded only inside pages of the same origin, or totally prohibits embedding of a webpage.

The main purpose of the X-Frame-Options header is to protect against ClickjackingClickjacking is an attack when the vulnerable page is loaded in a frame inside the malicious page, and the users are tricked into interaction with buttons and other clickable UI elements (e.g. unknowingly clicking “likes” or downloading malicious files) of a vulnerable page without their knowledge.

Sample Code Snippet

HTTP/1.1 200 OK
Date: Thu, 21 Mar 2019 09:05:07 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: close
Cache-Control: max-age=600
Content-Security-Policy: script-src 'self' *.followcybersecurity.com 'unsafe-inline' 'unsafe-eval'  www.google-analytics.com; img-src 'self' *.followcybersecurity.com
Expires: Thu, 21 Mar 2019 09:15:06 GMT
Location: https://followcybersecurity.com
strict-transport-security: max-age=31536000
Vary: Accept-Language, Accept-Encoding
x-content-type-options: nosniff
X-Frame-Options: DENY
X-Robots-Tag: noodp
x-xss-protection: 1; mode=block  

How to implement activeMQ JMS Listener in Spring-boot application?

There are thousands use cases where application required some sort of Java Messaging service API. And, I would like to put one use case to explain the need of JMS listener.

Let’s consider a scenario where your application is deployed in clustering environment and application handles thousands of email request to handle it. To solve this problem, You could simple trigger an API endpoints and post the message to the process which sends email. This could solve the problem however when an application received 100’s message per seconds, You have to handle concurrency. You got to have a queue to handle these messages and that’s where you need JMS & ActiveMQ. ActiveMQ is implementation of JMS like any other JMS implementation (RabbitMQ, AmazonMQ etc).

As you know, Spring boot controllers do not provide concurrency.

In this post, I have assumed that application is receiving messages and you need to implement an Active MQ listener to handle those messages. Follow below each step to implement listener in your Spring boot application.

Maven POM.XML Dependencies

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
#Add dependencies if you have producer too in same environment.
<dependency>
   <groupId>org.apache.activemq</groupId>
   <artifactId>activemq-client</artifactId>
   <version>5.15.8</version>
</dependency>
<dependency>
	<groupId>org.apache.activemq</groupId>
	<artifactId>activemq-pool</artifactId>
	<version>5.15.8</version>
</dependency>

ActiveMQ Configuration: application.properties

activemq.packages.trusted=<Optional but for security you can configure package name where the listener is>
activemq.brokerUrl=<brokenURL>
activemq.connection.pool=5
activemq.maximumThreads=10
activemq.prefetch.limit=50
#consumer
consumer.user=<userName>
consumer.password=<Password>
consumer.queues=<Queue Name>

ActiveMQ Java Configuration File mapped with application.properties file.

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

@Service
@Configuration
public class AMQConfig {

    @Value("${activemq.packages.trusted}")
    private String trustedPackages;

    @Value("${activemq.connection.pool}")
    private String noOfConnections;

    @Value("${activemq.brokerUrl}")
    private String brokerUrl;

    @Value("${consumer.user}")
    private String consumerUser;

    @Value("${consumer.password}")
    private String consumerPassword;

    @Value("${consumer.queues}")
    private String queues;

    @Value("${activemq.maximumThreads}")
    private int maximumThreads = 10;

    @Value("${activemq.prefetch.limit}")
    private int prefetchLimit=50;

Springboot Java JMS Listener Service

@Component
@Configuration
@EnableJms
public class MessageConsumer {

    private static final Logger LOGGER = LoggerFactory.getLogger(MessageConsumer.class);
    @Autowired
    AMQConfig amqConfig;

    @Bean
    public ActiveMQConnectionFactory receiverActiveMQConnectionFactory() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
        connectionFactory.setBrokerURL(amqConfig.getBrokerUrl());
        connectionFactory.setUserName(amqConfig.getConsumerUser());
        connectionFactory.setPassword(amqConfig.getConsumerPassword());
        ActiveMQPrefetchPolicy activeMQPrefetchPolicy = new ActiveMQPrefetchPolicy();
       activeMQPrefetchPolicy.setQueuePrefetch(amqConfig.getPrefetchLimit());
        activeMQPrefetchPolicy.setMaximumPendingMessageLimit(amqConfig.getPrefetchLimit());

        connectionFactory.setPrefetchPolicy(activeMQPrefetchPolicy);
        return connectionFactory;
    }

    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory =new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(receiverActiveMQConnectionFactory());
        return factory;
    }

    @Bean
    public MessageReceiver receiver() {
        return new MessageReceiver();
    }
    // Stop message receiver.
    class MessageReceiver {
        private CountDownLatch latch = new CountDownLatch(1);
        public CountDownLatch getLatch() {
            return latch;
        }
        @JmsListener(destination = "${consumer.queues}")
        public void receive(String message) {
            try {
                LOGGER.info("***************** Message Received *****************");
                Thread.sleep(100);
                if (StringUtils.isNotBlank(message)) {
                    //Execute Your code here.
                  LOG.info(" Message received {}",  message);
                }
                latch.countDown();
            }catch (Exception ex){
                LOGGER.error(" error occurs while creating new thread from message receiver {}", ex.getMessage());
            }
        }
    }
}

Note: This is a working solution however there is a chance that code could throw error due to typing mistake. Reach out to me, will do my best to help you out.

References

https://activemq.apache.org/

https://activemq.apache.org/what-is-the-prefetch-limit-for

https://docs.aws.amazon.com/amazon-mq/latest/developer-guide/getting-started-activemq.html

https://activemq.apache.org/using-apache-activemq