SQL Injection у мобилном развоју: шта је то, методе напада и заштита

Аутор: IT Sectr Објављено: 2026-04-06 Време читања: 9 мин

SQL Injection — врста напада на базу података апликације при којем нападач убацује злонамерни SQL код у параметре упита, добијајући неовлашћени приступ подацима или могућност њихове измене. Према подацима OWASP (2025), SQL Injection остаје једна од критичних рањивости, способна да доведе до потпуне компромитације базе података. Инјекција SQL кода омогућава нападачу да чита, мења и брише записе, ау неким случајевима — да добије приступ оперативном систему сервера.

Главно

  • SQL Injection — убацивање SQL кода преко корисничких параметара, које мења логику упита бази података
  • Параметризација упита — основни метод заштите: одвајање SQL кода од података помоћу prepared statements
  • Типови напада — класична инјекција (кроз WHERE), Blind SQLi (логички закључци), UNION-based (читање туђих табела)
  • Error-based SQLi — извлачење података кроз поруке о грешкама базе података
  • ORM оквири — смањују ризик од SQLi уз правилну употребу, али га не уклањају у потпуности

Шта је SQL Injection?

SQL Injection је рањивост која настаје када апликација формира SQL упит путем конкатенације стрингова са корисничким подацима. Нападач преноси у параметар упита посебно конструисан стринг који мења структуру SQL команде. Уместо да буде податак, унети стринг постаје део SQL кода, што омогућава нападачу да извршава произвољне упите бази података. Према Verizon Data Breach Report (2025), SQL Injection је присутан у 8% свих истражених цурења података.

Зашто је SQL Injection још увек актуелан?

Упркос познатости рањивости (први помени — крај 1990-их), SQL Injection се јавља у савременим апликацијама. Разлог — људски фактор: програмери допуштају конкатенацију стрингова у коду, legacy код се не рефакторише, а ORM оквири се користе неправилно (нпр. сирови упити са заменом вредности кроз стрингове). Према подацима Veracode (2026), око 14% свих скенираних апликација садржи бар једну SQLi рањивост.

Шта нападач може да уради?

Успешна SQL Injection даје нападачу широк спектар могућности: читање било којих табела базе података, укључујући хешеве лозинки и личне податке корисника; измена и брисање записа; извршавање административних операција (DROP TABLE, TRUNCATE); у неким конфигурацијама — даљинско извршавање команди преко xp_cmdshell (MSSQL) или INTO OUTFILE (MySQL). Последице — од цурења корисничких података до потпуног губитка контроле над системом.

Типови SQL инјекција

SQL инјекције се класификују према начину извлачења података из базе. Избор метода зависи од тога како апликација обрађује резултате упита и поруке о грешкама. OWASP класификација издваја три главна типа: In-band (подаци се извлаче кроз исти канал), Inferential/Blind (логички закључци) и Out-of-band (подаци се преносе кроз други канал).

ТипНачин извлачења податакаСложеностУчесталост
In-band (класични)Непосредно кроз резултат упитаНискаВисока
Blind SQLiЛогички закључци на основу одговора сервераВисокаСредња
Out-of-bandКроз спољни канал (DNS, HTTP)СредњаНиска

In-band SQL Injection (класична)

Најчешћи тип. Нападач убацује SQL код у параметар упита, а резултат убацивања је видљив директно у одговору сервера. Два подтипа: Error-based (кроз поруке о грешкама базе података) и UNION-based (кроз оператор UNION SELECT). Error-based користи информације из порука о грешкама, на пример синтаксну грешку MySQL која може да открије назив табеле или структуру упита. UNION-based омогућава спајање резултата легитимног упита са подацима из других табела базе података.

Blind SQL Injection (слепа)

Користи се када апликација не приказује резултате упита или поруке о грешкама. Нападач поставља питања типа „да/не”, шаљући упите са логичким условима и анализирајући разлику у одговору сервера (нпр. време одговора или садржај странице). Time-based Blind SQLi користи функцију кашњења (SLEEP, WAITFOR DELAY) за потврду услова — ако се страница дуже учитава, услов је тачан. Овај метод је веома спор — извлачење једног записа може трајати сатима.

