├── LICENSE ├── README.md └── burp-encode-ip.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Eric Labrador Sainz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## About 2 | 3 | This extension will encode an IP address into a bunch of less known encoding techniques. 4 | 5 | This technique is focused on testing vulnerabilities such as SSRF [Server-Side Request Forgery], Open Redirect or RFI [Remote File Inclusion]. 6 | 7 | ## TL;DR 8 | 9 | ### Easy Install 10 | 11 | If you have Burp Pro it is possible to install directly on BApp: 12 | 13 | ![image](https://github.com/e1abrador/Burp-Encode-IP/assets/74373745/3cb11dfd-1fba-4ec2-ad5a-242d9a2e12d5) 14 | 15 | Don't forget to rate the extension with ⭐⭐⭐⭐⭐ stars ;) 16 | 17 | ### Installation 18 | 19 | Go to the Extensions -> Installed -> Add -> burp-encode-ip.py 20 | 21 | In order to use Unicode characters please follow the steps in the video: 22 | 23 | [change_burp_font.webm](https://github.com/e1abrador/Burp-Encode-IP/assets/74373745/6cc9b169-766f-4693-aab3-9bb4977f1e60) 24 | 25 | ## Using 26 | 27 | [Demo.webm](https://github.com/e1abrador/Burp-Encode-IP/assets/74373745/a97b1425-518c-4515-944a-743aea6d9745) 28 | 29 | ## Encodes 30 | 31 | Unicode Encoding (Url Encoded) -> Will convert an IP address First to Unicode format and then to URL Encode. 32 | 33 | Unicode Encoding (Copy to Clipboard) -> Wil convert the IP address to its Unicode version. Could you paste it on the same action? I did not find any way on Burp Suite to paste Unicode from the script, therefore I added a popup window that will let the user copy the characters on the clipboard and then paste it directly to Burp Suite. 34 | 35 | IPv4 on IPv6 Unicode Encoding (URL Encoded) -> Will convert an IP address to the following format (URL Encoded): ``[::ⓕⓕⓕⓕ:unicoded-ip-address-here]:80``. This can be useful to bypass some filters / WAF rules. [Twitter PoC](https://twitter.com/HusseiN98D/status/1681347329243201553) 36 | 37 | IPv4 on IPv6 Unicode Encoding (Copy to Clipboard) -> As well as ``Unicode Encoding (Copy to Clipboard)`` i did not find a way to paste Unicode special characters on Burp Suite (Repeater and Proxy) so when clicking this option the user will see a popup window to copy and paste the generated payload. 38 | 39 | Class B Encoding -> Will convert the IP address in two parts: the first two octets are preserved as is and the last two are combined into a single value. 40 | 41 | Class A Encoding -> Will preserve the first octet as is and will combine the remaining three octets into a single value. 42 | 43 | Hex Encoding -> Will convert the octets of the IP address to hexadecimal values. 44 | 45 | Hex w/o dots -> Will convert the IP address to a single hexadecimal value without dots. 46 | 47 | Hex Encoding v1 -> Will convert the first octet to hex and combine the remaining three octets into a single hexadecimal value. 48 | 49 | Hex Encoding v2 -> Will convert the first two octets to individual hexadecimal values, and the last two octets are combined into a single hexadecimal value. 50 | 51 | Octal Encoding -> Will convert the octets of the IP address to octal values. 52 | 53 | Octal with 0s Encoding -> Will convert each octet into a zero-padded octal value. 54 | 55 | Mixed Encoding -> Will treat the entire IP address as a single integer value. Each octet of the IP address is interpreted as a byte, and these bytes are combined to form a single integer. 56 | 57 | Collaborator in IPv6 -> Will use a collaborator URL (automatically obtained from Burp API) and will convert it to an IPv6 valid domain. 58 | 59 | DNS Rebinding -> Will generate a domain configured with the DNS Rebinding technique (thanks to https://twitter.com/taviso). In any case, there's the possibility of adding a custom domain (Note that in order for the custom domain to work, this https://github.com/taviso/rbndr must be configured first). 60 | 61 | All -> Will generate a popup window that will contain the IP address encoded in all configured conversions currently existing on the extension. 62 | 63 | Good luck and good hunting! 64 | If you really love the tool (or any others), or they helped you find an awesome bounty, consider [BUYING ME A COFFEE!](https://www.buymeacoffee.com/e1abrador) ☕ (I could use the caffeine!) 65 | 66 | ⚪ e1abrador 67 | 68 | Buy Me a Coffee at ko-fi.com 69 | 70 | ## TODO 71 | 72 | - Implement random number of octets encoding, in example: 0251.254.169.254 = 169.254.169.254. 73 | 74 | ## Changelog 75 | 76 | **25/08/2023** -> Update integrating DNS Rebinding technique. 77 | 78 | ## Advisory 79 | 80 | This Burp Suite extension should be used for authorized penetration testing and/or educational purposes only. Any misuse of this software will not be the responsibility of the author or of any other collaborator. Use it at your own networks and/or with the network owner's permission. 81 | -------------------------------------------------------------------------------- /burp-encode-ip.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from burp import IBurpExtender 3 | from javax.swing import BoxLayout 4 | from burp import IBurpCollaboratorClientContext 5 | from burp import IContextMenuFactory 6 | from burp import IContextMenuInvocation 7 | from javax.swing import JMenuItem 8 | from java.util import ArrayList 9 | from java.net import URLEncoder 10 | from javax.swing import JMenuItem, JOptionPane, JDialog, JTextArea, JButton, JScrollPane 11 | from java.awt import BorderLayout 12 | import socket 13 | import sys 14 | from javax.swing import JLabel 15 | import re 16 | from javax.swing import JTextField 17 | from java.awt.datatransfer import StringSelection 18 | from java.awt import Toolkit 19 | from javax.swing import JPanel, JEditorPane 20 | from javax.swing import Box 21 | from java.awt import BorderLayout 22 | from javax.swing.border import EmptyBorder 23 | 24 | class BurpExtender(IBurpExtender, IContextMenuFactory): 25 | 26 | def registerExtenderCallbacks(self, callbacks): 27 | self._callbacks = callbacks 28 | self._collaboratorClient = callbacks.createBurpCollaboratorClientContext() 29 | sys.stdout = callbacks.getStdout() # Redirige stdout a la pestaña de alertas de Burp 30 | self._callbacks = callbacks 31 | self._helpers = callbacks.getHelpers() 32 | callbacks.setExtensionName("Encode IP") 33 | callbacks.registerContextMenuFactory(self) 34 | print("Encode IP - v1.4") 35 | print("by Eric Labrador") 36 | print("") 37 | print("The documentation can be found at https://github.com/e1abrador/Burp-Encode-IP/blob/main/README.md") 38 | print("If you ever see anything in the Errors tab, please raise an issue on Github so I can fix it!") 39 | 40 | def createMenuItems(self, invocation): 41 | self.context = invocation 42 | menu_list = ArrayList() 43 | menu_list.add(JMenuItem("Unicode Encoding (URL Encoded)", actionPerformed=self.encode_ip)) 44 | menu_list.add(JMenuItem("Unicode Encoding (Copy to Clipboard)", actionPerformed=self.encode_ip_unicode)) 45 | menu_list.add(JMenuItem("IPv4 on IPv6 Unicode Encoding (URL Encoded)", actionPerformed=self.apply_unicode_encoding)) 46 | menu_list.add(JMenuItem("IPv4 on IPv6 Encoding (Show and Copy to Clipboard)", actionPerformed=self.show_and_encode_ipv4_to_ipv6)) 47 | menu_list.add(JMenuItem("Class B Encoding", actionPerformed=self.class_b_encoding)) 48 | menu_list.add(JMenuItem("Class A Encoding", actionPerformed=self.class_a_encoding)) 49 | menu_list.add(JMenuItem("Hex Encoding", actionPerformed=self.hex_encoding)) 50 | menu_list.add(JMenuItem("Hex w/o dots", actionPerformed=self.hex_no_dots_encoding)) 51 | menu_list.add(JMenuItem("Hex Encoding v1", actionPerformed=self.hex_v1_encoding)) 52 | menu_list.add(JMenuItem("Hex Encoding v2", actionPerformed=self.hex_v2_encoding)) 53 | menu_list.add(JMenuItem("Octal Encoding", actionPerformed=self.octal_encoding)) 54 | menu_list.add(JMenuItem("Octal with 0s Encoding", actionPerformed=self.octal_with_zeros_encoding)) 55 | menu_list.add(JMenuItem("Mixed Encoding", actionPerformed=self.mixed_encoding)) 56 | menu_list.add(JMenuItem("Decimal Integer Encoding", actionPerformed=lambda _: self.integer_encoding())) 57 | menu_list.add(JMenuItem("Insert Collaborator IPv6 payload", actionPerformed=self.domain_ipv6)) 58 | menu_list.add(JMenuItem("Insert DNS Rebinding payload", actionPerformed=lambda _: self.insert_dns_rebinding_payload())) 59 | menu_list.add(JMenuItem("All", actionPerformed=self.encode_all)) 60 | menu_list.add(JMenuItem("Help", actionPerformed=self._tabHelpUI)) 61 | 62 | return menu_list # Agregar esta línea 63 | 64 | def _tabHelpUI(self, event): 65 | dialog = JDialog() 66 | dialog.setSize(1000, 1000) # Adjust size as necessary 67 | dialog.setLayout(BorderLayout()) 68 | 69 | panel = JPanel(BorderLayout()) 70 | panel.setBorder(EmptyBorder(10, 10, 10, 10)) 71 | 72 | editorPaneInfo = JEditorPane() 73 | editorPaneInfo.setEditable(False) 74 | editorPaneInfo.setContentType("text/html") 75 | 76 | htmlString = "

