package com.nvarghese.beowulf.sfe.webtest.tm.injection; import org.bson.types.ObjectId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.nvarghese.beowulf.common.http.txn.AbstractHttpTransaction; import com.nvarghese.beowulf.common.http.txn.HttpTxnDAO; import com.nvarghese.beowulf.common.http.txn.HttpTxnDocument; import com.nvarghese.beowulf.common.scan.dao.ReportIssueDAO; import com.nvarghese.beowulf.common.scan.model.ReportIssueDocument; import com.nvarghese.beowulf.common.scan.model.ReportIssueVariantDocument; import com.nvarghese.beowulf.common.webtest.ReportThreatType; import com.nvarghese.beowulf.common.webtest.ThreatSeverityType; import com.nvarghese.beowulf.sfe.webtest.library.SqlInjectionLibrary; import com.nvarghese.beowulf.sfe.webtest.tm.AbstractTestModule; import com.nvarghese.beowulf.sfe.webtest.types.HttpQueryParameterTestType; public class SingleQuoteSQLInjection extends AbstractTestModule implements HttpQueryParameterTestType { static Logger logger = LoggerFactory.getLogger(SingleQuoteSQLInjection.class); @Override public void testByQueryParameter(ObjectId txnObjId, String parameterName) { logger.info("Running the SingleQuoteSQLInjection module for the txnObjId: {} with data store: {}", txnObjId.toString(), scanInstanceDataStore .getDB().getName()); HttpTxnDAO txnDAO = new HttpTxnDAO(scanInstanceDataStore); HttpTxnDocument httpTxnDocument = txnDAO.getHttpTxnDocument(txnObjId); if (httpTxnDocument == null) return; AbstractHttpTransaction transaction = AbstractHttpTransaction.getObject(httpTxnDocument); AbstractHttpTransaction testTransaction = AbstractHttpTransaction.clone(httpTxnDocument); String paramValue = transaction.getQueryParamater(parameterName); testTransaction.addQueryParameter(parameterName, paramValue + "'"); testTransaction.execute(); String platform = null; String bodyText = testTransaction.getResponseBodyAsString(); bodyText = bodyText.replaceAll("\\s++", " "); platform = SqlInjectionLibrary.findSQLErrorMessages(bodyText); if (platform != null) { txnDAO.createHttpTxnDocument(testTransaction.toHttpTxnDocument()); recordFinding(transaction, testTransaction, parameterName, platform, bodyText); } } private void recordFinding(AbstractHttpTransaction transaction, AbstractHttpTransaction testTransaction, String parameterName, String platform, String bodyText) { String uri = testTransaction.getURI().toString(); ReportIssueDAO issueDAO = new ReportIssueDAO(scanInstanceDataStore); ReportIssueDocument reportIssueDocument = issueDAO.findByUrlAndThreatTypeAndModuleNumber(uri, ReportThreatType.SQL_INJ, moduleNumber, false); if (reportIssueDocument == null) { reportIssueDocument = new ReportIssueDocument(); reportIssueDocument.setThreatSeverityType(ThreatSeverityType.HIGH); reportIssueDocument.setThreatType(ReportThreatType.SQL_INJ); reportIssueDocument.setIssueUrl(uri); reportIssueDocument.setModuleName(moduleName); reportIssueDocument.setModuleNumber(moduleNumber); // reasoning reportIssueDocument.setReasoning("The application responded with known SQL Error " + "messages to specially crafted test request."); // remediation reportIssueDocument.setRemediation("Sanitize user input from special characters with proper validation " + "on client and server side"); // references reportIssueDocument.setReferences("OWASP - http://www.owasp.org/index.php/SQL_Injection"); issueDAO.createReportIssueDocument(reportIssueDocument); } // set issue variant ReportIssueVariantDocument issueVariant = new ReportIssueVariantDocument(); String description = "When a single quote (') was appended to the parameter listed below, " + "a SQL error message was returned. This could indicate a SQL injection " + "vulnerability. This attack may compromise the integrity of your " + "database and/or expose sensitive information"; description += "</br>"; description += "SQL Injection detected with the following details:"; description += "</br>"; description += "  URL: " + transaction.getResourcePath() + transaction.getResourceName(); description += "  Parameter name: " + parameterName; description += "  Platform: " + platform; issueVariant.setDescription(description); issueVariant.setOrigicalTxn(transaction.getObjId()); issueVariant.setTestTxn(testTransaction.getObjId()); issueDAO.addReportIssueVariants(reportIssueDocument.getId(), issueVariant); } }