zaproxy: Not able to detect sql injection using zap active scan
Describe the bug I’ve simple flask application one of endpoint has sql injection vulnerable but when tried to detect using zap it was not working properly.
Could someone tell me, what would be the evidence for sql injection?
To Reproduce Steps to reproduce the behavior:
- Create simple flask application and run app.py
import sqlite3
def get_sqli_output(form_userid):
db = sqlite3.connect('app/database.db')
get_user_query = "SELECT user_id, first_name, last_name FROM users WHERE `user_id` = '" + form_userid + "'"
sqli_output = db.cursor().execute(get_user_query).fetchall()
sqli_output = [Users(user_id=i[0], first_name=i[1], last_name=i[2]) for i in sqli_output]
return None if sqli_output == [] else sqli_output
@app.route('/sqli', methods=['GET', 'POST'])
def vulnerable_sqli():
sqli_output = []
try:
if request.method == "POST":
sqli_output = get_sqli_output(request.form["user_id"])
sqli_output = [sqli_output] if sqli_output is not None and type(sqli_output) != list else sqli_output
if sqli_output is None:
return jsonify({"message": "Data Not found"}), 400
return render_template("sqli.html", sqli_output=sqli_output)
except Exception as e:
return jsonify(message="SQL Error"), 400
sqli.html
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body class="home">
<div id="container">
<div id="main_body">
<div class="body_padded">
<div class="vulnerable_code_area">
<form action="http://localhost:8000/sqli" method="POST">
<p>
User ID: <br><br>
<input type="text" size="15" name="user_id"> <br><br>
<button type="submit">Submit</button>
</p>
</form>
{% for output in sqli_output %}
<pre>ID: {{ output.user_id }} <br />First name: {{ output.first_name }}<br />Surname: {{ output.last_name }}</pre>
{% endfor %}
</div>
</div>
</div>
</div>
</body>
</html>
- Go to owasp zap tool
- Click on spider scan and followed by active scan
- Scroll down to alerts and check sql injection has been detected
- See error: No errors
Expected behavior After successfull active scan, zap should show the alert as sqlinjection
Screenshots
Software versions
- ZAP: Tried both 2.9.0 and 2.10.0
- OS: Ubuntu 20.01 LTS
- Java: openjdk version “1.8.0_171”
- Browser: chrome 90
About this issue
- Original URL
- State: open
- Created 3 years ago
- Comments: 16 (8 by maintainers)
Yes, I think it is working as intended, given a good initial input. Arguably a bad initial input might be mitigated against or the user could be warned. That might be more trouble than its worth. On the other hand, Active Scan could add a single additional sqli test that throws away the user input and just inputs
'-- or 1=1
so the user cannot “defeat” this test by starting with'--
as their initial input. So at least sqli would still be detected in this case. But this may just be a usability issue, not really a bug.Hello, I took a look at this issue. I think I understand what is going on. I had to make a few minor changes to the example to get it to execute, but nothing significant. Note that this is a pretty simple web service with a simple sql injection vulnerability, I don’t think its any more complicated a test case than that. The biggest question is where does this input come from that appears to be undetected sql injection?
user_id=ZAP' UNION ALL SELECT 'TfIWasusON',NULL,NULL--
My active scan did not trigger this input, not by default anyway. However, my active scan did trigger a simpler sqli input:
1' AND '1'='1' --
That was was correctly triggered and caught as an alert as a sql injection.
Here is the case where everything works fine:
1
, for User ID 1.http://localhost:5000
Now do this again, but for number 3 in the list above, instead of a “normal” input like
1
, put in a sql injection input, eg1' AND '1'='1' --
, or the OPs query, or just'--
. Then proceed with the Active Scan. At this point, this input in the browser causes the Active Scan to fail to alert on SQL Injection. If this sqli input is entered in the browser, BEFORE running the Active Scan, then SQL Injection does not appear as an alert.This sqli input that I hand crafted does however appear under User Agent Fuzzer, even though there is no alert on SQL Injection. This User Agent Fuzzer does not appear at all until after the Active Scan.
But then what happens is that the sqli input that I used in the browser gets prepended to many other inputs used by the scan, here is one relevant example, but this appears in quite a few of the Active Scan requests (but not all of them!):
My guess is that the original POST input gets used by the Active Scan, sometimes, when it does its own sqli tests. If your input is a sqli input, with
'--
in it, then when the Active Scan attempts to do its own sqli it fails to find its expected results, because your initial'--
commented them out. So it does not look like sqli to ZAP (even though it is) because ZAP does not get back its own expected sqli results.Let me know if this makes sense, I can give this another test if I am missing something here. It is an interesting usability issue, if my explanation is correct,not necessarily a bug. But a user (such as myself when I first started looking at this) might easily mess up their tests if they are not careful with this.
Have tried all, but no changes. Same it is not detecting.