SQL Injection — isang uri ng pag-atake sa database ng application kung saan ang attacker ay nag-i-inject ng malisyosong SQL code sa mga parameter ng query, na nakakakuha ng hindi awtorisadong access sa data o kakayahang baguhin ang mga ito. Ayon sa datos ng OWASP (2025), ang SQL Injection ay nananatiling isa sa mga kritikal na kahinaan na maaaring humantong sa kumpletong kompromiso ng database. Pag-i-inject ng SQL code ay nagpapahintulot sa attacker na magbasa, magbago at magtanggal ng mga record, at sa ilang mga kaso — makakuha ng access sa operating system ng server.
Mga pangunahing punto
Ang SQL Injection ay isang kahinaan na lumalabas kapag ang application ay bumubuo ng SQL query sa pamamagitan ng pag-concatenate ng mga string gamit ang data ng user. Ang attacker ay nagpapadala ng espesyal na ginawang string sa parameter ng query na nagbabago sa istraktura ng SQL command. Sa halip na maging data, ang ipinasok na string ay nagiging bahagi ng SQL code, na nagpapahintulot sa attacker na magsagawa ng mga arbitraryong query sa database. Ayon sa Verizon Data Breach Report (2025), ang SQL Injection ay naroroon sa 8% ng lahat ng na-imbestigahang data leaks.
Sa kabila ng pagiging kilala ng kahinaan (unang pagbanggit — huling bahagi ng 1990s), ang SQL Injection ay matatagpuan pa rin sa mga modernong application. Ang dahilan — human factor: pinapayagan ng mga developer ang concatenation ng string sa code, ang legacy code ay hindi nire-refactor, at ang ORM frameworks ay ginagamit nang hindi tama (halimbawa, raw query na may pagpapalit ng mga halaga sa pamamagitan ng mga string). Ayon sa datos ng Veracode (2026), humigit-kumulang 14% ng lahat ng na-scan na application ay naglalaman ng kahit isang SQLi vulnerability.
Ang matagumpay na SQL Injection ay nagbibigay sa attacker ng malawak na hanay ng mga kakayahan: pagbasa ng anumang tables ng database, kabilang ang mga hash ng password at personal na data ng mga user; pagbabago at pagtanggal ng mga record; pagsasagawa ng mga administratibong operasyon (DROP TABLE, TRUNCATE); sa ilang configuration — malayuang pagpapatupad ng mga command sa pamamagitan ng xp_cmdshell (MSSQL) o INTO OUTFILE (MySQL). Ang mga kahihinatnan — mula sa pagtagas ng data ng user hanggang sa kumpletong pagkawala ng kontrol sa system.
Ang mga SQL injection ay inuuri ayon sa paraan ng pagkuha ng data mula sa database. Ang pagpili ng paraan ay depende sa kung paano pinoproseso ng application ang mga resulta ng query at mga error message. Pag-uuri ng OWASP ay nagtatangi ng tatlong pangunahing uri: In-band (ang data ay kinukuha sa pamamagitan ng parehong channel), Inferential/Blind (lohikal na konklusyon) at Out-of-band (ang data ay ipinapadala sa pamamagitan ng ibang channel).
| Uri | Paraan ng pagkuha ng data | Pagiging kumplikado | Dalas |
|---|---|---|---|
| In-band (klasiko) | Direkta sa pamamagitan ng resulta ng query | Mababa | Mataas |
| Blind SQLi | Lohikal na konklusyon batay sa mga tugon ng server | Mataas | Katamtaman |
| Out-of-band | Sa pamamagitan ng panlabas na channel (DNS, HTTP) | Katamtaman | Mababa |
Ang pinakakaraniwang uri. Ang attacker ay nag-i-inject ng SQL code sa parameter ng query, at ang resulta ng injection ay direktang nakikita sa tugon ng server. Dalawang subtype: Error-based (sa pamamagitan ng mga error message ng database) at UNION-based (sa pamamagitan ng UNION SELECT operator). Ang Error-based ay gumagamit ng impormasyon mula sa mga error message, halimbawa, syntax error ng MySQL na maaaring magbunyag ng pangalan ng table o istraktura ng query. Ang UNION-based ay nagpapahintulot na pagsamahin ang mga resulta ng lehitimong query sa data mula sa ibang mga table ng database.
Ginagamit kapag ang application ay hindi nagpapakita ng mga resulta ng query o mga error message. Ang attacker ay nagtatanong ng „oo/hindi” na mga tanong sa pamamagitan ng pagpapadala ng mga query na may lohikal na kondisyon at pagsusuri ng pagkakaiba sa tugon ng server (halimbawa, oras ng pagtugon o nilalaman ng pahina). Ang Time-based Blind SQLi ay gumagamit ng delay function (SLEEP, WAITFOR DELAY) upang kumpirmahin ang mga kondisyon — kung ang pahina ay nag-load nang mas matagal, ang kondisyon ay totoo. Ang paraang ito ay napakabagal — ang pagkuha ng isang record ay maaaring tumagal ng mga oras.
# Halimbawa ng Blind SQL Injection (time-based)
# Kung ang SQLi ay mahina, ang SLEEP(2) ay isinasagawa sa ilalim ng kondisyon
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
# Kung ang tugon ay dumating pagkatapos ng >2 segundo — ang unang titik ng password ay 'a'
print(f"Time: {elapsed:.2f}s - First letter is 'a'" if elapsed > 2 else "First letter is not 'a'")
Ang data ay ipinapadala hindi sa pamamagitan ng HTTP response, kundi sa pamamagitan ng alternatibong mga channel: DNS query, HTTP request sa panlabas na server, SMTP. Ginagamit kapag ang application ay hindi nagbabalik ng mga resulta ng query at hindi nagpapakita ng mga error. Ang MySQL ay sumusuporta sa function na LOAD_FILE(), na maaaring magpasimula ng DNS query, at MSSQL — xp_dirtree para sa pagpapadala ng data sa malayuang SMB server. Ang Out-of-band SQL Injection ay epektibo, ngunit nangangailangan ng karagdagang setup sa server ng attacker at pagkakaroon ng mga tiyak na function ng database.
Ang mekanismo ng SQL Injection ay batay sa katotohanan na ang SQL ay gumagamit ng mga panipi para sa string literals. Kung ang application ay mag-substitute ng input ng user nang direkta sa SQL query nang walang escaping, ang attacker ay maaaring „isara” ang string at magdagdag ng arbitraryong SQL code. Halimbawa, sa query na SELECT * FROM users WHERE name = '$input' ang pag-substitute ng ' OR '1'='1 ay ginagawang SELECT * FROM users WHERE name = '' OR '1'='1' ang query, na nagbabalik ng lahat ng user.
Isaalang-alang ang login form na may query na SELECT * FROM users WHERE username = '$user' AND password = '$pass'. Kung ang attacker ay magpasok sa username field ng admin' -- at iwanang blangko ang password, ang resultang query ay magiging SELECT * FROM users WHERE username = 'admin' -- ' AND password = ''. Ang mga karakter na -- ay nagko-comment sa natitirang bahagi ng query, at ang kondisyon ng pagsusuri ng password ay na-deactivate. Ibinabalik ng server ang record ng user na admin, at ang attacker ay pumapasok sa system nang hindi alam ang password.
# Halimbawa ng SQL Injection — pag-bypass ng authentication
# MAHINANG CODE: direktang concatenation ng string
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' --" nag-aalis ng pagsusuri ng password
# LIGTAS NA BERSIYON: naka-parametrize na query
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
Ang operator na UNION SELECT ay nagpapahintulot na pagsamahin ang mga resulta ng dalawang SELECT query. Kung ang attacker ay makahanap ng vulnerable na parameter, nagdadagdag siya ng UNION SELECT na may query mula sa ibang table. Halimbawa: ' UNION SELECT username, password FROM admins --. Kondisyon para sa tagumpay — ang bilang ng mga column sa parehong query ay dapat magtugma. Ang bilang ng mga column ay tinutukoy sa pamamagitan ng ORDER BY (pag-substitute ng ' ORDER BY 1--, pagkatapos 2, 3... hanggang sa error). Alam ang bilang ng mga column, ang attacker ay nag-substitute ng UNION SELECT na may parehong bilang ng mga field.
Ang mga mobile application ay nakakaranas ng SQL Injection pareho sa server side (API) at sa client side — sa mga lokal na database (SQLite, Realm). Kahit na ang panganib ng server SQLi sa mobile API ay katulad ng web applications, ang lokal na database ay lumilikha ng karagdagang vector. Kung ang application ay nag-iimbak ng data sa SQLite at nagsasagawa ng mga query na may concatenation ng string, ang malisyosong data na pumasok sa lokal na database sa pamamagitan ng API ay maaaring magdulot ng SQLi sa kasunod na pagproseso.
Ang lokal na SQLite database sa device ay mahina rin sa SQL Injection kung ang application ay bumubuo ng mga query sa pamamagitan ng concatenation ng string. Content Providers sa Android at Core Data sa iOS ay gumagamit ng parametrization bilang default, ngunit ang mga raw query ay nangangailangan ng atensyon ng developer. Ang SQLite ay hindi sumusuporta ng maramihang query sa pamamagitan ng semicolon, na naglilimita sa mga kakayahan ng attacker, ngunit hindi nagpoprotekta laban sa pagbasa ng data sa pamamagitan ng WHERE conditions. Palaging gamitin ang selectionArgs sa Android at NSPredicate na may mga parameter sa iOS.
Ang API na ginagamit ng mobile application ay kasing vulnerable ng anumang web server. Ang mga mobile developer ay madalas na iniisip na ang SQLi ay problema lamang ng backend, ngunit ang kahinaan ay lumalabas sa antas ng API endpoint na tumatanggap ng mga parameter mula sa client. Paghahati ng responsibilidad ay hindi nagpoprotekta: kung ang backend developer ay nakalimutang i-parametrize ang query, ang mobile application ng user ay nagiging vector ng pag-atake. Hilingin sa backend na gumamit ng ORM o prepared statements.
// Halimbawa ng SQL Injection sa lokal na SQLite sa Android
// MAHINANG CODE: direktang concatenation
fun getUserVulnerable(db: SQLiteDatabase, userId: String): Cursor {
return db.rawQuery(
"SELECT * FROM users WHERE id = $userId", null
)
}
// LIGTAS NA BERSIYON: parametrization sa pamamagitan ng selectionArgs
fun getUserSecure(db: SQLiteDatabase, userId: String): Cursor {
return db.rawQuery(
"SELECT * FROM users WHERE id = ?",
arrayOf(userId)
)
}
Ang proteksyon laban sa SQL Injection ay batay sa isang simpleng prinsipyo: huwag kailanman magtiwala sa input ng user sa mga SQL query. Ang tanging maaasahang paraan — parametrization ng mga query (prepared statements), kung saan ang SQL code at data ay ipinapadala nang hiwalay. Lahat ng iba pang paraan — escaping, validation, WAF — ay mga karagdagang layer ng proteksyon, ngunit hindi pinapalitan ang parametrization. Ayon sa datos ng OWASP (2025), ang parametrization ay pumipigil sa 100% ng mga SQL Injection attack.
Kapag gumagamit ng prepared statements, ang SQL query ay unang ina-assemble ng database server nang walang data, pagkatapos ang mga halaga ng parameter ay ipinapadala nang hiwalay. Itinuturing ng database ang mga parameter bilang data, hindi bilang executable code. Kahit na ang attacker ay magpadala ng ' OR '1'='1, ini-interpret ito ng database bilang string value, hindi bilang SQL code. Ang prepared statements ay sinusuportahan ng lahat ng modernong wika at frameworks: PDO sa PHP, PreparedStatement sa Java, cursor.execute sa Python.
Ang mga modernong ORM (Hibernate, Entity Framework, SQLAlchemy, Room) ay awtomatikong gumagamit ng parametrization kapag nagsasagawa ng mga query, maliban kung ang developer ay lumipat sa raw query. Gayunpaman, ang ORM ay hindi ganap na nagpoprotekta: mga konstruksyon tulad ng @Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true) sa JPA ay nangangailangan ng pagpapadala ng mga parameter sa pamamagitan ng named parameters, hindi concatenation. Ang Query Builders (Knex, jOOQ) ay nagpa-parametrize rin ng mga query bilang default, kung hindi ginagamit ang mga raw method.
Pag-escape ng mga espesyal na karakter (mysql_real_escape_string) — isang lumang paraan na hindi nagpoprotekta laban sa lahat ng uri ng SQL Injection. Problema: ang pag-escape ay depende sa encoding at maaaring i-bypass gamit ang multi-byte encodings (halimbawa, GBK sa mga Asian system). Gamitin ang pag-escape lamang sa legacy code kung saan hindi posible ang parametrization, at palaging kasama ng mahigpit na validation ng uri ng input data.
| Paraan | Epektibidad | Rekomendasyon |
|---|---|---|
| Prepared Statements | 100% | Kinakailangan para sa lahat ng query |
| ORM (tamang paggamit) | 99% | Inirerekomenda |
| Pag-escape ng string | 70% (depende sa encoding) | Legacy lamang |
| Validation ng input (white-list) | 50% (para lamang sa mga numero) | Karagdagan |
| WAF (Web Application Firewall) | 60% | Karagdagan |
Ang account ng application ay dapat magkaroon ng pinakamababang kinakailangang pribilehiyo: SELECT, INSERT, UPDATE, DELETE — sa mga table lamang na talagang kailangan ng application. Ipagbawal ang paggamit ng DROP, TRUNCATE, CREATE para sa account ng application. Ito ay maglilimita sa pinsala kahit na sa kaso ng matagumpay na SQL Injection: hindi magagawang tanggalin ng attacker ang mga table o magsagawa ng mga administratibong operasyon.
Ang regular na pagsubok para sa SQL Injection ay dapat maging bahagi ng pipeline ng secure development. Ang kumbinasyon ng static analysis, dynamic scanning at manual penetration testing ay nagbibigay ng pinakamahusay na mga resulta. Ayon sa Synopsys Cybersecurity Report (2025), ang mga automatic scanner ay nakakatuklas ng hanggang 70% ng SQLi vulnerabilities, ngunit ang mga kumplikadong Blind attack ay nangangailangan ng manual testing.
Para sa mga mobile application, mahalaga rin ang pagsusuri ng lokal na SQLite: suriin ang lahat ng rawQuery calls, ContentProvider queries at Room queries na may rawQuery. Mga tool: Android Studio Lint (nakakatuklas ng SQLi sa SQLite), MobSF (Mobile Security Framework) para sa automatic static at dynamic analysis ng APK/IPA. Inirerekomenda rin ang pagsubok ng API endpoints sa pamamagitan ng sqlmap na may proxy interception ng traffic ng mobile application.
Mga madalas itanong
Ang SQL Injection ay umaatake sa relational databases sa pamamagitan ng SQL queries. Ang NoSQL Injection ay umaapekto sa non-relational databases (MongoDB, Couchbase) sa pamamagitan ng kanilang query operators ($gte, $ne, $where). Sa MongoDB, posible ang injection kung ang application ay bumubuo ng BSON document mula sa JSON string. Ang mga mekanismo ng proteksyon ay magkatulad: parametrization at type validation.
Hanapin ang lahat ng lugar kung saan ang mga SQL query ay nabubuo sa pamamagitan ng pag-concatenate ng string gamit ang data ng user. Hanapin ang mga pattern tulad ng "SELECT ... WHERE id = " + userId o f"UPDATE ... SET name = '{name}'". Bawat ganoong string ay potensyal na SQL injection. Palitan lahat ng naka-parametrize na query o prepared statements.
Ang ORM frameworks ay awtomatikong nagpoprotekta lamang kung gagamitin mo ang kanilang Query Builder methods at named parameters. Kung gagamit ka ng raw queries (nativeQuery sa JPA, rawQuery sa Room), hindi gagana ang proteksyon — kailangan mong ipadala ang mga parameter sa pamamagitan ng prepared expressions, hindi sa pamamagitan ng concatenation ng string.
Ang Second-Order SQL Injection ay isang pag-atake kung saan ang malisyosong data ay iniimbak sa database bilang ligtas ngunit pagkatapos ay ginagamit sa ibang query nang walang escaping. Halimbawa, nagparehistro ang attacker na may username na ' OR '1'='1. Ang data ay iniimbak bilang string — sa pagpaparehistro walang atake. Ngunit kung ang ibang query ay mag-substitute ng username sa SQL nang walang parametrization, mag-a-activate ang injection.
Ang NoSQL Injection ay potensyal na mas mapanganib dahil sa mas mababang kamalayan ng mga developer. Alam ng mga developer ang tungkol sa SQL Injection at karamihan ay gumagamit ng ORM, ngunit kakaunti ang nakakaalam tungkol sa NoSQL Injection. Sa MongoDB, ang maling pagkakabuo ng query ay maaaring magbalik ng lahat ng dokumento ng collection. Proteksyon — parehong prepared statements (BSON parametrization) at mahigpit na validation ng input data.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din