Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions addOns/ascanrules/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- SQL Injection - MsSQL
- SQL Injection - MySQL
- SQL Injection - Hypersonic
- SQL Injection - PostgreSQL

### Added
- Rules (as applicable) have been tagged in relation to HIPAA and PCI DSS.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.net.SocketException;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.configuration.ConversionException;
Expand All @@ -42,11 +41,11 @@
import org.zaproxy.zap.model.TechSet;

/**
* The SqlInjectionPostgreScanRule identifies Postgresql specific SQL Injection vulnerabilities
* using Postgresql specific syntax. If it doesn't use Postgresql specific syntax, it belongs in the
* generic SQLInjection class! Note the ordering of checks, for efficiency is : 1) Error based (N/A)
* 2) Boolean Based (N/A - uses standard syntax) 3) UNION based (N/A - uses standard syntax) 4)
* Stacked (N/A - uses standard syntax) 5) Blind/Time Based (Yes)
* This scan rule identifies Postgresql specific SQL Injection vulnerabilities using Postgresql
* specific syntax. If it doesn't use Postgresql specific syntax, it belongs in the generic
* SQLInjection class! Note the ordering of checks, for efficiency is : 1) Error based (N/A) 2)
* Boolean Based (N/A - uses standard syntax) 3) UNION based (N/A - uses standard syntax) 4) Stacked
* (N/A - uses standard syntax) 5) Blind/Time Based (Yes)
*
* <p>See the following for some great specific tricks which could be integrated here
* http://www.websec.ca/kb/sql_injection
Expand All @@ -60,11 +59,9 @@
*
* @author 70pointer
*/
public class SqlInjectionPostgreScanRule extends AbstractAppParamPlugin
public class SqlInjectionPostgreSqlTimingScanRule extends AbstractAppParamPlugin
implements CommonActiveScanRuleInfo {

private boolean doTimeBased = false;

private int doTimeMaxRequests = 0;

private int sleepInSeconds;
Expand All @@ -80,23 +77,6 @@ public class SqlInjectionPostgreScanRule extends AbstractAppParamPlugin
private static final double TIME_CORRELATION_ERROR_RANGE = 0.15;
private static final double TIME_SLOPE_ERROR_RANGE = 0.30;

/**
* create a map of SQL related error message fragments, and map them back to the RDBMS that they
* are associated with keep the ordering the same as the order in which the values are inserted,
* to allow the more (subjectively judged) common cases to be tested first Note: these should
* represent actual (driver level) error messages for things like syntax error, otherwise we are
* simply guessing that the string should/might occur.
*/
private static final Map<String, String> SQL_ERROR_TO_DBMS = new LinkedHashMap<>();

static {
SQL_ERROR_TO_DBMS.put("org.postgresql.util.PSQLException", "PostgreSQL");
SQL_ERROR_TO_DBMS.put("org.postgresql", "PostgreSQL");
// Note: only Postgresql mappings here.
// TODO: is this all?? we need more error messages for Postgresql for different languages.
// PHP, ASP, JSP(JDBC), etc.
}

/**
* The sleep function in Postgresql cast it back to an int, so we can use it in nested select
* statements and stuff.
Expand Down Expand Up @@ -209,7 +189,8 @@ public class SqlInjectionPostgreScanRule extends AbstractAppParamPlugin
}

/** for logging. */
private static final Logger LOGGER = LogManager.getLogger(SqlInjectionPostgreScanRule.class);
private static final Logger LOGGER =
LogManager.getLogger(SqlInjectionPostgreSqlTimingScanRule.class);

@Override
public int getId() {
Expand Down Expand Up @@ -252,16 +233,12 @@ public void init() {

// set up what we are allowed to do, depending on the attack strength that was set.
if (this.getAttackStrength() == AttackStrength.LOW) {
doTimeBased = true;
doTimeMaxRequests = 3;
} else if (this.getAttackStrength() == AttackStrength.MEDIUM) {
doTimeBased = true;
doTimeMaxRequests = 5;
} else if (this.getAttackStrength() == AttackStrength.HIGH) {
doTimeBased = true;
doTimeMaxRequests = 10;
} else if (this.getAttackStrength() == AttackStrength.INSANE) {
doTimeBased = true;
doTimeMaxRequests = 100;
}
// Read the sleep value from the configs
Expand Down Expand Up @@ -289,7 +266,6 @@ public void scan(HttpMessage originalMessage, String paramName, String paramValu
int countTimeBasedRequests = 0;
for (int timeBasedSQLindex = 0;
timeBasedSQLindex < SQL_POSTGRES_TIME_REPLACEMENTS.length
&& doTimeBased
&& countTimeBasedRequests < doTimeMaxRequests;
timeBasedSQLindex++) {
countTimeBasedRequests++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ <H2 id="id-40022">SQL Injection - PostgreSQL (Time Based)</H2>
<br>
Post 2.5.0 you can change the length of time used for the attack by changing the <code>rules.common.sleep</code> parameter via the Options 'Rule configuration' panel.
<p>
Latest code: <a href="https://github.com/zaproxy/zap-extensions/blob/main/addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionPostgreScanRule.java">SqlInjectionPostgreScanRule.java</a>
Latest code: <a href="https://github.com/zaproxy/zap-extensions/blob/main/addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionPostgreSqlTimingScanRule.java">SqlInjectionPostgreSqlTimingScanRule.java</a>
<br>
Alert ID: <a href="https://www.zaproxy.org/docs/alerts/40022/">40022</a>.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ ascanrules.sqlinjection.mssql.name = SQL Injection - MsSQL (Time Based)
ascanrules.sqlinjection.mysql.name = SQL Injection - MySQL (Time Based)
ascanrules.sqlinjection.name = SQL Injection
ascanrules.sqlinjection.oracle.name = SQL Injection - Oracle (Time Based)
ascanrules.sqlinjection.postgres.name = SQL Injection - PostgreSQL
ascanrules.sqlinjection.postgres.name = SQL Injection - PostgreSQL (Time Based)
ascanrules.sqlinjection.refs = https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
ascanrules.sqlinjection.soln = Do not trust client side input, even if there is client side validation in place.\nIn general, type check all data on the server side.\nIf the application uses JDBC, use PreparedStatement or CallableStatement, with parameters passed by '?'\nIf the application uses ASP, use ADO Command Objects with strong type checking and parameterized queries.\nIf database Stored Procedures can be used, use them.\nDo *not* concatenate strings into queries in the stored procedure, or use 'exec', 'exec immediate', or equivalent functionality!\nDo not create dynamic SQL queries using simple string concatenation.\nEscape all data received from the client.\nApply an 'allow list' of allowed characters, or a 'deny list' of disallowed characters in user input.\nApply the principle of least privilege by using the least privileged database user possible.\nIn particular, avoid using the 'sa' or 'db-owner' database users. This does not eliminate SQL injection, but minimizes its impact.\nGrant the minimum database access that is necessary for the application.
ascanrules.sqlinjection.sqlite.alert.errorbased.extrainfo = The following known SQLite error message was provoked: [{0}].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@
import org.zaproxy.zap.model.TechSet;
import org.zaproxy.zap.testutils.NanoServerHandler;

/** Unit test for {@link SqlInjectionPostgreScanRule}. */
class SqlInjectionPostgreScanRuleUnitTest extends ActiveScannerTest<SqlInjectionPostgreScanRule> {
/** Unit test for {@link SqlInjectionPostgreSqlTimingScanRule}. */
class SqlInjectionPostgreSqlTimingScanRuleUnitTest
extends ActiveScannerTest<SqlInjectionPostgreSqlTimingScanRule> {

@Override
protected SqlInjectionPostgreScanRule createScanner() {
return new SqlInjectionPostgreScanRule();
protected SqlInjectionPostgreSqlTimingScanRule createScanner() {
return new SqlInjectionPostgreSqlTimingScanRule();
}

@Test
Expand Down