危险漫步博客
新鲜的“黑客思维”就是从全新的角度看待黑客技术,从更高的层面去思考;专注于黑客精神及技术交流分享的独立博客。
文章2306 浏览20613502

个人隐私的危机——身份证安全分析与批量猜解

现在很多游戏注册帐号的时候,其要求必须输入身份证号,而且带有身份证验证机制,并且一个身份证只能注册一个帐号。对于大多数玩家来说,仅仅注册一个号是远远不够用的。这让我想到要猜解身份证号,比如要个1988年8月8日的身份证号,就好了。下面来具体介绍一下过程。

一、身份证号组成

要想猜解身份证号,就必须先了解身份证号的组成,如果你已经了解的可以跳过。如果你并不是很清楚,我建议你还是看一下,它是后面猜解的基本原则。

比如号码为:110102197810272321的一张身份证。

身份证号的组成关于需要注意的部分:

1、将出生日期的年份与月日是分开,是为了猜解方便。

2、“编号”部分的最后一位,其单数为男性,偶数为女性。

3、“验证码”部分,由于网络上有人提出一种算法可以将其直接算出,但本文将不采用此种方法。因为当你需要的时候,未必手头就有这个程序,到不如通过手动猜解的方式来实现。

二、手动网络猜解

现在,我们要用手动猜解一个身份证号,其号码为18位。位数很多,而我们手动重复的次数有限,所以必须用最少的次数猜出一个正确的号码来。那么那一部分可能的重复次数最少呢?我想大家首先想到的部分是我刚才表明部分,即110102197810**2321中的星号部分(以百度的样证的号码为例),这部分只需要少于31次就有机会猜出一个号码来。那我们现在来实验一下,看看是否能得到一个真实的身份证号码,先搜索一个验证身份证的网站。

本人现在使用的是[IP探索者],现在,将号码110102197810**2321中的星号部分填入数字01,也就是从10月1号开始猜解:其号码为110102197810012321,结果就出来了。

在尝试到10月4号的时候就可以得出正确的结果。

好的,应当说很幸运的,这么快就得到了一个!但也产生了一个问题,我们刚才猜解一个身份证号时,需要一个18位身份证号中的16位(例如110102197810**2321)。那有什么办法能像刚才那样,能给出我们一些接近16位的身份证号呢?当然是搜索引擎了。用百度搜一下,经过我的尝试,用11010219来搜索比较快一些,也就是用“所在地区的6位号码+19”来进行搜索。

虽然只给出了18位身份证中的12位,这还是给猜解以很大的帮助,但因为缺少位很高使猜解变得重复操作次数很高。而现在大多数的身份证号查询网站并没有对查询次数进行限制,甚至辅助验证码都没有,这使程序化操作可行而且容易。

先不急着说程序化的方法,而是做另外的一种尝试,来看看是否有方法来提高一下手动猜解的速度呢?

我们再以“样证110102197810272321”的这个号码为例,来做后两位的猜解。首先,用尝试猜解11010219781027232*中的最后一位,看看是否能够得到一个正确的号码。即从0到9进行10次。大家可以自己尝试一下,其结果是10次均为失败。那难道后4位的猜解,真的是成功率很低吗?

于是我对倒数第二位(1101021978102723*1)减1之后(11010219781027231*)再进行猜解,得到了正确的结果。

然后又猜解了11010219781027233*、11010219781027234*都能得到正确的结果。看来这样猜解的成功率也是很高,而且大家会发现要这样猜下去,我们会得到很多很多的真确的身份证号。

那可不可以自己安照自己的需求定制一个号码呢?比如北京市西城区(1101021978)1978年1月1日出生的一名男性的号码,以0010开始,倒数第二位增2,进行猜解。

好的,那得到一名女性的北京市西城区(1101021978)1978年1月1日出生的号码,可以以0000开始,倒数第二位增2,进行猜解。 

太好了,可以说只要按照身份证号码规则随意写个号码,在几十次以内几乎均可得到一个真实的身份证号。于是,我做了多次测试,大概身份证后面4位在1000到5000之间的其成功率可能会高一些。

还有一个问题,如何得到区县的号码(身份证号的前六位)呢?很多的身份证号查询网站中都附带了这个功能。除此之外,本人还将其整理了下来,你可以在源代码中找到这个程序(是JS语言写的,我镶人到HTML里了)。

那好,我们加快一下获取速度,来了解一下编程的方法吧!   

