Wednesday, June 23, 2010

SQLmap 0.8 and SOAP based Web-Services

I Love SQLmap , it's clean, fast, super efficient, fully automated and get's the job done when a POC is needed.

Lately I was pen-testing SOAP Web-Services, and I came to learn that SQLmap wasn't aware of SOAP syntax.

Being the lazy hacker I am the thought of manually testing the entire application using SOAPUI and some tweaking gave me a chill ,So, I have fired up my Python and patched a small mod to let SQLmap do it's magic on SOAP request too.

Basically, the mod instructs SQLmap to parse XML input into parameter-value map in the same manner that SQLmap was parsing GET/POST parameters.

In the same manner of looking for &parametera=valueA&paramB=valueB.. etc. SQLmap now looks into the XML request and parse it to Child and Value (current mod omit the attributes)

That said, if you wanna get some serious injection and SOAP'n dirty (Ha!) try this patch and let me know ;)

There are three files to patch for version 0.8: agent.py, common.py and traget.py
Happy Hunting ;)

--- /Users/osx/Downloads/sqlmap/./lib/core/agent.py 2010-03-05 11:14:36.000000000 +0200
+++ ./lib/core/agent.py 2010-06-20 13:08:35.000000000 +0300
@@ -32,7 +32,7 @@ from lib.core.data import kb
from lib.core.data import queries
from lib.core.data import temp
from lib.core.exception import sqlmapNoneDataException
-
+from xml.etree import ElementTree as ET

class Agent:
"""
@@ -77,7 +77,15 @@ class Agent:
retValue = value.replace(value, newValue)
else:
paramString = conf.parameters[place]
- retValue = paramString.replace("%s=%s" % (parameter, value),
+ if conf.paramDict["POSTxml"]:
+ root = ET.XML(paramString)
+ iterator = root.getiterator(parameter)
+ for child in iterator:
+ child.text =newValue
+ retValue=ET.tostring(root)
+
+ else:
+ retValue = paramString.replace("%s=%s" % (parameter, value),
"%s=%s" % (parameter, newValue))

return retValue
--- /Users/osx/Downloads/sqlmap/./lib/core/common.py 2010-03-05 11:14:36.000000000 +0200
+++ ./lib/core/common.py 2010-06-20 13:54:01.000000000 +0300
@@ -53,6 +53,7 @@ from lib.core.settings import IS_WIN
from lib.core.settings import SITE
from lib.core.settings import SQL_STATEMENTS
from lib.core.settings import VERSION_STRING
+from xml.etree import ElementTree as ET

def paramToDict(place, parameters=None):
"""
@@ -81,9 +82,9 @@ def paramToDict(place, parameters=None):
splitParams = parameters.split(";")
else:
splitParams = parameters.split("&")
-
- for element in splitParams:
- elem = element.split("=")
+ if place is not "POSTxml":
+ for element in splitParams:
+ elem = element.split("=")

if len(elem) == 2:
parameter = elem[0].replace(" ", "")
@@ -94,6 +95,12 @@ def paramToDict(place, parameters=None):
if condition:
value = elem[1]
testableParameters[parameter] = value
+ else:
+
+ root = ET.XML(parameters)
+ iterator = root.getiterator()
+ for child in iterator:
+ testableParameters[child.tag] =child.text

if conf.testParameter and not testableParameters:
paramStr = ", ".join(test for test in conf.testParameter)
--- /Users/osx/Downloads/sqlmap/./lib/core/target.py 2010-03-05 11:14:36.000000000 +0200
+++ ./lib/core/target.py 2010-06-21 12:47:53.000000000 +0300
@@ -24,6 +24,8 @@ Franklin St, Fifth Floor, Boston, MA 02

import os
import time
+"""for RegEx identification of partterns in POST data"""
+import re

from lib.core.common import dataToSessionFile
from lib.core.common import paramToDict
@@ -44,7 +46,7 @@ def __setRequestParams():
"""

__testableParameters = False
-
+ __paramDict = list()
# Perform checks on GET parameters
if conf.parameters.has_key("GET") and conf.parameters["GET"]:
parameters = conf.parameters["GET"]
@@ -60,14 +62,19 @@ def __setRequestParams():
raise sqlmapSyntaxException, errMsg

if conf.data:
- conf.parameters["POST"] = conf.data
- __paramDict = paramToDict("POST", conf.data)
-
- if __paramDict:
- conf.paramDict["POST"] = __paramDict
- __testableParameters = True
+ conf.parameters["POST"] = conf.data
+ """Search the POST data for tags if found - treat as XML"""
+ if re.match(".*<.*>.*", conf.data):
+ conf.paramDict["POSTxml"] = True
+ __paramDict = paramToDict("POSTxml",conf.data)
+ else:
+ __paramDict = paramToDict("POST", conf.data)
+
+ if __paramDict:
+ conf.paramDict["POST"] = __paramDict
+ __testableParameters = True

- conf.method = "POST"
+ conf.method = "POST"

# Perform checks on Cookie parameters
if conf.cookie: