
다른 호스트의 여러 관점에서 네트워크 가시성을 확장합니다.
전쟁에서 CornerShot은 군인이 모퉁이 너머를 살펴보고(어쩌면 사격도) 적에게 노출되지 않고 공격할 수 있게 해주는 무기입니다. 이와 유사하게, CornerShot 패키지를 사용하면 원격 호스트에서 특별한 권한 없이도 해당 호스트의 네트워크 접근 상태를 확인할 수 있습니다.
CornerShot을 사용하면 소스(source)가 캐리어(carrier)에 네트워크 접근이 가능할 때, 특정 포트 p에 대해 캐리어와 타겟(target) 사이에 네트워크 접근이 있는지 확인할 수 있습니다.
예를 들어, 레드팀이 "침해된" 소스 호스트 A에서 타겟 호스트 X로 전파하려고 하는데, 호스트 A는 X에 접근할 수 없다고 가정해 봅시다. 만약 호스트 B를 통해 전파한다면, 그제서야 호스트 B와 X 사이에 네트워크 접근이 없음을 알게 됩니다.
CornerShot을 사용하면 팀은 호스트 C가 실제로 타겟 X에 접근 가능하다는 것을 발견할 수 있으며, 따라서 타겟 X로의 전파는 먼저 호스트 C를 거쳐야 합니다.
+-----+ +-----+ +-----+
| | | | filtered | |
| A +--------> B +----X--->(p) X |
| | | | | |
+-----+ +-----+ +-(p)-+
source carrier target
+ ^
| |
| +-----+ |
| | | open |
+---------->+ C +-------------+
| |
+-----+
nmap과 유사하게 CornerShot은 포트 상태를 open(열림), closed(닫힘), filtered(필터링됨), unknown(확인 불가)으로 구분합니다.
다음 데모는 두 캐리어 호스트 172.0.1.12와 172.0.1.13에 대해 CornerShot을 실행하여 이들이 192.168.200.1에 네트워크 접근이 가능한지 확인하는 모습입니다:

자세한 내용은 여기를 참조하십시오.
네트워크 내 어떤 호스트 B가 호스트 C에 접근 가능한지 식별하는 단순해 보이는 작업은 대규모 네트워크 센서 배포, 디바이스 에이전트 설치, 또는 수많은 방화벽 규칙, 라우터 설정, 호스트 정책 수집을 필요로 할 수 있습니다.
CornerShot은 하나(또는 소수)의 에이전트를 사용하여 네트워크의 다른 호스트를 쿼리하고, 해당 호스트의 원격 호스트 접근 상태를 확인함으로써 이 과정을 단순화할 수 있습니다.
BloodHound를 사용하여 네트워크 내 권한 상승 경로를 찾고 완화하는 보안 팀은 종종 BloodHound가 발견한 수백만 개의 논리적 경로로 어려움을 겪습니다.
ShotHound는 CornerShot과 BloodHound를 통합하여 네트워크 접근이 실제로 뒷받침되는 실용적인 경로를 발견하는 도구입니다.
CornerShot은 패키지로 사용하거나 독립 실행형 모듈로 사용할 수 있습니다. 필요한 것은 Python 3와 impacket 패키지뿐입니다.
pip install cornershot
기본 사용법은 유효한 도메인 사용자의 자격 증명, FQDN 도메인, 캐리어 IP 및 타겟 IP가 필요합니다.
python -m cornershot <user> <password> <domain> <carrier> <target>
캐리어 범위와 타겟 범위를 스캔하려면 서브넷 또는 IP 범위를 쉼표로 구분된 목록으로 사용할 수 있습니다:
python -m cornershot <user> <password> <domain> 192.168.1.10-192.168.1.20 192.168.5.0/24,192.168.6.0/24
기본적으로 CornerShot은 다음 포트를 스캔합니다: 135, 445, 3389, 5985, 5986. 사용자는 쉼표로 구분된 포트 및 포트 범위 목록을 제공할 수 있습니다:
python -m cornershot -tp 22,8080,45000-45005 <user> <password> <domain> <carrier> <target>
코드 내에서 유효한 도메인 사용자의 사용자 이름, 비밀번호 및 도메인 이름으로 CornerShot 객체를 인스턴스화해야 합니다. 캐리어, 타겟 및 포트를 추가하는 것은 add_shots 메서드를 통해 수행됩니다. 준비가 되면 open_fire 메서드를 호출할 수 있으며, 이 메서드는 필요한 포트에 따라 관련 RPC 호출만 수행합니다.
from cornershot import CornerShot
cs = CornerShot("username", "password", "fqdn")
cs.add_shots(carriers=["192.168.1.1"],targets=["192.168.1.2","192.168.1.3"])
results = cs.open_fire()
open_fire의 결과는 캐리어를 키로 하는 사전이며, 각 캐리어는 다시 타겟을 키로 하는 사전을 가지고, 마지막으로 각 타겟은 포트와 해당 상태를 담은 사전을 가집니다. 결과 형식 예시:
{'carrier_1':
{'target_1':
{135: 'unknown', 445: 'filtered', 3389: 'filtered', 5986: 'filtered', 5985: 'filtered'},
'target_2':
{135: 'unknown', 445: 'open', 5985: 'unknown', 5986: 'filtered', 3389: 'open'}
},
'carrier_2':
{'target_1':
{3389: 'filtered', 135: 'filtered', 5985: 'filtered', 445: 'filtered', 5986: 'unknown'},
'target_2':
{5985: 'filtered', 5986: 'filtered', 445: 'filtered', 135: 'filtered', 3389: 'open'}
}
}
CornerShot은 다양한 Microsoft 서비스에서 사용되는, 잘 문서화된 표준 RPC(Remote Procedure Call) 메서드에 의존합니다. 도메인에서 인증된 계정만 필요로 하는 메서드를 사용함으로써 CornerShot은 캐리어 호스트에서 타겟으로의 네트워크 트래픽을 트리거할 수 있습니다.
CornerShot은 RPC 호출에 소요된 시간과 각 RPC 메서드의 오류 코드를 측정하여 원격 포트 상태를 판별합니다.
독자는 Lee Christensen이 발견한 "프린터 버그"에 익숙할 수 있습니다. 버그라고 불리지만, 이는 인쇄 서비스의 잘 문서화된 동작으로, 인증된 사용자가 RpcRemoteFindFirstPrinterChangeNotificationEx 메서드를 사용하여 원격 서버가 모든 머신에 인증하도록 강제할 수 있습니다.
CornerShot은 여러 Microsoft 프로토콜의 다음 RPC 메서드를 활용합니다 (향후 버전에서 구현될 추가 메서드가 많이 있습니다):
프로토콜 자체의 구현은 훌륭한 impacket 패키지를 통해 이루어집니다.
이 메서드는 printerName을 매개변수로 받습니다. printerName은 로컬 파일, 원격 파일 또는 웹 프린터의 경로가 될 수 있습니다. WEB_PRINT_SERVER 형식에 맞는 이름을 제공하면 모든 원격 포트를 쿼리할 수 있습니다. 원격 호스트와 포트로 HTTP 트래픽을 트리거하는 웹 인쇄 서버 이름의 예: "http://<target_ip>:<target_port>/printers/ppp/.printer"
이 메서드를 활용하려면 두 단계 접근 방식이 필요합니다. 먼저 원격 호스트에서 레지스트리 키를 열어 유효한 핸들을 얻은 다음, 이 핸들의 백업을 원격 파일에 저장하려고 시도합니다. BaseRegSaveKey 메서드는 레지스트리 백업을 저장할 파일 경로를 받으며, 이는 타겟으로 445 포트(및 백업으로 135)를 통해 SMB 트래픽을 트리거합니다. CornerShot이 여는 레지스트리 키는 HKEY_CURRENT_USER로, 대부분의 클라이언트 호스트에서 기본적으로 읽기 열려 있습니다.
이 함수는 Windows 이벤트를 파일 경로에 백업하려고 시도합니다. 파일 경로는 원격일 수 있으며, 이 경우 서비스는 원격 호스트와 경로에 접근하려고 시도합니다.
EVEN 메서드와 유사하지만, 이 메서드는 Windows Events 프로토콜의 다른 버전을 활용하며 TCP를 통해 직접 수행됩니다. SMB 포트가 열려 있을 필요가 없습니다.
CornerShot은 타이밍 요소와 RPC 메서드 또는 기본 전송에서 수신된 오류 메시지를 기반으로 원격 포트의 상태를 추정합니다. 다양한 Windows 호스트 및 다양한 RPC 프로토콜을 실험한 결과, 대부분의 네트워크 환경에서 작동하는 3가지 다른 타이밍 임계값을 도출했습니다. 이 임계값은 다음 그림으로 가장 잘 설명됩니다:
+ + +
| | |
unknown | open / closed | filtered | open
/ | | |
open | | |
| | |
+-------------+------------------+-----------------+--------------+
0 0.5 20 40 Seconds
MIN FILTERED UPPER
MIN 임계값은 0.5초이며, 이 임계값 미만의 응답은 기본 RPC 메서드 또는 기본 전송의 오류를 의미하거나 타겟 호스트로부터 응답을 받았을 수 있습니다.
FILTERED 임계값(20초) 미만의 응답은 메서드에 대해 수신된 오류 메시지 유형에 따라 열린 포트 또는 닫힌 포트를 나타낼 수 있습니다.
FILTERED 임계값과 UPPER 임계값(40초) 사이의 응답은 테스트된 모든 메서드에 대해 필터링된 포트를 나타냅니다(현재까지). UPPER 한계를 초과하는 요청은 장기간 지속되는 열린 TCP 연결을 나타냅니다.
다양한 OS 버전 및 구성에 대해 CornerShot을 실행하면 다른 결과가 나옵니다. 모든 Windows 버전이 동일한 named pipe를 가지거나 동일한 RPC 메서드로 쿼리할 때 동일하게 동작하지는 않습니다. 대부분의 Windows OOTB는 네트워크를 통해 SMB 및 기타 RPC 서비스를 노출하지 않지만, 대규모 환경에서는 이러한 포트가 대부분의 자산에 대해 열려 있고 접근 가능한 경향이 있습니다.
다음 표는 적절한 포트가 캐리어 호스트에서 접근 가능하고 호스트에 구성 변경이 없을 때 다양한 RPC 프로토콜에 대한 기본 지원을 보여줍니다:
* 클라이언트 머신에서 Webclient 서비스가 실행 중이면 추가 포트를 스캔할 수 있습니다. 현재 CornerShot은 이 옵션을 지원하지 않습니다.
** RPRN 프로토콜은 서버 호스트에서 지원되지만 원격 웹 프린터 열기가 작동하지 않습니다(따라서 ANY 타겟 포트를 스캔할 수 없음). 해결 방법을 찾을 때까지는 😉
추가 RPC 샷이나 기타 기여는 환영합니다!
모든 RPC 메서드는 /shots 아래에 구현되어 있으며, BaseRPCShot 추상 클래스를 상속합니다. /example 폴더는 사용자 지정 RPC 샷을 만들고 코드에서 사용하는 방법을 보여줍니다.
CornerShot은 Apache 2.0 라이선스로 배포됩니다. 자세한 내용은 LICENSE를 참조하십시오.
여러분의 소식을 기다립니다! 이 패키지에 대한 버그, 패치, 제안 사항은 [email protected]으로 연락해 주십시오.
| OS | 지원되는 RPC 프로토콜 | 필요한 열린 캐리어 포트 | 스캔 가능한 타겟 포트 |
|---|
| Windows 7 | EVEN,EVEN6 | 445 / 135 및 even6 tcp 포트 | 445* |
| Windows 8 | EVEN,EVEN6 | 445 / 135 및 even6 tcp 포트 | 445* |
| Windows 10 | EVEN,EVEN6,RPRN | 445 / 135 및 even6 tcp 포트 | ANY |
| Server 2008 | EVEN,EVEN6,RRP,RPRN** | 445 / 135 및 even6 tcp 포트 | 445 |
| Server 2012 | EVEN,EVEN6,RRP,RPRN** | 445 / 135 및 even6 tcp 포트 | 445 |
| Server 2016 | EVEN,EVEN6,RRP,RPRN** | 445 / 135 및 even6 tcp 포트 | 445 |
| Server 2019 | EVEN,EVEN6,RRP,RPRN** | 445 / 135 및 even6 tcp 포트 | 445 |