python
# Пример Blind SQL Injection (time-based)
# Ако је SQLi рањив, SLEEP(2) се извршава под условом
import requests
import time

payload = "' OR IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a',SLEEP(2),0) -- "
url = "http://example.com/user?id=1" + payload

start = time.time()
response = requests.get(url)
elapsed = time.time() - start

# Ако је одговор стигао после >2 секунде — прво слово лозинке је 'a'
print(f"Time: {elapsed:.2f}s - First letter is 'a'" if elapsed > 2 else "First letter is not 'a'")

Out-of-band SQL Injection

Подаци се преносе не кроз HTTP одговор, већ кроз алтернативне канале: DNS упите, HTTP захтеве ка спољном серверу, SMTP. Користи се када апликација не враћа резултате упита и не приказује грешке. MySQL подржава функцију LOAD_FILE(), која може да иницира DNS упит, а MSSQL — xp_dirtree за слање података на удаљени SMB сервер. Out-of-band SQL Injection је ефикасан, али захтева додатна подешавања на серверу нападача и присуство одређених функција базе података.

Како функционише SQL инјекција?

Механизам SQL Injection се заснива на томе што SQL користи наводнике за стринг литерале. Ако апликација замењује кориснички унос директно у SQL упит без екранизације, нападач може да „затвори” стринг и дода произвољан SQL код. На пример, у упиту SELECT * FROM users WHERE name = '$input' замена ' OR '1'='1 претвара упит у SELECT * FROM users WHERE name = '' OR '1'='1', што враћа све кориснике.

Класичан пример: заобилажење аутентификације

Размотримо формулар за пријаву са упитом SELECT * FROM users WHERE username = '$user' AND password = '$pass'. Ако нападач унесе у поље username admin' -- , а лозинку остави празну, резултујући упит постаје SELECT * FROM users WHERE username = 'admin' -- ' AND password = ''. Знакови -- коментаришу остатак упита, а услов провере лозинке се искључује. Сервер враћа запис корисника admin, а нападач улази у систем без познавања лозинке.

python
# Пример SQL Injection — заобилажење аутентификације
# РАЊИВИ КОД: директна конкатенација стрингова
def login_vulnerable(username, password):
    query = f"SELECT * FROM users WHERE username='{username}' AND password='{password}'"
    cursor.execute(query)
    return cursor.fetchone() is not None

# username = "admin' --" поништава проверу лозинке
# БЕЗБЕДНА ВЕРЗИЈА: параметризовани упит
def login_secure(username, password):
    query = "SELECT * FROM users WHERE username = %s AND password = %s"
    cursor.execute(query, (username, password))
    return cursor.fetchone() is not None

UNION-based: читање туђих табела

Оператор UNION SELECT омогућава спајање резултата два SELECT упита. Ако нападач пронађе рањиви параметар, додаје UNION SELECT са упитом из друге табеле. На пример: ' UNION SELECT username, password FROM admins --. Услов успеха — број колона у оба упита мора да се поклапа. Број колона се одређује кроз ORDER BY (замена ' ORDER BY 1--, затим 2, 3... до грешке). Знајући број колона, нападач замењује UNION SELECT са истим бројем поља.

SQL Injection у мобилним апликацијама

Мобилне апликације се сусрећу са SQL Injection како на серверској страни (API), тако и на клијенту — у локалним базама података (SQLite, Realm). Иако је ризик од серверске SQLi у мобилном API-ју сличан веб апликацијама, локална база података ствара додатни вектор. Ако апликација чува податке у SQLite-у и извршава упите са конкатенацијом стрингова, злонамерни подаци који су доспели у локалну базу података кроз API могу изазвати SQLi приликом касније обраде.

SQL Injection у SQLite-у на Android/iOS

