Skip to content

Commit 33512a4

Browse files
committed
ascanrules: SQLi Oracle rename scan rule (all time based)
Signed-off-by: kingthorin <kingthorin@users.noreply.github.com>
1 parent 8afbdb0 commit 33512a4

File tree

5 files changed

+16
-56
lines changed

5 files changed

+16
-56
lines changed

addOns/ascanrules/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1212
- Rules (as applicable) have been tagged in relation to HIPAA and PCI DSS.
1313
- The Cloud Metadata Potentially Exposed scan rules now has a CWE reference.
1414
- Scan rules which execute time based attacks now include the "TEST_TIMING" alert tag.
15+
- The SQL Injection - Oracle scan rule and alerts have been renamed to clarify that they're time based (Issue 7341).
1516

1617
## [72] - 2025-06-20
1718
### Added
Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import java.util.Collections;
2323
import java.util.HashMap;
24-
import java.util.LinkedHashMap;
2524
import java.util.Map;
2625
import org.apache.logging.log4j.LogManager;
2726
import org.apache.logging.log4j.Logger;
@@ -38,11 +37,11 @@
3837
/**
3938
* TODO: maybe implement a more specific UNION based check for Oracle (with table names)
4039
*
41-
* <p>The SqlInjectionOracleScanRule identifies Oracle specific SQL Injection vulnerabilities using
42-
* Oracle specific syntax. If it doesn't use Oracle specific syntax, it belongs in the generic
43-
* SQLInjection class! Note the ordering of checks, for efficiency is : 1) Error based (N/A) 2)
44-
* Boolean Based (N/A - uses standard syntax) 3) UNION based (TODO) 4) Stacked (N/A - uses standard
45-
* syntax) 5) Blind/Time Based (Yes)
40+
* <p>This scan rule identifies Oracle specific SQL Injection vulnerabilities using Oracle specific
41+
* syntax. If it doesn't use Oracle specific syntax, it belongs in the generic SQLInjection class!
42+
* Note the ordering of checks, for efficiency is : 1) Error based (N/A) 2) Boolean Based (N/A -
43+
* uses standard syntax) 3) UNION based (TODO) 4) Stacked (N/A - uses standard syntax) 5) Blind/Time
44+
* Based (Yes)
4645
*
4746
* <p>See the following for some great specific tricks which could be integrated here
4847
* http://www.websec.ca/kb/sql_injection
@@ -60,44 +59,16 @@
6059
*
6160
* @author 70pointer
6261
*/
63-
public class SqlInjectionOracleScanRule extends AbstractAppParamPlugin
62+
public class SqlInjectionOracleTimingScanRule extends AbstractAppParamPlugin
6463
implements CommonActiveScanRuleInfo {
6564

6665
private int expectedDelayInMs = 5000;
6766

68-
private boolean doUnionBased = false; // TODO: use in Union based, when we implement it
69-
private boolean doTimeBased = false;
70-
71-
private int doUnionMaxRequests = 0; // TODO: use in Union based, when we implement it
7267
private int doTimeMaxRequests = 0;
7368

7469
/** Oracle one-line comment */
7570
public static final String SQL_ONE_LINE_COMMENT = " -- ";
7671

77-
/**
78-
* create a map of SQL related error message fragments, and map them back to the RDBMS that they
79-
* are associated with keep the ordering the same as the order in which the values are inserted,
80-
* to allow the more (subjectively judged) common cases to be tested first Note: these should
81-
* represent actual (driver level) error messages for things like syntax error, otherwise we are
82-
* simply guessing that the string should/might occur.
83-
*/
84-
private static final Map<String, String> SQL_ERROR_TO_DBMS = new LinkedHashMap<>();
85-
86-
static {
87-
SQL_ERROR_TO_DBMS.put("oracle.jdbc", "Oracle");
88-
SQL_ERROR_TO_DBMS.put("SQLSTATE[HY", "Oracle");
89-
SQL_ERROR_TO_DBMS.put("ORA-00933", "Oracle");
90-
SQL_ERROR_TO_DBMS.put("ORA-06512", "Oracle"); // indicates the line number of an error
91-
SQL_ERROR_TO_DBMS.put("SQL command not properly ended", "Oracle");
92-
SQL_ERROR_TO_DBMS.put("ORA-00942", "Oracle"); // table or view does not exist
93-
SQL_ERROR_TO_DBMS.put("ORA-29257", "Oracle"); // host unknown
94-
SQL_ERROR_TO_DBMS.put("ORA-00932", "Oracle"); // inconsistent datatypes
95-
96-
// Note: only Oracle mappings here.
97-
// TODO: is this all?? we need more error messages for Oracle for different languages. PHP
98-
// (oci8), ASP, JSP(JDBC), etc
99-
}
100-
10172
/** the 5 second sleep function in Oracle SQL */
10273
private static String SQL_ORACLE_TIME_SELECT =
10374
"SELECT UTL_INADDR.get_host_name('10.0.0.1') from dual union SELECT UTL_INADDR.get_host_name('10.0.0.2') from dual union SELECT UTL_INADDR.get_host_name('10.0.0.3') from dual union SELECT UTL_INADDR.get_host_name('10.0.0.4') from dual union SELECT UTL_INADDR.get_host_name('10.0.0.5') from dual";
@@ -167,7 +138,8 @@ public class SqlInjectionOracleScanRule extends AbstractAppParamPlugin
167138
}
168139

