分类 信息技术 下的文章

FROM alpine:3.15.0
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \
apk update && \
apk add --no-cache lighttpd php8-fpm php8-sqlite3 php8-pdo php8-pdo_sqlite php8-json \
php8-mysqli php8-pdo_mysql php8-dom php8-mbstring php8-gd php8-curl php8-session && \
echo 'include "mod_fastcgi_fpm.conf"' >> /etc/lighttpd/lighttpd.conf 
EXPOSE 80/tcp
CMD php-fpm8 && lighttpd -D -f /etc/lighttpd/lighttpd.conf
VOLUME /var/www/localhost/htdocs
  • 当版本更新时,修改Alpine和PHP的版本号即可
  • 如果不在国内,可以不用修改源,或者可以使用更快的源
  • 可根据需要自行增删PHP扩展

缘起

今年9月,学生组队报名准备参加本年度的全市中职学生技能竞赛。由于我在学校一直负责学校服务器运维和学校网络维护的技术支持,加之刚刚在9月份参加了全省职工的网络安全大赛,取得了还算说得过去的成绩。所以学校这边也让我配合唐刚老师一起辅导参赛学生。

比赛原定于遵义市职校承办,但由于设备没有到位(不由吐槽一句,现在的技能大赛已经沦为设备厂商的推销大会了,好多的项目不是面向实际的职业技能,而是绑定到了具体的厂家具体的设备上面),市里面决定取消今年本项目的赛事。我校信息学部部长兼网信办主任张明庆老师知道了这个消息,很想把这个比赛承担下来。于是来征询我的意见,问我能不能搞定这套系统。我经过认真思考,综合考量了我校的硬件、技术、人员以及比赛时间等各个方面的情况后,觉得能把这个事情搞定。于是张老师请示了学校领导得到许可之后向市教育局提出了承办赛事的申请。市里面同意了我校的申请,此时距离比赛也就一个月左右的时间,其中还包含国庆节7天的假期。时间紧急,所以在放假前我们开发小组的几个人碰了头,首先确定系统的总体设计。

准备阶段 & 系统设计

  • 硬件系统设计:首先要把各组参赛选手从逻辑上隔离。我最先考虑的是通过配置交换机,按端口分为若干个VLAN ,但是比赛所用的机房是新建的,我对里面的交换机并不熟悉,且时间紧急,没有足够的时间去查询手册和调试设备。所以最后决定新增一些设备直接物理隔离。具体的方法就是每组一个交换机,然后每个交换机连接到路由器不同的接口上,路由器再连接到服务器上。
  • 软件系统设计:我们分解了若干个子任务,分由不同的人负责。

    1. 首先确定了第一部分也就是单兵渗透测试部分,全部出Web方面的试题,分为3个大任务8个小任务,分别是:

      • 网页包含和上传漏洞。
      • 密码爆破、身份伪造、XSS攻击。
      • 古典加解密、SQL注入、SQL盲注。
    2. 第二部分也就是攻防对战阶段使用Linux系统 + Web程序的方式,在两方面都要留若干漏洞。
    3. 靶机系统使用服务器上不同的虚拟机实现。
    4. 编写一个计分系统。

然后我们就分配任务,我负责软硬件部分的总协调、路由器的配置、虚拟机的部署以及单兵模式的第二大题的出题。

路由器配置

一共有7支队伍参赛,因此我们调配了7个交换机来分组隔离,另外购买了两个8口的路由器来分别连接各组和服务器,购买两个的原因是一个使用一个后备。得到的路由器本身带有 iKuai 系统,但是经过测试,iKuai系统不能完成需求,于是我决定使用 pfSense 系统,具体配置过程如下。

  1. 定义了14个基于IP地址的别名,命名为 ctf1-1 ~ ctf1-7的用于各组第一阶段的服务器。命名为 ctf2-1 ~ ctf2-7的用于各组第二阶段的服务器。
  2. 定义了3个时间计划,命名为 ctf1、ctf2-1、ctf2-2,分别对应 单兵阶段、攻防加固阶段、攻防混战阶段
  3. 设置规则策略,根据上面定义的IP和时间段定义不同时间的不同访问策略

    • 浮动规则 中,让所有IP均可访问裁判机
    • 浮动规则 中,让所有IP在ctf2-2时段均可访问 ctf2-1~ctf2-7
    • 在各网络规则中,让本网络在ctf1时段能访问机器ctf1-n,在ctf2-1时段能访问机器ctf2-n
  4. 如果需要,为服务器所在的网卡设置NAT规则

