ModSecurity rule giving SQL Injection false positives, generating 500 Internal Server Error, even when using PHP PDO prepared statements


#1

TL;DR - A default ModSecurity rule on my server is generating a 500 Internal Server Error when trying to submit a PHP form field that contains the word "from", since it's seeing it as a possible SQL injection, even though I'm using PDO prepared statements. Not sure of the best way to fix this.

When trying to submit a form that has a textarea that contains "changed email from x to x" I'm getting a 500 Internal Server error, and I've narrowed it down the word "from" being the culprit. Based on what I'm seeing in the logs it appears as though the form submission is being seen as a possible SQL injection. I disabled this particular rule (300016) as a test and the form started working properly.

From Apache error log:

[:error] [pid 39495] [client x.x.x.x] ModSecurity: Access denied with code 500 (phase 2). Pattern match "(insert[[:space:]]+into.+values|select.*from.+[a-z|A-Z|0-9]|select.+from|bulk[[:space:]]+insert|union.+select|convert.+\\\\(.*from)" at ARGS:notes. [file "/etc/apache2/conf.d/modsec/modsec2.user.conf"] [line "247"] [id "300016"] [rev "2"] [msg "Generic SQL injection protection"] [severity "CRITICAL"] [hostname "xxxxxxxxxx.com"] [uri "/path/to/page/with/form.php"] [unique_id "WiGVQoP7XCbNIjL9nZzrKAAAAAo"]

From ModSecurity audit log:

Message: Access denied with code 500 (phase 2). Pattern match "(insert[[:space:]]+into.+values|select.*from.+[a-z|A-Z|0-9]|select.+from|bulk[[:space:]]+insert|union.+select|convert.+\\(.*from)" at ARGS:notes. [file "/etc/apache2/conf.d/modsec/modsec2.user.conf"] [line "247"] [id "300016"] [rev "2"] [msg "Generic SQL injection protection"] [severity "CRITICAL"]
Action: Intercepted (phase 2)
Stopwatch: 1512150338540293 2147 (- - -)
Stopwatch2: 1512150338540293 2147; combined=549, p1=96, p2=449, p3=0, p4=0, p5=3, sr=32, sw=1, l=0, gc=0
Producer: ModSecurity for Apache/2.9.0 (http://www.modsecurity.org/).
Server: Apache
Engine-Mode: "ENABLED"

ModSecurity rule:

#Generic SQL sigs
SecRule REQUEST_URI "!(/node/[0-9]+/edit|/forum/posting\.php|/admins/wnedit\.php|/alt_doc\.php\?returnUrl=.*edit|/admin/categories\.php\?cPath=.*|modules\.php\?name=Forums&;file=posting&;mode=.*)" "chain,id:300016,t:lowercase,rev:2,severity:2,msg:'Generic SQL injection protection'"
SecRule ARGS "(insert[[:space:]]+into.+values|select.*from.+[a-z|A-Z|0-9]|select.+from|bulk[[:space:]]+insert|union.+select|convert.+\(.*from)"
  • The ModSecurity rule seems a bit restrictive, however I would prefer to not disable it entirely because it definitely has some value (I believe this rule was automatically implemented when my WHM/cPanel was upgraded recently)
  • One of the solutions I've seen is to disable this particular rule for the file (or folder) I'm trying to access, but that only solves the problem for this one section of one domain, and other users on my server could still run into this issue
  • The form that's generating the error is using PDO prepared statements

I'm not very experienced with ModSecurity and I'm really not sure what the best way to solve this would be, so I figured I would see if anyone here has any suggestions.

PS - Since the form works when the ModSecurity rule is disabled I don't think the form itself is the issue, but just in case...

Form:

<form method="post">
    <textarea class="form-control" placeholder="Notes" name="notes" cols="40" rows="10" wrap="VIRTUAL">
    <input class="form-control" type="submit" name="Submit" value="Save Changes">
</form>

Form Processing:

$notes = $_POST['notes'];
$stmt = $pdo->prepare("
	UPDATE links
	SET notes = :notes
	WHERE id = :link_id");
$stmt->bindValue('notes', $notes, PDO::PARAM_LOB);
$stmt->bindValue('link_id', $link_id, PDO::PARAM_INT);
$stmt->execute();

#4

Nobody has any suggestions?


#5

I saw this before but only had a guess so didn't reply. As no one else has jumped in yet, here's my guess.

The "from" is coming from $notes. The script sees this as a possible attempt to modify the query.

Are you certain you need to use large object instead of string?

$stmt->bindValue('notes', $notes, PDO::PARAM_LOB);

My guess is that large object doesn't get the sanitizing a string would get.

Because you're getting a server error (never the most informative error message) might the large object be too large?


#6

Mod Security is run against the content when it reach the server. This means before the content is sent to PHP, so it should have nothing to do with your query.

What happen if you send something else than "changed email from x to x" with the form?
What happen if you change "notes" to "info"?

Finally, have you tried changing the file name, it can be a combination of filename and form content triggering the issue.


#7

The notes field is LONGTEXT in the database, and based on what I've read a field of that size should be PARAM_LOB. I even tried PARAM_STR and was still having the same issue.

And the size of the textfield I'm submitting is definitely small enough for a LONGTEXT field.

After an absurd amount of time wasted trying to figure out what's triggering the ModSec rule, in the end I finally just disabled the rule, and now everything is working fine. I would've liked to keep the rule for some extra security, but it didn't exist before a cPanel update, so it's not the end of the world that it doesn't exist now.

Thanks for trying to help, I really appreciate it!

PS - Sorry for the late reply. For some reason I'm not getting email notifications and I didn't realize that anyone had responded to my post yet.


#8

If I send other data in the form it works sometimes but not others, depending on what the text is. Trial and error with the text is what made me realize it was the word "from" that was causing the issue.

I changed both the notes field in the database as well as the $notes variable in the php file, and I renamed the php file, and was still having the same issue.

In the end I just disabled the ModSec rule that was triggering the error. Not ideal, but I've spent way too much time trying to figure out why the rule is triggering, so I just cut it off entirely. I'll get back to it soon to do some more troubleshooting, but for now I'm good with it being gone completely.

PS - Sorry for the late reply. For some reason I'm not getting email notifications and I didn't realize that anyone had responded to my post yet.


#9

Mod Security can be a handle sometimes, especially if you have a form that accept large amounts of text, like on a forum for example. I would not worry too much if you only disabled one rule for one specific page, while it is not something we do on every site we setup, it is not uncommon to do that. Since the rules grasp rather wide.


#10

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.