V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bccber
V2EX  ›  程序员

hosts 劫持域名.怎么破?

  •  
  •   bccber · 2017-03-13 09:18:04 +08:00 · 3140 次点击
    这是一个创建于 2820 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一个 c#写的客户端
    登录时使用 HTTP 协议到服务端验证
    假如有用户修改 hosts,把我服务器的域名指向到 localhost 并且返回正确的内容
    那验证这块是不是就废了?
    怎么破?
    13 条回复    2017-03-14 23:28:16 +08:00
    myleon
        1
    myleon  
       2017-03-13 09:30:21 +08:00
    ssl
    linescape
        2
    linescape  
       2017-03-13 09:50:35 +08:00
    一楼的办法,加 ssl 。要么返回的数据用自己的私钥加密,客户端用公钥解密后再验证
    shoaly
        3
    shoaly  
       2017-03-13 09:53:21 +08:00
    http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html
    看看上面链接 数字签名的一块, 通过数字签名 你的客户端就能确定 对方是不是具有私钥的一方(假设就你服务器有私钥)
    artandlol
        4
    artandlol  
       2017-03-13 09:55:20 +08:00
    每次登陆在客户端和服务端生成一组有规律的数(比如是 sha256 ( date ) xor 365 )进行二次验证 /斜眼
    bccber
        5
    bccber  
    OP
       2017-03-13 10:33:22 +08:00
    @myleon
    @linescape
    @shoaly
    @artandlol
    流程大概是这样的,假如一个用户现在是正常状态,服务器返回的 json 是{"ret":1} (当然,json 字符串是经过简单加密的)
    然后在后台把这个用户禁用{"ret":0}
    用户发现用不了,把域名指向 localhost 自己写的一个简单的网页,也一样返回加密后的{"ret":1}
    应该要在 json 里加上使用时间
    henices
        6
    henices  
       2017-03-13 11:05:06 +08:00
    这个问题解决起来并不困难。楼主的问题在于验证的服务器被假冒了,所以问题就转化为了如何防止验证服务器被假冒。

    上面 @shoaly 的回答就是一种思路。

    总体看有两个思路:

    1. 验证的方法不被用户所知,但是程序是可以逆向的, ssl 流量也可是可以被中间人劫持的。(无非是增加点难度)
    2. 把验证放到服务端来做,验证不过就不提供服务
    (比如校验一个 token ,这个 token 的算法的其中一步是由你的服务器的提供的独有的计算结果)
    lslqtz
        7
    lslqtz  
       2017-03-13 11:46:48 +08:00 via iPhone
    https 可以中间人 应该加 hpkp
    changwei
        8
    changwei  
       2017-03-13 14:32:04 +08:00
    我在想的是,既然是 C#写的客户端,那么意味着用户可以反编译 ,可以直接去除验证功能,无论什么 ssl 之类的解决方案都是无效的。
    bccber
        9
    bccber  
    OP
       2017-03-13 15:00:26 +08:00
    @changwei 嗯 这也是最大的问题 但会在外面随便加个壳 随便限制就行了
    现在的方案是:

    启动后先做域名解析,解析出服务器真正的 IP 地址,然后在返回的 JSON 中带上服务器 IP
    并且和客客户端解析出来的 IP 做校验,不相同就报错
    giuem
        10
    giuem  
       2017-03-13 15:20:38 +08:00 via iPhone
    验证后返回一个 token 设置有效期(比如一个小时)
    所有的操作都要验证 token ,这样行不行
    bccber
        11
    bccber  
    OP
       2017-03-13 15:38:09 +08:00
    @giuem
    不太行
    因为 token 的前提是要连接上正常的网站接口,如果劫持了域名,token 就失去了作用了
    as463419014
        12
    as463419014  
       2017-03-13 19:45:41 +08:00
    这看你做个客户端是用来做什么功能的
    1.如果你客户端只是操作的发起者,而操作的具体执行在服务端完成,那么这么登录验证别人就无法模拟,即使模拟了登录成功,也不能模拟后续的具体功能操作(比如调用支付宝的支付 api 发起一个支付的动作,客户端只是发起支付,但是支付的具体过程是在支付宝的服务器后台完成的)
    2.如果你的客户端就可以完成功能而不依赖服务器,那么这个验证无论如何都是可以破解的,只是复杂的验证可以增加破解的难度,如果破解的成本超过了使用你这个软件的成本,那么别人就不会来破解你这个软件了(比如 VC,IDEA 等,都是付费的软件,但是软件的使用不依赖于服务器,所以大家都能找到破解版)
    wafm
        13
    wafm  
       2017-03-14 23:28:16 +08:00
    曾经做过一个类似网络验证的程序,提供 2 条思路.

    1.既然害怕别人模拟你的算法,那么就尽量做到算法尽可能难被逆向..比如返回 JSON 加密按照服务器的时间作为参数和本地作对比?如果过期那么就作废,这招可以防止本地的模拟和保障验证的合法性,也就是说 封包唯一性.

    2.业界有说法叫暗桩的东西,既然你知道破解者可能利用这点来进行破解,那么你应该正当维护自己的合法性,正常用户使用不可能去修改 HOSTS 指向本地,那么 是否有策略让非法使用者付出代价?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2854 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 12:17 · PVG 20:17 · LAX 04:17 · JFK 07:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.