经测试,这样设定可以达到网络分组、定时通放的目标。只是在测试过程中,一台路由器不明原因死机,另一台不明原因温度飙升到50度,所以我们在后面一直提心吊胆,担心设备出现故障。

单兵试题

我自己写的部分并没有花费多少时间,倒是修改别的同事负责的部分费时不少。主要有这样一些值得说道的地方:

  • 为了方便部署,所有使用数据库的地方都改成了Sqlite。
  • 为了减少和服务器的通信,决定Key值在本地生成,服务器上验算的方式,为了减少被猜出算法的几率,计算的时候使用了服务器IP、时间戳、题号另外再加盐。还对本地的PHP代码用pack+unpack+eval的方式进行了处理。
  • 对于 密码爆破古典加密 等部分的账号和密码,均改成了在第一次运行时动态生成。
  • 对于文件上传,为了避免本题对其他问题的影响,设定了只能上传指定的内容。不然选手上传了一个Webshell,什么问题都可以解决了。

攻防对战试题

系统采用Linux,在上面部署一个具有上传、包含、注入等漏洞的CMS系统让选手通过Web攻击提权攻击,给选手一个低权限账号,并且把这个账号的主目录设置成Web的根目录,方便进去防守修改。另外再留一些系统后门。

系统后门我首先想到的是用netcat、后面还是选用了 php -S 来启动一个WEB服务器,再把/flag软链接到这个服务的根,当然这个服务必须用上面的低权限账号启动,这样防守的时候才能关闭。

另外我还设计了一个简单密码的系统账号,当然密码也是随机的,让选手使用SSH爆破登入。

最初我的flag是使用Bash生成的,调试的时候总是和裁判机对不上,后面反复调试才发现Bash的很多命令结果有换行符,最后还是用PHP写了一个,当然这个文件权限要设置为700,不能让选手阅读。

虚拟机部署

我最开始设想的是在服务器上部署虚拟机的方式,用桥接的方式即可拥有外部IP。但是我发现虚拟机的复制很麻烦,并且定制也很不方便。考虑到我们的题目都可以在Linux上部署,于是我决定使用Docker来完成需求,一个循环即可解决所有机器的部署。

至于靶机IP地址的解决,我是这样处理的:在Docker宿主机上设定网络别名,并设定IP和网络即可,概念代码如下:

ifdwon eh0:1 
ifup eth0:1 10.10.10.10 netmask 255.255.0.0

然后在生成容器的时候把需要开放的端口映射到容器即可,对于网络攻防阶段的后门端口,我采取了容器内部固定,在启动容器时用随机端口映射的方式,因为时间关系,我把随机端口的范围限制到了 5000~10000。

比赛过程

因为前期考虑还算周到,加之其他同事的配合,学校有关部门对外部环境的保障有力。比赛过程还是很顺利的,基本没有什么意外出现。只是我过于高估了学生的水准,题目难度偏难了一点,第一阶段开始30分钟了还没有人得分,后面我紧急调低了试题的难度。对于修改Cookie和XSS攻击这两部分去掉了必须转码的限制,才让数据好看一点。也幸好采用了Docker部署,一个循环即可把改变后的题目部署到所有容器。

赛后总结

  1. 自己的技术储备还行,没有太脱节于时代; 体力和精力也还将就,在压力面前也还能提起这口气。
  2. 目前组里面这批人还是可以的,在有任务、有组织的情况下还是能做很多事情的,工作态度端正、爱学习、肯钻研。
  3. 说句负能量的话:在单位做事真的是靠觉悟,当然有人支持,也有人不支持,甚至有的人可能在心里抱怨我们多事儿揽事儿,不过只要是对学校有益、对教学有帮助、自己认为有意义的事情,坚持去做就对了,岂能事事如意?但求无愧于心。
  4. 对中职学生不能期望值太高。本来我以为只是我校学生逻辑思维能力不够理想,结果至少对于遵义市来说是普遍现象。本次比赛的密码都是弱密码:由单个字母或数字重复6次,共62种可能。所以我没有提供字典,让学生临时自动生成,但是在赛场上没有一个学生用程序生成,全部使用的手工输入。来参加竞赛的选手都是如此,更遑论普通的学生!因此在以后的教学里,本学科的重点放在工具特别是Kali自带工具的使用上,对于编程部分只能降低标准,不作普遍要求,通过兴趣小组的方式让学有余力的学生学习相关知识。

