CTF Intro
0x00 前言
挖洞,也就是找漏洞,本身就是个很随缘的技术,而且多半是八分靠运气,二分靠实力,尤其是在你不知道你要渗透的网站后端源代码的情况下。所以说,即便找不到漏洞,也不要认为是你个人能力不行导致的。举个例子,Linux系统被安全人员研究了几十年了,但是到目前为止,被发现的内核提权漏洞你用一双手就能数得过来。这不是研究它的安全人员的能力不行,而是找漏洞本身就是个很随缘的过程。你缘分到了,有个漏洞可能就被你找着了。缘分没到,那也没办法。
很有幸,本科期间遇到一位对的老师,打过一年CTF比赛,也曾给校赛出过题。但是我和安全行业的缘分实在没到,所以后来读研、实习也没有选择安全方向。
现在只能以一位业余安全爱好者的身份,在组里,来介绍一些安全方面的常识,组织这么一场比赛,来增进大家的安全防范意识。也算对我曾经学过的知识的一次复习。
0x01 SQLi
SQL注入问题产生的根源在于直接拼接SQL语句,而使用预编译的SQL语句则没有SQL注入的问题。目前已经很少有场景下会直接拼接SQL语句了,所以SQL注入攻击也在逐渐淡出网络安全圈的视野。不过校级的CTF比赛往往还比较喜欢往这个方向上出题,因为其变化多样,手法多端,说白了就是好玩呗。
在登陆系统这个业务场景中,我们可能会使用如下SQL语句:
1 | SELECT password FROM user WHERE id='?' |
依据用户id在数据库中查找其密码,然后在业务层面将其密码与输入密码或输入密码的hash值进行对比。如果我们在?
处直接拼接SQL语句,就会产生SQL注入的问题。当输入的用户id
如下时:
1 | -1' UNION SELECT 123 # |
这样直接拼接后的SQL语句,就会变为:
1 | SELECT password FROM user WHERE id='-1' UNION SELECT 123 #' |
#
作为SQL中的注释符号,则后面的内容将会被全部忽略,当输入的用户id为-1
也就是一个不存在的id时,这个SQL的前半句,将不会有任何的返回结果。但是,我们UNION
了一个123,则整条数据的实际返回结果为123。这样程序就会错误地认为“正确的”密码是123,当我们输入的密码为123时,就会导致程序误判两个密码是正确的,继而以非法身份登陆系统。
CTF比赛,在这方面出题的着重点在于给你屏蔽掉一些关键词,比如屏蔽掉UNION
关键词,例如:
1 | String input = "-1' UNION SELECT 123 #".replace("UNION", ""); |
上面这段代码会把输入数据里面的UNION
给抹掉,但是这样也是有缺陷的,可以通过双写来绕过,当输入如下时,上述的安全策略即可被绕过:
1 | -1' UNUNIONION SELECT 123 # |
0x02 XSS
XSS即跨站脚本。SQL注入诱发的根源在于直接拼接SQL语句,而XSS诱发的根源则在于直接拼接网页的HTML代码。我大二的时候曾给百度文库反馈过一个XSS漏洞,以当时的例子,我们来简单介绍一下。
百度文库对文章的评价功能呢,有一段这样的代码:
1 | <div> |
这段代码的逻辑非常简单,就是希望用户可以点击评论区的头像,来跳转到评论人在百度文库的个人主页。但是,它犯了一个错误,就是它在代码里直接去拼接用户的昵称部分。
我们可以注册一个百度号,然后将昵称设置为:
1 | "onclick="alert(1)// |
这样百度文库在渲染这个网页时,将用户昵称拼接上之后,即为:
1 | <div> |
我们可以看到,这个拼接上的用户昵称为这个头像元素注册了一个onclick
事件,这个事件的作用是在页面弹出一个窗口。当用户点击这个头像时,所做的操作也不是打开评论人在百度文库的主页,而是这个onclick
事件所注册的操作。
如果这个onclick
事件注册的操作不是弹出一个窗口,而是使用JavaScript的document.cookie
来获取当前用户的cookie,然后将其发送到某黑客指定的远程服务器的话,这样黑客就悄无声息地偷走了用户cookie,继而可以伪装用户身份使用此系统。
0x03 文件上传漏洞
文件上传漏洞所产生的本质原因实则为用户将文件上传到服务器上的某个目录下,而这个目录偏偏又在当前的网页目录下所导致的。大型的系统一般不会出现此问题,因为大型的系统用户量往往很大,且多半会将图片或者用户上传的静态文件存放在单独的文件服务器中。容易出现此问题的多为小型的CMS系统或者WordPress这样的博客系统,因为用户量不会很大,所以索性将用户上传的图片、头像等都存储在网页目录下,而又忽略了屏蔽当前目录的可执行权限导致的。导致用户可以上传一个可执行脚本然后透过远程调用非法执行脚本中的内容。
如下附几个常见的PHP一句话木马
1 | eval($_POST['cmd']); @ |