三、自制软件使用

在了解编程具体过程之前,先了解一下,软件的使用方法。由于其猜解部分的不同而分为两种:

1、猜解日期

这里需要说明的是:“验证字符串”是当所猜解的身份证号为真时,网站上该页给出的提示信息,如果用过代理程序的话,可以很容易理解。 

2、猜解最后两位

如果你要猜解其它部位,可以根据上述方法两种方法组合使用,但中间的那个框必须为4位,这是编程时的设定。

四、程序的编程源码

本人的编程环境是在Windows 7、Delphi for Microsofi Win32(Borland Developer Studio 2007)、ADSL 2Mb下进行编程测试通过的。

1、空间说明

3、网页对接解析

手动操作时,是在网页中提交号码来进行验证。程序化的原理是一样的,所以需要先分析一下网页代码。我就以[IP探索者]的网页为例:

[IP探索者]是用PHP语言编写的动态网页代码,我们得不到其源码,但这对于本次编程操作没有任何干扰。无论是那种语言编写的,只需要将身份证号提交给该页,然后让它得出结果是真假就可以了。好了,思路以确定。

先来看一下该页中的表单部分代码:

在“form”中告诉我们,其身份证号的运算页为action=“id_card.php”,数据提交形式为method=“post”。

在“input”中告诉我们,身份证号的输入框的名字是name=“id_card”。 

4、主要代码分析

由于要多次访问同一个网站,而且每一次操作从提交数据到返回结果需要一些时间,用简单的循环会造成程序的长时间锁死。所以,我采用了TTimer控件来代替多线程,以减少代码的复杂程度,而且还能产生一个访问的时间间隔,以减少出错几率。

其代码倒是很简单,在Delphi2007中只需要仅仅百行的代码就解决了全部的问题,这里就不写出来了,需要的同学可以去网上找些东西看下。

五、猜解的意义

无论是手动猜解还是程序猜解,甚至是自己的随机手写,都可以使我们得到一些真实可用的身份证号码,那么它最终可以达到一个什么样的程度呢?比如,我们真的可以完整的猜解到一个个人的身份证的全部信息吗?

在本文的第二节手动猜解部分,对身份证的后4位进行了尝试,可以得出这样的结果:从倒数第二位到倒数第四位,绝大多数的数字组合都能找到正确的结果,也就是说我们无法准确的知道谁是谁。

那网上大多数是以1101021978****2321和11010219****272321的形式给出的,这种形式可以得到准确的结果吗?于是,我做了对110102197810**2321这个号码进行了测试,找到了3个号码。也就是说以1101021978****2321的形式给出的号码其结果应不少于36个。虽然这个范围很小,但我们乃然不能得到一个确定的结果。

六、猜解的防御

当你看到,能如此容易的得到一个真实可用的身份证号码时,你就一定会想到,我如何来辨别其身份证的真伪呢?

首先,我们先分析一下,我们能从身份证号中所获得的信息(以样证为例): 

那我们要防范假身份证,就要知道那些无法猜解的部分,有没有呢?

有,是姓名和相片部分。在身份网或发短信,都可以验证姓名与身份证号是否匹配同时还能得到一张此人的照片。在这些网站上,我们可以验证身份证的真伪。因为猜解得到的号码,无法知道其身份证所对应的姓名,给精确猜解带来困难,而且每次5元的手续费,永远的把你的想法拒之门外。

七、总结

危险漫步博客在此提示“身份证号”无论是真的还是假的,对于我们大多数人来说,根本没有什么意义。但能辨认的“身份证”的真假,这对于我们外出做事、防范受骗等有一定的好处。另一方面,我个人认为现在用的身份证号来区分其上网年龄的做法,看来没有多大用处。就算没有身份证号的猜解的方法,你可以去看看百度的贴吧,那里竟然有将身份证号与姓名同时公开的地方。唉……恐怖呀!

还有,现在在一些编程的书或网上,很多已经公布了验证码的算法,但我个人觉得,这只能作为网站开发人员的一种算法,而不能作为身份证号码的破解方法。最后,我强调一下,身份证号安全的隐藏方式。安全系数是1101021978****2321略小于11010219****272321,以110102197810****21形式的安全性要比前两者都好,最安全的是11010219781027****的形式(无论是那种形式,其隐藏位数都应不低于4位)。其次,一定要注意把姓名与身份证号分开。还有,希望能做身份证号查询的网站,能对同一IP地址的访问查询加以限制。