SciTE是一个非常轻量的开源的源代码编辑器,在Window和Linux下都能使用,不过默认不支持中文,这是中文支持的配置文件,通过菜单 Options | Open User Options File 输入。

code.page=65001 ; or cp936
output.code.page=65001; or cp936

font.base=font:!Monaco,size:16
font.small=font:!Monaco,size:12
font.comment=font:!Monaco,size:14
font.monospace=font:!文泉驿微米黑,size:16
font.code.comment.box=$(font.comment)
font.code.comment.line=$(font.comment)
font.code.comment.doc=$(font.comment)
font.code.comment.nested=$(font.comment)
font.text=font:!Monaco,size:16
font.text.comment=font:!Monaco,size:14
font.embedded.base=font:!Monaco,size:16
font.embedded.comment=font:!Monaco,size:16

作为编程的初学者,无论是是学校和培训机构的学生,还是编程爱好者,第一门语言的意义是不言而喻的,选择了一门语言,就选择了一种思维方式。

在八、九十年代,计算机相关专业选择的入门语言一般是C和Pascal,业余入门一般选择Basic。进入新世纪之后,专业的入门语言变成了Java,而业余的选择就是五花八门了,但是基本都是选择一门脚本语言如Python等入门。但是在笔者看来,无论是专业也好,业余也好,用Javascript入门都是一个不错的选择。

Javascript最初的设计意图是为了在浏览器(网景的导航者)端载入的Web页面和后台服务器端的应用程序之间提供脚本化的借口。由于这项技术产生于1995年,加上后来微软的IE浏览器也加入了对Javascript的支持,所以时至今日,Javascript不光已经成为Web开发的关键组件,还逐渐的拓展到越来越多的方面。

笔者为什么建议使用Javascript作为入门语言呢?主要是从语言学习的层面和应用范围的层面来考虑的。

从语言学习的层面来说:

首先, Javascript的开发调试环境配置及其简单。只要有文本编辑器和网页浏览器即可,且这两种软件在任何主流的操作系统中都是自带的。其中文本编辑器用于输入包含Javascript的HTML源代码,浏览器用于调试和运行这些文件。对于学习Javascript的语法而言,HTML的知识也不是必需的——只需要把源代码输入在<script></script>之间,把文件保存为.html或.htm格式,然后用浏览器打开即可。并且主流的浏览器都支持Javascript代码的单步调试。当然,这仅仅是说Javascript 可以马上上手,要更好的使用 Javascript,还是需要更优秀的编辑器的。

其次,Javascript的基本语法和主流的C/C++/Java类似,有利于学习类似的语言。例如 C 语言的赋值(如基本赋值、连等赋值、自运算赋值等)语句、运算符(如算术运算、逻辑运算、位运算、三目运算等)、流程控制(如if、for、while)等均可在Javascript中使用,所以在学习Javascript之后如果需要学习这些类似的语言也能平滑过渡。作为入门来说,由于Javascript是脚本语言,语法比较宽松,比如变量不需要预先定义,又比如在大多数情况下,行尾的分号可以省略,这些特性相比C/C++/Java对于初学者来说都更加的友好。

第三,Javascript支持目前主流的编程方式——面向对象编程。虽然Javascript采用的原型继承的方式和C++/Java不尽相同,但也支持继承、多态和封装。了解这些概念后如果需要转向主流的面向对象编程语言也会很轻松。

第四,在Javascript中,函数也是基本的数据类型,所以在Javascript要实现匿名函数,函数作为返回值,闭包等功能都是很方便的。因此,在Javascript中也能实现函数式编程。

第五,Javascript的网上资源非常丰富,有利于自我解决学习过程中出现的问题。就目前来说,在github中Javascript的项目以及在编程问答网站StackOver中Javascript的问题都名列前茅。

第六,随着 ES6的定稿和 ES7的即将推出,Javascript 也越来越规范化和模块化,比如可以使用“use strict”使用严格模式,这样就和很多静态类型的编程语言一样,变量使用之前必须初始化,有助于培养良好的编程习惯;在学习这些最新规范的过程中还能了解 Generator、Promise 等新的编程理念。

第七,Javascript中对象的写法已经成为现在一种通用的数据存储和交换格式JSON,以后转到其它语言时,也会接触到这种格式的数据。

综上所述,用Javascript作为入门语言,可以了解编程的基本要素,为学习其他主流编程语言打下必要的基础。

