见得多的: 编写代码那个时代存在的手机号段正则表达式(人才)。。。
不能忍的: 编写代码那个时代存在的顶级域名正则表达式(还不全)。。。
最近遇到个扫码工具不认一个 url,小众顶级域名,改成.com 这个顶级域名就可以就可以认。不难猜想,写这个代码的程序员如此的牛逼,找了一段自认为可以降服一切的域名下 url 的匹配方式。。让每年可能会出那个个把子的顶级域名情何以堪?
昨天在微博上搞微博登录,发现应用信息里面可以填安全域名,我的一个小众顶级域名后缀域名死活不认,工信部都认了。。。改成 com 就这种问题,今天研究了一下他们家代码,真是写的一手好代码呀,微博前端团队+后端团队,估计前后端这个限制代码都是同一个人写的吧,绕都绕不过。。。人才
解决办法:简化规则,皆大欢喜~ 手机号,url 大部分地方都可以使用最简化的正则表达式来判断。
随手写一个域名判断:/^([\w-]+.)+(\w+)$/,应该能适用大部分地方,小部分除外,新出顶级域名还不用更新。 随手写一个手机号判断:/^1\d{10}$/,应该能适用大部分地方,小部分除外,新出号段还不用更新。
另:记得 chrome 里面使用的是一个地方维护着的顶级域名列表,这种需要判断顶级域名的地方并且需要显示自己牛逼的地方,不学学?
主要呼叫微博吧,其他的就算了,开放平台->我的应用->基本信息->安全域名
1
nervdy 2019-01-16 13:34:25 +08:00
你的随手写可能会留下更大的坑
|
2
drydiy 2019-01-16 13:40:23 +08:00
你这随手写思考过??
这不严谨的态度明显不对。 |
3
xiangyuecn OP @nervdy 我觉得微博这里就算不验证格式,随便写 abcd,也不会对业务逻辑产生任何影响,也不会有安全问题,你能用 abcd 这个域名访问微博接口,说明你已经持有了 abcd 这个域名,虽然这个域名看起来不合规。
留坑也比不能用好更好些吧~ |
4
frye 2019-01-16 13:42:57 +08:00
处于安全的角度,我觉得微博的做法没错
|
5
xiangyuecn OP @drydiy 大部分场合不需要这种多此一举的严谨,你觉得呢。尤其是这个扫码的,想想就怪怪的
|
6
flyingghost 2019-01-16 13:44:52 +08:00 1
宽标准=前瞻性=漏洞百出的校验?
严标准=基于现实=无法适应变化? 这两条路都不是什么好路子。 好路子难道不是 基于当前的严标准 + 配置化等易扩展易维护的结构 + 最重要的时时刻刻维护更新 嘛? |
7
xiangyuecn OP @frye 这是导致不能用的安全。。
这个地方重要的应该是判断书写是否错误,而不是用来判断域名有效性。如果要判断输入有效性,应该判断这个域名的有效性( DNS 解析、whois 之类的),而非特定格式。 |
8
xiangyuecn OP @flyingghost 难在维护更新,要是他们会更新,也就不会导致这种问题。
|
9
sagaxu 2019-01-16 13:49:59 +08:00 via Android 9
小众域名客户的商业价值低,爱用不用
|
10
xiangyuecn OP @sagaxu 无言以对,事实如此呀,记得前几年这个域名注册商哪里注册好了,然后自己很多地方自己都不支持这个域名,无奈~
|
11
reus 2019-01-16 13:56:51 +08:00
程序员才懒得做这种事情,一般是傻逼产品的锅
|
12
gesse 2019-01-16 13:58:48 +08:00
你怎么知道人家是手写、固定死了的? 现在很多 JS 都是配置然后生成的
|
13
xiangyuecn OP 想到一个绝佳的例子:
手机号,不会错的地方不校验也不会错,会错的地方怎么校验都可能出错。 注册:手机号要收验证码这种,就算不校验手机号格式,也 100%不会出错。 收获地址:手机号随便填大部分好像不会验证真实性,这个地方就算校验了格式,还是可能输错,而且还发货了,快递小哥找不到人这种。。 |
14
xiangyuecn OP @gesse 哈哈,神奇的在于配置是手写固定死的,还不更新,虽然经过 build 这个伪动态过程,按这个逻辑往上盘
|
15
geelaw 2019-01-16 14:10:34 +08:00 via iPhone
🙄您连 dot 都忘了转义
|
16
xiangyuecn OP @geelaw 哦,改不了啦,被你发现了~
|
17
iNaru 2019-01-16 14:17:50 +08:00 2
https://www.publicsuffix.org/learn/
Some people use the PSL to determine what is a valid domain name and what isn't. This is dangerous, particularly in these days where new gTLDs are arriving at a rapid pace, if your software does not regularly receive PSL updates, because it will erroneously think new gTLDs are not valid. The DNS is the proper source for this information. If you must use it for this purpose, please do not bake static copies of the PSL into your software with no update mechanism. |
18
wysnylc 2019-01-16 14:21:19 +08:00
您可真不自作聪明
|
19
lhx2008 2019-01-16 14:22:24 +08:00
QQ 邮箱还只能发几个后缀的邮箱呢,V2EX 也有一票域名不能识别
|
20
alvin666 2019-01-16 14:23:46 +08:00 via Android
手机号重置全是这样写死的,199 刚出来的时候哪里都不能充值
|
21
zsdroid 2019-01-16 14:28:39 +08:00 4
老是有 自作聪明的 程序员在 需要验证的地方说不要验证
|
22
iwtbauh 2019-01-16 14:35:27 +08:00 via Android
这个问题不是“不需要验证”,而是“验证的方式不对”。
当然需要验证,但是把收集后戳作为知识塞入代码明显是不对的。而且也是违反互联网标准的。DNS 不就是为了解决这个诞生的吗。 |
23
zwh2698 2019-01-16 14:39:10 +08:00 via Android
建议学习安全编码
|
24
daixu 2019-01-16 15:37:31 +08:00
这种东西大概率是测试或者产品提出来。然后开发才写死的。关开发的猫猫关系啊。没事谁愿意把这东西写死咯。
|
25
corkspin 2019-01-16 15:50:10 +08:00
@daixu 说得对,产品和测试说 abcd.abcd 不是一个域名,199..不是一个手机号。 楼主那两个正则可比下面的简单太多了。
|
26
xnode 2019-01-16 16:05:14 +08:00
...喷的点不对吧,要喷就喷 新浪不能快速迭代验证
|
27
tianyou666shen 2019-01-16 16:18:39 +08:00
楼主没上过班吗?
这种业务需求能是程序员定的 ? 没见过一种生物叫做产品吗? 不晓得这位大佬在哪里高就 是几个人团队的 leader ... |
28
woodensail 2019-01-16 16:24:37 +08:00
@xiangyuecn
很多时候安全性是重于可用性的 |
29
woodensail 2019-01-16 16:25:14 +08:00
嗯,我好像回错人了,算了……
|
30
ioven 2019-01-16 16:30:31 +08:00
@xiangyuecn 收验证码的手机号不用验证?难道直接发短信?
|
31
xiangyuecn OP @ioven 我说的没这么极端。。。我在 13 楼 说的意思是通过格式验证并不能校验有效性,能简化的尽量简化,就算把正则写出花了,复杂表达式和简单表达式在对安全性上的作用基本属于同一个量级。
|
32
gesse 2019-01-16 16:54:35 +08:00
大家都散了吧, 无法沟通。
|
33
zhttty 2019-01-16 16:56:58 +08:00 3
看了你的内容和“随手写”,我觉得楼主就是那种程序员,拿自己举例挺好的,这下子大家都明白什么叫做“自作聪明”了。
|
34
rqzheng2008 2019-01-16 16:59:29 +08:00 via Android
可以,很自作聪明的 lz
|
35
balamiao 2019-01-16 17:03:14 +08:00
楼主够沙雕~
|
36
weixiangzhe 2019-01-16 17:11:03 +08:00 via iPhone
通用正则搞个 cdn 更剩事吧
|
37
xiangyuecn OP |
38
lincanbin 2019-01-16 17:20:57 +08:00
域名还支持中文域名。
http://中文.tw |
39
xiangyuecn OP @lincanbin 嗯,如果要直接支持中文域名,正则会难写好多,不过也许绕一下会简单好多,如果用户的域名带 Unicode 字符,可以填写 Punycode 表示的域名。微博开放平台别说小众顶级域名不支持了,中文域名就更不支持,哈哈,上午我试了下,挺好玩的
|
40
allenhu 2019-01-16 18:17:37 +08:00
没毛病,够用就好,那些奇奇怪怪的域名,可以忽略
|
41
pkoukk 2019-01-16 18:19:42 +08:00
说不定程序员当初写的挺宽泛的
然后测试表示:abc.bcd 不是一个有效域名,你程序错了 |
42
firebroo 2019-01-16 18:30:14 +08:00 via Android
你这两个随手真的会产生很多安全问题
|
43
cdwyd 2019-01-16 18:33:00 +08:00 via Android
v2 也不能识别我的小众域名,狗头
meizi.lol |
44
atonku 2019-01-16 18:50:55 +08:00
你牛逼行了吧
|
45
xiangyuecn OP @firebroo 有没有比较常见的场景例子?冗长的表达式没有问题,而我这个随手写的会有问题。我想了一下,没有想到哪里会产生比较大的差异,觉得短的有问题的时候,长的可能也会有问题。
|
46
hiboshi 2019-01-16 19:01:14 +08:00
你为什么选那 千分之一。
|
47
secondwtq 2019-01-16 19:05:05 +08:00
Firefox 的地址栏现在可以直接搜索,但是只要是 xxx.x 格式的串,都会直接被当成域名尝试解析,然后“找不到服务器”
导致我想搜一个类似 libpthread.a 之类的单文件名的时候很蛋疼 |
48
autoxbc 2019-01-16 19:42:02 +08:00 3
你说到某些人的痛处了,他们自然要喷你
tldjs.parse('xxx.life') >>> domain "xxx.life" hostname "xxx.life" isIp false isValid true publicSuffix "life" subdomain "" tldExists true https://github.com/oncletom/tld.js/ |
49
hellowes 2019-01-16 19:54:47 +08:00
com 域名可以,其他的就不行,我觉得这就很歧视了,纯粹是程序员水平问题,产品怎么干涉的了域名这种东西呢?
|
50
workwonder 2019-01-16 20:33:00 +08:00 via Android
支持楼主
|
51
jimrok 2019-01-16 20:40:20 +08:00
找到他们的 QA,最好的办法就是这个了。
|
52
azh7138m 2019-01-16 20:47:15 +08:00 via Android
推荐按照 rfc1738 和 rfc3986 来做。
安利一下我的 demo,https://github.com/muzea/parser/blob/master/sample/rfc1738.ts 多好 :D |
53
firebroo 2019-01-16 21:09:20 +08:00 via Android
@xiangyuecn 文件上传之类的,最好的方式就是白名单文件后缀,正则和黑名单被绕过可能性很大。实际安全漏洞还需要结合实际情景,千奇白怪的正则导致被绕过的例子网上很多,所有我都是建议用万金油白名单
|
54
xiangyuecn OP @firebroo 你提到的这点和这个帖子说的内容偏离的蛮大,感觉有点跑题了喔 (无奈脸
|
55
ioven 2019-01-16 22:07:58 +08:00
|
56
firebroo 2019-01-16 23:01:51 +08:00 via Android
@xiangyuecn 非要让我意淫出个漏洞吗。。比如域名匹配那个,我服务端截取最后一个.字符到结尾的子字符串填充到一个 1024 字节长度的缓冲期里面做处理,你写的正则没有限制后缀长度就会缓冲区溢出,白名单方式后缀长度可估量,肯定远小于 1024 字节,所以安全。当然这是我意淫的漏洞,线上环境千奇百怪也不是说不可能出现这种。
|
57
applehater 2019-01-16 23:29:26 +08:00
公司线上在运行的就有这样的问题
|
58
xiangyuecn OP @firebroo #56 哈哈,这个算。缓冲区这种从来没接触过这么底层的东西,我换成了一维数组来看,不检查边界乱塞数据会导致比空指针还恶心的异常。
没想到域名检测在什么样常见的场景会出安全问题,我举个稍微偏一点的例子吧,搭边一点点: 场景:用户提交任意 https? url,服务器端会对这个 url 进行请求,比如远程图片抓取保存到服务器本地。 问题:如果不检测 url 中的主机名,可能导致内网地址被恶意调用。 解决办法:提取 url 中的主机名,如果是 ip 结构,判断是不是公网 IP。如果是域名结构,判断是否是 xx.xx 结构(排除 localhost ) 当然这仅仅是发起请求前的一项安全检测。 |
59
Ansonyi 2019-01-17 02:24:24 +08:00 via iPhone
百度统计,好多后缀域名不认。
|
60
KasuganoSoras 2019-01-17 02:30:12 +08:00
这么麻烦,搞个 whois 查询接口不就好了,查一下域名的 whois 信息,就可以判断一个域名是否正确了啊
怕接口滥用可以限制一下接口的请求频率 + 登录验证 |
61
lincanbin 2019-01-17 02:37:43 +08:00 via Android 7
事实上我也这么枚举号段。
因为以前手机号没对号段做限制。 测试给我提了个 bug,我说这不是 bug,是个为未来考虑的 feature。 测试不听我说,我就把手机号段做了枚举检验,并且在 commit 里写下了测试的名字,注明是他要求的。 后来新增了 166、170 号段啥的,导致一些用户无法注册。 我拉出 commit log,就让测试背锅了。 |
62
KasuganoSoras 2019-01-17 02:47:13 +08:00
@firebroo 过长的字符串让缓冲区溢出?不存在的
if(mb_strlen($_POST['domain']) > 80) echo "invalid domain"; 还没见过长度超过 80 的域名 另外,可以不必使用 whois,直接要求用户添加指定的 dns 解析,然后 dns_get_record 就行啦 还可以更简单,直接指定要求用户将指定域名前缀解析 A 记录到指定 IP,比如 127.0.0.1,然后用 gethostbyname 获取域名的 A 记录,如果解析成功就说明是有效域名,否则就是无效的,这种方法比查询 whois 更快,原理也和 CA 签发 SSL 证书验证一样。 我的 QQ 机器人的 ping 功能就是用 dns 判断域名是否有效的,公开丢到一百多个群里随便别人调戏玩耍,至今也没有被玩坏。 PHP 大法好 |
63
billwsy 2019-01-17 06:23:30 +08:00
"abc.local"这样的域名会不会带来安全隐患,如果服务器正好安装了 mDNS 的话
|
64
flowfire 2019-01-17 06:27:30 +08:00 via Android 1
前段的检验只是方便用户使用,第一时间反馈给用户,后端的校验才是安全校验,很明显,前段应该留一个宽松的标准,准确的校验应该留给后端
|
65
LeoSocks 2019-01-17 07:10:51 +08:00 via iPhone
@xiangyuecn 保住大鱼,放过小鱼。意思是,你这样的用户,他不要也罢
|
66
yamedie 2019-01-17 07:20:45 +08:00 via Android
您写的正则我举 2 个反例
域名:abc.abcdefghijklmnopqrstuvwxyz (后缀不限长度) 手机号:11012345678 (用座机拨个试试) |
67
isCyan 2019-01-17 07:43:20 +08:00 via Android
前端简单校验
后端基于已有数据校验 手机号可以用 libphonenumber 域名可以用 public-suffix |
68
workwonder 2019-01-17 07:53:47 +08:00 via Android
赞同楼主的人没几个,我是其中一个。
画蛇添足,形容很到位。 坚持自己的观点,别评论被扭歪了。 |
69
master13 2019-01-17 08:03:36 +08:00
挖坟一时爽,全家火葬场
|
70
yksoft1ex 2019-01-17 08:09:59 +08:00
我到只是觉得白名单不应该在前端 js 里面验证。
|
71
mytsing520 2019-01-17 08:31:46 +08:00
程序猿表示:产品的锅我不背
|
72
firebroo 2019-01-17 08:45:57 +08:00 via Android 1
|
73
MrJing1992 2019-01-17 09:01:58 +08:00
我们之前手机号验证也是写得无比复杂,后来,工信部加了新号段;又后来,公司业务切入到了海外。于是也改为使用 /^1\d{10}$/了。当然,我们有短信码校验。
|
74
xianxiaobo 2019-01-17 09:11:00 +08:00
某天出了 10 位或者 12 位的手机号,你的正则一样不行,然后就会有人发帖,为什么大家不会把手机号验证写为 20 位以内的数字就行呢?扩展性多好,新出的长度还不用更新
|
75
SakuraKuma 2019-01-17 09:23:31 +08:00
这样写没毛病啊,
猫并是,他不更新啊。 而且就算你绕过了前端。 后端估计也是一样的白名单。 |
76
TingHaiJamiE 2019-01-17 09:26:28 +08:00
别的不说,我个人十分赞同楼主手机号验证的方式。1 后面 10 个数字足够。
|
77
xiangyuecn OP @lincanbin #61 第一个测试的锅 真实案例 (〃'▽'〃) 还好准备充足呀
|
78
eliteYang 2019-01-17 09:32:22 +08:00
因为有一些 sb 产品经理会随时修改需求
|
79
veike 2019-01-17 09:36:05 +08:00
你这个域名判断,后缀不应该加上字数限制吗,这样更严谨啊。
一个域名最长的长度为:255 个字节(包括标点符号)。域名名称最长 63 字节,比如 example.com example 部分最长 63 字节。后缀最多也不会超过 20 个字节。 所以,按照我这个才更严谨。 |
80
murmur 2019-01-17 09:39:58 +08:00
楼上的不要喷了
如果这是其他的公司我会喷楼主 如果是微博我更相信微博的产品经理 sb |
81
xiangyuecn OP @xianxiaobo #74 根据我个人对 三大运营商 手机号的理解,几十年来首位 1 都是多余的。。除了增加号段、还没出现过增加位数的先例。如果 1 可以改成 2-9 还有很大的发展空间,就是不知道有什么难点,宁可复用垃圾号码也不增加容量。
|
82
xiangyuecn OP @firebroo #72 原来是 ssrf,怪不得眼熟,想起一个严峻的事情,就是人家提交过来的合法域名格式的 url 也不一定安全,谁知道他会不会把 DNS 记录写成内网地址,看样子水深了不少。。
不知道简书、掘金发文那里怎么把图片捞过来的? |
83
xiangyuecn OP @veike #79 本来有两个选择:宽松、严格,现在又加一个:宽松、中等、严格。选择恐惧症,我还是喜欢简单粗暴的,要么就是 True,要么就是 False
|
84
firebroo 2019-01-17 10:07:59 +08:00
@xiangyuecn 限制提交数据为.jpg ,.png 等白名单图片后缀格式的 url,也可以对返回数据做检测,根据前面几个字节判断是不是图片格式,这样即使可以 ssrf,危害也大大减小。单独划一个公网段和内网隔离做爬虫,黑名单内网 ip 段。
|
85
MrUser 2019-01-17 10:18:23 +08:00
这种验证确实很烦人,
我遇到的类似的情况:有些注册帐号的地方只认常见的邮箱后缀,你填个 [email protected] 非说邮箱不正确,只让填 @gmail.com \ @163.com \ @qq.com 类的 |
86
no1xsyzy 2019-01-17 10:52:15 +08:00
我 126 的邮箱很多国外网站不能注册,说邮箱域名不符合规范……
国内反而是更清楚地知道存在 126 和 163 这种纯数字一级域,导致兼容性更高…… |
87
Klingon 2019-01-17 12:47:22 +08:00
从安全角度和业务需求上,更倾向于白名单的写法
|