Author:\t\t\tEric Labrador Sainz

Github:\t\t\thttps://github.com/e1abrador/Burp-Encode-IP/

\t\t

Issues with the extension: https://github.com/e1abrador/Burp-Encode-IP/issues/new

\t\t

Ideas: https://github.com/e1abrador/Burp-Encode-IP/pulls

" 77 | htmlString += """ 78 |

About

\n

This extension will encode an IP address into a bunch of less known encoding techniques.

\n

This technique is focused on testing vulnerabilities such as SSRF [Server-Side Request Forgery], Open Redirect or RFI [Remote File Inclusion].

79 |

Prerequisites

80 |

In order to be able to use Unicode encoding functions you need to change the default Burp Suite font to Monospaced (or any other supporting Unicode characters), if the font is not changed you won't be able to use Unicode characters on Burp.

81 |

82 |

\"Change

83 |

Usage

84 | The usage of the extension is very easy, first you need to highlight an IP address: 85 |

86 |

\"Change

87 |

88 |

Then, you must just right-click and select the encoding you want to use. On most encodings the auto substitution works properly, but i did not found any way of automating that action with Unicode characters.

89 |

90 |

\"Change

91 |

92 |

Supported Encodes

93 |

Unicode Encoding (Url Encoded) -> Will convert an IP address First to Unicode format and then to URL Encode.

