svn泄露
一个下午,我扫着某个老牌论坛的附件下载记录,发现有个用户反复拉取同一份压缩包。那是个企业内部工具,按常理不该出现在这里。点进去一看,路径里赫然躺着.svn目录。没费什么劲,我就用svn工具把整个仓库历史拖了下来——数据库连接串、服务器部署脚本、还有一段写着“别提交这个”的注释,旁边就是明文密码。
这事不新鲜。SVN(Subversion)作为版本控制老将,至今仍在无数公司内部跑着。它不像Git那样把历史打包成对象存储,而是每个工作副本都保留一个.svn文件夹,记录着所有文件的元数据和基线。问题在于,很多人部署Web应用时,直接把这整个目录扔进了Apache或Nginx的根目录。服务器能访问,就意味着任何能猜对路径的人也能访问。
攻击者不需要什么高深技巧。直接请求/.svn/entries,如果返回200,那就成了。这个文件在旧版SVN里明文列出所有文件名,新版虽然改成哈希格式,但配合/.svn/wc.db(一个SQLite数据库),照样能完整还原源码结构。更绝的是,有些版本还支持svn cat式的远程读取——只要服务器允许,你可以像坐在开发者电脑前一样,逐行翻看每个版本的代码差异。
我见过最离谱的一次,是某政府网站的.svn目录里躺着三年前的数据库备份,里面包含几十万条公民身份证号和手机号。运维大概觉得“反正没人知道这个路径”,连基本的访问权限都没配。你说他们没安全意识?不,他们防火墙、WAF、入侵检测都上了,就是没人想过版本控制目录会被当成静态资源直接暴露。
修复其实很简单。要么在Web服务器配置里加一条拒绝规则,要么干脆把.svn目录从发布包里剔除。但问题在于,很多老项目已经没人维护,甚至当初写代码的人都离职了。新来的接手,看到.svn文件夹只会觉得是系统自动生成的,碰都不敢碰。
更麻烦的是,SVN本身没有提供类似Git的gitignore那样强制性的“不发布”机制。它只管版本控制,不管部署。所以这道防线完全依赖开发者的自觉和运维的细心——而这两样,在现实里恰恰是最稀缺的。
话说回来,Git也并非绝对安全。如果误把.git目录传到服务器上,同样能通过objects/下的文件反推整个历史。只不过Git的目录结构更隐蔽,而且多数人默认用Git时都会顺手加个.gitignore,而SVN的老用户习惯里根本没这概念。
所以你要问我的态度,就一句话:别信“没人会发现”。安全这东西,永远是懒人给勤快人挖的坑。你省下的那几分钟配置时间,可能日后要拿整个数据库来还。