# Pantera - Web Pen-Test Proxy # # FILENAME : panterautils.py # CODER : Simon Roses Femerling # DATE : 9/23/2004 # LAST UPDATE : 9/04/2006 # ABSTRACT : Python Web Pen-Test Proxy :) # Pantera utils. Heavely base on SpikeProxy. # # - Roses Labs Innovations (RL+I) # Roses Labs # http://www.roseslabs.com # # Copyright (c) 2003-2006 Roses Labs. # # You may not distribute, transmit, repost this software for commercial # purposes without Roses Labs written permission. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, publish, # distribute the Software, and to permit persons to whom the Software # is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ''' @author: Simon Roses Femerling @license: GNU General Public License 2.0 or later @contact: pantera.proxy@gmail.com @organization: OWASP / Roses Labs ''' # Pantera Utils Imports import os import random import string import cPickle from htmllib import HTMLParser from formatter import DumbWriter, AbstractFormatter from cStringIO import StringIO import re from random import random, choice, uniform import codecs import pantera import panteraLib ############################################################################################# # Defines ############################################################################################# YES = 1 NO = 0 hd = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',] ############################################################################################# # Our Functions ############################################################################################# ############################################################################################# # FUNC : def readuntil # PARAMS : mysocket, mybreakpoint # RETURN : Return data read or "" if none # ABSTRACT : Read until... def readuntil(mysocket,mybreakpoint): ''' Read data until condition @type mysocket: socket @param mysocket: Socket descriptor. @type mybreakpoint: string @param mybreakpoint: string end tag. @return: Return string. ''' data="" length=-len(mybreakpoint) #print "length=%d"%length while data[length:]!=mybreakpoint: newdata=mysocket.recv(1) data+=newdata #print "data=%s"%(data[length:]) return data # EOF: def reauntil ############################################################################################# # FUNC : def urlnormalize # PARAMS : url # RETURN : string # ABSTRACT : Normalize URL def urlnormalize(url): ''' Normalize a URL /cow/../../../bob/bob2.php -> /bob/bob2.php @type url: string @param url: String to mormalize. @return: Return string. ''' #for win32 users f=url.replace("\\","/") if f[-1]=="/": tailslash=1 else: tailslash=0 dot=f.split("/") #while "." in dot: for i in dot: if i == ".": #print dot #dot=dot.remove(".") _=dot.pop(dot.index(".")) while "" in dot: dot.remove("") while ".." in dot: firstdotdot=dot.index("..") #go one directory up if firstdotdot==0: dot.remove(dot[0]) continue #get rid of parent directory dot.remove(dot[firstdotdot-1]) #do this again to get rid of the .. dot.remove(dot[firstdotdot-1]) fin="/".join(dot)+"/"*tailslash if fin=="": fin="/" if fin[0]!="/": fin="/"+fin return fin # EOF: def urlnormalize ############################################################################################# # FUNC : def dmkdir # PARAMS : newdir # RETURN : ... # ABSTRACT : stolen from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/82465 def dmkdir(newdir): ''' works the way a good mkdir should :) - already exists, silently complete - regular file in the way, raise an exception - parent directory(ies) does not exist, make them as well @type newdir: string @param newdir: Create directory with the give name. ''' if os.path.isdir(newdir): pass elif os.path.isfile(newdir): raise OSError("a file with the same name as the desired " \ "dir, '%s', already exists." % newdir) else: head, tail = os.path.split(newdir) if head and not os.path.isdir(head): dmkdir(head) #print "_mkdir %s" % repr(newdir) if tail: if os.path.isdir(newdir): pass try: os.mkdir(newdir) except OSError: pass # EOF: def dmkdir ############################################################################################# # FUNC : def joinallspaces # PARAMS : input # RETURN : string # ABSTRACT : Joins all the spaces in a string def joinallspaces(input): ''' Joins all the spaces in a string. @type input: string @param input: String to join spaces. @return: Return string. ''' inputold="" inputnew=input[:] while inputold!=inputnew: inputold=inputnew[:] inputnew=inputnew.replace(" "," ") return inputnew # EOF: def joinallspaces ############################################################################################# # FUNC : def getrandomnumber # PARAMS : ... # RETURN : Number # ABSTRACT : Get random number def getrandomnumber(): ''' Get a random number. @return: Return number. ''' return random.randrange(1,100000,1) # EOF: def getrandomnumber ############################################################################################# # FUNC : def pathjoin # PARAMS : *paths # RETURN : string # ABSTRACT : Join path def pathjoin(*paths): ''' Join path. @type *paths: list of strings @param *paths: List of string to join. @return: Return string. ''' temp="" for path in paths: #print "Pathjoin "+path if path!="": if path[0]=="/" or path[0]=="\\": #we are windoze compliant! path=path[1:] temp=os.path.join(temp,path) #if the first was an absolute path... if paths[0][0]=="/": temp="/"+temp #add that back return temp # EOF: def pathjoin ############################################################################################# # FUNC : def pathsplit # PARAMS : path # RETURN : list # ABSTRACT : Split path def pathsplit(path): ''' Split path. @type path: string @param path: String to split. @return: Return list. ''' temp=path last="tempval" retList=[] while last!="": temp,last=os.path.split(temp) if last!="": retList=[last]+retList return retList # EOF: pathsplit #following inits are for prettyprint norm = string.maketrans('', '') #builds list of all characters non_alnum = string.translate(norm, norm, string.letters+string.digits) trans_nontext=string.maketrans(non_alnum,'#'*len(non_alnum)) ############################################################################################# # FUNC : def prettyprint # PARAMS : data # RETURN : string # ABSTRACT : Pretty print def prettyprint(data): ''' Pretty Print. @type data: string @param data: String to print. @return: Return string. ''' cleaned=string.translate(data,trans_nontext) return cleaned # EOF: def prettyprint ############################################################################################# # FUNC : def getURLfromFile # PARAMS : file # RETURN : string # ABSTRACT : Open a requestandresponse object in a file and # obtains the url from the header def getURLfromFile(file): ''' Open a requestandresponse object in a file and obtains the url from the header. @type file: path @param file: Path of the file to open. @return: Return string. ''' #load our request and response object infile=open(file,"rb") obj=cPickle.load(infile) infile.close() url=obj.clientheader.URL return url # EOF: def getURLfromFile ############################################################################################# # FUNC : def getDirsFromURL # PARAMS : url # RETURN : list # ABSTRACT : Takes a url like /bob/bob2/bob3/asdf.cgi # and returns [bob,bob2,bob3,asdf.cgi] def getDirsFromURL(url): ''' Takes a url like /bob/bob2/bob3/asdf.cgi and returns [bob,bob2,bob3,asdf.cgi] @type url: string @param url: String to split @return: Return list. ''' dirList=url.split("/") #check for a file at the last one if dirList[-1].count(".")>0: dirList=dirList[:-1] #now combine them up start="/" realDirList=[] for dir in dirList: start+= "%s/" % dir start=start.replace("_directory_","") start=start.replace("///","/") start=start.replace("//","/") realDirList.append(start) return realDirList # EOF: def getDirsFromURL ############################################################################################# # FUNC : def constructRequest # PARAMS : myheader, mybody # RETURN : string # ABSTRACT : Constructs a request given a header and optionally a body def constructRequest(myheader,mybody=None): ''' Constructs a request given a header and optionally a body. @type myheader: class @param myheader: HTTP header class @type myheader: class @param myheader: HTTP body class @return: Return string. ''' #for null value if (mybody==None): mybody = pantera.HTTPBody() #debug if 0: return "GET / HTTP/1.1\r\nHost: www.roseslabs.com\r\nContent-Length: 0\r\n\r\n" request="%s %s%s" % (myheader.verb,myheader.getProxyHeader(),myheader.URL) #if we have arguments if myheader.useRawArguments: if len(myheader.allURLargs) > 0: request+= "?%s" % myheader.allURLargs else: if len(myheader.URLargsDict) > 0: request+="?" request+=joinargs(myheader.URLargsDict,orderlist=myheader.orderlist) request+=" %s\r\n" % myheader.version #ok, the first line is done! #do the rest of the headers that need order #I dunno if any except Host really need ordering, but I do it #to erase any chance of lame bugs later on #plus, python makes it quite easy needOrdered=["Host","User-Agent","Accept","Accept-Language","Accept-Encoding","Accept-Charset","Keep-Alive","Connection","Pragma","Cache-Control"] for avalue in needOrdered: request+=myheader.grabHeader(avalue) #now work on the header pairs we haven't already done for akey in myheader.headerValuesDict.keys(): if akey not in needOrdered: request+=myheader.grabHeader(akey) #ok, headers are all done except for content-length #Content-Length: 0 should always be valid, but it's #not working for some reason on get requests! if mybody.mysize!=0 or myheader.verb!="GET": r = len(mybody.data) if not myheader.surpressContentLength() or r != 0: request+="Content-Length: %s\r\n" % str(len(mybody.data)) #ok, all headers are done, finish with blank line request+="\r\n" #ok, now add body request+="".join(mybody.data) #done! return request # EOF: def constructRequest ############################################################################################# # FUNC : def joinargs # PARAMS : argdict, orderlist # RETURN : string # ABSTRACT : Takes in a dict, returls A=B&C=D,etc def joinargs(argdict,orderlist=[]): ''' Takes in a dict, returls A=B&C=D,etc @type argdict: dict @param argdict: Dict. @type orderlist: list @param orderlist: Follow order. @return: Return string. ''' first=1 result="" donelist=[] for akey in orderlist: donelist.append(akey) if not first: result+="&" first=0 result+= "%s=%s" % (akey,argdict[akey]) for akey in argdict.keys(): if akey in donelist: continue if not first: result+="&" first=0 result+= "%s=%s" % (akey,argdict[akey]) return result # EOF: def joinargs( ############################################################################################# # FUNC : def splitargs # PARAMS : argstring, orderlist # RETURN : dict on succes or none on error # ABSTRACT : Returns a dictionary of a string split like a normal HTTP argument list def splitargs(argstring,orderlist=[]): ''' Returns a dictionary of a string split like a normal HTTP argument list. @type argstring: string @param argstring: String argument. @type orderlist = list @param orderlist: Follow order. @return: Return string. ''' resultDict={} templist=argstring.split("&") for pair in templist: if pair!="": templist2=pair.split("=") if len(templist2)<2: #print "Failed to parse the URL arguments because of #invalid number of equal signs in one argument in: #\""+pair+"\" len="+str(len(templist2)) return None else: #add this argument to the Dict orderlist.append(templist2[0]) resultDict[templist2[0]]="=".join(templist2[1:]) return resultDict # EOF: def splitargs ############################################################################################# # FUNC : def splitstring # PARAMS : astring # RETURN : list # ABSTRACT : Turns a string into a one character list def splitstring(astring): ''' Turns a string into a one character list. @type astring = list @param astring: String to convert into a list. @return: Return string. ''' alist = [ch for ch in astring] return alist # EOF: def splitstring ############################################################################################# # FUNC : def printFormEntry # PARAMS : text, name, value # RETURN : string # ABSTRACT : Print a form entry def printFormEntry(text, name,value, inside_table=0, size=15): ''' Print a form entry. @type text: string @param text: String to display. @type name: string @param name: Name of the input tag. @type inside_table: int @param inside_table: If 0 input tag inside html table, else if 1 input is not in html table. @type size: int @param size: Size of the input tag. @return: Return string. ''' if inside_table==1: result= "%s:\r\n" % (text, name, value, str(size)) else: result= "%s: \r\n" % (text, name, value, str(size)) return result # EOF: def printFormEntry ############################################################################################# # FUNC : def printFormEntryAndValue # PARAMS : name, key, value, file # RETURN : string # ABSTRACT : Here is where you would add actions that you want to take when # you have an argument or variable (on the rewrite request page) def printFormEntryAndValue(name,key,value,inside_table=0, size=15): ''' Here is where you would add actions that you want to take when you have an argument or variable (on the rewrite request page) @type name: string @param name: Name of the input tag. @type key: string @param key: Key of input tag. @type value: string @param value: Value of input tag. @type inside_table: int @param inside_table: If 0 input tag inside html table, else if 1 input is not in html table. @type size: int @param size: Size of the input tag. @return: Return string. ''' result="" if inside_table==1: result+= "%s: :\r\n" % (name,name, key, str(size)) result+= "" % (name,value,str(size)) else: result+= "%s: : " % (name, name, key, str(size)) result+= "" % (name, value, str(size)) result+= "
\n" return result # EOF: def printFormEntryAndValue ############################################################################################# # FUNC : def printFormCheckbox # PARAMS : name, checked # RETURN : string # ABSTRACT : Print a checkbox form def printFormCheckbox(text, name,checked, inside_table=0, size=15): ''' Print a checkbox form. @type text: string @param text: String to display. @type name: string @param name: Name of the input tag. @type checked: string @param checked: Set input check. @type inside_table: int @param inside_table: If 0 input tag inside html table, else if 1 input is not in html table. @type size: int @param size: Size of the input tag. @return: Return string. ''' """ printFormCheckbox func """ result="" if inside_table==1: result+= "%s:\r\n" % (name, value) else: result+= "\r\n" % (name, value) return result # EOF: def printHiddenEntry ############################################################################################# # FUNC : def printFormSelectMenu # PARAMS : string, string, dict, value # RETURN : string # ABSTRACT : print select menu to use in a form def printFormSelectMenu(text, name, dict, inside_table=0): ''' Print select menu to use in a form. @type text: string @param text: String to display. @type name: string @param name: Name of the input tag. @type dict: dict @param dict: Dict to use in select tag. @type inside_table: int @param inside_table: If 0 input tag inside html table, else if 1 input is not in html table. @return: Return string. ''' result = "" if inside_table==1: result+= "%s" % text result+= "\r\n" result+= "\r\n" else: result+= "

%s" % (text) result+= "\r\n" result+= "

\r\n" return result # EOF: def printFormSelectMenu ############################################################################################# # FUNC : def printFormSelectMenuID # PARAMS : string, string, dict, value # RETURN : string # ABSTRACT : print select menu with ID to use in a form def printFormSelectMenuID(text, name, dict, inside_table=0): ''' Print select menu with ID to use in a form. @type text: string @param text: String to display. @type name: string @param name: Name of the input tag. @type dict: dict @param dict: Dict to use in select tag. @type inside_table: int @param inside_table: If 0 input tag inside html table, else if 1 input is not in html table. @return: Return string. ''' result = "" if inside_table==1: result+= "%s" % text result+= "\r\n" result+= "\r\n" else: result+= "

%s" % text result+= "\r\n" result+= "

\r\n" return result # EOF: def printFormSelectMenuID ############################################################################################# # FUNC : def headerdictcmp # PARAMS : dict1, dict2 # RETURN : Return 1 if they are the same, 0 if not # ABSTRACT : Filters out Date: and whatnot # this is basically to detect if we get different Cookies # this is lame, but it should work ok def headerdictcmp(dict1,dict2): ''' Filters out Date: and whatnot this is basically to detect if we get different Cookies this is lame, but it should work ok @type dict1: dict @param dict1: First dict. @type dict2: dict @param dict2: Second dict. @return: Return 0 if they are different, else 1. ''' for akey in dict1.keys(): if akey=="Date": continue if not dict2.has_key(akey): return 0 for bkey in dict1[akey]: if not bkey in dict2[akey]: return 0 return 1 # EOF: def headerdictcmp ############################################################################################# # FUNC : def genhash # PARAMS : clientheader, clientbody, serverheader, serverbody # RETURN : string # ABSTRACT : Hashes a requestandresponse so we can do matches quickly # returns a string as the hash def genhash(clientheader,clientbody,serverheader,serverbody): ''' Hashes a requestandresponse so we can do matches quickly returns a string as the hash @type clientheader: class @param clientheader: Contains a HTTP header class. @type clientbody: class @param clientbody: Contains a HTTP body class. @type serverheader: class @param serverheader: Contains a HTTP body class. @type serverbody: class @param serverbody: Contains a HTTP body class. @return: Return string hash. ''' #print "in genhash" CH=clientheader.genhash() CB=clientbody.genhash() SH=serverheader.genhash() SB=serverbody.genhash() return CH+CB+SH+SB # EOF: def genhash ############################################################################################# # FUNC : def hashstring # PARAMS : astring # RETURN : string # ABSTRACT : Hashes a string to a number, then returns that number as a string def hashstring(astring): ''' Hashes a string to a number, then returns that number as a string. @type astring: string @param astring: String to hash. @return: Return string. ''' i=0 #print "in hashstring" if astring=="": return "" hashnum=0 l=len(astring) while i0: # catch " sign inside, some headers have " inside, so we need to deal with them res = string.replace(res,'\n',' ') # we need all these replaces as some sites send weirds headers.. res = string.replace(res,'\t',' ') res = string.replace(res,'\r\n',' ') response+= "\"%s\\r\\n\"+\r\n" % FixString(res) else: res = string.replace(res,'\n',' ') # we need all these replaces as some sites send weirds headers.. res = string.replace(res,'\t',' ') res = string.replace(res,'\r\n',' ') response+= "\"%s\\r\\n\"+\r\n" % res igrab = myheader.igrabHeader for akey in myheader.headerValuesDict.keys(): #don't send 2 Content-lengths if akey not in [ "Content-Length", "Content-length"]: if akey not in needOrdered: z = "" z = igrab(akey) if z.count('"')>0: # catch " sign inside, some headers have " inside, so we need to deal with them z = string.replace(z,'\n',' ') # we need all these replaces as some sites send weirds headers.. z = string.replace(z,'\t',' ') z = string.replace(z,'\r\n',' ') response+= "\"%s\\r\\n\"+\r\n" % FixString(z) else: z = string.replace(z,'\n',' ') z = string.replace(z,'\t',' ') z = string.replace(z,'\r\n',' ') response+="\"%s\\r\\n\"+\r\n" % z #this may be lame and need to be taken out, but I want people to know. response+= "\"Content-Length: %s\\r\\n" % str(mybody.mysize) return response # EOF: def constructResponseJS ############################################################################################# # FUNC : def daveFormParse # PARAMS : page # RETURN : list # ABSTRACT : Returns a list of urls with arguments we've parsed from the page # very kludgy function def daveFormParse(page): ''' Returns a list of urls with arguments we've parsed from the page very kludgy function. @type page: string @param page: String to be parser. @return: Return list. ''' formList=[] resultList=[] debug_daveformparse=0 if debug_daveformparse: print "ENTERED FORM PARSER" #split the forms out formList=page.split("") if index2==-1: continue form=form[:index2] if debug_daveformparse: print "***Form Url is "+url argsDict={} inputList=form.split(" def collectURLSFromPage(page): ''' Takes in the page as a string, then returns a list of URLS eventally this will do forms as well. :> @type page: string @param page: String to be parser. @return: Return list. ''' resultList=[] #print "Doing form parser" if page.count("0: otherlist=daveFormParse(page) for key in otherlist: resultList.append(key) pass #print "Doing RAW Parser" spamList=rawParse(page) for key in spamList: resultList.append(key) pass #the whole "AbstractFormater()" line is a bunch of crap I copied #That needs to be documented somehow, but I have no idea what it does try: parser=HTMLParser(AbstractFormatter(DumbWriter(StringIO()))) parser.feed(page) parser.close() except: #print "DEBUG: Caught an exception trying to parse that html file." #print "(Not sure why this happens - you'll have to crawl this page manually)" return resultList #print "Adding HTML Parser data" for key in parser.anchorlist: resultList.append(key) pass return resultList # EOF: def collectURLSFromPage ############################################################################################# # FUNC : def Str2List # PARAMS : string, splitter # RETURN : list # ABSTRACT : Convert a string to a list def Str2List(str1,splitter=","): ''' Convert a string to a list @type str1: string @param str1: String to be converted. @type splitter: string @param splitter: String to be used as separator. @return: Return list. ''' d = [] d = str1.split(splitter) return d # EOF: def Str2List ############################################################################################# # FUNC : def List2Str # PARAMS : list, splitter # RETURN : string # ABSTRACT : Convert a list to a string def List2Str(l,splitter=""): ''' Convert a list to a string @type l: list @param l: List to be converted. @type splitter: string @param splitter: String to be used as separator. @return: Return list. ''' s = "" c = 0 for d in l: if c == 0: # ugly but should do s += str(d) else: s += splitter + str(d) c += 1 return s # EOF: def List2Str ############################################################################################# # FUNC : def FixString # PARAMS : string # RETURN : string # ABSTRACT : Fix a string to be displayed def FixString(t): ''' Fix a string to be displayed. @type t: string @param t: String to be displayed. @return: Return list. ''' c_h = "" slen = t.count('"') t1 = string.split(t,'"') i = 0 for c in t1: c_h += c if i < slen: c_h += "\\\"" i+=1 return c_h # EOF: def FixString ############################################################################################# # FUNC : def encode_hex # PARAMS : string # RETURN : string # ABSTRACT : Encode a string to hex def encode_hex(istr): ''' Encode a string to hex @type istr: string @param istr: String to be encoded. @return: Return string. ''' strt = "" con = "%%%02x" for c in istr: if c == '/': continue strt += con % ord(c) return strt # EOF: def encode_hex ############################################################################################# # FUNC : def encode_hex_random # PARAMS : string # RETURN : string # ABSTRACT : Encode a string to hex randomly def encode_hex_random(istr): ''' Encode a string to hex randomly. @type istr: string @param istr: String to be encoded. @return: Return string. ''' strt = "" con = "%%%02x" for c in istr: if c == '/': continue i = int(uniform(0,10)) i = i % 2 if i == 1: strt += con % ord(c) else: strt += c return strt # EOF: def encode_hex_random ############################################################################################# # FUNC : def encode_anti_ids # PARAMS : string, value # RETURN : string # ABSTRACT : Encode a string for Anti-IDS :) def encode_anti_ids(uri, mode = ""): ''' Encode a string for Anti-IDS :) @type uri: string @param uri: URI to be encoded. @type mode: string @param mode: Mode as the URI will be encoded. (1-7) @return: Return string. ''' m = 0 ENCODED = 0 #print uri # mode 4 - prepend long random string if '4' in mode: s = '' if re.match('^/',uri): while(len(s) < 512): x = randstr() s += x uri= "/%s/..%s" % (s, uri) # mode 7 - (windows) random case sensitivity if '7' in mode: strt = "" t = string.split(uri,'/') i = len(t) z = 0 for str in t: for c in str: x = int(uniform(0,10)) x = x % 2 if x == 1: strt += c.upper() else: strt += c if z < i-1: strt += "/" z = z + 1 uri = strt # mode 2 - directory self-reference (/./) if '2' in mode: str = uri p = re.compile('/') str = p.sub('/./', str) uri = str # mode 8 - windows directory separator (\) if '8' in mode: str = uri p = re.compile('/') str = p.sub('\\\\', str) p = re.compile('^\\\\') str = p.sub('/', str) p = re.compile('^(http|file|ftp|nntp|news|telnet):\\\\\\\\',re.IGNORECASE) str = p.sub('://', str) p = re.compile('\\\\$') str = p.sub('/', str) uri = str # mode 1 - random URI (non-UTF8) encoding if '1' in mode: if ENCODED == 0: uri = encode_hex_random(uri) ENCODED = 1 # mode 5 - fake parameter if '5' in mode: s = randstr() y = randstr() uri = "/"+s+".html%3f"+y+"=/../"+uri # mode 3 - premature URL ending if '3' in mode: s = randstr() uri = "/%20HTTP/1.1%0D%0A%0D%0AAccept%3A%20"+s+"/../.."+uri # mode 6 - TAB as request spacer if '6' in mode: uri = "\\t%s" % uri return uri # EOF: def encode_anti_ids ############################################################################################# # FUNC : def randstr # PARAMS : value, string # RETURN : string # ABSTRACT : Return a string value len with random chars def randstr(drift = 10, chars = None): ''' Return a string value len with random chars. @type drift: int @param drift: Number of chars to be return. @type chars: None or string @param chars: Character set to be used. @return: Return string. ''' str = "" if chars == None: chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" while drift > 0: ch = choice(chars) str += ch drift = drift - 1 return str # EOF: def randstr ############################################################################################# # FUNC : def TruncateURL # PARAMS : string, value # RETURN : string # ABSTRACT : Truncate a URL def TruncateURL(u, n=100): ''' Truncate URL. @type u: string @param u: URI to be truncated. @type n: int @param n: Length of URI to be truncated. @return: Return string. ''' s = len(u) if s > n: n = n-3 t = u[:n] t += "..." return t else: return u # EOF: def TruncateURL ############################################################################################# # FUNC : def FilterBadCard # PARAMS : string, value # RETURN : string # ABSTRACT : Filter bad chars in string def FilterBadCar(s="",mode=0): ''' Filter bad chars in string @type s: string @param s: String to be filter out. @type mode: int @param mode: Select which mode to filter. 1) filter out 2) HTML encoding @return: Return string. ''' # we dont allow: <>;-'%;,()#&+"* if mode==0: p = re.compile('[\<\>\;\-\'\%\;\,\(\)\#\&\+\"\*]+') strx = p.sub('',s) else: s = s.replace("&", "&") s = s.replace("<", "<") strx = s.replace(">", ">") #strx = s.replace('"', """) return strx # EOF: def FilterBadCar ############################################################################################# # FUNC : def hex2str # PARAMS : string # RETURN : string # ABSTRACT : Convert hex string to text string. Ripped from NTLM Proxy def hex2str(hex_str): ''' Convert hex string to text string. Ripped from NTLM Proxy. @type hex_str: string @param hex_str: Hex string to be converted. @return: Return string. ''' res = '' for i in range(0, len(hex_str), 2): res = res + (chr(hd.index(hex_str[i]) * 16 + hd.index(hex_str[i+1]))) return res # EOF: def hex2str ############################################################################################# # FUNC : defstr2unicode # PARAMS : string # RETURN : string # ABSTRACT : Convert string to unicode. Ripped from NTLM Proxy def str2unicode(string): ''' Converts ascii string to dumb unicode. Ripped from NTLM Proxy. @type string: string @param string: String to be converted. @return: Return string. ''' res = '' for i in string: res = res + i + '\000' return res # EOF: str2unicode ############################################################################################# # FUNC : utils_split_dir # PARAMS : uri, mode # RETURN : None on error, a list on success # ABSTRACT : Split the URI into a list of dirs def utils_split_dir(uri = None, mode = 1): ''' Split the URI into a list of dirs @type uri: string @param uri: String to be spittled. @type mode: int @param mode: If 1 put / after dir, else put / in front of dir. @return: Return list. ''' uri_split = [] if uri == None: return None i = uri.count('/') if (i >= 0): for z in range(i): str,uri = uri.split('/',1) if str != "": if mode == 1: # Put / after dir str += '/' if mode == 2: # Put / in front of dir t = "" t += '/' + str str = "" str = t uri_split.append(str) # mode != 1 or 2, no / return uri_split else: return None # EOF: def utils_split_dir ############################################################################################# # FUNC : SearchPattern # PARAMS : string, list, regex options # RETURN : Return 1 or 0 # ABSTRACT : Split the URI into a list of dirs def SearchPattern(my_string, l = [], re_ = re.IGNORECASE | re.MULTILINE): ''' Split the URI into a list of dirs @type my_string: string @param my_string: String to be searched. @type l: list @param l: List of string to search for. @type re_: Regex options @param re_: Regex Options (re.IGNORECASE, etc.) @return: Return 1 on pattern found, else 0. ''' for i in l: p = re.compile(i,re_) r = p.search(my_string) if r: return 1 return 0 # EOF: def SearchPattern ############################################################################################# # FUNC : SearchSensibleWords # PARAMS : string, string, regex options # RETURN : list # ABSTRACT : Search sensible words in text data. def SearchSensibleWords(data, file='sensible_words.xml', re_ = re.IGNORECASE | re.MULTILINE): ''' Search sensible words in text data. @type data: string @param data: data to be searched. @type file: string @param file: XML file. @type re_: Regex options @param re_: Regex Options (re.IGNORECASE, etc.) @return: list ''' l = [] # Get XML file data xmlp = panteraLib.SensibleWordsParser() fil = pathjoin(os.getcwd(),"data") xmlp.SetFileName(pathjoin(fil,file)) res = xmlp.BeginParser() if res != 0: return -1 words_l = xmlp.ReturnData() add = l.append for i in words_l: name,re_str = i p = re.compile(re_str,re_) r = p.findall(data) if r: for c in r: s = "%s (%s)" % (name,str(c)) add(s) return l # EOF: def SearchSensibleWords ############################################################################################# # FUNC : FixStringForXML # PARAMS : string, int # RETURN : string # ABSTRACT : Fix text string to be used in XML file. def FixStringForXML(s='', mode=0): ''' Fix text string to be used in XML file. @type s: string @param s: String to be fixed. @type mode: int @param mode: Mode to apply. @return: string ''' strx = '' if mode == 1: s = s.replace("&", "&") s = s.replace("<", "<") s = s.replace(">", ">") strx = s.replace('"', '"') else: # mode 0 s = s.replace("&", "&") s = s.replace("<", "<") s = s.replace(">", ">") strx = s.replace('"', """) return strx # EOF: def FixStringForXML ############################################################################################# # FUNC : quoteattr # PARAMS : string # RETURN : string # ABSTRACT : Escape and quote an attribute value. Ripped from saxutils.py def quoteattr(data): ''' Escape and quote an attribute value. Escape &, <, and > in a string of data, then quote it for use as an attribute value. The \" character will be escaped as well, if necessary. You can escape other strings of data by passing a dictionary as the optional entities parameter. The keys and values must all be strings; each key will be replaced with its corresponding value. Ripped from saxutils.py @type data: string @param data: Data to be escaped and quoted. @return: string ''' data = FilterBadCar(data,1) if '"' in data: if "'" in data: data = '%s' % data.replace('"', """) else: data = "%s" % data else: data = '%s' % data return data # EOF: def quoteattr ############################################################################################# # FUNC : encode_uri_double_percent_hex # PARAMS : string # RETURN : string # ABSTRACT : Encode a URI with Double Percent Hex Encoding. Ripped from wsfuzzer # i.e. 'A' => %2541 def encode_uri_double_percent_hex(str = ""): ''' Encode a URI with Double Percent Hex Encoding. Ripped from wsfuzzer i.e. 'A' => %2541 @type str: string @param str: String to be encoded. @return: Encoded string. ''' strt = "" con = "%%%02x" # first get it in straight hex strt = encode_hex(str) strt = strt.replace("%", con % ord("%")) return strt # EOF: def encode_uri_double_percent_hex ############################################################################################# # FUNC : encode_uri_double_nibble_hex # PARAMS : string # RETURN : string # ABSTRACT : Encode a URI with Double Nibble Hex Encoding. Ripped from wsfuzzer. # i.e. 'A' => %%34%31 def encode_uri_double_nibble_hex(str = ""): ''' Encode a URI with Double Nibble Hex Encoding. Ripped from wsfuzzer. i.e. 'A' => %%34%31 @type str: string @param str: String to be encoded. @return: Encoded string. ''' strt = "" fin = "" con = "%%%02x" p = re.compile(r"/|;|=|:|&|@|\\|\?") # first get it in straight hex strt = encode_hex(str) for c in strt: if not c == "%": if p.search(c): fin += c continue fin += con % ord(c) else: fin += c return fin # EOF: def encode_uri_double_nibble_hex ############################################################################################# # FUNC : encode_uri_first_nibble_hex # PARAMS : string # RETURN : string # ABSTRACT : Encode a URI with First Nibble Hex Encoding. Ripped from wsfuzzer. # i.e. 'A' => %%341 def encode_uri_first_nibble_hex(str = ""): ''' Encode a URI with First Nibble Hex Encoding. Ripped from wsfuzzer. i.e. 'A' => %%341 @type str: string @param str: String to be encoded. @return: Encoded string. ''' strt = "" fin = "" con = "%%%02x" p = re.compile(r"/|;|=|:|&|@|\\|\?") # first get it in straight hex strt = encode_hex(str) count = 0 for c in strt: if not c == "%": if p.search(c): fin += c continue if count == 1: fin += con % ord(c) if count == 2: fin += c else: fin += c count += 1 # reset counter to 0 so as to handle the # hex pattern of %XX if count == 3: count = 0 return fin # EOF: def encode_uri_first_nibble_hex ############################################################################################# # FUNC : encode_uri_second_nibble_hex # PARAMS : string # RETURN : string # ABSTRACT : Encode a URI with Second Nibble Hex Encoding. Ripped from wsfuzzer. # i.e. 'A' => %4%31 def encode_uri_second_nibble_hex(str = ""): ''' Encode a URI with Second Nibble Hex Encoding. Ripped from wsfuzzer. i.e. 'A' => %4%31 @type str: string @param str: String to be encoded. @return: Encoded string. ''' strt = "" fin = "" con = "%%%02x" p = re.compile(r"/|;|=|:|&|@|\\|\?") # first get it in straight hex strt = encode_hex(str) count = 0 for c in strt: if not c == "%": if p.search(c): fin += c continue if count == 1: fin += c if count == 2: fin += con % ord(c) else: fin += c count += 1 # reset counter to 0 so as to handle the # hex pattern of %XX if count == 3: count = 0 return fin # EOF: def encode_uri_second_nibble_hex # RL+I EOF