94 |

Unicode Encoding (Copy to Clipboard) -> Wil convert the IP address to its Unicode version. Could you paste it on the same action? I did not find any way on Burp Suite to paste Unicode from the script, therefore I added a popup window that will let the user copy the characters on the clipboard and then paste it directly to Burp Suite.

95 |

IPv4 on IPv6 Unicode Encoding (URL Encoded) -> Will convert an IP address to the following format (URL Encoded): [::ffff:unicoded-ip-address-here]:80. This can be useful to bypass some filters / WAF rules.

96 |

IPv4 on IPv6 Unicode Encoding (Copy to Clipboard) -> As well as Unicode Encoding (Copy to Clipboard) i did not find a way to paste Unicode special characters on Burp Suite (Repeater and Proxy) so when clicking this option the user will see a popup window to copy and paste the generated payload.

97 |

Class B Encoding -> Will convert the IP address in two parts: the first two octets are preserved as is and the last two are combined into a single value.

98 |

Class A Encoding -> Will preserve the first octet as is and will combine the remaining three octets into a single value.

99 |

Hex Encoding -> Will convert the octets of the IP address to hexadecimal values.

100 |

Hex w/o dots -> Will convert the IP address to a single hexadecimal value without dots.

101 |

Hex Encoding v1 -> Will convert the first octet to hex and combine the remaining three octets into a single hexadecimal value.

102 |

Hex Encoding v2 -> Will convert the first two octets to individual hexadecimal values, and the last two octets are combined into a single hexadecimal value.

103 |

Octal Encoding -> Will convert the octets of the IP address to octal values.

104 |

Octal with 0s Encoding -> Will convert each octet into a zero-padded octal value.

105 |

Mixed Encoding -> Will treats the entire IP address as a single integer value. Each octet of the IP address is interpreted as a byte, and these bytes are combined to form a single integer.

106 |

Collaborator in IPv6 -> Will convert a collaborator URL (automatically obtained from Burp API) and will convert it to a IPv6 valid domain. 107 |

