
How I bypassed Cloudflare's SQL Injection filter - gskourou
https://www.astrocamel.com/web/2020/09/04/how-i-bypassed-cloudflares-sql-injection-filter.html
======
jonahss
Ran into a funny bug once from either Cloudflare or AWS's implementation of a
similar service.

Marketing made a big push for a new Promo code on the site we were running,
but the promo code wasn't working. Reports came in that the promo code worked
if you entered it as lowercase, rather than all caps.

Double-checked a dozen times, we take whatever string the user passes in an
converted it to upper case, and all the values in the db were upper case. Keep
thinking we must have messed this up somewhere.

In the end, the devops guy realizes that AWS (or Cloudflare, I forget) was
blocking the uppercase requests, since the promo code was `SELECT` >.<

Assumed it was an injection attack, but only when uppercase.

~~~
awirth
Years ago helped handle a support request from a man named "fread" who had a
similar issue.

~~~
chiph
We had a customer named Mr. Echo who was having difficulties paying us. Turns
out our credit card processor was blocking the names of common Unix command
line programs.

------
akersten
I wonder if the fix for this was just adding some more RegEx to the WAF and
calling it patched.

To me, it seems like it's not possible for a WAF to honestly promise "SQL
Injection Prevention," because it's surely just string matching and not
actually building an AST/simulating a database query before passing the HTTP
query along to the application server. The WAF can't possibly know how the
application server operates on the HTTP query, so if the programmer went
outside of a pre-imagined pattern, all bets about the WAF's security promises
are off.

So I agree with the other comment in this thread about WAFs being snake oil.
Good for pattern analysis and deep packet inspection to block specific known
threats, but claiming it's a solution for all but the most basic SQL injection
is a claim that can't be fulfilled.

~~~
Edmond
Obviously the correct solution for SQL injection is to use prepared statements
or "proper" input validation.

I however wouldn't call WAF solutions snake oil...Web security in general
follows an approach of layering Swiss cheese with holes in them, you hope that
if you layer enough protection you can plug all the holes.

Leading WAF solutions have pretty decent coverage for SQLi and other payload
attacks. If you're not sure of security in your code then your next best
choices is a WAF.

~~~
nicoburns
Isn't it a fairly simple, mechanical job convert a non-parameterised query
into a parameterised one. No non-local reasoning required. Things must bw
pretty bad if you're running code with known SQL injection vulnerabilities!

~~~
nucleardog
Until you run across code that's doing something like:

    
    
        def search(key, value):
            query("select * from my_table where `" + key + "` = '" + value + "'")
    

Not that I'm suggesting this is a good thing to do, but it's not something you
can simply replace with a single line of context or easily.

~~~
nicoburns
I believe you could handle that case with an escaping function for the `key`
variable. Column names are generally quite restricted in what characters they
can contain, so this is fairly easy to do in a water-tight way. Of course this
won't restrict which column you're giving access to, but a WAF won't catch
that either.

------
divbzero
Highlighting the key PSA from the article:

“ _The safest way to mitigate SQL injections on your databases is prepared
statements. These come in most database interaction libraries for most
languages. You can find a full list of ways to mitigate SQL injections at_
[OWASP] _._ ”

[OWASP]:
[https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection...](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html)

------
rasz
>I got a free t-shirt

wait, I thought "And All I Got Was This Lousy T-Shirt" was just a meme

~~~
judge2020
Cloudflare's bug bounty program used to be exclusively T-Shirts/swag but it
looks like they now might give out service credits, it doesn't state the exact
reward:

> Reporters under the age of 18 will not be eligible to receive Cloudflare
> service rewards

