新闻发布
管理系统GoAgent 利用 Google AppEngine (GAE) 来绕过 GFW的封锁,以免费、快速、稳定的特点深受网民的欢迎 但是,GoAgent的安装和配置中存在两点严重安全风险的问题却鲜为人知 这两点安全风险都可能被攻击者利用进行“中间人攻击(man-in-the-middle attack)” 来窃取 GoAgent用户的网络帐号密码等敏感信息,其概括描述如下
GoAgent 在启动时会尝试自动往系统的可信根证书中导入一个名为 “GoAgent CA”的证书 由于这个证书的私钥是公开的,导致任何人都可以利用这个私钥来伪造任意网站的证书进行HTTPS 中间人攻击 即使在不开启 GoAgent时,这种攻击的风险仍然存在 换而言之,一旦这个证书被导入,攻击者可以用此绕过几乎所有网站的 HTTPS 保护 GoAgent 本身对 TLS证书的认证存在问题,而且默认时不对证书进行检查,这导致在使用 GoAgent时存在 HTTPS 中间人攻击的风险
事实上曾经有用户在 GoAgent主页上的问题跟踪列表中指出了这两个安全问题(见以下链接),但既没有修复也没有广泛公开,多数用户,尤其是非中文用户可能并不知情 下面是这两个问题的详细解释
https://code.google.com/p/goagent/issues/detail?id=11091
https://code.google.com/p/goagent/issues/detail?id=8031 GoAgent
导入公开私钥根证书的问题
GoAgent 在启动时会尝试在系统中导入一个根证书来避免访问 HTTPS网站时的证书报警,但在默认情况下所导入证书的私钥是公开的 因为私钥公开,任何人可以作为“GoAgent CA” 来签发任何网站的证书 即使在 GoAgent没有启动甚至卸载的情况下,这个公钥仍会遗留在系统中 在有些系统中,GoAgent所导入的根证书不仅被 GoAgent默认使用的浏览器信任,其他的浏览器也可能会信任这一根证书,从而受到这一问题的影响
GoAgent 所导入的这一公开私钥根证书的指纹是
SHA1 Fingerprint=AB:70:2C:DF:18:EB:E8:B4:38:C5:28:69:CD:4A:5D:EF:48:B4:0E:33 MD5 Fingerprint=56:B1:20:86:1B:0A:B0:61:38:00:1B:C3:67:CF:0C:CC
包含这一 “GoAgent CA” 证书以其私钥(文件中 -----BEGIN RSA PRIVATEKEY----- 位置)的文件 URL 为
https://github.com/goagent/goagent/blob/c4386808ea943e2ebed25f1e5264943354e3f9cb/local/CA.crt
根据版本信息,这一证书和私钥从 2011 年 6月甚至更早的时间以来一直保持不变
https://github.com/goagent/goagent/blob/fa9959e577395e48a477fd5495afbc2363a51baa/local/CA.key
GoAgent 主要包含两个部分 一个在用户计算机上运行的本地代理程序proxy.py,以及一个在 GAE 上运行的远程代理程序gae.py
https://github.com/goagent/goagent/blob/c4386808ea943e2ebed25f1e5264943354e3f9cb/local/proxy.py
https://github.com/goagent/goagent/blob/c4386808ea943e2ebed25f1e5264943354e3f9cb/server/gae/gae.py
安装时,用户需要上传 gae.py 到 GAE 用户浏览器通过设置一个本地代理将 HTTP/HTTPS 请求转发到proxy.py,再由 proxy.py 和 gae.py进行通信
默认情况下,GoAgent 在启动时试图导入上述 GoAgent CA 证书 具体的代码为proxy.py 中的 CertUtil.import_ca
https://github.com/goagent/goagent/blob/c4386808ea943e2ebed25f1e5264943354e3f9cb/local/proxy.py#L337
这个函数会根据用户操作系统通过不同的方式尝试导入证书,在某些情况下会需要管理员(root/administrator)权限 在 Windows 下,这个函数会调用CertAddEncodedCertificateToStore 这一 API 在 OS X下,会尝试执行系统命令
security find-certificate -a -c "GoAgent" | grep "GoAgent" >/dev/null || security add-trusted-cert -d -r trustRoot -k "/Library/Keychains/System.keychain" "pwd/CA.crt"
在 Ubuntu 下,会拷贝证书文件到/usr/local/share/ca-certificates 然后执行update-ca-certificates 在其他 GNU/Linux发行版中,会尝试执行以下命令更改 NSS 数据库
certutil -L -d sql:$HOME/.pki/nssdb | grep "GoAgent" || certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n "GoAgent" -i "pwd/CA.crt"
由于 Firefox 采用了不同的方式存储证书,这一自动安装过程不会导入 GoAgentCA 证书到 Firefox 中 但是 GoAgent 的安装指南和 FAQ中说明了如何手动导入这一证书
https://code.google.com/p/goagent/wiki/InstallGuide
https://code.google.com/p/goagent/wiki/FAQ
这一证书随后被 proxy.py 用来作为 HTTPS中间人来避免浏览器在访问 HTTPS 网站时出现报警 GoAgent的工作原理如下 首先 proxy.py 将浏览器的 HTTP请求进行编码并转发给 gae.py,gae.py完成收到的请求然后将结果进行编码后返回给 proxy.py,后proxy.py 将结果转发给浏览器来完成 “翻墙” 过程 由于 GAE 的限制 (免费 app 无法使用 socket 接口),对于 HTTPS请求,proxy.py无法进行透明转发,只能作为中间人先和浏览器完成连接,然后获得其中的明文请求以后在转发给gae.py 当收到 CONNECT请求(这意味着浏览器正在浏览一个 HTTPS 网站), proxy.py首先利用 GoAgent CA签发一个假的证书来和浏览器完成握手,从用户的角度,所有的 HTTPS网站的证书都是由事先导入的 “GoAgent CA”认证的,所以不会报警 有些浏览器会对少数网站的证书进行特别的检查(CertificatePinning),这种情况下 "GoAgent CA”所签发的证书可能会触发证书不安全的报警 GoAgent 的这种工作方式导致 HTTPS不再是浏览器到网站的端到端安全通信,而变成了 proxy.py 到GAE,以及 GAE 到网站两段独立的 HTTPS 连接,GAE能够看到请求和应答的明文