Локална SQLite база на уређају је такође рањива на SQL Injection ако апликација формира упите конкатенацијом стрингова. Content Providers на Android-у и Core Data на iOS-у користе параметризацију подразумевано, али сирови упити захтевају пажњу програмера. SQLite не подржава вишеструке упите кроз тачку-запету, што ограничава могућности нападача, али не штити од читања података кроз WHERE услове. Увек користите selectionArgs у Android-у и NSPredicate са параметрима у iOS-у.

SQL Injection кроз API мобилне апликације

API коме се обраћа мобилна апликација рањив је исто као и сваки веб сервер. Мобилни програмери често сматрају да је SQLi само проблем бекенда, али рањивост настаје на нивоу API ендпоинта који прима параметре од клијента. Подела одговорности не штити: ако је бекенд програмер заборавио да параметризује упит, мобилна апликација корисника постаје вектор напада. Захтевајте од бекенда коришћење ORM-а или prepared statements.

kotlin
// Пример SQL Injection у локалном SQLite-у на Android-у
// РАЊИВИ КОД: директна конкатенација
fun getUserVulnerable(db: SQLiteDatabase, userId: String): Cursor {
    return db.rawQuery(
        "SELECT * FROM users WHERE id = $userId", null
    )
}

// БЕЗБЕДНА ВЕРЗИЈА: параметризација кроз selectionArgs
fun getUserSecure(db: SQLiteDatabase, userId: String): Cursor {
    return db.rawQuery(
        "SELECT * FROM users WHERE id = ?",
        arrayOf(userId)
    )
}

Методе спречавања SQL инјекција

Заштита од SQL Injection се заснива на једноставном принципу: никада не верујте корисничком уносу у SQL упитима. Једини поуздани метод — параметризација упита (prepared statements), при којој се SQL код и подаци преносе одвојено. Сви остали методи — екранизација, валидација, WAF — представљају додатне слојеве заштите, али не замењују параметризацију. Према подацима OWASP (2025), параметризација спречава 100% SQL Injection напада.

Prepared Statements (параметризовани упити)

При коришћењу prepared statements, SQL упит се прво компајлира на серверу базе података без података, а затим се вредности параметара преносе одвојено. База података третира параметре као податке, а не као извршиви код. Чак и ако нападач пренесе ' OR '1'='1, база података то интерпретира као стринг вредност, а не као SQL код. Prepared statements подржавају сви савремени језици и оквири: PDO у PHP-у, PreparedStatement у Java-и, cursor.execute у Python-у.

ORM оквири и Query Builders

Савремени ORM (Hibernate, Entity Framework, SQLAlchemy, Room) аутоматски користе параметризацију при извршавању упита, ако програмер не пређе на сирове упите. Међутим, ORM не штити у потпуности: конструкције попут @Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true) у JPA захтевају пренос параметара кроз именоване параметре, а не конкатенацију. Query Builders (Knex, jOOQ) такође параметризују упите подразумевано, ако се не користе сирови методи.

Екранизација стрингова (не препоручује се као главни метод)

Екранизација специјалних знакова (mysql_real_escape_string) — застарели метод који не штити од свих типова SQL Injection. Проблем: екранизација зависи од кодирања и може се заобићи коришћењем вишебајтних кодирања (нпр. GBK у азијским системима). Користите екранизацију само у legacy коду где параметризација није могућа, и увек у комбинацији са строгом валидацијом типа улазних података.

МетодЕфикасностПрепорука
Prepared Statements100%Обавезно за све упите
ORM (правилна употреба)99%Препоручује се
Екранизација стрингова70% (зависи од кодирања)Само legacy
Валидација уноса (бела листа)50% (само за бројеве)Додатно
WAF (Web Application Firewall)60%Додатно

Принцип најмањих привилегија за базу података

Кориснички налог апликације треба да има минимално неопходна права: SELECT, INSERT, UPDATE, DELETE — само на табелама које су стварно потребне апликацији. Забраните коришћење DROP, TRUNCATE, CREATE за налог апликације. Ово ће ограничити штету чак и у случају успешне SQL Injection: нападач неће моћи да обрише табеле или изврши административне операције.

