// Path: src/main/java/burp/j2ee/CustomScanIssue.java
// public class CustomScanIssue implements IScanIssue {
// 
//     private IHttpService httpService;
//     private URL url;
//     private IHttpRequestResponse httpMessages;
//     private String name;
//     private String detail;
//     private Risk severity;
//     private String remedy;
//     private Confidence confidence = Confidence.Certain;
//     
//     public CustomScanIssue(
//             IHttpService httpService,
//             URL url,
//             IHttpRequestResponse httpMessages,
//             String name,
//             String detail,
//             String remedy,
//             Risk severity,
//             Confidence confidence) {
//         this.httpService = httpService;
//         this.url = url;
//         this.httpMessages = httpMessages;
//         this.name = "J2EEScan - " + name;
//         this.detail = detail;
//         this.remedy = remedy;
//         this.severity = severity;
//         this.confidence = confidence;
//     }      
//     
// 
//     @Override
//     public URL getUrl() {
//         return url;
//     }
// 
//     @Override
//     public String getIssueName() {
//         return name;
//     }
// 
//     @Override
//     public int getIssueType() {
//         return 0;
//     }
// 
//     @Override
//     public String getSeverity() {
//         return severity.toString();
//     }
// 
//     @Override
//     // "Certain", "Firm" or "Tentative"
//     public String getConfidence() {
//         return confidence.toString();
//     }
// 
//     @Override
//     public String getIssueBackground() {
//         return null;
//     }
// 
//     @Override
//     public String getRemediationBackground() {
//         return null;
//     }
// 
//     @Override
//     public String getIssueDetail() {
//         return detail;
//     }
// 
//     @Override
//     public String getRemediationDetail() {
//         return remedy;
//     }
// 
//     @Override
//     public IHttpRequestResponse[] getHttpMessages() {
//         return new IHttpRequestResponse[]{httpMessages};
//     }
// 
//     @Override
//     public IHttpService getHttpService() {
//         return httpService;
//     }
// 
// }
// 
// Path: src/main/java/burp/j2ee/IssuesHandler.java
// public class IssuesHandler {
//     
//         
//         /**
//          * 
//          * Verify for a specific protocol - host a specific
//          * issue has been already detected
//          * 
//          * @param callbacks IBurpExtenderCallbacks
//          * @param vulnerabilityName vulnerability to check if it's present into the issues
//          * @param protocol (http/https)
//          * @param host the hostname 
//          * 
//          */
//         public static boolean isvulnerabilityFound(IBurpExtenderCallbacks callbacks, 
//                 String vulnerabilityName,
//                 String protocol,
//                 String host) {
// 
//         IScanIssue[] allIssues;
// 
//         allIssues = callbacks.getScanIssues(protocol + "://" + host);
//         
//         for (IScanIssue a : allIssues) {
// 
//             if (a.getIssueName().contains(vulnerabilityName)) {
//                 return true;
//             }
//         }
//         
//         return false;
//     }
// }


import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import burp.IBurpExtenderCallbacks;
import burp.IHttpRequestResponse;
import burp.IHttpService;
import burp.IRequestInfo;
import burp.IResponseInfo;
import burp.j2ee.Confidence;
import burp.j2ee.CustomScanIssue;
import burp.j2ee.IssuesHandler;
import burp.j2ee.Risk;
package burp.j2ee.passive;



/**
 * This scanner try to identify a Liferay istallation on the system by analyzing the header which usually contains
 * a string relating to the current version. Some examples of these strings are:
 * - Liferay-Portal: Liferay Portal Standard Edition 5.2.3 (Augustine / Build 5203 / May 20, 2009)
 * - Liferay-Portal: Liferay Portal Community Edition 6.2.0 CE GA1 (Newton / Build 6200 / November 1, 2013)
 * - Liferay-Portal: Liferay Portal Community Edition 6.2 CE GA4 (Newton / Build 6203 / April 16, 2015)
 * - Liferay-Portal: Liferay DXP Digital Enterprise 7.0.10 GA1 (Wilberforce / Build 7010 / June 15, 2016)
 * 
 * If the header doesn't contains any string with "Liferay" the body is checked.
 * 
 * This scanner has been tested on the following Liferay versions:
 * - Portal 7.3.6-ga7
 * - Portal 7.2.0-ga1
 * - Portal 7.1.2-ga3
 * - Portal 7.0.3-ga3
 * - DXP 7.3.10-ga1
 */

