2012年10月26日星期五

GFW临时升级设置,演习?


2012年10月26日上午11时左右,Google北京服务器的IP段再次出现异常,但这次的异常有着与以往不一样的情况。

简单地说,GFW升级设置了。这次应该是覆盖了203.208.45/46/47.*中的所有IP(其中45段全部被设IP黑洞),并且针对443端口采用了特殊的屏蔽手段。体现为IP或许可以ping通,但telnet 443端口大部分情况下超时(不是连接重置)。而80端口则畅通无阻,但可想而知所有的非加密HTTP数据包肯定都会接受GFW的关键词过滤等内容审查,随之而来的就是小黑屋。

少数时候有HTTPS包可以漏过(低于5%),多次尝试telnet发现偶尔可以建立连接。在开启了SPDY的Chrome上体现为页面很难刷开,但一旦刷开则该站点就此畅通。应该是因为SPDY的长连接会话机制保障了后续不会有握手包,从而避免了被干扰所致。这从某个侧面也反映了这次的封锁技术是以监视并干扰SYN/ACK包为主,并不针对所有类型的数据包(估计忙不过来)。

猜测可能是之前Tor项目组检测到的GFW新研制的HTTPS探测技术(或者是某种类似的技术)投入了使用。(估计)其原理在于发现HTTPS(443端口)的SYN包之后,GFW自身也发HTTPS连接请求去探测该端口可能会返回什么内容。一旦审查到内容有害,就干扰TCP握手过程,丢弃匹配地址组的SYN/ACK包。并且从测试的表现看来似乎有小黑屋效应,也就是说之后一段时间都会无法连通443端口,但休息一阵子后第一次连接的成功率很高。

目前看来这个手段的效果还不错,虽然还有漏网之鱼,但至少可以消磨掉绝大部分人的耐性,并让决意翻墙者苦不堪言。但HTTPS探测需要与服务器建立真实有效的SSL连接,还要处理加解密相关事宜。对于以全体压制为原则的GFW设备而言,计算资源(主要是CPU)的耗用可能会相当大。这一方面可以说明为什么会有漏网之鱼,另一方面也解释了为什么会有小黑屋机制作辅助。可以预言这种手段短期内还不会投入日常使用,更多可能出现在特殊时期临时高压维稳。

总之,这几个IP段在18大期间很可能会被咬住不放,不过分赃大会之后应该会松口。但一旦该手段被启用,目前通过hosts+HTTPS翻墙的人,应对措施应该只有换别的IP,要不就得耐心点,多刷刷页面了。
真心祈祷大家不要再公布可用的IP地址了,公布一些就少一些啊!

下午开会去了,回来(16时)发现这些IP段已恢复到之前的状况。目前估计有以下的可能:
1.HTTPS探测功能需要GFW去干一些很费CPU的事情,相关人员发现撑不住,最后还是放弃了。
2.为了关键那几天能顶上用场,在搞演习,测试效果。

2012年10月25日星期四

头一次埋彩蛋哩


在改某个Bug的时候,需要通过已知的HWND来判断该子窗口是不是一个DateTimePicker控件。办法很简单,只要给这个子窗口发一个DateTimePicker控件的特定消息,如果返回值正确,那么就认为猜对了。

但是在选择这个【特定消息】的时候,我犯了难。DateTimePicker支持的消息本来就不多。为了避免对正在编辑的数据带来扰动,只能选择GETXXX之类的消息。并且这个消息还得有定义良好的返回值,用于鉴别消息是不是发对了人。

一开始我选的是DTM_GETSYSTEMTIME,这货能返回当前编辑的时间。但我发现控件一旦响应了这个消息,键盘输入就像按过回车一样被COMMIT过了,导致年份之类的多位数字根本输不完整。回头看了看DTM_GETMCCOLOR,又无法确定返回值是不是能够鉴别出来。有个DTM_GETDATETIMEPICKERINFO倒是看上去挺好,可惜只支持VISTA往上。最后我选择了DTM_GETRANGE。

DTM_GETRANGE可以返回设计者在IDE上给DateTimePicker控件定下的最大/最小值。所以我只要把最小值设一个特定的日子,然后看看返回值正不正确就OK。实验下来对输入也没有扰动,是个很好的选择。那么,日子选哪一天呢?

……我敲入了 1989-06-04

2012年10月22日星期一

简介GFW的三板斧

上次写了一篇《翻墙菜鸟指南》,讲的主要是一些道理和原则之类的东西。这次来一篇偏技术一点的东西,讲讲GFW用来对付屁民的手段,我称之为GFW的【三板斧】。


零、前言
首先要声明的一点是:GFW并不是一个单独的设备,而是一个系统。不要把它想象成接入网络的一台类似交换机的东西那么简单。它可能是由数个设备,在数个层面间协同工作的结果。可以这样理解:GFW就是目前在技术上针对所谓【有害信息】的屏蔽过滤技术的一个集合体。


