从零开始写OJ---评测姬安全

来源:互联网 发布:数据分析主要分析哪些 编辑:程序博客网 时间:2024/04/30 02:53

我们的OJ系统需要运行用户提交上来的代码,但谁也无法保证不会有别有用心或者只是单纯好奇的同学(比如大一的我…)来搞我们,提交恶意代码。而恶意代码可以造成的破坏是很大的,从崩掉自己,到获得本应保密的信息,甚至清空整个系统,比如用户提交个system("rm -rf /*"),而你的评测姬正好又有权限的话……因此评测姬的安全是必须要得到保证的。

这里列出一些常被同学们使用的攻击方式,还有评测姬针对这些攻击的防护方法。基本都是我在各大OJ上曾经见过(或者别人在我们学校的OJ)的攻击,希望看到这篇博客的同学不要贸然尝试这些攻击方法。如果单纯的想帮助完善某OJ,请先征得OJ管理员同意,对于未经授权使用本篇博客方法攻击产生的后果,我概不负责。

评测姬对于每个代码的评测大致为:编译-运行-对比结果三部分,对于这三个环节,都有对应的攻击方式。

首先是编译阶段

include关键文件

很多OJ(包括我校之前)对这个阶段都是没有什么防范的,毕竟就算你提交恶意代码,也不过是编译不过嘛。但是事实真的如此吗?你在你的电脑上尝试include一个不正确的头文件试试。
passwd
我们知道,大部分的OJ在你编译错误的时候是会返回编译错误信息的,如果我们包括的是/etc/passwd或者其它的什么关键性的文件的话,是不是也会暴露我们的文件呢。
那么这个问题怎么解决呢?方法有很多,可以降权编译,也可以单独为编译评测创建一个Linux用户,以这个用户来进行编译操作,这个用户没有读取其他文件的权限,自然,报错信息也就不会暴露关键文件了。这样,编译时再尝试包括不正确的文件,会直接编译错误,返回的信息就是无法打开文件。
修改权限之后再次尝试:
chmod 700

编译超时

写个代码,只有一行
#include </dev/random>或者#include </dev/tty> //(Linux)
#include <CON> //(Windows)
不需要写其他的东西,就这一行就够了,写完之后编译试试。怎么样,能编译出来吗?
这个就是曾经卡过各大OJ评测的奇妙代码,大部分OJ都已经修复了这个BUG,其它OJ的做法我不清楚,我当时做的是限制编译时间,超过一定时间的编译结束掉,并且返回CE。还有其它几个编译BUG,我都是用这个方法修复的。

编译产生巨大文件

main[-1u]={1};,一行代码,编译试试。会产生16G的文件,会卡住相当久。这个可以限制编译内存资源,或者,其实如果已经限制了编译时间的话,这个可以不用管,因为在有限的时间内,编译也并不能产生很大量的文件。

编译产生巨量错误信息

据称有的代码很短,但是会在编译时产生巨量的错误信息,这样的代码我还没有实际见过,不过,我认为,限制编译时读写文件大小应该可以解决这个问题。

以上三个BUG的修复,我用的是C语言的setitimersetrlimit函数设置限制,fork子进程去编译的方法,因为一些原因,源代码现在还没有放到github上,估计之后应该会放上去。可以看这里,按照之前写的自行编码修复。

运行阶段

shell攻击

system("mkdir /home/helloworld"),代码含义一目了然,这个的防范,可以弄个新用户来跑程序,破坏性的代码会因为权限不足自己失败的。

系统函数攻击

while (1) fork();(V2EX上找到的fork炸弹,不要轻易尝试,容易卡死),或者调用其它的系统函数。虽然如果你有程序运行限制,会在限制达到后自动结束程序,但是这个程序还是会卡住你的系统一阵。
防范方法:ptrace监听系统调用,系统调用白名单可以使用hustoj的开源版本,但是经我测试,使用这个玩意之后,程序运行耗时会增加三分之一到四分之一,用不用自己权衡,我校的OJ评测姬有这个功能,但是平时是不开启的。(还有一点,hustoj评测机写的相当混乱,单文件近两千五百行,代码风格变化多端,在我来看,对接任的维护人员是个不小的阻碍)

网络模块攻击

我校的OJ是可以提交Python代码的,我在大一的时候,曾经提交过效果是登录我校OJ提交十份代码的代码,果不其然,刷新之后,状态里多了十一发提交……当时大概知道这玩意的威力,因此也没有提交死循环或者递归提交自己的代码。但是利用这个漏洞找到了评测服务器的文件结构,还有结果所在的文件夹。最后和另一个小伙伴一晚上AC了一千七百多道题,刚干完就感觉不对劲,第二天果然被老师查水表了……
这个的防范措施也有很多,比如评测服务器和WEB服务器分离,评测服务器不能连接外网之类的,当然,通过setuid降权也是可以防止这样的操作的。

对比结果阶段

其实对比结果阶段,和用户提交上来的代码就没有什么关系了,纯粹就是服务器上的两个文件对比,哪能有什么漏洞嘛。且慢,虽然两个文件都是在服务器上,但是一个文件完全是由用户的代码生成的,虽然纯文本也不能带有什么恶意程序,但是,如果这个文件特别大的话呢?
OJ上会有一些时限比较长的题目,比如省赛、区域赛的题目,动辄5S、10S,甚至我们OJ上有个100S的题,如果用户提交一个代码,100S内一刻不停的输出,那就不是文件特别大的问题了,很可能根本无法写入文件。而巨大的文件也会导致对比正确结果很慢。
解决方案和解决巨量编译错误信息一样,对于运行的代码限制输入输出大小,超过的直接结束运行,并返回OLE。

以上就是我所见过的对OJ评测的攻击方式,还有评测姬的防护措施。这些并不能保证评测的绝对安全,安全也不能全靠这些措施。像校内OJ,就可以采取实名学号注册,每个提交都记录IP,这样一旦有了问题,也可以迅速定位到个人。而那些公开的OJ,则可以通过限制注册(邮箱+验证码),限制频繁提交,管理员手动封禁IP等方式来加强安全保护。要知道,一个系统最容易被攻破的地方,永远是人。

本篇博客参考了Online Judge 是如何解决判题端安全性问题的?、怎样做一个 Online Judge(在线评测系统)?、OJ技术思考:评测安全、谷歌、V2EX、还有多个OJ上的恶意提交源代码等资料。当然,还参考了我们被攻击的经历。

另外, 自2017年6月1日起施行中华人民共和国网络安全法

原创粉丝点击