[关闭]
@ruanxingzhi 2017-05-18T19:53:28.000000Z 字数 1591 阅读 1808

OJ技术思考:评测安全

先不讨论文件结构了……此文用来讨论评测鸡。
……大概是基于我这两年的经验吧。可能会有不完善的地方。

评测鸡的实现,已经有了很多不考虑安全问题的版本。因此这里只讨论安全问题。

我大概把评测攻击分为两部分:编译时攻击、运行时攻击

编译时攻击

编译时攻击是很多评测鸡并没有防范的。例如下面几种攻击情况:

编译超时

  1. #include </dev/random> # Linux
  2. #include <CON> # Windows

这种攻击方式的原理是,让编译器读一个永远也读不完的文件,把评测鸡卡死在编译阶段。BZOJ已经被这段代码卡掉很多次了。

示例:http://pyoj.ml/submission/3019
解决办法:设置编译的时间限制,或者用vfk的办法,把编译器监控起来。

输出巨大文件

我们在做数论题的时候玩过这种事情:int a[10000000]={1,0},这样编译出来的文件会特别大。在我的机器上,它的大小是39MB。

我们想到,让编译器生成一个极大的文件。下面是一个针对gcc的编译炸弹,从wikicoding.org蒯来的。全文如下:

  1. main[-1u]={1};

编译这段代码之后,会生成16GB的文件。

示例:http://pyoj.ml/submission/2912
解决办法:设置编译出来的可执行文件的大小限制。

include攻击
include攻击同时被vfleaking(UOJ)和李扬(QDUOJ)描述。向二位致敬。

include攻击是指:用C/C++代码include网站的配置文件,然后通过返回的编译错误信息,读取密码。

例如。对于hustoj,可以采用下面的代码:

  1. #include "/var/www/JudgeOnline/include/db_info.inc.php"

这份代码将会include数据库的配置文件。上交这份代码,将会返回如下的编译信息:

return

事发后,hustoj的这个漏洞已经在一年前修复

示例:http://pyoj.ml/submission/3020
我的解决方法:

vfk的解决办法:把编译器监视起来。

另外riteme提出了另一种鬼畜的解决办法。见https://github.com/hzxie/voj/issues/14

运行时攻击

运行时攻击,已经有比较好而且通用的解决方案。解决这个问题难度并不大。

运行系统指令

  1. system("shutdown now");

这种攻击方式很早就被解决了。

示例:http://pyoj.ml/submission/3021
解决方法:用沙箱跑评测,可以采用ptrace。但是我准备用一种更暴力的方案。直接把程序扔进docker里面跑,它爱玩成什么样就玩成什么样吧233。

fork炸弹
曾经有OJ被选手程序不停地fork()搞炸了。

我没有拿到代码,因此这里没法分析。

故意运行超时

  1. while(1): pass

如果评测时开了-O2,上面的代码可以改成求斐波那契数列。反正只要确保超时就行了。

然后突然交一大堆这种程序,以达到类似DDOS的效果……

这种东西很没技术含量。这是一份针对hustoj的脚本:https://gist.github.com/Ruanxingzhi/9f0caba5e2d8a690ae1e89bcfb92abba

效果是用1000个账号,每个账号提交10次,每个账号在提交之后休息11s。
体现为:两分钟内,OJ上面多了一万份提交。

解决方法:注册的时候设置验证码,如果一个账号短时间内多次提交,在这个账号下一次提交的时候也需要验证码。

请注意,注册的时候,只用邮箱验证,不用验证码是不行的!

总结

我玩了这么久的OJ,一共也就发现这几种攻击方式……
但是好像很多OJ对编译时攻击防范并不好。
点蜡烛。希望OJ做得越来越好吧。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注