壹、DNS污染
由于大家现在上网基本都通过域名来找到网站,比如www.youtube.com。所以GFW的第一招就是对国内互联网上接入的终端进行DNS污染,让终端拿到的IP地址是错误的,于是就当然无法访问被墙的网站了。

GFW要污染DNS通常有两个办法:

  1. 如果DNS服务器能够被控制(比如电信、移动等国内ISP提供的DNS),那么GFW会让该服务器直接返回一个错误的结果。
  2. 如果DNS服务器不受控制(比如Google的8.8.8.8),那么GFW会伪造一个DNS应答包,里面给出的IP地址是错误的。由于这个应答包往往比正确的DNS应答包要来得快(因为不用去查真正的IP地址嘛),于是PC就上当了。
这一招简单有效,就封锁某个网站而言,对付麻瓜足矣。但这招有时候也会有例外。比如GFW发伪造包的时候,终端可能会先收到真正的DNS应答包,那它就白忙活了。稍懂技术的用户也可以通过修改本地hosts文件来强迫终端按修正过的列表进行DNS域名解析,从而使DNS污染完全失效。但没关系,GFW还有下一招……


贰、TCP连接重置
TCP协议中规定了一种包,叫做连接重置包。这个功能被GFW用来拆散所谓“有害”的TCP连接。GFW会先对网络上捕获到的数据包进行审查,一旦发现内容“有害”,就向双方分别发送伪造过发送方的连接重置包。形象地说,就是GFW替你向服务器说了“BYE-BYE”,同时也替服务器向你道了别。由于你的终端和远处的服务器都是好孩子,严格遵守TCP协议,因此也就各自断了连接。

招数其实挺简单,关键在于其触发机制。根据被观察到的行为,GFW通常有以下几个工作模式:

1.关键词过滤
这对于HTTP协议尤其有效。因为HTTP包是明文的,很容易解析。关键词可能是某个字眼,也可能是某个网站的域名之类。通过在HTTP包里面翻关键词,GFW甚至可以做到对某个网站的某些链接(博文、新闻)进行屏蔽,而不会影响该站的其它内容。
对于Google、Yahoo等不受控制的搜索引擎,GFW大多采用这一招。因为搜索的结果是事先无法预料的,所以“事后追杀”非常必要。
另外,这一招可以很好地应对未知的“威胁”——谁知道哪个国外的“乖乖”网站哪一天发了神经要发一篇“有害”文章呢?一些比较知名的外媒,比如纽约时报中文网之类,就偶尔会有这种待遇。
HTTPS/SPDY协议因为其数据包的内容是加过密的,所以能够有效地避开关键词过滤。但GFW项目组似乎也一直在发展相应的技术来克服这一局限性。

2.IP/端口屏蔽
对于有一些“有害”网站,IP地址已知(并且不多)。GFW就会对这些IP地址进行“蹲守”,重点屏蔽。此时不管你连接过去是干什么,连到什么端口,一律强制“分手”。有的时候GFW也会只针对某些端口开启这个功能,这个就全看方校长怎么想了。

3.关小黑屋
GFW貌似还有一种机制,即如果探测到的某一次“有害”连接(信息/数据包),则针对它的源地址/端口和目的地址/端口,如果再有新的访问请求,先关一段时间的禁闭再说。根据Google上次放出来的视频,这个时间大约有90秒左右。在这段时间内,哪怕是正常的、“无害”的访问请求,GFW也一律给双方强制“分手”。于是,就经常会出现这种情况:NAT下面有人触发了“老鼠夹子”,于是整个公司的人一段时间内都用不了Google,最终导致大量麻瓜弃Google转Baidu。

实际运用中,以上工作模式可能会同时混杂使用。用telnet可以很容易地验证服务器是否被蹲守或关小黑屋了。

其实,个人觉得这一招比较类似于老鼠夹子,不碰它没事,一旦触发,则很难避免被“制裁”。终端还可以通过某种程度的措施来拒绝连接重置包,但服务器因为还要面向非GFW控制区域提供服务,一般不会这样做,所以这招的有效性一直都还不错。对于GFW而言,由于这种“事后追杀”的方式,开销非常小,只是发两个包而已。并且,由于关键词搜索机制带来的“智能化”的感觉,被用得最多最滥的就是它。不得不说,它跟DNS污染联合起来用,效果确实相当好,麻瓜伏下一大片。