public class LiferayRule implements PassiveRule {

    @Override
    public void scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse,
                     String reqBody, String respBody, IRequestInfo reqInfo, IResponseInfo respInfo,
                     String httpServerHeader, String contentTypeResponse, String xPoweredByHeader){

        List<String> strHeader = respInfo.getHeaders();
        String version = "Not determinable";
        Pattern p = Pattern.compile("Liferay\\s.*\\d\\.\\d.*"); 
        Matcher m;

        IHttpService httpService = baseRequestResponse.getHttpService();
        String host = httpService.getHost(), protocol = httpService.getProtocol();

        if (IssuesHandler.isvulnerabilityFound(callbacks,
                    "J2EEScan - Liferay detected",
                    protocol,
                    host)) {
                return;
        } 

        Iterator<String> iterator = strHeader.iterator();

        while(iterator.hasNext()){
            String s = iterator.next();

            /**
             * "liferayAUICSS" is the link id for the current theme stylesheet of Liferay, while 
             * "liferayPortalCSS" is also an id but for another stylesheet
             */
            if(s.contains("Liferay") || (!iterator.hasNext() 
                                        && respBody.contains("id=\"liferayAUICSS\"") 
                                        && respBody.contains("id=\"liferayPortalCSS\""))){
                m = p.matcher(s);
                if(m.find()){
                    version = m.group();

// Path: src/main/java/burp/j2ee/CustomScanIssue.java
// public class CustomScanIssue implements IScanIssue {
// 
//     private IHttpService httpService;
//     private URL url;
//     private IHttpRequestResponse httpMessages;
//     private String name;
//     private String detail;
//     private Risk severity;
//     private String remedy;
//     private Confidence confidence = Confidence.Certain;
//     
//     public CustomScanIssue(
//             IHttpService httpService,
//             URL url,
//             IHttpRequestResponse httpMessages,
//             String name,
//             String detail,
//             String remedy,
//             Risk severity,
//             Confidence confidence) {
//         this.httpService = httpService;
//         this.url = url;
//         this.httpMessages = httpMessages;
//         this.name = "J2EEScan - " + name;
//         this.detail = detail;
//         this.remedy = remedy;
//         this.severity = severity;
//         this.confidence = confidence;
//     }      
//     
// 
//     @Override
//     public URL getUrl() {
//         return url;
//     }
// 
//     @Override
//     public String getIssueName() {
//         return name;
//     }
// 
//     @Override
//     public int getIssueType() {
//         return 0;
//     }
// 
//     @Override
//     public String getSeverity() {
//         return severity.toString();
//     }
// 
//     @Override
//     // "Certain", "Firm" or "Tentative"
//     public String getConfidence() {
//         return confidence.toString();
//     }
// 
//     @Override
//     public String getIssueBackground() {
//         return null;
//     }
// 
//     @Override
//     public String getRemediationBackground() {
//         return null;
//     }
// 
//     @Override
//     public String getIssueDetail() {
//         return detail;
//     }
// 
//     @Override
//     public String getRemediationDetail() {
//         return remedy;
//     }
// 
//     @Override
//     public IHttpRequestResponse[] getHttpMessages() {
//         return new IHttpRequestResponse[]{httpMessages};
//     }
// 
//     @Override
//     public IHttpService getHttpService() {
//         return httpService;
//     }
// 
// }
// 
// Path: src/main/java/burp/j2ee/IssuesHandler.java
// public class IssuesHandler {
//     
//         
//         /**
//          * 
//          * Verify for a specific protocol - host a specific
//          * issue has been already detected
//          * 
//          * @param callbacks IBurpExtenderCallbacks
//          * @param vulnerabilityName vulnerability to check if it's present into the issues
//          * @param protocol (http/https)
//          * @param host the hostname 
//          * 
//          */
//         public static boolean isvulnerabilityFound(IBurpExtenderCallbacks callbacks, 
//                 String vulnerabilityName,
//                 String protocol,
//                 String host) {
// 
//         IScanIssue[] allIssues;
// 
//         allIssues = callbacks.getScanIssues(protocol + "://" + host);
//         
//         for (IScanIssue a : allIssues) {
// 
//             if (a.getIssueName().contains(vulnerabilityName)) {
//                 return true;
//             }
//         }
//         
//         return false;
//     }
// }


// Path: src/main/java/burp/j2ee/passive/LiferayRule.java
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import burp.IBurpExtenderCallbacks;
import burp.IHttpRequestResponse;
import burp.IHttpService;
import burp.IRequestInfo;
import burp.IResponseInfo;
import burp.j2ee.Confidence;
import burp.j2ee.CustomScanIssue;
import burp.j2ee.IssuesHandler;
import burp.j2ee.Risk;

package burp.j2ee.passive;



/**
 * This scanner try to identify a Liferay istallation on the system by analyzing the header which usually contains
 * a string relating to the current version. Some examples of these strings are:
 * - Liferay-Portal: Liferay Portal Standard Edition 5.2.3 (Augustine / Build 5203 / May 20, 2009)
 * - Liferay-Portal: Liferay Portal Community Edition 6.2.0 CE GA1 (Newton / Build 6200 / November 1, 2013)
 * - Liferay-Portal: Liferay Portal Community Edition 6.2 CE GA4 (Newton / Build 6203 / April 16, 2015)
 * - Liferay-Portal: Liferay DXP Digital Enterprise 7.0.10 GA1 (Wilberforce / Build 7010 / June 15, 2016)
 * 
 * If the header doesn't contains any string with "Liferay" the body is checked.
 * 
 * This scanner has been tested on the following Liferay versions:
 * - Portal 7.3.6-ga7
 * - Portal 7.2.0-ga1
 * - Portal 7.1.2-ga3
 * - Portal 7.0.3-ga3
 * - DXP 7.3.10-ga1
 */

public class LiferayRule implements PassiveRule {

    @Override
    public void scan(IBurpExtenderCallbacks callbacks, IHttpRequestResponse baseRequestResponse,
                     String reqBody, String respBody, IRequestInfo reqInfo, IResponseInfo respInfo,
                     String httpServerHeader, String contentTypeResponse, String xPoweredByHeader){

        List<String> strHeader = respInfo.getHeaders();
        String version = "Not determinable";
        Pattern p = Pattern.compile("Liferay\\s.*\\d\\.\\d.*"); 
        Matcher m;

        IHttpService httpService = baseRequestResponse.getHttpService();
        String host = httpService.getHost(), protocol = httpService.getProtocol();

        if (IssuesHandler.isvulnerabilityFound(callbacks,
                    "J2EEScan - Liferay detected",
                    protocol,
                    host)) {
                return;
        } 

        Iterator<String> iterator = strHeader.iterator();

        while(iterator.hasNext()){
            String s = iterator.next();

            /**
             * "liferayAUICSS" is the link id for the current theme stylesheet of Liferay, while 
             * "liferayPortalCSS" is also an id but for another stylesheet
             */
            if(s.contains("Liferay") || (!iterator.hasNext() 
                                        && respBody.contains("id=\"liferayAUICSS\"") 
                                        && respBody.contains("id=\"liferayPortalCSS\""))){
                m = p.matcher(s);
                if(m.find()){
                    version = m.group();

                    callbacks.addScanIssue(new CustomScanIssue(