169140
/** for logging. */
170-
private static final Logger LOGGER = LogManager.getLogger(SqlInjectionOracleScanRule.class);
141+
private static final Logger LOGGER =
142+
LogManager.getLogger(SqlInjectionOracleTimingScanRule.class);
171143

172144
@Override
173145
public int getId() {
@@ -210,25 +182,13 @@ public void init() {
210182

211183
// set up what we are allowed to do, depending on the attack strength that was set.
212184
if (this.getAttackStrength() == AttackStrength.LOW) {
213-
doTimeBased = true;
214185
doTimeMaxRequests = 3;
215-
doUnionBased = true;
216-
doUnionMaxRequests = 3;
217186
} else if (this.getAttackStrength() == AttackStrength.MEDIUM) {
218-
doTimeBased = true;
219187
doTimeMaxRequests = 5;
220-
doUnionBased = true;
221-
doUnionMaxRequests = 5;
222188
} else if (this.getAttackStrength() == AttackStrength.HIGH) {
223-
doTimeBased = true;
224189
doTimeMaxRequests = 10;
225-
doUnionBased = true;
226-
doUnionMaxRequests = 10;
227190
} else if (this.getAttackStrength() == AttackStrength.INSANE) {
228-
doTimeBased = true;
229191
doTimeMaxRequests = 100;
230-
doUnionBased = true;
231-
doUnionMaxRequests = 100;
232192
}
233193
}
234194

@@ -256,7 +216,6 @@ public void scan(HttpMessage originalMessage, String paramName, String paramValu
256216
long originalTimeUsed = msgTimeBaseline.getTimeElapsedMillis();
257217
// end of timing baseline check
258218

259-
int countUnionBasedRequests = 0;
260219
int countTimeBasedRequests = 0;
261220

262221
LOGGER.debug(
@@ -269,7 +228,6 @@ public void scan(HttpMessage originalMessage, String paramName, String paramValu
269228
// Check for time based SQL Injection, using Oracle specific syntax
270229
for (int timeBasedSQLindex = 0;
271230
timeBasedSQLindex < SQL_ORACLE_TIME_REPLACEMENTS.length
272-
&& doTimeBased
273231
&& countTimeBasedRequests < doTimeMaxRequests;
274232
timeBasedSQLindex++) {
275233
HttpMessage msgAttack = getNewMsg();

addOns/ascanrules/src/main/javahelp/org/zaproxy/zap/extension/ascanrules/resources/help/contents/ascanrules.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ <H2 id="id-40021">SQL Injection - Oracle (Time Based)</H2>
404404
<br>
405405
Note that this rule does not currently allow you to change the length of time used for the timing attacks due to the way the delay is caused.
406406
<p>
407-
Latest code: <a href="https://github.com/zaproxy/zap-extensions/blob/main/addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionOracleScanRule.java">SqlInjectionOracleScanRule.java</a>
407+
Latest code: <a href="https://github.com/zaproxy/zap-extensions/blob/main/addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/SqlInjectionOracleTimingScanRule.java">SqlInjectionOracleTimingScanRule.java</a>
408408
<br>
409409
Alert ID: <a href="https://www.zaproxy.org/docs/alerts/40021/">40021</a>.
410410

addOns/ascanrules/src/main/resources/org/zaproxy/zap/extension/ascanrules/resources/Messages.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ ascanrules.sqlinjection.mssql.alert.timebased.extrainfo = The query time is cont
185185
ascanrules.sqlinjection.mssql.name = SQL Injection - MsSQL
186186
ascanrules.sqlinjection.mysql.name = SQL Injection - MySQL
187187
ascanrules.sqlinjection.name = SQL Injection
188-
ascanrules.sqlinjection.oracle.name = SQL Injection - Oracle
188+
ascanrules.sqlinjection.oracle.name = SQL Injection - Oracle (Time Based)
189189
ascanrules.sqlinjection.postgres.name = SQL Injection - PostgreSQL
190190
ascanrules.sqlinjection.refs = https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
191191
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.
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,13 @@
3636
import org.zaproxy.zap.model.TechSet;
3737
import org.zaproxy.zap.testutils.NanoServerHandler;
3838

39-
/** Unit test for {@link SqlInjectionOracleScanRule}. */
40-
class SqlInjectionOracleScanRuleUnitTest extends ActiveScannerTest<SqlInjectionOracleScanRule> {
39+
/** Unit test for {@link SqlInjectionOracleTimingScanRule}. */
40+
class SqlInjectionOracleTimingScanRuleUnitTest
41+
extends ActiveScannerTest<SqlInjectionOracleTimingScanRule> {
4142

4243
@Override
43-
protected SqlInjectionOracleScanRule createScanner() {
44-
return new SqlInjectionOracleScanRule();
44+
protected SqlInjectionOracleTimingScanRule createScanner() {
45+
return new SqlInjectionOracleTimingScanRule();
4546
}
4647

4748
@Test

0 commit comments

Comments
 (0)