├── 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 | 
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 |
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\tIssues with the extension: https://github.com/e1abrador/Burp-Encode-IP/issues/new
\t\tIdeas: https://github.com/e1abrador/Burp-Encode-IP/pulls
"
77 | htmlString += """
78 | About
\nThis extension will encode an IP address into a bunch of less known encoding techniques.
\nThis 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 | 
83 | Usage
84 | The usage of the extension is very easy, first you need to highlight an IP address:
85 |
86 | 
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 | 
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 |
--------------------------------------------------------------------------------