只是,被这种招数掐断的连接,断得非常快,作为用户能够很明显地察觉出来与“超时”的不一样,不太容易忽悠成“网络不通”。另外,TCP连接中断了,但服务器却还能ping通(因为ping用的是ICMP协议)。麻瓜们基本上ping还是知道的,这样就更不容易忽悠了。
并且,这个“分手”手段并不是十分的可靠。它得建立在通讯双方都严格遵守TCP协议的基础之上。何况就算连接被拆散了,但双方可能在断掉之前已经互通过了一部分“有害”信息。对于某些人而言,仅仅这样是不够的,于是有了第三招……


叁、IP黑洞
最后这一招就是GFW最后的杀手锏,那就是让网络彻底不通。在通常情况下是针对特定的目的IP地址进行断网,也就是说发往该IP的所有数据包都丢弃不理,好像进入到了一个黑洞一般。最终的结果体现出来是超时,跟对方服务器出问题的感觉很像,因此效果相当不错。

这也就是所谓的“黑名单”模式。据说GFW也可以设置为“白名单”模式,这时候就只有发往名单上的IP地址的数据包才能送达,其余的都被丢弃。这是终极大杀着,我想可能会留到最后用吧。白名单一旦使出来,所有翻墙手段基本上都会失效,但网络的正常使用也大受影响,基本等同于小中华局域网了。

不过,要设置IP黑洞,基本等同于在路由器上改路由表。即使是“黑名单”模式,折腾一次好像动静也比较大。所以一般都是针对重点对象使用。Twitter和Facebook目前就受到这种级别的招待。用tracert/traceroute往往可以看到路由在中间断掉,而不是目标主机无响应。对付这种招数,除了彻底绕开GFW,没有什么别的更好的办法了。


肆、后记
本文的内容系独立撰写,重在普及相关知识。在网上可以搜到一个名为《GFW的工作原理及突破技术》的PDF文档。该文内容更严谨一些,并且图文并茂,有不错的参考价值。

2012年10月19日星期五

一个关于浮点运算的坑


这两天遇到一个很奇怪的问题,后来通过排除法终于把故障点缩小到一句代码,但还是很奇怪:

某个同事以前用VC写了一个DLL用于提供某类通用计算,相当于一个计算模块,由我这边写BCB程序来调用。不过在这次的问题中发现,一旦线程调用过pow()这个C库函数来计算过一个非整数指数的幂,那么这个计算模块接下来同样的参数再次用就会得出不一样的结果。调用过pow()之前是一种结果,调用之后是另一种结果,现象相当稳定。

诡异就诡异在pow()的返回值既没有错,也没有被采用过。比如仅仅一句:
pow(2.0, 3.1);
函数返回值根本没有用来干过任何事情,相当于直接丢掉了。那么按道理来说这行代码应该不会对之前或之后的代码造成任何影响。但它确确实实影响了。
然而指数如果是整数,就不会,比如:
pow(2.0, 3.0);

那个写DLL的同事对此也是一头雾水。怀疑点一度被放在VC/BCB身上,因为它们的CRT不一样。但因为正好有一个测试工具,稍加改造便可以针对计算过程输出详细的结果报表,因此用来比较了一下,发现了问题:出问题的地方,有两个本来应该用来比较的double型输入数据正好是相等的。在pow()调用之前,它们的确被判断为相等。但调用pow()之后,计算结果显示它们被判断为不相等了。

这种事情对于常写浮点运算相关代码的程序员而言是很容易引起警惕的。浮点数不能直接用==之类来比较,必须去判断两数相减的绝对值是否小于某个精度。所以将这个测试结果提交给写DLL的同事之后,很快就定位并解决了问题。
但这里我更关注的是以下几个问题:

  1. pow(2.0, 3.0)和pow(2.0, 3.1)的不同,使我相信CRT肯定对前者作了优化。这种事情,想得通,但后果可能是个坑。
  2. 很明显,CRT在pow()被调用之后,处理浮点数时的行为模式改变了。通过观察_statusfp()的返回值,我发现调用前为0,调用后变成了0x20。但这个0x20是一个Undocumented的东西,哪怕是最新的MSDN上也找不到。并且我通过_fpreset()将状态字变回了0,但计算模块仍然会出错,说明应该还有别的东西也被改了。这个坑是不是VC和BCB联合挖的,目前还不知道。
  3. 如果不知道有这个坑,就可能导致一些大麻烦。在特定的代码逻辑中,这个问题很难通过黑盒测试发现。它可能在很长一段时间内都能工作得很好,直到某一次有个用户算了一个指数带小数点的幂,然后……一切就不一样了。这简直就是逻辑炸弹嘛!让我想起了《深渊上的火》里面可怜的蓝荚和绿茎。
  4. MSDN真心不是完全靠得住的。

在本文最后,还要对提供过重要帮助的Libin Yan表示感谢!并感谢所有关注和评论过这个PO的G+网友!

2012年10月12日星期五

黑客故事2:关于弱口令设备的闲话


