Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d13ad8b

Browse files
committed
fixes #181 - proper save/resume information about single entry UNION SQL injection
1 parent d00e4a4 commit d13ad8b

6 files changed

Lines changed: 92 additions & 46 deletions

File tree

lib/core/agent.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ def payload(self, place=None, parameter=None, value=None, newValue=None, negativ
5555
retValue = ""
5656
newValue = urlencode(newValue)
5757

58-
if negative or conf.paramNegative:
58+
if negative or kb.unionNegative:
5959
negValue = "-"
60-
elif falseCond or conf.paramFalseCond:
60+
elif falseCond or kb.unionFalseCond:
6161
randInt = randomInt()
62-
falseValue = " AND %d=%d" % (randInt, randInt + 1)
62+
falseValue = urlencode(" AND %d=%d" % (randInt, randInt + 1))
6363

6464
# After identifing the injectable parameter
6565
if kb.injPlace == "User-Agent":

lib/core/option.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -872,8 +872,6 @@ def __setConfAttributes():
872872
conf.outputPath = None
873873
conf.paramDict = {}
874874
conf.parameters = {}
875-
conf.paramFalseCond = False
876-
conf.paramNegative = False
877875
conf.path = None
878876
conf.port = None
879877
conf.progressWidth = 54
@@ -932,6 +930,9 @@ def __setKnowledgeBaseAttributes():
932930
kb.unionComment = ""
933931
kb.unionCount = None
934932
kb.unionPosition = None
933+
kb.unionNegative = False
934+
kb.unionFalseCond = False
935+
935936

936937
def __saveCmdline():
937938
"""

lib/core/session.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def setStacked():
199199
if condition:
200200
dataToSessionFile("[%s][%s][%s][Stacked queries][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.stackedTest))
201201

202-
def setUnion(comment=None, count=None, position=None):
202+
def setUnion(comment=None, count=None, position=None, negative=False, falseCond=False):
203203
"""
204204
@param comment: union comment to save in session file
205205
@type comment: C{str}
@@ -226,7 +226,7 @@ def setUnion(comment=None, count=None, position=None):
226226
kb.unionComment = comment
227227
kb.unionCount = count
228228

229-
elif position:
229+
if position:
230230
condition = (
231231
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
232232
( not kb.resumedQueries[conf.url].has_key("Union position")
@@ -238,6 +238,30 @@ def setUnion(comment=None, count=None, position=None):
238238

239239
kb.unionPosition = position
240240

241+
if negative:
242+
condition = (
243+
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
244+
( not kb.resumedQueries[conf.url].has_key("Union negative")
245+
) )
246+
)
247+
248+
if condition:
249+
dataToSessionFile("[%s][%s][%s][Union negative][Yes]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace]))
250+
251+
kb.unionNegative = True
252+
253+
if falseCond:
254+
condition = (
255+
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
256+
( not kb.resumedQueries[conf.url].has_key("Union false condition")
257+
) )
258+
)
259+
260+
if condition:
261+
dataToSessionFile("[%s][%s][%s][Union false condition][Yes]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace]))
262+
263+
kb.unionFalseCond = True
264+
241265
def setRemoteTempPath():
242266
condition = (
243267
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
@@ -430,6 +454,20 @@ def resumeConfKb(expression, url, value):
430454
logMsg += "%s from session file" % kb.unionPosition
431455
logger.info(logMsg)
432456

457+
elif expression == "Union negative" and url == conf.url:
458+
kb.unionNegative = True if value[:-1] == "Yes" else False
459+
460+
logMsg = "resuming union negative "
461+
logMsg += "%s from session file" % kb.unionPosition
462+
logger.info(logMsg)
463+
464+
elif expression == "Union false condition" and url == conf.url:
465+
kb.unionFalseCond = True if value[:-1] == "Yes" else False
466+
467+
logMsg = "resuming union false condition "
468+
logMsg += "%s from session file" % kb.unionPosition
469+
logger.info(logMsg)
470+
433471
elif expression == "Remote temp path" and url == conf.url:
434472
conf.tmpPath = value[:-1]
435473

lib/request/inject.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,16 +368,16 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
368368
warnMsg += "technique, sqlmap is going blind"
369369
logger.warn(warnMsg)
370370

371-
oldParamFalseCond = conf.paramFalseCond
372-
oldParamNegative = conf.paramNegative
373-
conf.paramFalseCond = False
374-
conf.paramNegative = False
371+
oldParamFalseCond = kb.unionFalseCond
372+
oldParamNegative = kb.unionNegative
373+
kb.unionFalseCond = False
374+
kb.unionNegative = False
375375

376376
if blind and not value:
377377
value = __goInferenceProxy(expression, fromUser, expected, batch, resumeValue, unpack, charsetType, firstChar, lastChar)
378378

379-
conf.paramFalseCond = oldParamFalseCond
380-
conf.paramNegative = oldParamNegative
379+
kb.unionFalseCond = oldParamFalseCond
380+
kb.unionNegative = oldParamNegative
381381

382382
if value and isinstance(value, str):
383383
value = value.strip()

lib/techniques/inband/union/test.py

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,26 @@
3333
from lib.parse.html import htmlParser
3434
from lib.request.connect import Connect as Request
3535

36+
def __forgeUserFriendlyValue(payload):
37+
value = ""
38+
39+
if kb.injPlace == "GET":
40+
value = "%s?%s" % (conf.url, payload)
41+
elif kb.injPlace == "POST":
42+
value = "URL:\t'%s'" % conf.url
43+
value += "\nPOST:\t'%s'\n" % payload
44+
elif kb.injPlace == "Cookie":
45+
value = "URL:\t'%s'" % conf.url
46+
value += "\nCookie:\t'%s'\n" % payload
47+
elif kb.injPlace == "User-Agent":
48+
value = "URL:\t\t'%s'" % conf.url
49+
value += "\nUser-Agent:\t'%s'\n" % payload
50+
51+
return value
52+
3653
def __unionPosition(negative=False, falseCond=False):
54+
value = None
55+
3756
if negative or falseCond:
3857
negLogMsg = "partial (single entry)"
3958
else:
@@ -73,6 +92,7 @@ def __unionPosition(negative=False, falseCond=False):
7392

7493
if randQuery in resultPage and not htmlParsed:
7594
setUnion(position=exprPosition)
95+
value = __forgeUserFriendlyValue(payload)
7696

7797
break
7898

@@ -90,47 +110,36 @@ def __unionPosition(negative=False, falseCond=False):
90110

91111
logger.warn(warnMsg)
92112

113+
return value
114+
93115
def __unionConfirm():
116+
value = None
117+
94118
# Confirm the inband SQL injection and get the exact column
95119
# position
96120
if not isinstance(kb.unionPosition, int):
97-
__unionPosition()
121+
value = __unionPosition()
98122

99123
# Assure that the above function found the exploitable full inband
100124
# SQL injection position
101125
if not isinstance(kb.unionPosition, int):
102-
__unionPosition(falseCond=True)
126+
value = __unionPosition(falseCond=True)
103127

104128
# Assure that the above function found the exploitable partial
105129
# (single entry) inband SQL injection position by appending
106130
# a false condition after the parameter value
107131
if not isinstance(kb.unionPosition, int):
108-
__unionPosition(negative=True)
132+
value = __unionPosition(negative=True)
109133

110134
# Assure that the above function found the exploitable partial
111135
# (single entry) inband SQL injection position with negative
112136
# parameter value
113137
if not isinstance(kb.unionPosition, int):
114138
return
115139
else:
116-
conf.paramNegative = True
140+
setUnion(negative=True)
117141
else:
118-
conf.paramFalseCond = True
119-
120-
def __forgeUserFriendlyValue(payload):
121-
value = ""
122-
123-
if kb.injPlace == "GET":
124-
value = "%s?%s" % (conf.url, payload)
125-
elif kb.injPlace == "POST":
126-
value = "URL:\t'%s'" % conf.url
127-
value += "\nPOST:\t'%s'\n" % payload
128-
elif kb.injPlace == "Cookie":
129-
value = "URL:\t'%s'" % conf.url
130-
value += "\nCookie:\t'%s'\n" % payload
131-
elif kb.injPlace == "User-Agent":
132-
value = "URL:\t\t'%s'" % conf.url
133-
value += "\nUser-Agent:\t'%s'\n" % payload
142+
setUnion(falseCond=True)
134143

135144
return value
136145

@@ -142,7 +151,6 @@ def __unionTestByNULLBruteforce(comment):
142151
"""
143152

144153
columns = None
145-
value = None
146154
query = agent.prefixQuery(" UNION ALL SELECT NULL")
147155

148156
for count in range(0, 50):
@@ -161,15 +169,13 @@ def __unionTestByNULLBruteforce(comment):
161169

162170
if seqMatcher >= 0.6:
163171
columns = count + 1
164-
value = __forgeUserFriendlyValue(payload)
165172

166173
break
167174

168-
return value, columns
175+
return columns
169176

170177
def __unionTestByOrderBy(comment):
171178
columns = None
172-
value = None
173179
prevPayload = ""
174180

175181
for count in range(1, 51):
@@ -182,13 +188,11 @@ def __unionTestByOrderBy(comment):
182188
columns = count
183189

184190
elif columns:
185-
value = __forgeUserFriendlyValue(prevPayload)
186-
187191
break
188192

189193
prevPayload = payload
190194

191-
return value, columns
195+
return columns
192196

193197
def unionTest():
194198
"""
@@ -205,25 +209,28 @@ def unionTest():
205209
infoMsg += "'%s' with %s technique" % (kb.injParameter, technique)
206210
logger.info(infoMsg)
207211

208-
value = ""
212+
value = None
209213
columns = None
210214

211215
for comment in (queries[kb.dbms].comment, ""):
212216
if conf.uTech == "orderby":
213-
value, columns = __unionTestByOrderBy(comment)
217+
columns = __unionTestByOrderBy(comment)
214218
else:
215-
value, columns = __unionTestByNULLBruteforce(comment)
219+
columns = __unionTestByNULLBruteforce(comment)
216220

217221
if columns:
218-
setUnion(comment, columns)
222+
setUnion(comment=comment, count=columns)
219223

220224
break
221225

222226
if kb.unionCount:
223-
__unionConfirm()
227+
value = __unionConfirm()
224228
else:
225229
warnMsg = "the target url is not affected by an "
226230
warnMsg += "inband sql injection vulnerability"
227231
logger.warn(warnMsg)
228232

233+
if value is None:
234+
value = ""
235+
229236
return value

lib/techniques/inband/union/use.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
7070
expression = agent.concatQuery(expression, unpack)
7171
expression = unescaper.unescape(expression)
7272

73-
if ( conf.paramNegative or conf.paramFalseCond ) and not direct:
73+
if ( kb.unionNegative or kb.unionFalseCond ) and not direct:
7474
_, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
7575

7676
if len(expressionFieldsList) > 1:

0 commit comments

Comments
 (0)