如果要深入的学习Javascript,可不可以以它作为唯一的语言?它又能用在什么地方?下面就列举一下Javascript目前的一些应用场景:

首先,Javascript在WEB开发方面扮演重要的角色。

在Javascript的“本职工作”前端开发方面,随着Ajax技术的发展,Javascript已成为当前的Web开发的关键组件。最初的网页都是静态的,服务器程序呈现的是什么内容就只能浏览什么内容, 有了Javascript,浏览者就可以和网页进行简单的交互。再后来出现了Ajax技术,可以在不刷新网页的情况下更新网页的内容,这就使得网页从单纯的呈现内容的载体发展到了Web应用的容器,为各种B/S程序提供了坚实的基础。在这之前,B/S的程序要么使用Flash,要么使用ActiveX,要么使用JavaApplet,而这些技术都有各自的缺陷,所以Ajax技术出现之后,特别是随着jQuery等框架的流行,使得前端开发更加的便利,于是这些“过时”的技术都淡出了B/S应用的舞台。而Ajax中的“J”,就是Javascript的缩写。

其次,Javascript支持跨平台的移动开发。

随着HTML5标准的定稿,Javascript也越来越重要,在HTML5中新增的Canvas、本地存储等功能必需结合Javascript才能真正发挥作用。另外,HTML5还可以进行跨平台的移动开发,如国外的PhoneGap、React Native等就是利用HTML5开发苹果、安卓、Windows Phone、黑莓等平台的移动程序;国内也有阿里巴巴的 Weex、数字天堂的HBuilder等移动开发工具和平台;特别是最近腾讯推出的微信小程序,更是让 HTML5的移动开发火上添油!

第三,Javascript可以用于服务器端的应用程序开发。

在原来的ASP时代,虽然使用VBScript的人更多,但是也可以使用JScript开发服务器端的应用程序,在微软停止支持ASP以后,仍然可以在ASP.Net中继续使用JScript,而JScript就是微软的Javascript。

对于用Javascript服务器端应用程序设计而言,现在有了更好的选择,那就是Node.js。Node.js是基于Google Chrome的Javascript解析引擎V8建立的一个平台,用来方便地搭建快速的 易于扩展的网络应用。Node.js 借助事件驱动,非阻塞I/O 模型变得轻量和高效,非常适合运行在分布式设备的数据密集型的实时应用。V8引擎执行Javascript的速度非常快,性能非常好。Node对一些特殊用例进行了优化,提供了替代的API,使得V8在非浏览器环境下运行得更好。特别地,针对服务器端的WEB编程,产生了Express.js、koa等应用框架来简化开发。

第四,Javascript可以作为操作系统的管理工具。

如前文所言,Node.JS既然可以在非浏览器环境下运行,那么自然可以作为系统管理的脚本语言,特别是在分布式设备的数据密集型的实时应用,例如各种网络程序和各种NoSQL数据库。

在Windows下还可以使用WScript.Shell来执行操作系统常见的外壳操作,如读写注册表、环境变量等,可以说是DOS下BAT的升级替代品。JScript就是WSH内嵌支持的两种语言之一。

受到Node.js的启发,出现了基于V8的phantomjs和基于火狐解析引擎的slimerjs等语言,这两种语言都是一个基于Javascript的Webkit/Gecko内核无头浏览器,也就是没有显示界面的浏览器,这样访问网页就省去了浏览器的界面绘制所消耗的系统资源,比较适合用于如爬虫等网络测试等应用 。

第五,Javascript可以开发桌面应用程序。

在Windows操作系统中直接将HTML保存成HTA的格式,就是一个独立的应用软件,不但可以使用通常的HTML技术,还可以使用系统自带的各种ActiveX控件(当然,这些都得用我们今天的主角Javascript或VBScript来操控),是一种很方便快捷的桌面应用程序设计方法。

时下也出现了一种新的基于HTML的新的桌面应用开发方式:使用的WebKit来渲染界面,用Node.js来和系统通信。有跨平台的Electron、NW.js、腾讯推出的AlloyDesktop等。例如 GitHub 的 Atom 和微软的 VS Code还有Adobe 的Brackets等软件都是使用这种技术开发出来的。

所以,如果想成为“全栈工程师”,学习Javascript也是一个不错的选择。

综上所述,如果选择Javascript作为入门的语言,既容易学习,又能找到很多的应用场景,还可以很容易的过渡到其他的语言。所以,笔者建议选择Javascript作为入门的编程语言。