DNS Rebinding -> Will generate a domain configured with the DNS Rebinding technique (thanks to https://twitter.com/taviso). In any case, there's the possibility of adding a custom domain (Note that in order for this to work, this https://github.com/taviso/rbndr must be configured first). 108 |

All -> Will generate a popup window that will contain the IP address encoded in all configured conversions currently existing on the extension.

109 |

Advisory

110 |

This Burp Suite extension should be used for authorized penetration testing and/or educational purposes only. Any misuse of this software will not be the responsibility of the author or of any other collaborator. Use it at your own networks and/or with the network owner's permission.

111 |

Good luck and good hunting! If you really love the tool (or any others), or they helped you find an awesome bounty, consider BUYING ME A COFFEE! [https://www.buymeacoffee.com/e1abrador] (I could use the caffeine!)

112 | """ 113 | editorPaneInfo.setText(htmlString) 114 | 115 | # Create a JScrollPane and add your JEditorPane to it 116 | scrollPane = JScrollPane(editorPaneInfo) 117 | panel.add(scrollPane, BorderLayout.CENTER) 118 | dialog.add(panel) 119 | 120 | dialog.setVisible(True) 121 | 122 | def insert_dns_rebinding_payload(self): 123 | # Create a popup with three fields: two for IP addresses and one for domain 124 | panel = JPanel() 125 | panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS)) 126 | 127 | label1 = JLabel("Enter IP Address 1:") 128 | ipField1 = JTextField(15) 129 | 130 | label2 = JLabel("Enter IP Address 2:") 131 | ipField2 = JTextField(15) 132 | 133 | label3 = JLabel("Enter Domain (optional, default rbndr.us):") 134 | domainField = JTextField(15) 135 | 136 | panel.add(label1) 137 | panel.add(ipField1) 138 | panel.add(Box.createVerticalStrut(10)) 139 | 140 | panel.add(label2) 141 | panel.add(ipField2) 142 | panel.add(Box.createVerticalStrut(10)) 143 | 144 | panel.add(label3) 145 | panel.add(domainField) 146 | 147 | panel.setBorder(EmptyBorder(10,10,10,10)) 148 | 149 | result = JOptionPane.showConfirmDialog(None, panel, "Insert DNS Rebinding payload", JOptionPane.OK_CANCEL_OPTION) 150 | 151 | if result == JOptionPane.OK_OPTION: 152 | ip1 = ipField1.getText() 153 | ip2 = ipField2.getText() 154 | 155 | # If the domain field is empty, use 'rbndr.us'. Otherwise, use the domain provided by the user. 156 | custom_domain = domainField.getText() or "rbndr.us" 157 | 158 | if self.valid_ip(ip1) and self.valid_ip(ip2): 159 | domain = self.convert_dotted_quad(ip1) + "." + self.convert_dotted_quad(ip2) + "." + custom_domain 160 | self.insert_into_request(domain) 161 | else: 162 | print("") 163 | 164 | def valid_ip(self, addr): 165 | pattern = re.compile(r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$') 166 | return pattern.match(addr) is not None 167 | 168 | def convert_dotted_quad(self, addr): 169 | ip_parts = addr.split('.') 170 | hex_parts = [format(int(part), '02x') for part in ip_parts] 171 | return ''.join(hex_parts) 172 | 173 | def insert_into_request(self, domain): 174 | http_traffic = self.context.getSelectedMessages() 175 | for traffic in http_traffic: 176 | request = traffic.getRequest() 177 | selectedData = self._helpers.bytesToString(request) 178 | 179 | # Simplemente añadir el dominio al final de la petición 180 | modifiedData = selectedData + domain 181 | 182 | traffic.setRequest(self._helpers.stringToBytes(modifiedData)) 183 | 184 | 185 | def integer_encoding(self): 186 | http_traffic = self.context.getSelectedMessages() 187 | bounds = self.context.getSelectionBounds() 188 | start, end = bounds[0], bounds[1] 189 | 190 | for traffic in http_traffic: 191 | request = traffic.getRequest() 192 | selectedIP = self._helpers.bytesToString(request[start:end]) 193 | 194 | try: 195 | socket.inet_aton(selectedIP) 196 | encodedIP = self.encode_ip_integer(selectedIP) 197 | encodedBytes = self._helpers.stringToBytes(encodedIP) 198 | newRequest = request[:start] + encodedBytes + request[end:] 199 | traffic.setRequest(newRequest) 200 | except socket.error: 201 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 202 | pass 203 | 204 | def encode_ip_integer(self, ip): 205 | ip_parts = ip.split('.') 206 | if len(ip_parts) != 4: 207 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 208 | 209 | encoded = (int(ip_parts[0]) << 24) + (int(ip_parts[1]) << 16) + (int(ip_parts[2]) << 8) + int(ip_parts[3]) 210 | 211 | return str(encoded) 212 | 213 | def mixed_encoding(self, event): 214 | http_traffic = self.context.getSelectedMessages() 215 | bounds = self.context.getSelectionBounds() 216 | start, end = bounds[0], bounds[1] 217 | 218 | for traffic in http_traffic: 219 | request = traffic.getRequest() 220 | selectedIP = self._helpers.bytesToString(request[start:end]) 221 | 222 | try: 223 | socket.inet_aton(selectedIP) 224 | encodedIP = self.encode_ip_mixed(selectedIP) 225 | encodedBytes = self._helpers.stringToBytes(encodedIP) 226 | newRequest = request[:start] + encodedBytes + request[end:] 227 | traffic.setRequest(newRequest) 228 | except socket.error: 229 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 230 | pass 231 | 232 | def encode_ip_mixed(self, ip): 233 | ip_parts = ip.split('.') 234 | if len(ip_parts) != 4: 235 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 236 | 237 | encoded = ip_parts[0] + '.0x%x.' % int(ip_parts[1]) + '%012o.' % int(ip_parts[2]) + '0x%x' % int(ip_parts[3]) 238 | 239 | return encoded 240 | 241 | def octal_with_zeros_encoding(self, event): 242 | http_traffic = self.context.getSelectedMessages() 243 | bounds = self.context.getSelectionBounds() 244 | start, end = bounds[0], bounds[1] 245 | 246 | for traffic in http_traffic: 247 | request = traffic.getRequest() 248 | selectedIP = self._helpers.bytesToString(request[start:end]) 249 | 250 | try: 251 | socket.inet_aton(selectedIP) 252 | encodedIP = self.encode_ip_octal_with_zeros(selectedIP) 253 | encodedBytes = self._helpers.stringToBytes(encodedIP) 254 | newRequest = request[:start] + encodedBytes + request[end:] 255 | traffic.setRequest(newRequest) 256 | except socket.error: 257 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 258 | pass 259 | 260 | def encode_ip_octal_with_zeros(self, ip): 261 | ip_parts = ip.split('.') 262 | if len(ip_parts) != 4: 263 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 264 | 265 | encoded = '.'.join('%012o' % int(part) for part in ip_parts) 266 | return encoded 267 | 268 | def octal_with_zeros_encoding(self, event): 269 | http_traffic = self.context.getSelectedMessages() 270 | bounds = self.context.getSelectionBounds() 271 | start, end = bounds[0], bounds[1] 272 | 273 | for traffic in http_traffic: 274 | request = traffic.getRequest() 275 | selectedIP = self._helpers.bytesToString(request[start:end]) 276 | 277 | try: 278 | socket.inet_aton(selectedIP) 279 | encodedIP = self.encode_ip_octal_with_zeros(selectedIP) 280 | encodedBytes = self._helpers.stringToBytes(encodedIP) 281 | newRequest = request[:start] + encodedBytes + request[end:] 282 | traffic.setRequest(newRequest) 283 | except socket.error: 284 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 285 | pass 286 | 287 | def encode_ip_octal_with_zeros(self, ip): 288 | ip_parts = ip.split('.') 289 | if len(ip_parts) != 4: 290 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 291 | 292 | encoded = '.'.join('%012o' % int(part) for part in ip_parts) 293 | return encoded 294 | 295 | def octal_encoding(self, event): 296 | http_traffic = self.context.getSelectedMessages() 297 | bounds = self.context.getSelectionBounds() 298 | start, end = bounds[0], bounds[1] 299 | 300 | for traffic in http_traffic: 301 | request = traffic.getRequest() 302 | selectedIP = self._helpers.bytesToString(request[start:end]) 303 | 304 | try: 305 | socket.inet_aton(selectedIP) 306 | encodedIP = self.encode_ip_octal(selectedIP) 307 | encodedBytes = self._helpers.stringToBytes(encodedIP) 308 | newRequest = request[:start] + encodedBytes + request[end:] 309 | traffic.setRequest(newRequest) 310 | except socket.error: 311 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 312 | pass 313 | 314 | def encode_ip_octal(self, ip): 315 | ip_parts = ip.split('.') 316 | if len(ip_parts) != 4: 317 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 318 | 319 | encoded = '.'.join('0%o' % int(part) for part in ip_parts) 320 | return encoded 321 | 322 | def hex_v2_encoding(self, event): 323 | http_traffic = self.context.getSelectedMessages() 324 | bounds = self.context.getSelectionBounds() 325 | start, end = bounds[0], bounds[1] 326 | 327 | for traffic in http_traffic: 328 | request = traffic.getRequest() 329 | selectedIP = self._helpers.bytesToString(request[start:end]) 330 | 331 | try: 332 | socket.inet_aton(selectedIP) 333 | encodedIP = self.encode_ip_hex_v2(selectedIP) 334 | encodedBytes = self._helpers.stringToBytes(encodedIP) 335 | newRequest = request[:start] + encodedBytes + request[end:] 336 | traffic.setRequest(newRequest) 337 | except socket.error: 338 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 339 | pass 340 | 341 | def encode_ip_hex_v2(self, ip): 342 | ip_parts = ip.split('.') 343 | if len(ip_parts) != 4: 344 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 345 | 346 | # Hex Encoding v2: convert the first two parts individually to hex, 347 | # then convert the last two parts combined to hex 348 | encoded = '0x%x.0x%x.0x%04x' % (int(ip_parts[0]), int(ip_parts[1]), int(ip_parts[2])*256 + int(ip_parts[3])) 349 | 350 | return encoded 351 | 352 | def hex_v1_encoding(self, event): 353 | http_traffic = self.context.getSelectedMessages() 354 | bounds = self.context.getSelectionBounds() 355 | start, end = bounds[0], bounds[1] 356 | 357 | for traffic in http_traffic: 358 | request = traffic.getRequest() 359 | selectedIP = self._helpers.bytesToString(request[start:end]) 360 | 361 | try: 362 | socket.inet_aton(selectedIP) 363 | encodedIP = self.encode_ip_hex_v1(selectedIP) 364 | encodedBytes = self._helpers.stringToBytes(encodedIP) 365 | newRequest = request[:start] + encodedBytes + request[end:] 366 | traffic.setRequest(newRequest) 367 | except socket.error: 368 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 369 | pass 370 | 371 | def encode_ip_hex_v1(self, ip): 372 | ip_parts = ip.split('.') 373 | if len(ip_parts) != 4: 374 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 375 | 376 | # Hex Encoding v1: take the first part of IP separately and rest combined 377 | encoded = '0x%x.' % int(ip_parts[0]) + '0x' + ''.join('%02x' % int(part) for part in ip_parts[1:]) 378 | 379 | return encoded 380 | 381 | def hex_no_dots_encoding(self, event): 382 | http_traffic = self.context.getSelectedMessages() 383 | bounds = self.context.getSelectionBounds() 384 | start, end = bounds[0], bounds[1] 385 | 386 | for traffic in http_traffic: 387 | request = traffic.getRequest() 388 | selectedIP = self._helpers.bytesToString(request[start:end]) 389 | 390 | try: 391 | socket.inet_aton(selectedIP) 392 | encodedIP = self.encode_ip_hex_no_dots(selectedIP) 393 | encodedBytes = self._helpers.stringToBytes(encodedIP) 394 | newRequest = request[:start] + encodedBytes + request[end:] 395 | traffic.setRequest(newRequest) 396 | except socket.error: 397 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 398 | pass 399 | 400 | def encode_ip_hex_no_dots(self, ip): 401 | ip_parts = ip.split('.') 402 | if len(ip_parts) != 4: 403 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 404 | 405 | # Codificación hexadecimal sin puntos 406 | encoded = ''.join('%02x' % int(part) for part in ip_parts) 407 | 408 | return '0x' + encoded 409 | 410 | def hex_encoding(self, event): 411 | http_traffic = self.context.getSelectedMessages() 412 | bounds = self.context.getSelectionBounds() 413 | start, end = bounds[0], bounds[1] 414 | 415 | for traffic in http_traffic: 416 | request = traffic.getRequest() 417 | selectedIP = self._helpers.bytesToString(request[start:end]) 418 | 419 | try: 420 | socket.inet_aton(selectedIP) 421 | encodedIP = self.encode_ip_hex(selectedIP) 422 | encodedBytes = self._helpers.stringToBytes(encodedIP) 423 | newRequest = request[:start] + encodedBytes + request[end:] 424 | traffic.setRequest(newRequest) 425 | except socket.error: 426 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 427 | pass 428 | 429 | def encode_ip_hex(self, ip): 430 | ip_parts = ip.split('.') 431 | if len(ip_parts) != 4: 432 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 433 | encoded = '.'.join('0x%x' % int(part) for part in ip_parts) 434 | return encoded 435 | 436 | def show_and_encode_ipv4_to_ipv6(self, event): 437 | http_traffic = self.context.getSelectedMessages() 438 | bounds = self.context.getSelectionBounds() 439 | start, end = bounds[0], bounds[1] 440 | 441 | for traffic in http_traffic: 442 | request = traffic.getRequest() 443 | selectedIP = self._helpers.bytesToString(request[start:end]) 444 | 445 | try: 446 | socket.inet_aton(selectedIP) 447 | encodedIP = self.transform_ip_to_unicode(selectedIP) 448 | self.show_popup_dialog("IPv4 on IPv6 Encoded IP", encodedIP) 449 | except socket.error: 450 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 451 | pass 452 | 453 | def transform_ip_to_unicode(self, ip): 454 | unicode_nums = [u'⓪', u'①', u'②', u'③', u'④', u'⑤', u'⑥', u'⑦', u'⑧', u'⑨'] 455 | ip_parts = ip.split('.') 456 | 457 | if len(ip_parts) != 4: 458 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 459 | 460 | encoded = u"[::ⓕⓕⓕⓕ:" 461 | for part in ip_parts: 462 | for digit in part: 463 | if digit.isdigit(): 464 | encoded += unicode_nums[int(digit)] 465 | else: 466 | encoded += digit 467 | encoded += u"。" 468 | encoded = encoded.rstrip(u"。") + u"]:80" # remove the last dot and append ]:80 469 | 470 | return encoded 471 | 472 | def encode_ip_unicode(self, event): 473 | http_traffic = self.context.getSelectedMessages() 474 | bounds = self.context.getSelectionBounds() 475 | start, end = bounds[0], bounds[1] 476 | 477 | for traffic in http_traffic: 478 | request = traffic.getRequest() 479 | selectedIP = self._helpers.bytesToString(request[start:end]) 480 | 481 | try: 482 | socket.inet_aton(selectedIP) 483 | encodedIP = self.convert_ip_to_unicode(selectedIP) 484 | self.show_popup_dialog("Encoded IP", encodedIP) 485 | except socket.error: 486 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 487 | pass 488 | 489 | def convert_ip_to_unicode(self, ip): 490 | unicode_ip = "" 491 | for part in ip.split("."): 492 | for digit in part: 493 | if digit == '0': 494 | unicode_ip += u'\u24EA' # caso especial para 0 495 | else: 496 | unicode_ip += unichr(0x245F + int(digit)) # 0x2460 es para 1, por lo que 0x245F + dígito da la asignación correcta 497 | unicode_ip += u'\u3002' # Unicode para punto final ideográfico 498 | return unicode_ip[:-1] 499 | 500 | def show_popup_dialog(self, title, message): 501 | dialog = JDialog() 502 | dialog.title = title 503 | dialog.setModal(True) 504 | 505 | text_area = JTextArea(message) 506 | text_area.editable = False 507 | scroll_pane = JScrollPane(text_area) 508 | 509 | copy_button = JButton("Copy") 510 | #copy_button.addActionListener(lambda event: self.copy_to_clipboard(message)) 511 | copy_button.addActionListener(lambda event: self.copy_to_clipboard()) 512 | 513 | 514 | dialog.add(scroll_pane, BorderLayout.CENTER) 515 | dialog.add(copy_button, BorderLayout.PAGE_END) 516 | 517 | dialog.pack() 518 | dialog.setLocationRelativeTo(None) 519 | dialog.setVisible(True) 520 | 521 | 522 | def copy_to_clipboard(self): 523 | text_to_copy = "\n".join(self.encodings_to_copy) 524 | selection = StringSelection(text_to_copy) 525 | clipboard = Toolkit.getDefaultToolkit().getSystemClipboard() 526 | clipboard.setContents(selection, None) 527 | 528 | 529 | def encode_ip(self, event): 530 | http_traffic = self.context.getSelectedMessages() 531 | bounds = self.context.getSelectionBounds() 532 | start, end = bounds[0], bounds[1] 533 | 534 | for traffic in http_traffic: 535 | request = traffic.getRequest() 536 | selectedIP = self._helpers.bytesToString(request[start:end]) 537 | 538 | try: 539 | socket.inet_aton(selectedIP) 540 | encodedIP = self.encode_ip_unicode_url(selectedIP) 541 | encodedBytes = self._helpers.stringToBytes(encodedIP) 542 | newRequest = request[:start] + encodedBytes + request[end:] 543 | traffic.setRequest(newRequest) 544 | except socket.error: 545 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 546 | pass 547 | 548 | def encode_ip_unicode_url(self, ip): 549 | unicode_ip = "" 550 | for part in ip.split("."): 551 | for digit in part: 552 | if digit == '0': 553 | unicode_ip += u'\u24FF' # caso especial para 0 554 | else: 555 | unicode_ip += unichr(0x245F + int(digit)) # 0x2460 es para 1, por lo que 0x245F + dígito da la asignación correcta 556 | unicode_ip += u'\u3002' # Unicode para punto final ideográfico 557 | return URLEncoder.encode(unicode_ip[:-1].encode('utf-8'), "UTF-8") 558 | 559 | 560 | def encode_ipv4_on_ipv6_url(self, ip): 561 | encoded_ip = self.transform_ip_to_unicode(ip) 562 | return URLEncoder.encode(encoded_ip.encode('utf-8'), "UTF-8").replace("+", "%20") if encoded_ip else None 563 | 564 | 565 | def apply_unicode_encoding(self, event): 566 | http_traffic = self.context.getSelectedMessages() 567 | bounds = self.context.getSelectionBounds() 568 | start, end = bounds[0], bounds[1] 569 | 570 | for traffic in http_traffic: 571 | request = traffic.getRequest() 572 | selectedIP = self._helpers.bytesToString(request[start:end]) 573 | 574 | try: 575 | socket.inet_aton(selectedIP) 576 | encodedIP = self.transform_ip_to_unicodex(selectedIP) 577 | encodedIP = self.convert_unicode_to_urlencoding(encodedIP) 578 | encodedBytes = self._helpers.stringToBytes(encodedIP) 579 | newRequest = request[:start] + encodedBytes + request[end:] 580 | traffic.setRequest(newRequest) 581 | except socket.error: 582 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 583 | pass 584 | 585 | def transform_ip_to_unicodex(self, ip): 586 | unicode_nums = ['⓪', '①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨'] 587 | ip_parts = ip.split('.') 588 | 589 | if len(ip_parts) != 4: 590 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 591 | 592 | encoded = "[::ⓕⓕⓕⓕ:" 593 | for part in ip_parts: 594 | for digit in part: 595 | encoded += unicode_nums[int(digit)] 596 | encoded += "。" 597 | encoded = encoded.rstrip("。") + "]:80" # remove the last dot and append ]:80 598 | 599 | return encoded 600 | 601 | def convert_unicode_to_urlencoding(self, s): 602 | res = "" 603 | for char in s: 604 | if ord(char) > 127: 605 | res += "%" + format(ord(char), 'x').zfill(2) 606 | else: 607 | res += char 608 | return res 609 | 610 | def class_b_encoding(self, event): 611 | http_traffic = self.context.getSelectedMessages() 612 | bounds = self.context.getSelectionBounds() 613 | start, end = bounds[0], bounds[1] 614 | 615 | for traffic in http_traffic: 616 | request = traffic.getRequest() 617 | selectedIP = self._helpers.bytesToString(request[start:end]) 618 | 619 | try: 620 | socket.inet_aton(selectedIP) 621 | encodedIP = self.encode_ip_class_b(selectedIP) 622 | encodedBytes = self._helpers.stringToBytes(encodedIP) 623 | newRequest = request[:start] + encodedBytes + request[end:] 624 | traffic.setRequest(newRequest) 625 | except socket.error: 626 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 627 | pass 628 | 629 | def encode_ip_class_b(self, ip): 630 | ip_parts = ip.split('.') 631 | if len(ip_parts) != 4: 632 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 633 | 634 | first_two = ".".join(ip_parts[:2]) 635 | last_two = int(ip_parts[2]) * 256 + int(ip_parts[3]) 636 | 637 | return first_two + '.' + str(last_two) 638 | 639 | def class_a_encoding(self, event): 640 | http_traffic = self.context.getSelectedMessages() 641 | bounds = self.context.getSelectionBounds() 642 | start, end = bounds[0], bounds[1] 643 | 644 | for traffic in http_traffic: 645 | request = traffic.getRequest() 646 | selectedIP = self._helpers.bytesToString(request[start:end]) 647 | 648 | try: 649 | socket.inet_aton(selectedIP) 650 | encodedIP = self.encode_ip_class_a(selectedIP) 651 | encodedBytes = self._helpers.stringToBytes(encodedIP) 652 | newRequest = request[:start] + encodedBytes + request[end:] 653 | traffic.setRequest(newRequest) 654 | except socket.error: 655 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 656 | pass 657 | 658 | def encode_ip_class_a(self, ip): 659 | ip_parts = ip.split('.') 660 | if len(ip_parts) != 4: 661 | raise ValueError("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 662 | 663 | first_one = ip_parts[0] 664 | last_three = int(ip_parts[1]) * 65536 + int(ip_parts[2]) * 256 + int(ip_parts[3]) 665 | 666 | return first_one + '.' + str(last_three) 667 | 668 | @staticmethod 669 | def convert_ipv4_to_ipv6(ipv4): 670 | ipv4_parts = ipv4.split('.') 671 | ipv6_parts = [] 672 | 673 | # Agrupar los octetos en pares y convertirlos a hexadecimal 674 | for i in range(0, len(ipv4_parts), 2): 675 | hex_part = hex(int(ipv4_parts[i]) << 8 | int(ipv4_parts[i + 1]))[2:] 676 | ipv6_parts.append(hex_part) 677 | 678 | # Unir los pares convertidos y añadir el prefijo IPv4-mapped 679 | return "::ffff:" + ':'.join(ipv6_parts) 680 | 681 | def domain_ipv6(self, event): 682 | # Generar una URL de colaborador 683 | collaboratorPayload = self._collaboratorClient.generatePayload(True) 684 | print("Collaborator payload:", collaboratorPayload) 685 | 686 | path_string = collaboratorPayload.split('.')[0] 687 | 688 | # Aquí tienes el dominio generado por Burp Collaborator 689 | domain_to_query = collaboratorPayload 690 | 691 | # Obtiene el tráfico HTTP seleccionado 692 | http_traffic = self.context.getSelectedMessages() 693 | bounds = self.context.getSelectionBounds() 694 | start, end = bounds[0], bounds[1] 695 | 696 | for traffic in http_traffic: 697 | request = traffic.getRequest() 698 | specific_part = self._helpers.bytesToString(request[start:end]) 699 | 700 | ipv4_addresses = self.get_ipv4_from_domain(domain_to_query) 701 | unique_ipv4 = set(ipv4_addresses) 702 | 703 | for ipv4 in unique_ipv4: 704 | ipv6 = self.convert_ipv4_to_ipv6(ipv4) 705 | url = "http://[{0}]/{1}".format(ipv6, path_string) 706 | url_bytes = self._helpers.stringToBytes(url) 707 | newRequest = request[:start] + url_bytes + request[end:] 708 | traffic.setRequest(newRequest) 709 | 710 | def get_ipv4_from_domain(self, domain_name): 711 | try: 712 | ipv4_addresses = [ip[4][0] for ip in socket.getaddrinfo(domain_name, None, family=socket.AF_INET)] 713 | return ipv4_addresses 714 | except Exception as e: 715 | print("An error occurred: " + str(e)) 716 | 717 | return [] 718 | 719 | 720 | def encode_all(self, event): 721 | http_traffic = self.context.getSelectedMessages() 722 | bounds = self.context.getSelectionBounds() 723 | start, end = bounds[0], bounds[1] 724 | 725 | for traffic in http_traffic: 726 | request = traffic.getRequest() 727 | selectedIP = self._helpers.bytesToString(request[start:end]) 728 | 729 | try: 730 | socket.inet_aton(selectedIP) 731 | # Unicode encoding 732 | unicode_encoded_IP = self.convert_ip_to_unicode(selectedIP) 733 | # IPv4 on IPv6 encoding 734 | ipv6_encoded_IP = self.transform_ip_to_unicode(selectedIP) 735 | # Unicode IP (urlencoded) 736 | unicode_ip_urlencoded = self.encode_ip_unicode_url(selectedIP) 737 | # IPv4 on IPv6 encoding (URL) 738 | ipv6_unicode_url_encoding = self.encode_ipv4_on_ipv6_url(selectedIP) 739 | # Class B 740 | class_b_encoding_url_x = self.encode_ip_class_b(selectedIP) 741 | # Class A 742 | class_a_encoding_url_x = self.encode_ip_class_a(selectedIP) 743 | # Hex encoding 744 | hex_encoding_x = self.encode_ip_hex(selectedIP) 745 | # Hex without dots 746 | hex_without_dots = self.encode_ip_hex_no_dots(selectedIP) 747 | # Hex v1 748 | hex_v1_enc = self.encode_ip_hex_v1(selectedIP) 749 | # hex v2 750 | hex_v2_enc = self.encode_ip_hex_v2(selectedIP) 751 | # octal 752 | octal_enc = self.encode_ip_octal(selectedIP) 753 | # octal with 0s 754 | octal_w_0 = self.encode_ip_octal_with_zeros(selectedIP) 755 | # mixed encoding 756 | mixed_enc = self.encode_ip_mixed(selectedIP) 757 | # Decimal intiger 758 | decimal_intiger = self.encode_ip_integer(selectedIP) 759 | 760 | # Guardar los encodings en una lista 761 | self.encodings_to_copy = [unicode_ip_urlencoded, unicode_encoded_IP, ipv6_encoded_IP, ipv6_unicode_url_encoding, class_b_encoding_url_x, class_a_encoding_url_x, hex_encoding_x, hex_without_dots, hex_v1_enc, hex_v2_enc, octal_enc, octal_w_0, mixed_enc, decimal_intiger] 762 | 763 | # Generar el texto final para mostrar 764 | final_text_to_display = u"Unicode Encoding (URL Encoded): {}\nUnicode Encoding: {}\nIPv4 on IPv6 Encoding: {}\nIPv4 on IPv6 Encoding (URL Encoded): {}\nClass B Encoding: {}\nClass A Encoding: {}\nHex Encoding: {}\nHex w/o dots: {}\nHex Encoding v1: {}\nHex Encoding v2: {}\nOctal Encode: {}\nOctal Encode with 0s: {}\nMixed Encoding: {}\nDecimal Intiger Encoding: {}".format( 765 | *self.encodings_to_copy) 766 | 767 | # Mostrar 768 | self.show_popup_dialog("All Encodings - {}".format(selectedIP), final_text_to_display) 769 | 770 | except socket.error: 771 | print("Non IPv4 detected. Please select an IPv4 to perform a correct encoding. ") 772 | pass 773 | --------------------------------------------------------------------------------