[https://hackerone.com/cloudflare](https://hackerone.com/cloudflare)

~~~
bruno207
Check the top:

>Cloudflare runs a private bug bounty program. If you submit a valid report on
bounty-eligible assets through our disclosure program, we will transfer your
report to our bug bounty program and invite you as a participant.

------
beaker52
A recent client of mine had their WAF configured to block requests with '%' in
the URL. Yup. No URL encoding.

"Can we remove that?"

> "No, it could open up vulnerabilities"

Yup. Yes, it could. Silly me.

------
creatonez
A hidden "SQL injection filter" in cloudflare seems like a truly awful idea.

What happens when an incompetent developer codes up a vulnerable website, and
it seems to be protected through this feature, and this goes unnoticed for
many years until cloudflare is phased out, the feature is disabled, or some
other change to the way things are done outside the original dev's control
comes along?

And what happens when you can bypass it as soon as there is some other way
(i.e. base64 encoded, or not in HTTP at all) for user input to reach the API?

And of course, what happens when you can bypass it due to it having a bug or
being deficient by design?

The lesson: do NOT "sanitize" your inputs, ever. Just keep your data types
straight (by using things like prepared statements to convert a string to an
SQL-escaped string) and _block_ all inputs that should never end up in the
database in the first place.

------
Snitch-Thursday
So...if I naively parameterize the inputs for my queries (select blah, blah,
blah FROM customers WHERE id LIKE @id) and have the incoming request just
check for an id parameter and make a SQL parameter named @id, with value =
whatever the input is, am I 90% there?

Or are there still vulns/exploits for that kind of usage?

~~~
grey-area
Another safety measure worth looking at is always enforcing types for params
before using them for anything. So if id is an int parse it to an int first.
That way you know no extra data/commands can be in the param.

~~~
nkozyra
You don't need to, though, that's what parameterized queries are for. I'd
argue that providing out-of-bounds checks like that will increase the
likelihood of someone relying on them down the road.

~~~
grey-area
The boundary for variable parsing should be the edge of your application.
Otherwise you can't be sure that your validity checks (for example) are doing
what you think they are, or that your sql is doing what you think it is.

As one example of this consider the rails vuln CVE-2013-0156. Lax param
parsing and cleaning (or none), can lead to problems like this and even sqli
if you meant to accept a string and instead accept something like an array or
a symbol.

------
unlog
If you ever need this or something like this, then it means you don't trust
100% how input is handled. I think my projects reached this point, even with
some little flaws in between, to expect this from any company that isn't
organised enough to handle security properly.. sounds unteslistic. From there
it just depends at which cost you add this additional layer of "security", I
learned from cloudbleed to avoid as much as posible anything that could modify
the document in some way.

------
seanwilson
Is there a name for the fallacy when people say something like "you shouldn't
be using this to protect your app anyway - doing so will give you a false
sense of security and make you write riskier code"? I see this argument quite
often for features like this that give partial protection. It's partly a false
dilemma anyway.

~~~
patrec
What "fallacy"? I'm actually horrified that several high profile companies are
proudly advertising using this abomination on
[https://www.cloudflare.com/waf/](https://www.cloudflare.com/waf/).

I really do not want to use the product of a company that thinks it's a good
idea to "protect" their software by paying someone to put something in front
of it that strips out all input that "looks too much like SQL".

This is a bit like a food manufacturer paying someone to add antibiotics to
their products because their hygiene processes are so terrible they suspect
some E. coli might slip in from time to time.

Unlike say the insane sing-and-dance-de-jour you have to perform to make sure
your server sets the right set of security related HTTP headers, SQL injection
attacks, despite their prevalence, are a completely bogus problem. I'd go so
far and say if you have an SQL Injection attack, the solution is to fire
someone and review your processes and not to pay a third party to corrupt data
coming in and cross your fingers and hope that they do so in a way that will
hopefully both protect you from your engineering incompetence and not mess up
genuine requests too much.

~~~
seanwilson
> I'd go so far and say if you have an SQL Injection attack, the solution is
> to fire someone and review your processes and not to pay a third party to
> corrupt data coming in

The fallacy you're making is proposing a false dilemma. You can review your
processes AND layer defences on top. You don't have to pick between one or the
other.

Whether Cloudflare is a worthwhile defence is not what I'm commenting on
though, although surely the whole point of it is that it gives you some
protection when you don't know you have an SQL injection exploit. I can't
imagine anyone knows they have exploits and is using Cloudflare as a
solution/bandaid.

~~~
patrec
And the fallacy you are making is describing adding more shit sauce on top as
"a layered defense". A layered defense is when you take multiple,
_individually sane_ steps, with well defined boundaries to reduce risks that
remain despite following good engineering practice. Some aspects of WAF may
fit this bill, but SQL Injection defence assuredly does not.

There is no way in hell that something that basically takes arbitrary input
without any context and says "oh, well, this looks a bit too much like an SQL
fragment for my liking, let's corrupt it a bit, lest some piece of garbage
downstream tries to string interpolate executable code together with it and
it'll end in tears" will not, in some cases, cause other problems, maybe even
security-relevant ones.

It's real easy not to have SQL injection exploits, you inform people that
using anything apart from prepared statements to talk to the DB is a firing
offence. If software vendors would face liability claims as other engineering
professions do, this would be fixed overnight. As things are, I'm 100% sure
you are wrong and there are countless places that do know they have exploits
and just slap Cloudflare on top as a bandaid.

~~~
seanwilson
> And the fallacy you are making is describing adding more shit sauce on top
> as "a layered defense". A layered defense is when you take multiple,
> individually sane steps, with well defined boundaries to reduce risks that
> remain despite following good engineering practice. Some aspects of WAF may
> fit this bill, but SQL Injection defence assuredly does not.

I haven't commented about how effective WAF is or if you should use it or not,
so you're on a soapbox attacking a strawman here.

> It's real easy not to have SQL injection exploits, you inform people that
> using anything apart from prepared statements to talk to the DB is a firing
> offence.

I think relying on nobody to make mistakes (because you tried to scare them
not to or otherwise) is awful advice in general. Even frameworks you rely on
to create safe SQL queries can have exploits as well so you need to consider
human error at several layers.

Expect human error and plan your processes around it.

------
DoctorNick
All you got was a lousy t-shirt? You could have easily sold that on the black
market for tens of thousands of dollars.

~~~
ivanche
True, but now he has a $0.50 t-shirt! /s

------
girst
Cloudflare's and all other "Webapp Firewalls" are just snake oil. They can't
know what transformations are done server-side on untrusted input, so you'll
always (with enough time and determination) be able to craft a string that
passes the WAF but exploits the backend.

Just a few examples: [https://github.com/frizb/Bypassing-Web-Application-
Firewalls](https://github.com/frizb/Bypassing-Web-Application-Firewalls)

~~~
ejcx
(I work at Cloudflare and manage the Product Security team, so...disclaimer).

WAFs definitely help. No WAF is perfect, but having an additional layer to
make exploitation harder, and having a tool designed to block specific attacks
(like when a new CVE is issued for a CMS) is powerful.

Not to mention that WAFs are a requirement in regulated industries. PCI
mandates it. And your SOC2 + ISO auditors probably will ask about it too.

~~~
jcims
For me the main benefit of a WAF is that ability to rapidly respond to zero
day/CVE.

A good set of filters deters casual abusers and can amplify the signal from a
skilled attack, but ultimately they tend to fail.