Алати за откривање SQL инјекција

Редовно тестирање на SQL Injection треба да буде део pipeline-а безбедног развоја. Комбинација статичке анализе, динамичког скенирања и ручног пентеста даје најбоље резултате. Према Synopsys Cybersecurity Report (2025), аутоматски скенери проналазе до 70% SQLi рањивости, али сложени Blind напади захтевају ручно тестирање.

  • sqlmap — најпопуларнији алат за аутоматско откривање и експлоатацију SQL Injection
  • OWASP ZAP — бесплатни DAST скенер са модулима активног скенирања SQLi
  • Burp Suite Scanner — професионални алат са аутоматским детектовањем SQL Injection
  • SonarQube — статичка анализа кода на рањивости, укључујући SQLi обрасце
  • CodeQL — семантичка анализа кода за проналажење SQL инјекција у изворном коду

За мобилне апликације важна је и анализа локалног SQLite-а: проверите све rawQuery позиве, ContentProvider упите и Room упите са rawQuery. Алати: Android Studio Lint (детектује SQLi у SQLite-у), MobSF (Mobile Security Framework) за аутоматску статичку и динамичку анализу APK/IPA. Препоручује се и тестирање API ендпоинта путем sqlmap-а са прокси пресретањем саобраћаја мобилне апликације.

Често постављана питања

Која је разлика између SQL Injection и NoSQL Injection?

SQL Injection напада релационе базе података кроз SQL упите. NoSQL Injection утиче на нерелационе базе података (MongoDB, Couchbase) кроз њихове операторе упита ($gte, $ne, $where). У MongoDB-ју инјекција је могућа ако апликација формира BSON документ из JSON стринга. Механизми заштите су слични: параметризација и валидација типова.

Како самостално открити SQL Injection у коду?

Пронађите сва места где се SQL упити формирају кроз конкатенацију стрингова са корисничким подацима. Тражите обрасце попут "SELECT ... WHERE id = " + userId или f"UPDATE ... SET name = '{name}'". Сваки такав стринг је потенцијална SQL инјекција. Замените све параметризованим упитима или prepared statements.

Да ли ORM аутоматски штити од SQL Injection-а?

ORM оквири штите аутоматски само ако користите њихове методе Query Builder-а и именоване параметре. Ако користите сирове упите (nativeQuery у JPA, rawQuery у Room-у), заштита не ради — потребно је преносити параметре кроз припремљене изразе, а не кроз конкатенацију стрингова.

Шта је Second-Order SQL Injection?

Second-Order SQL Injection — напад при којем се злонамерни подаци чувају у бази података као безбедни, али се затим користе у другом упиту без екранизације. На пример, нападач се региструје са username-ом ' OR '1'='1. Подаци се чувају као стринг — при регистрацији нема напада. Али ако други упит замени username у SQL-у без параметризације, инјекција се активира.

Може ли NoSQL Injection бити опаснији од SQL Injection-а?

NoSQL Injection је потенцијално опаснији због мање свести програмера. Програмери знају за SQL Injection и већина користи ORM, али за NoSQL Injection знају ретки. У MongoDB-ју неправилно формиран упит може вратити све документе колекције. Заштита — исти prepared statements (BSON параметризација) и строга валидација улазних података.

Закључак

  • SQL Injection — напад убацивањем SQL кода кроз неекранизоване корисничке параметре у упитима бази података
  • Главни типови — In-band (класични), Blind (слепи, временски), Out-of-band (кроз спољни канал)
  • Параметризација упита — једини 100% поуздани метод заштите од SQL Injection-а
  • Мит о ORM-у — ORM штити само при коришћењу уграђених метода, сирови упити са конкатенацијом су и даље рањиви
  • Принцип најмањих привилегија — ограничавање права налога базе података минимизира штету при успешном нападу
  • Редовно тестирање — sqlmap, OWASP ZAP, SonarQube треба да буду део CI/CD pipeline-а
  • Локални SQLite — мобилне апликације такође треба да параметризују упите ка локалној бази података

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође