Što je ranjivost uvjeta utrke?

Što je ranjivost uvjeta utrke?
Čitatelji poput vas pomažu podržati MUO. Kada kupujete koristeći veze na našoj stranici, možemo zaraditi partnersku proviziju.

Stanje utrke se događa kada se dvije operacije moraju izvesti određenim redoslijedom, ali se mogu izvoditi suprotnim redoslijedom.





Na primjer, u višenitnoj aplikaciji, dvije zasebne niti mogu pristupiti zajedničkoj varijabli. Kao rezultat toga, ako jedna nit promijeni vrijednost varijable, druga može i dalje koristiti stariju verziju, zanemarujući najnoviju vrijednost. To će uzrokovati neželjene rezultate.





MAKEUSEOF VIDEO DANA

Za bolje razumijevanje ovog modela bilo bi dobro pobliže ispitati proces prebacivanja procesa procesora.





Kako procesor prebacuje procese

Moderni operativni sustavi može pokrenuti više od jednog procesa istovremeno, što se naziva multitasking. Kada ovaj proces pogledate u smislu CPU-ov ciklus izvršenja , možda ćete otkriti da multitasking zapravo ne postoji.

Umjesto toga, procesori se stalno prebacuju između procesa kako bi ih pokrenuli istovremeno ili se barem ponašali kao da to rade. CPU može prekinuti proces prije nego što se dovrši i nastaviti s drugim procesom. Operativni sustav kontrolira upravljanje tim procesima.



Na primjer, Round Robin algoritam, jedan od najjednostavnijih algoritama za prebacivanje, radi na sljedeći način:

  Dijagram koji prikazuje 3 procesa u čekanju, u stanju mirovanja i 1 aktivni proces koji CPU trenutno izvodi

Općenito, ovaj algoritam dopušta svakom procesu da se izvodi vrlo male dijelove vremena, kako odredi operativni sustav. Na primjer, to može biti razdoblje od dvije mikrosekunde.





CPU preuzima svaki proces redom i izvršava naredbe koje će trajati dvije mikrosekunde. Zatim se nastavlja na sljedeći proces, bez obzira na to je li trenutni završio ili nije. Stoga, sa stajališta krajnjeg korisnika, čini se da se više od jednog procesa izvodi istovremeno. Međutim, kada pogledate iza kulisa, CPU još uvijek radi stvari kako treba.

Usput, kao što gornji dijagram pokazuje, Round Robin algoritmu nedostaju pojmovi optimizacije ili prioriteta obrade. Kao rezultat toga, to je prilično rudimentarna metoda koja se rijetko koristi u stvarnim sustavima.





Sada, da biste sve ovo bolje razumjeli, zamislite da se pokreću dvije niti. Ako niti pristupaju zajedničkoj varijabli, može se pojaviti stanje utrke.

Primjer web aplikacije i uvjet utrke

U nastavku pogledajte jednostavnu aplikaciju Flask da razmislite o konkretnom primjeru svega što ste do sada pročitali. Svrha ove aplikacije je upravljanje novčanim transakcijama koje će se odvijati na webu. Spremite sljedeće u datoteku pod nazivom novac.py :

from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)

class Account(db.Model):
id = db.Column(db.Integer, primary_key = True)
amount = db.Column(db.String(80), unique = True)

def __init__(self, count):
self.amount = amount

def __repr__(self):
return '' % self.amount

@app.route("/")
def hi():
account = Account.query.get(1) # There is only one wallet.
return "Total Money = {}".format(account.amount)

@app.route("/send/")
def send(amount):
account = Account.query.get(1)

if int(account.amount) < amount:
return "Insufficient balance. Reset money with /reset!)"

account.amount = int(account.amount) - amount
db.session.commit()
return "Amount sent = {}".format(amount)

@app.route("/reset")
def reset():
account = Account.query.get(1)
account.amount = 5000
db.session.commit()
return "Money reset."

if __name__ == "__main__":
app.secret_key = 'heLLoTHisIsSeCReTKey!'
app.run()

Da biste pokrenuli ovaj kod, morat ćete stvoriti zapis u tablici računa i nastaviti transakcije preko tog zapisa. Kao što možete vidjeti u kodu, ovo je testno okruženje, tako da izvršava transakcije prema prvom zapisu u tablici.

from money import db 
db.create_all()
from money import Account
account = Account(5000)
db.session.add(account)
db.session.commit()

Sada ste kreirali račun sa stanjem od 5000 USD. Na kraju, pokrenite gornji izvorni kod pomoću sljedeće naredbe, pod uvjetom da imate instalirane pakete Flask i Flask-SQLAlchemy:

python money.py 

Dakle, imate Flask web aplikaciju koja radi jednostavan proces ekstrakcije. Ova aplikacija može izvoditi sljedeće operacije s vezama GET zahtjeva. Budući da Flask prema zadanim postavkama radi na portu 5000, adresa na kojoj mu pristupate je 127.0.0.1:5000/ . Aplikacija pruža sljedeće krajnje točke:

  • 127.0.0.1:5000/ prikazuje trenutno stanje.
  • 127.0.0.1:5000/pošalji/{iznos} oduzima iznos s računa.
  • 127.0.0.1:5000/poništavanje resetira račun na 5000 dolara.

Sada, u ovoj fazi, možete ispitati kako dolazi do ranjivosti uvjeta utrke.

Vjerojatnost ranjivosti uvjeta utrke

Gore navedena web aplikacija sadrži moguću ranjivost uvjeta utrke.

Zamislite da imate 5000 USD za početak i izradite dva različita HTTP zahtjeva koji će poslati 1 USD. U tu svrhu možete poslati dva različita HTTP zahtjeva na vezu 127.0.0.1:5000/pošalji/1 . Pretpostavite da, čim web poslužitelj obradi prvi zahtjev, CPU zaustavlja ovaj proces i obrađuje drugi zahtjev. Na primjer, prvi proces se može zaustaviti nakon pokretanja sljedećeg retka koda:

account.amount = int(account.amount) - amount 

Ovaj kod je izračunao novi ukupni iznos, ali još nije spremio zapis u bazu podataka. Kada započne drugi zahtjev, izvršit će isti izračun, oduzimajući 1 USD od vrijednosti u bazi podataka—5000 USD—i pohranjujući rezultat. Kada se prvi proces nastavi, pohranit će vlastitu vrijednost—4.999 USD—koja neće odražavati najnovije stanje računa.

Dakle, dva su zahtjeva ispunjena i svaki je trebao oduzeti 1 USD od salda računa, što je rezultiralo novim saldom od 4998 USD. No, ovisno o redoslijedu kojim ih web poslužitelj obrađuje, konačno stanje na računu može biti 4.999 USD.

Nisam primio svoj Amazon paket

Zamislite da pošaljete 128 zahtjeva za prijenos od 1 USD ciljnom sustavu u vremenskom okviru od pet sekundi. Kao rezultat ove transakcije, očekivani izvod na računu bit će 5000 USD - 128 USD = 4875 USD. Međutim, zbog uvjeta utrke, konačni saldo može varirati između 4.875 i 4.999 dolara.

Programeri su jedna od najvažnijih komponenti sigurnosti

U softverskom projektu, kao programer, imate dosta odgovornosti. Gore navedeni primjer bio je za jednostavnu aplikaciju za prijenos novca. Zamislite da radite na softverskom projektu koji upravlja bankovnim računom ili pozadinom velike web-lokacije za e-trgovinu.

Morate biti upoznati s takvim ranjivostima kako bi program koji ste napisali za njihovu zaštitu bio bez ranjivosti. To zahtijeva veliku odgovornost.

Ranjivost uvjeta utrke samo je jedna od njih. Bez obzira koju tehnologiju koristite, morate paziti na ranjivosti u kodu koji pišete. Jedna od najvažnijih vještina koje možete steći kao programer je poznavanje sigurnosti softvera.