家庭路由器都有HTTP的管理界面的。不过我估计给这些人家布网络的人大概都很不耐烦,因为那些用着admin/admin这样密码的路由器,80或者8080端口就这样开在WAN口上,在自己附近的网段上完全是一扫一大片。另外,早期家庭路由器大概厂商这边投入也不够,大部分都偷懒把PPPoE密码写在了网页上。据我当时看下来,什么网件、D-Link、腾达、贝尔,统统中招。唯一做了防范措施的,是TP-Link,这导致我之后没有买过别的任何牌子的小路由。

话说这PPPoE密码我轻易拿到了一大批。要是到了坏人手里头,互联星空就有得赚了。不过我系好人呀,好人我只是去电信营业厅看了看大家的住址,从来没用来干过坏事。不过就算不知道PPPoE的密码,也能干坏事。断网什么的都是小事。当年还没有360,一台没打过补丁的Ghost机器被DMZ暴露在外网是什么情况?简直可以说比裸体美女还惨。

这些年,中国电信大力推广它的定制路由器。无论是管理密码还是无线安全都得到了加强,从这方面我觉得还是应该予以正面的肯定。不过我还是嫌它太烦,让它下岗了。用刀能自杀,也能防身。既然我不是小白,就不需要给我学生剪刀玩吧。

专业级的设备,比如机架式的路由器、防火墙,铁皮壳子,比家用路由器那种塑料玩意儿容易让人觉得可靠。呵呵,看起来可靠,于是某些人就不设密码,23端口开着就往外网上放。哎呀,这种设备要是被扫到那能怪谁?其实我很多次都怀疑这些统统都是蜜罐。23端口开着,弱口令,轻易就能拿到最高权限。哦,被我第一个找到?这世上有这么好的事情?

当然,从这些设备上的情况看来,它们只是被当作傻瓜型设备在使用。SSH没开就不用说了,连私钥都没有,说明SSH从来就没开起来用过。日志也是只开了默认的syslogd。有个单位的硬件千兆防火墙连一条IP过滤规则都没有配,完全当路由器在用,下面接的PC却只有五台。但即使这样,我也只是逛了逛,浏览并学习了一下这些网络设备的命令和界面,除了清掉日志停掉syslogd,不敢做任何改动。没必要自己给自己找麻烦,对吧?

我想说的是,这些设备,完全可能成为僵尸网络的一部分。不要以为只有电脑才能被僵尸网络控制。防火墙不好好设置,比PC还残,关键是你根本想不到它会成为威胁的一部分。为了维护自己网络的安全,你可能还离不开它,但真正的内鬼其实就是它。甚至也许都不是防火墙、路由器。交换机?也有可能。但问一句,你们单位有VoIP网关吗?

黑客故事1:图形验证码上的SQL注入点


有一次,遇到有人在街上发宣传材料。本以为是什么餐馆开张之类,拿回家一看才发现是个类似网络传销的东西。我当然无意参加,但既然是【网络】传销,就必定得有网站和服务器,于是打开电脑看了看。

网站挺简单,就是一些宣传页。但我觉得肯定得有后台系统。果然没多久就被我找到了,PHP+MySQL做的。登录输用户名+密码,另外还有图形验证码,没有SQL注入漏洞。看来开发者对登录这块还是相当注意的。又看了几个页面,还是没有注入点。我想撤,但又有点儿不甘心。向这种非法组织的服务器下手,基本上是没有法律风险的。他们显然不敢报警。所以我又回到登录界面上。在看HTML代码的时候,图形验证码那部分吸引了我。

我发现他们的图形验证码没有用Session来控制,用的是URL传参,GET方式。也就是说在URL中给出了一个数字,然后服务器上返回一个生成的验证码图片。我在表单中也找到了那个数字,试着刷新了一下页面,数字加了1。用旧的URL还是能拿回原来那幅图片,但一旦该图片中的验证码被【使用】过,就不能再拿到了。

这意味着什么?这意味着验证码与这个数字之间有某种联系,某种对应关系。这个联系可能是Hash出来的,但根据现象,更可能是存下来的。我决定赌一把。果然,验证码图片的URL存在SQL注入点。每次读出来的是存起来的四个字母,然后交给PHP生成图片。

也许开发者认为,就算被注入,入侵者面对着四个字母的图片也干不了什么破坏。但他可能忘了有MID这个函数。我利用这个漏洞确认了admin这个用户名确实存在,也拿到了Hash过的密码。不过接下来我收手了。我想再潜伏一段时间再动手。结果一个月之后,我再去看的时候,这个服务器已经不在了,网站也不在了。大概被警方打掉了吧,可惜!

在这个故事里面,我想强调的是,SQL注入每一个地方都要防!哪怕再小的漏洞,也能造成危害,一个都不能疏忽。