4

One of my clients has a PHP script that kept crashing inexplicably. After hours of research, I determined if you send any PHP script a variable (either through GET or POST) that contains " having t", or escaped for the URL "+having+t", it crashes the script and returns a "403 forbidden error". To test it, I made a sample script with the entire contents:

<?php echo "works";

I put it live (temporarily) here: http://primecarerefer.com/test/test.php

Now if you try sending it some data like: http://primecarerefer.com/test/test.php?x=+having+x

It fails. The last letter can be any letter and it will still crash, but changing any other letter makes the script load fine. What would cause this and how can it be fixed? The link is live for now if anyone wants to try out different combinations.

PS - I found that if I get the 403 error a bunch of times in a row, the sever blocks me for 15 minutes.

Phil
  • 157,677
  • 23
  • 242
  • 245
Dan Goodspeed
  • 3,484
  • 4
  • 26
  • 35
  • 1
    How do you know it's *crashing the script* and that 403 isn't being returned on purpose? – alex Oct 07 '15 at 03:18
  • Sounds unrelated to PHP. I'd be checking the web server's error log as well as any URL rewriting / access control rules that may be in place – Phil Oct 07 '15 at 03:19
  • and without the plusses? could htaccess be blocking special chars? – Jorg Oct 07 '15 at 03:19
  • @HarshitShrivastava what do you mean? I did show all of the code! – Dan Goodspeed Oct 07 '15 at 03:19
  • @Jorg The original post had a story several hundred characters long with tons of plusses, I had to edit it down character by character until I found the couple characters that are causing the problem. – Dan Goodspeed Oct 07 '15 at 03:21
  • @Phil, I checked the web servers error logs and it only complains about not being able to find a custom 403 page. I also checked the .htaccess, and there's nothing questionable there. – Dan Goodspeed Oct 07 '15 at 03:25
  • 1
    FYI, the characters around *"having"* seem to be mostly irrelevant. If I was to hazard a guess at a matching regular expression it would be `\bhaving\b.+` – Phil Oct 07 '15 at 03:27
  • I would expect a 'PHP crash' to result in a 5xx, not a 403.. how is the PHP being hosted? Which version? What mods/additions are in effect? Are there other server handlers? – user2864740 Oct 07 '15 at 03:28
  • @Phil, did you find any other letters besides "+" and "%20" cause it to crash? – Dan Goodspeed Oct 07 '15 at 03:30
  • @DanGoodspeed I tried `.`, `,`, `_` and `:` before the StackOverflow hug of death killed your test site. You sure you're looking at the error log and not the access log. Usually a 403 response will log why it was blocked – Phil Oct 07 '15 at 03:31
  • 2
    Does it only happen on PHP files? Can you try a HTML file? – Phil Oct 07 '15 at 03:32
  • @user2864740, It's a LAMP-based Cloudflare site, if that answers your question. – Dan Goodspeed Oct 07 '15 at 03:33
  • @Phil it wasn't the stackoverflow hug... the site blocked your IP address (as it did mine several times). And YOU'RE RIGHT! I just tried a regular html file and it causes the same issue! http://primecarerefer.com/test/test.html?x=+having+t – Dan Goodspeed Oct 07 '15 at 03:35

1 Answers1

5

I had this type of issue on a webserver that ran apache mod_security, but it was very poorly configured, actually mod_security has very bad default regex rules, which are very easy to trip with valid POST or GET data.

To be clear, this has nothing to do with PHP or HTML, it's about POST and GET data passing through mod_security, almost certainly, and mod_security rejecting the request because it believes it is an sql injection attempt.

You can edit the rules yourself depending on the server access, but I don't believe you can do anything, well, if it's mod_security, I know you can't do anything via PHP to get around this.

/etc/httpd/conf.d/mod_security.conf (old path, it's changed, but it gives the idea)

Examples of the default rules:

SecFilter "delete[[:space:]]+from"
SecFilter "insert[[:space:]]+into"
SecFilter "select.+from"

These are samples of the rules https://www.howtoforge.com/apache_mod_security

here they trip the filter:

http://primecarerefer.com/test/test.php?x=%20%22%20%20select%20from%22

Note that the article is very old and the rules actually are quite differently structured now, but the bad regex remains, ie: select[any number of characters, no matter how far removed, or close]from will trip it, any sql that matches these loose rules will trip it.

But since editing those default files requires access to them, and also assumes they won't be altered in an upgrade of apache mod_security at some point, it's not a good way to fix the problem I found, moving to a better, more professionally setup, hoster, fixed those issues for us. But it does help if you talk to the hosting support to know what the cause of the issue is.

In fact 'having' is not irrelevant at all, it's part of sql injection filters in the regex rules in the security filters run on POST/GET. We used to hit this all the time when admins would edit CMS pages, which would trigger invariably some sql filter, since any string of human words would invariably contain something like 'select.*from' or 'insert.*into' etc.

This mod_security issue used to drive me bonkers trying to debug why backend edit form updates would just hang, until I finally realized it was badly done generic regex patterns in the mod_security file itself.

In a sense, this isn't an answer, because the only fix is going into the server and either editing the rules file, which is pretty easy, or disabling mod_security, or moving to a web hoster that doesn't use those bad generic defaults.

Lizardx
  • 1,165
  • 10
  • 16
  • I've tried a bunch of SQL keywords and so far, nothing else trips the error. – Phil Oct 07 '15 at 03:41
  • I'll see if I can find the file that had that data on it, but as noted, we left that hoster because of such issues, among many others, so I may not be able to find it. Our case was the same by the way, it was only one or two sql key words, which is why it was so darned hard to figure out. – Lizardx Oct 07 '15 at 03:43
  • http://primecarerefer.com/test/test.php?x=%20%22having%20zowder%22 I was curious, and you can clearly see the pattern: space plus having plus space plus any characters. The real question is if this filter is running via mod_security or if it's some manual set of rules they created. Either way you probably have to call the hoster to find out. – Lizardx Oct 07 '15 at 03:48
  • 2
    http://primecarerefer.com/test/test.php?x=%20%22%20select%20zowder%22 yes, it's clearly the mod_security, there's another one. I can't find my copy of the security filter rules, but I recognize this because I fixed the rules to be less sloppy. I was actually surprised to see Apache ship defaults that were so bad that most users would just turn them off rather than try to fix them, which defeats the purpose. – Lizardx Oct 07 '15 at 03:57
  • http://primecarerefer.com/test/test.php?x=%20%22%20%20union%20zowder%22 there's more. https://www.howtoforge.com/apache_mod_security shows some of the filters used. This is definitely mod_security. – Lizardx Oct 07 '15 at 04:15
  • Believe me, this issue used to drive me up the wall, lol, until I actually looked at the regex for the rules and realized that almost any human english text of any complexity will trip them. It's easy to fix them, and I'm amazed at this late date that they remain profoundly broken, ie, the POST/GET filters only work if you have no POST / GET data, sigh. – Lizardx Oct 07 '15 at 04:24
  • The web host company just disabled mod_security to make it work. Good enough, I guess. Thanks for your help! – Dan Goodspeed Oct 07 '15 at 14:57
  • As I noted, a security rule that is so badly written that it leads you to turn security off is a serious bug in the security rule, I find it odd that Apache, who tend to do great work, have not corrected the sloppy regex in in these filters years ago, so that they actually work as intended, rather than forcing one to turn the rules off to get functioning POST/GET. This is so non intuitive that it's very hard to figure out when you hit it, since normal english in a post/get request should NOT trip any filter, but it does. – Lizardx Oct 07 '15 at 17:28