前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用DNS名称作为安全性依据的漏洞优化

使用DNS名称作为安全性依据的漏洞优化

作者头像
chenchenchen
发布2019-09-18 14:45:07
4.3K0
发布2019-09-18 14:45:07
举报
文章被收录于专栏:chenchenchenchenchenchen

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/weixin_38004638/article/details/100605199

漏洞

问题描述:程序中采用DNS名称进行安全认证,但DNS名称是容易被攻击者进行欺骗的。

许多 DNS 服务器都很容易被攻击者欺骗,所以应考虑到某天软件有可能会在有问题的 DNS 服务器环境下运行。如果允许攻击者进行 DNS 更新(有时称为 DNS 缓存中毒),则他们会通过自己的机器路由您的网络流量,或者让他们的 IP 地址看上去就在您的域中。勿将系统安全寄托在 DNS 名称上。

例如:下面代码片段中,如果发生DNS欺骗,会绕过安全验证。

String ip = request.getRemoteAddr();

InetAddress inetAddress = InetAddress.getByName(ip);

if (inetAddress.getCanonicalHostName().endsWith("demo.com")) {

//Verification passed

}

修复建议: 不要依赖DNS名称进行安全认证。

IP 地址相比 DNS 名称而言更为可靠,但也还是可以被欺骗的。攻击者可以轻易修改要发送的数据包的源 IP 地址,但是响应数据包会返回到修改后的 IP 地址。为了看到响应的数据包,攻击者需要在受害者机器与修改的 IP 地址之间截取网络数据流。为实现这个目的,攻击者通常会尝试把自己的机器和受害者的机器部署在同一子网内。攻击者可能会巧妙地采取源地址路由的方法来回避这一要求,但是在今天的互联网上通常会禁止源地址路由。总而言之,核实 IP 地址是一种有用的 authentication 方式,但不应仅使用这一种方法进行 authentication。

解决方案:如果通过域名检查的方式可以确保主机接受和发送的 DNS 记录的一致性,您可以更加信任这一方式。攻击者如若不能控制目标域的域名服务器,就无法同时欺骗接受和发送的 DNS 记录。虽然这种方法并不简单,但是:攻击者也许可以说服域注册者把域移交给一个恶意的域名服务器。依赖于 DNS 记录的 authentication 是有风险的。 虽然没有十分简单的 authentication 机制,但是还有比基于主机的 authentication 更好的方法。密码系统提供了比较不错的安全性,但是这种安全性却易受密码选择不当、不安全的密码传送和 password management 失误的影响。类似于 SSL 的方法值得考虑,但是通常这样的方法过于复杂,以至于使用时会有运行出错的风险,而关键资源也随时面临着被窃取的危险。在大多数情况下,包括一个物理标记的多重 authentication 可以在合理的代价范围内提供最大程度的安全保障。 Tips: 1. 检查 DNS 信息的使用情况。除了考虑程序员的 authentication 机制能否起作用以外,还应该考虑在社会工程攻击中是如何利用 DNS 欺骗的。例如,如果攻击者可以使自己发出的数据包看上去像是来自内部机器的,他们是否可以通过验证程序获得信任呢?

修复方案1:添加ip校验

代码语言:javascript
复制
ip = ipMatch(IpUtil.getIpAddress().getHostAddress());
代码语言:javascript
复制
private static String ipMatch(String ip){
    if (Pattern.matches("[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?", ip)) {
        return ip;
    }
    return "0";
}

对于IP

可以简单的用JDK提供的方法进行校验: try { InetAddress.getByName(ip); } catch (UnknownHostException uhe) { throw new Exception("Ip address " +ip + " is invalid!"); }

getByName方法原本是传入host name,解析成IP返回,但是也支持传入IP,返回IP,同时对该IP做了校验。

再对IP进行正则表达式判断:

一个IP字串,由四段组成,每一段是0~255的数字,段与段之间用小数点隔开,比如61.139.2.69就是一个合法的IP字串。

如果正则表达式写成/d{1,3}(/./d{1,3}){3}无疑是不负责的,因为它可以匹配300.400.555.666这样的非法IP字串。

要匹配一个0~255之间的数,有几种匹配方式,下面是其中一种:

匹配 正则表达式 说明 0~9 /d 单个数字 10~99 [1-9]/d 两位数 100~199 1/d/d 百位为1的三位数 200~249 2[0-4]/d 三位数,百位是2,十位是0~9 250~255 25[0-5] 三位数,百位是2,十位是5,个位是0~5 写成正则表达式,即:(/d|([1-9]/d)|(1/d/d)|(2[0-4]/d)|(25[0-5])),但是这样的正则表达式在匹配254这样的字串时,会分别匹配2、5、4,得到3个匹配,达不到预期效果,正确做法是将次序颠倒为((25[0-5])|(2[0-4]/d)|(1/d/d)|([1-9]/d)|/d),因为在(xxx|yyy)这种匹配行为中,是从左向右搜索的。

完整的正则表达式是:

((25[0-5])|(2[0-4]/d)|(1/d/d)|([1-9]/d)|/d)(/.((25[0-5])|(2[0-4]/d)|(1/d/d)|([1-9]/d)|/d)){3} 按:

象061这样的高位为0的数是不能被匹配的。 太麻烦,不如自己写一小段代码解析来得容易,呵呵 一个完整的域名,由根域、顶级域、二级、三级……域名构成,每级域名之间用点分开,每级域名由字母、数字和减号构成(第一个字母不能是减号),不区分大小写,长度不超过63。

很显然,单独的名字可以由正则表达式[a-zA-Z0-9][-a-zA-Z0-9]{0,62}来匹配,而完整的域名至少包括两个名字(比如google.com,由google和com构成),最后可以有一个表示根域的点(在规范中,最后有一个点的才是完整域名,但一般认为包括两个以上名字的域名也是完整域名,哪怕它后面没有点)。

匹配完整域名的正则表达式:

[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?

对于HOSTNAME

用正则表达式: 这里顺便把校验IPV4和V6的REG也写出来: public static String REG_IPV4 = "\\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4}\\b"; public static String REG_IPV6 = "^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}|([0-9A-F]{1,4}:){6})(\\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]|(2[0-4]|1\\d|[1-9])?\\d)(\\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,4})(?<![^:]:|\\.)\\z";

public static String VALID_HOST_REGEX = "^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\\b-){0,61}[0-9A-Za-z])?(?:\\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\\b-){0,61}[0-9A-Za-z])?)*\\.?$";

用的时候很简单: Pattern pattern = Pattern.compile(VALID_HOST_REGEX, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(host); if(!matcher.find()) {

throw new Exception("Invalid gateway host"); }

https://www.jb51.net/article/72601.htm

https://www.baidu.com/link?url=jZ_QuN3XINVhP2iN13WjrQFL69NeNecQwCYHcJ5LQwVcNCtg16wkSHA6ByDaKJXxWV6f0UsbLw_NxbWqp5xmuf6cP3QgQgdlXkLAP5Z8Bsm&wd=&eqid=b8fbbc510016d604000000035d73709b

https://blog.csdn.net/seawave/article/details/1520988

修复方案2:更换获取IP的方法

https://www.iteye.com/blog/lafecat-2229184

https://www.jianshu.com/p/6c445ea8211b

参考:

https://www.cnblogs.com/eyesmoon/p/7421477.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年09月07日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 漏洞
  • 修复方案1:添加ip校验
    • 对于IP
      • 对于HOSTNAME
      • 修复方案2:更换获取IP的方法
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档