Saturday, 24 October 2015

[EN] SOAP testing

During one of last projects I needed to test some webservices.

I was wondering: if I can do it with Burp or by manual testing,
maybe I can also write some quick code in python...

And that's how I wrote soapee.py:



---<code>---

root@kali:~/code/soapee-v3# cat soapee3.py
#!/usr/bin/env python
# -------------------------------------
# soapee.py - SOAP fuzz - v0.2
# -------------------------------------
# 16.10.2015

import urllib2
import sys
import re
from bs4 import BeautifulSoup
import httplib
from urlparse import urlparse

target = sys.argv[1]


def sendNewReq(method):
  global soap_header
  print '[+] Sending new request to webapp...'
  toSend = open('./logs/clear-method-'+str(method)+'.txt','r').read()

  parsed = urlparse(target)
  server_addr = parsed.netloc
  service_action =  parsed.path

  body = toSend
  print '[+] Sending:'

  print '[+] Response:'

  headers = {"Content-type": "text/xml; charset=utf-8",
        "Accept": "text/plain",
        "SOAPAction" : '"' + str(soap_header) + '"'
        }

#  print '***********************************'
#  print 'headers: ', headers
#  print '***********************************'
  conn = httplib.HTTPConnection(server_addr)
  conn.request("POST", parsed.path, body, headers)
#  print body
  response = conn.getresponse()

  print '[+] Server said: ', response.status, response.reason
  data = response.read()

  logresp = open('./logs/resp-method-'+ method + '.txt','w')
  logresp.write(data)
  logresp.close()

  print '............start-resp...........................................'
  print data
  print '............stop-resp...........................................\n'


  print '[+] Finished. Next step...'
  print '[.] -----------------------------------------\n'

##

def prepareNewReq(method):
  print '[+] Preparing new request for method: '+str(method)

  fp = open('./logs/method-'+str(method)+'.txt','r')
  fp2 = open('./logs/fuzz-method-'+str(method)+'.txt','w')

  for line in fp:
    if line.find('SOAPAction') != -1:
      global soap_header
      soap_header = line
      soap_header = soap_header.split(" ")
      soap_header = soap_header[1].replace('"','')
      soap_header = soap_header.replace('\r\n','')
#     print soap_header

    newline = line.replace('<font class="value">','')
    newline2 = newline.replace('</font>','')

    newline3 = newline2.replace('string','";\'>')
    newline4 = newline3.replace('int','111111111*11111')
    newline5 = newline4.replace('length','1337')
    newline6 = newline5.replace('<soap:','<soap:')
    newline7 = newline6.replace('</soap:','</soap:')
    newline8 = newline7.replace(' or ','or')

    fp2.write(newline8)

  print '[+] New request prepared.'

  fp2.close()
  print '[+] Clearing file...'
  linez = open('./logs/fuzz-method-'+str(method)+'.txt').readlines()
  open('./logs/clear-method-'+str(method)+'.txt','w').writelines(linez[6:])


  fp.close()
  fp2.close()
  sendNewReq(method)

##


# compose_link(method), get it, and save new req to file
def compose_link(method):
  methodLink = target + '?op='+ method
  print '[+] Getting: ', method

  fp = open('./logs/method-'+str(method)+'.txt','w')

  req = urllib2.urlopen(methodLink)
  page = req.read()
  soup = BeautifulSoup(page)

  for pre in soup.find('pre'):
    fp.write(str(pre))

  print '[+] Method body is saved to file for future analysis.'
  fp.close()

  prepareNewReq(method)

##

## main
def main():
  print '        _________________'
  print '        (*(( soapee ))*)'
  print '             ^^^^^^\n'

  url1 = urllib2.urlopen(target)
  page1 = url1.readlines()

  # get_links_to_methods
  print '[+] Looking for methods:\n------------------------'
  for href in page1:
    hr = re.compile('<a href="(.*)\.asmx\?op=(.*?)">') #InfoExpert.asmx?op=GetBodyList">GetBodyList</a>')
    found = re.search(hr,href)
    if found: # at this stage we need to create working link for each found method
      method = found.group(2)

      # found method get as URL for pre content to next request
      compose_link(method)



  # ...
  #     ... get example of each req
  #           ... change each str/int to fuzzval
  #     ... send modified req
  print '---------------------------\ndone.'

##



try:
  main()

except IndexError, e:
  print 'usage: ' + str(sys.argv[1]) + ' http://link/to/WebService.asmx\n'

root@kali:~/code/soapee-v3#

---</code>---
Also@pastebin;)



As you can see it's just a proof of concept (mosty to find some useful information disclosure bugs) but the skeleton can be used to prepare more advanced tools.

Maybe you will find it useful.

Enjoy ;)




No comments:

Post a comment

What do You think...?