mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-30 11:29:02 +00:00
Ahead with the improvements to the comparison algorithm.
Added support internally to forge CASE statements, used only by --is-dba query at the moment. Allow DDL, DML (INSERT, UPDATE, etc.) from user in SQL query and SQL shell. Minor code adjustments.
This commit is contained in:
@@ -306,30 +306,26 @@ def checkStability():
|
||||
condition &= secondPage == thirdPage
|
||||
|
||||
if condition == False:
|
||||
# Prepare for the comparison algorithm based on Content-Length
|
||||
# header value
|
||||
contentLengths = []
|
||||
requestsHeaders = ( firstHeaders, secondHeaders, thirdHeaders )
|
||||
# Prepare for the comparison algorithm based on page length value
|
||||
pageLengths = []
|
||||
requestsPages = ( firstPage, secondPage, thirdPage )
|
||||
|
||||
for requestHeaders in requestsHeaders:
|
||||
requestHeaders = str(requestHeaders).lower()
|
||||
for requestPages in requestsPages:
|
||||
pageLengths.append(len(str(requestPages)))
|
||||
|
||||
clHeader = re.search("content-length:\s+([\d]+)", requestHeaders, re.I | re.M)
|
||||
if pageLengths:
|
||||
conf.pageLengths = ( min(pageLengths) - ( ( min(pageLengths) * 2 ) / 100 ),
|
||||
max(pageLengths) + ( ( max(pageLengths) * 2 ) / 100 ) )
|
||||
|
||||
if clHeader and clHeader.group(1).isdigit():
|
||||
contentLengths.append(int(clHeader.group(1)))
|
||||
if conf.pageLengths[0] < conf.pageLengths[1]:
|
||||
warnMsg = "url is not stable, sqlmap inspected the page "
|
||||
warnMsg += "and identified that page length can be used "
|
||||
warnMsg += "in the comparison algorithm"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if contentLengths:
|
||||
conf.contentLengths = ( min(contentLengths), max(contentLengths) )
|
||||
kb.defaultResult = True
|
||||
|
||||
warnMsg = "url is not stable, sqlmap inspected the headers "
|
||||
warnMsg += "and identified that Content-Length can be used "
|
||||
warnMsg += "in the comparison algorithm"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
kb.defaultResult = True
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
# Prepare for the comparison algorithm based on page content's
|
||||
# stable lines subset
|
||||
|
||||
@@ -468,5 +468,25 @@ class Agent:
|
||||
return limitedQuery
|
||||
|
||||
|
||||
def forgeCaseStatement(self, expression):
|
||||
"""
|
||||
Take in input a query string and return its CASE statement query
|
||||
string.
|
||||
|
||||
Example:
|
||||
|
||||
Input: (SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)) LIMIT 0, 1)='Y'
|
||||
Output: SELECT (CASE WHEN ((SELECT super_priv FROM mysql.user WHERE user=(SUBSTRING_INDEX(CURRENT_USER(), '@', 1)) LIMIT 0, 1)='Y') THEN 1 ELSE 0 END)
|
||||
|
||||
@param expression: expression to be processed
|
||||
@type num: C{str}
|
||||
|
||||
@return: processed expression
|
||||
@rtype: C{str}
|
||||
"""
|
||||
|
||||
return queries[kb.dbms].case % expression
|
||||
|
||||
|
||||
# SQL agent
|
||||
agent = Agent()
|
||||
|
||||
@@ -40,6 +40,7 @@ from lib.core.data import logger
|
||||
from lib.core.data import temp
|
||||
from lib.core.exception import sqlmapFilePathException
|
||||
from lib.core.data import paths
|
||||
from lib.core.settings import SQL_STATEMENTS
|
||||
from lib.core.settings import VERSION_STRING
|
||||
|
||||
|
||||
@@ -493,39 +494,11 @@ def parsePasswordHash(password):
|
||||
|
||||
|
||||
def cleanQuery(query):
|
||||
# SQL SELECT statement
|
||||
upperQuery = query.replace("select ", "SELECT ")
|
||||
upperQuery = upperQuery.replace(" from ", " FROM ")
|
||||
upperQuery = upperQuery.replace(" where ", " WHERE ")
|
||||
upperQuery = upperQuery.replace(" group by ", " GROUP BY ")
|
||||
upperQuery = upperQuery.replace(" order by ", " ORDER BY ")
|
||||
upperQuery = upperQuery.replace(" having ", " HAVING ")
|
||||
upperQuery = upperQuery.replace(" limit ", " LIMIT ")
|
||||
upperQuery = upperQuery.replace(" offset ", " OFFSET ")
|
||||
upperQuery = upperQuery.replace(" union all ", " UNION ALL ")
|
||||
upperQuery = upperQuery.replace(" rownum ", " ROWNUM ")
|
||||
upperQuery = query
|
||||
|
||||
# SQL data definition
|
||||
upperQuery = upperQuery.replace(" create ", " CREATE ")
|
||||
upperQuery = upperQuery.replace(" drop ", " DROP ")
|
||||
upperQuery = upperQuery.replace(" truncate ", " TRUNCATE ")
|
||||
upperQuery = upperQuery.replace(" alter ", " ALTER ")
|
||||
|
||||
# SQL data manipulation
|
||||
upperQuery = upperQuery.replace(" insert ", " INSERT ")
|
||||
upperQuery = upperQuery.replace(" update ", " UPDATE ")
|
||||
upperQuery = upperQuery.replace(" delete ", " DELETE ")
|
||||
upperQuery = upperQuery.replace(" merge ", " MERGE ")
|
||||
|
||||
# SQL data control
|
||||
upperQuery = upperQuery.replace(" grant ", " GRANT ")
|
||||
|
||||
# SQL transaction control
|
||||
upperQuery = upperQuery.replace(" start transaction ", " START TRANSACTION ")
|
||||
upperQuery = upperQuery.replace(" begin work ", " BEGIN WORK ")
|
||||
upperQuery = upperQuery.replace(" begin transaction ", " BEGIN TRANSACTION ")
|
||||
upperQuery = upperQuery.replace(" commit ", " COMMIT ")
|
||||
upperQuery = upperQuery.replace(" rollback ", " ROLLBACK ")
|
||||
for sqlStatements in SQL_STATEMENTS.values():
|
||||
for sqlStatement in sqlStatements:
|
||||
upperQuery = upperQuery.replace(sqlStatement, sqlStatement.upper())
|
||||
|
||||
return upperQuery
|
||||
|
||||
|
||||
@@ -570,7 +570,7 @@ def __setConfAttributes():
|
||||
logger.debug(debugMsg)
|
||||
|
||||
conf.cj = None
|
||||
conf.contentLengths = []
|
||||
conf.pageLengths = []
|
||||
conf.dbmsHandler = None
|
||||
conf.dumpPath = None
|
||||
conf.equalLines = []
|
||||
|
||||
@@ -68,3 +68,44 @@ SUPPORTED_DBMS = MSSQL_ALIASES + MYSQL_ALIASES + PGSQL_ALIASES + ORACLE_ALIAS
|
||||
# TODO: port to command line/configuration file options?
|
||||
SECONDS = 5
|
||||
RETRIES = 3
|
||||
|
||||
SQL_STATEMENTS = {
|
||||
"SQL SELECT statement": (
|
||||
"select ",
|
||||
" from ",
|
||||
" where ",
|
||||
" group by ",
|
||||
" order by ",
|
||||
" having ",
|
||||
" limit ",
|
||||
" offset ",
|
||||
" union all ",
|
||||
" rownum ",
|
||||
),
|
||||
|
||||
"SQL data definition": (
|
||||
"create ",
|
||||
"drop ",
|
||||
"truncate ",
|
||||
"alter ",
|
||||
),
|
||||
|
||||
"SQL data manipulation": (
|
||||
"insert ",
|
||||
"update ",
|
||||
"delete ",
|
||||
"merge ",
|
||||
),
|
||||
|
||||
"SQL data control": (
|
||||
"grant ",
|
||||
),
|
||||
|
||||
"SQL transaction": (
|
||||
"start transaction ",
|
||||
"begin work ",
|
||||
"begin transaction ",
|
||||
"commit ",
|
||||
"rollback ",
|
||||
),
|
||||
}
|
||||
|
||||
@@ -107,6 +107,10 @@ class queriesHandler(ContentHandler):
|
||||
data = sanitizeStr(attrs.get("query"))
|
||||
self.__queries.substring = data
|
||||
|
||||
elif name == "case":
|
||||
data = sanitizeStr(attrs.get("query"))
|
||||
self.__queries.case = data
|
||||
|
||||
elif name == "inference":
|
||||
data = sanitizeStr(attrs.get("query"))
|
||||
self.__queries.inference = data
|
||||
|
||||
@@ -68,15 +68,13 @@ def comparison(page, headers=None, content=False):
|
||||
return False
|
||||
|
||||
# By default it returns the page content MD5 hash
|
||||
if not conf.equalLines and not conf.contentLengths:
|
||||
if not conf.equalLines and not conf.pageLengths:
|
||||
return md5.new(page).hexdigest()
|
||||
|
||||
# TODO: go ahead from here
|
||||
|
||||
# Comparison algorithm based on Content-Length header value
|
||||
elif conf.contentLengths:
|
||||
minValue = conf.contentLengths[0] - 10
|
||||
maxValue = conf.contentLengths[1] + 10
|
||||
# Comparison algorithm based on page length value
|
||||
elif conf.pageLengths:
|
||||
minValue = conf.pageLengths[0]
|
||||
maxValue = conf.pageLengths[1]
|
||||
|
||||
if len(page) >= minValue and len(page) <= maxValue:
|
||||
return True
|
||||
|
||||
@@ -336,6 +336,8 @@ def goStacked(expression):
|
||||
TODO: write description
|
||||
"""
|
||||
|
||||
expression = cleanQuery(expression)
|
||||
|
||||
comment = queries[kb.dbms].comment
|
||||
query = agent.prefixQuery("; %s" % expression)
|
||||
query = agent.postfixQuery("%s;%s" % (query, comment))
|
||||
|
||||
Reference in New Issue
Block a user