
Linux, Windows, macOS에서의 파일 알림 부채널 공격에 대한 연구 자료로, inotify/FSEvents 누출, 키 입력 타이밍, 웹사이트 핑거프린팅을 시연합니다.
이 저장소는 CCS '26에 채택된 논문 "File Notification Attacks: Templating and Exploiting Side-Channel Leakage from the File-Notification Systems on Linux, Windows, and macOS"의 (아직 심사 중인!) 아티팩트를 포함하고 있습니다.
데모가 있는 웹사이트를 방문하세요: https://inoti.fyi/
논문 읽기: https://snee.la/pdf/pubs/file-notification-attacks.pdf 또는 http://inoti.fyi/pubs/file-notification-attacks.pdf
CCS'26의 아티팩트 평가 (아직 진행 중!)의 일환으로, 우리는 사전 패치된 커널이 포함된 Debian 13 + KDE Plasma 6 VM을 제공했습니다. 이 VM은 논문의 평가 결과를 산출하는 데 사용되지 않았으며, 그 정확한 규모를 재현하기 위한 것도 아닙니다. 이 저장소는 아티팩트 평가자들의 리뷰와 피드백을 반영하여 업데이트될 수 있습니다. 아티팩트 평가가 완료되면 VM을 공개적으로 접근 가능하게 만들 것입니다.
우리는 코드를 적절히 잘 문서화되고 고성능인 아티팩트로 감싸기 위해 Claude (Opus 4.8)를 사용했습니다 (예를 들어, Windows용은 약간 느렸습니다). 그러나 그것이 생성한 코드, 스크립트, makefile은 다음을 기반으로 했습니다
아래의 Linux 코드 테스트 지침은 VM에서 명령을 실행하는 것에 특화되어 있습니다. 대신
Linux/에 있는 코드를 살펴보세요.
VM은 순전히 편의를 위해 존재하며, 각 공격을 마운트할 때 처음부터 환경을 설정하거나 커널을 다운그레이드할 필요가 없도록 합니다. VM에서 시연되는 기본 메커니즘은 논문에서 설명된 것과 동일하지만, 우리가 논문에 보고된 수치를 산출하기 위해 VM을 사용하지 않았다는 점에 유의하시기 바랍니다. 절대적인 타이밍은 가상화 환경과 기반 하드웨어로 인해 다를 수 있습니다.
결과는 Debian 13 VM (linux-vm/) 내에서 재현되며, 공식 라이브 Debian ISO에서 KDE Plasma 6
(Wayland)와 함께 설치되었고, fsnotify
수정 이전의
커널을 사용합니다. inotify-tools, Qt6 개발 헤더, pkexec가 설치되어 있습니다. 그 외에는
아무것도 업그레이드되지 않으며, 설치 후 커널은 절대 건드리지 않습니다. 절대 apt upgrade를
실행하거나 커널을 업그레이드하려고 시도하지 마세요. 이 VM 이미지는 의도적으로 오래되었고,
최신 상태가 아니며, 최신 보안 패치가 없습니다. 이 VM 이미지는 빠른 검증과 테스트만을 위한
것입니다!
VM 내에 위치한 코드, 공격, 데모는 Linux/에 미러링되어 있습니다.
참고: 각 명령 블록 상단에 명령을 실행할 사용자를 명시합니다. VM을 실행하는 호스트
머신인 [host], VM 내 공격의 피해자인 [user], 설정이 필요하며 대부분의 Linux 공격에서
공격자가 될 [spyuser]가 있습니다.
디스크 이미지는 linux-vm-upload.qcow2로 제공되며, zstd로 압축되어 있습니다. run.sh를
실행하기 전에 linux-vm.qcow2로 이름을 바꾸세요 (해당 파일명을 기대합니다):
# Run As: [host]
cd linux-vm/
mv linux-vm-upload.qcow2 linux-vm.qcow2
./run.sh
zstd로 압축된 qcow2를 읽으려면 qemu-img/qemu-system-x86_64 버전 5.2 이상 (2020년 이후)이
필요합니다. qemu-img --version으로 확인하세요. 구버전 QEMU를 사용 중이고 이미지를 열지
못한다면, 먼저 플랫 qcow2로 압축을 해제하세요:
qemu-img convert -O qcow2 linux-vm-upload.qcow2 linux-vm.qcow2
4 코어, 4GB RAM, GUI 디스플레이. 로그인 정보:
root, 비밀번호 password,user, 비밀번호 password,spyuser, 비밀번호 password (spyuser로 로그인하지 마세요!)제공된 VM은 이미 취약한 사전 패치된 커널 (6.12.43+deb13-amd64)을 실행하므로, 사용하기 위해
다운그레이드할 필요가 없습니다. 이 이미지 (GUI 포함)를 실행하려면 QEMU가 필요합니다.
아티팩트는 VM 내 /home/user/Linux-File-Notification-Attacks에 있습니다.
하나의 명령으로 VM에서 처음부터 설정합니다: (i) 비특권 spyuser 계정 (비-sudo), (ii) 자체
아티팩트 디렉터리 사본 (별도의 비특권 계정은 그렇지 않으면 user의 홈 디렉터리로 들어갈 수
없습니다), (iii) 두 사본 모두에서 모든 스크립트를 실행 가능하게 만듭니다.
# In the VM, Run As: [user]
sudo bash ~/Linux-File-Notification-Attacks/setup_attacks.sh
아래의 모든 공격은 spyuser로 실행됩니다 (su - spyuser, 비밀번호 password), 단
auth-ui-redress는 user로 실행됩니다 (아래에서 설명).
부모 디렉터리를 읽을 수 있는 한, 직접 읽을 수 없는 파일에 대해서도 파일 작업 알림이 전달됨을 증명합니다.
# Run As: [spyuser]
# To switch to spyuser, in a new terminal type `su - spyuser`. The password
# is `password`.
cd ~/Linux-File-Notification-Attacks/unreadable-file-bypass
./watch-syslog.sh
실행 상태로 두고, 다른 터미널에서 user로 로그 줄을 생성하세요:
# Run As: [user]
logger "hello"
이 Debian 13 이미지에는 rsyslog가 없으므로, 논문에 나온 것처럼 /var/log/syslog 파일이
없습니다. 스크립트는 대신 /var/log/journal/<machine-id>/를 감시하는 것으로 대체합니다.
이는 동일한 아이디어인데, 감시되는 .journal 파일들이 root (사용자)와 systemd-journal
(그룹) 소유이며, 둘 다 spyuser가 아니기 때문입니다.
inotify의 알림 지연을 측정합니다.
# Run As: [user], ensure numpy is installed (or pip3)
sudo apt install python3-numpy
# Run As: [spyuser]
cd ~/Linux-File-Notification-Attacks/temporal-resolution
./run.sh
watcher는 테스트 파일에 inotify 감시를 열고 수신하는 모든 IN_ACCESS에 타임스탬프를
기록합니다. accessor는 동일한 파일을 읽기 사이에 무작위 5-10ms 지연을 두고 1000번 읽으며,
각 읽기에 자체적으로 타임스탬프를 기록합니다. stats.py는 두 타임스탬프 기록을 비교하여
읽기가 발생한 시점과 알림이 도착한 시점 사이의 평균/표준편차/최소 지연, 즉 inotify의 시간
해상도를 출력합니다.
논문의 전체 공격은 아니고, 공격이 기반으로 하는 필터링 개념 증명 프리미티브일 뿐입니다:
시스템 어디에서든 눌린 모든 키에 대해, /dev/input을 직접 읽지 않고 타임스탬프가 찍힌
알림 하나를 출력합니다.
# Run As: [spyuser]
cd ~/Linux-File-Notification-Attacks/inter-keystroke-timing
make
./find-keyboard.sh
아무 창에서나 입력하세요 (아마도 user로 새 터미널). 각 키 입력은 하나의 KEYPRESS 줄을
출력합니다. 억제 윈도우 (이 데모를 위해 우리가 휴리스틱하게 선택한 130ms)는 단일 물리적 키
누름에 의해 생성된 여러 IN_ACCESS 이벤트를 병합합니다. 실제로 우리는 이 윈도우가 하드웨어마다
(예: 기계식 키보드, 타이핑 스타일) 다르다는 것을 관찰했습니다.
자동 감지가 잘못된 장치 (또는 아무것도)를 선택하면, /proc/bus/input/devices를 확인하고
./build/keystroke-notify /dev/input event4로 직접 실행하세요.
우리는 (pkexec)[https://polkit.pages.freedesktop.org/polkit/]가 실행되는 시점을 감지하고,
그 위에 가짜 창을 그릴 수 있음을 시연합니다. 섹션 4.4.3에서 보여준 것처럼, 이 '인증 UI
리드레스 공격'은 Wayland를 사용하는 KDE Plasma 5 및 6에서 가능합니다. 우리는 이 공격을
동일 사용자 공격자 위협 모델에서 실행합니다: Wayland 소켓은 로그인 세션에 범위가 지정되며,
별도의 비특권 계정은 그 위에 그릴 수 없습니다.
기본 KDE 설치에서는 pkexec가 데스크톱에 의해 끌어와지지만, 이 라이브 ISO는 더 간소한
이미지이므로 설치되어 있지 않습니다. 따라서 우리는 VM 이미지를 작게 유지하려고 (노력하면서)
수동으로 설치했습니다.
# Run As: [user]
cd ~/Linux-File-Notification-Attacks/auth-ui-redress
make
./inotify-watcher-with-gui
터미널에서 실행 상태로 두세요. 다른 터미널에서 (디렉터리는 상관없음) 실제 pkexec 프롬프트를
트리거하세요, 예: pkexec ls. 감시자는 /usr/bin/pkexec에 대한 접근을 보고 가짜
"Authentication Required" 대화상자 (window-launcher)를 실제 대화상자 위에 화면에 그립니다.
가짜 대화상자에 입력하고 Authenticate를 누르면 입력한 텍스트가 감시자의 터미널에 출력된 후
창이 닫힙니다. 가짜 창은 쉽게 비교할 수 있도록 실제 창과 의도적으로 다르다는 점에
유의하세요.
페이지가 로드되는 동안 폰트 디렉터리를 감시하면 어떤 폰트 파일을 건드렸는지 드러납니다. 사이트마다 다른 폰트를 끌어오므로, 페이지가 로드되는 동안 출력되는 경로 집합은 그 자체로 핑거프린트이며, 이 최소 버전에는 타이밍이나 분류기가 필요하지 않습니다.
먼저, 사용자로서 Firefox를 열고 (화면 하단의 작업 관리자 독에 있는 아이콘을 클릭), 열려 있는
웹사이트가 없는지 확인하세요. 그런 다음, spyuser로서 터미널에서:
# Run As: [spyuser]
cd ~/Linux-File-Notification-Attacks/website-fingerprinting-fonts
./compare-fonts.sh
이것은 Firefox가 사용하는 폰트 디렉터리 모니터링을 시작하는 font-spy를 빌드합니다.
compare-fonts 스크립트는 두 개의 웹사이트를 방문하라고 안내합니다.
먼저, 한 웹사이트 (아마도 wikipedia.com)를 방문하고 로드될 때까지 몇 초 기다린 후, 새 탭을 열고, (웹사이트가 있는) 이전 탭을 닫은 다음, 터미널에서 ENTER를 누르세요.
둘째, 다른 웹사이트 (아마도 reddit.com)로 동일하게 하세요: 웹사이트를 방문하고 로드될 때까지 몇 초 기다린 후, 새 탭을 열고, 이전 탭을 닫은 다음, 터미널에서 ENTER를 누르세요.
스크립트는 웹사이트별로 접근된 폰트의 차이를 출력해야 합니다. 논문에서는 우리가 시간 정보, 즉 폰트가 언제 접근되었는지도 사용했다는 점에 유의하세요. 간단한 개념 증명을 위해 우리는 이 정보를 무시하고 단순히 두 폰트 접근 집합 간의 차이를 출력합니다. 정확한 폰트 접근 집합은 실행마다 다를 수 있지만, 웹사이트에 의해 항상 그리고 고유하게 접근되는 특정 폰트 파일들이 있습니다.
웹사이트는 시간이 지남에 따라 변경될 수 있으므로, 폰트 파일 접근이 다를 수 있다는 점에
유의하세요. 이 아티팩트를 작성할 당시, 우리는 Wikipedia가 항상
/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf에 접근하고 Reddit이 항상
/usr/share/fonts/truetype/vlgothic/VL-Gothic-Regular.ttf에 접근한다는 것을 관찰했습니다.
Scoped Storage 모델이 여전히 WhatsApp의 공유 미디어 디렉터리에 FileObserver (inotify의
Java 수준 래퍼)를 등록하는 것을 허용하는 Android 버전을 실행하는 물리적 장치 또는 에뮬레이터,
그리고 메시지 발신자 역할을 할 두 번째 장치/계정. 제공된 소스 (Android/source/)를
빌드하거나 제공된 APK (Android/app-release.apk)를 직접 설치하세요.
Android는 Linux 결과 전반에 사용된 것과 동일한 inotify 프리미티브를
android.os.FileObserver를 통해 노출합니다. 섹션 5.4.3은 비특권의 권한 없는 앱이 WhatsApp의
미디어 디렉터리에 그러한 옵저버를 등록하고, 결과적인 open/close/access 이벤트 스트림만으로
콘텐츠 자체를 읽을 수 있게 해주는 어떤 권한도 보유하지 않고 사적인 미디어가 수신되었음을
추론할 수 있음을 보여줍니다.