背景:
团队内一位资深同事在去年给大家share了最新的OWASP Top 10 的变化以及内容,并结合了OWASP的Juice Shop进行讲解,内容非常简洁易懂,让我以最简单的方式了解到了安全测试是什么,希望通过整理,让更多的人有所了解
环境准备:
- Juice Shop Github 地址 请按照其中Docker Container 部分搭建环境,我采用的是 v7.5.1这个版本,所以第2,3步相应的变为
docker pull bkimminich/juice-shop:v7.5.1
docker run --rm -p 3000:3000 bkimminich/juice-shop:v7.5.1
安装成功并启动后
网页中打开localhost:3000,即可看到Juice Shop的首页
- Charles,下载安装,免费试用一个月
实践 - OWASP Top 10
首先 OWASP 是 Open Web Application Security Project 的缩写,一个非盈利性组织, 详情请自行Google
下图为2013年和2017年的对比版本:
A1:2017 - 注入
练习1 预定圣诞节特供(已删除的商品):
步骤1: 打开Juice Shop的首页
步骤2:打开DevTools -> Network, 用delete按钮清除请求
步骤3:在Search的地方什么都不用输入,点击search搜索,并在Network中找到发送的请求 http://localhost:3000/rest/product/search?q=,看Response中有返回数据,一共有28条数据
步骤4:在search的输入框里输入 '; 然后点search,会在Network里看到发出去另一条请求并且报错,检查后找到报错内容
sql: "SELECT * FROM Products WHERE ((name LIKE '%';%' OR description LIKE '%';%') AND
deletedAt IS NULL) ORDER BY name”
步骤5:找到输入内容拼接的地方,进行修改,在search的输入框里输入 '))-- 然后再点击Search按钮,查看Response里的返回数据有32条
视频:练习2 登录管理员用户
步骤1:进入Login 页面
步骤2:输入任意账户和密码得到一个错误
步骤3:试试 '# 就会看到报错信息,找到其中的SQL语句
"sql":"SELECT * FROM Users WHERE email = ''#' AND password = 'e855b45052de9a85655f584589edd0f9'"
步骤4:根据出错点,重新输入 ' or 1=1-- 成功登录管理员账户了
练习3 找到管理员页面
步骤1:在DevTools里点Source Tab,找到dist目录,点juice-shop.min.js,搜索 ‘administr’ 这个字符串,会找到一个页面url '/administration'
步骤2:在上一个账户里,将URL中的search替换成administration,
http://localhost:3000/#/search
http://localhost:3000/#/administration
步骤3:你就会见到用户和Comments
A2:2017 - 失效的身份认证
练习4 更改Bender的密码
步骤1:在A1的练习2中的管理员页面,找到Bender的Email
步骤2:利用SQL注入的方式,即在login的账户中输入 bender@juice-sh.op'-- 进入到Bender的账户,可以点击Contact Us验证,会看到Author的地方有Bender的显示
步骤3:打开DevTools -> Network, 清空请求,点上边的 Change Password, 分别在当前密码,新密码,重复新密码三个输入框输入任意字符串,观察请求
步骤4:打开新Tab,在新Tab中分别进行以下3中尝试
http://localhost:3000/rest/user/change-password?current=A # 401Password cannot be empty
http://localhost:3000/rest/user/change-password?current=A&new=B # New and repeated password do not match.
http://localhost:3000/rest/user/change-password?current=A&new=B&repeat=C # New and repeated password do not match.
步骤5:猜测是否可以不给默认密码,进行第4次尝试,成功。
http://localhost:3000/rest/user/change-password?new=B&repeat=B # 200 success
A3:2017 - 敏感数据泄露
例子5 上个例子中修改密码时,密码是MD5加密的,非常容易反解密
例子6 非技术上,请不要把你的密码曝光到网上
A4:2017 - XML 外部实体 (XXE)
参考引用:XML外部实体(XXE)注入详解
A5:2017 - 失效的访问控制
练习7 0星评价
步骤1: 进入 Contact Us
步骤2:其他内容都填好,不给 星星 好评
步骤3:Submit 按钮是不让点的
步骤4:点上3星好评,但立马点掉
步骤5:可以Submit了,成功
例子8 之前例子中提到的/administration页面,理论上是只有管理员可以访问这个页面的,但是可以通过扫描源文件或暴力破解的方式查到
例子9 扫描同时可以找到一个被程序员遗忘了的备份文件夹
网上有很多开源扫描工具可以用,作为练习,可以使用owasp zap
练习10 获取其他人购物车数据
步骤1:用 'admin@ juice-sh.op/admin123' 登录
步骤2:打开Charles, 为了使用Charles,需要把URL替换成以下的URL,这样就不需要配置代理了
http://localhost.charlesproxy.com:3000/#/search
步骤3:点购物车,DevTools中会看到发出去的请求http://localhost.charlesproxy.com:3000/rest/basket/1
步骤4:basketid就是userid,在Charles中修改这个URL,改为http://localhost.charlesproxy.com:3000/rest/basket/3,意味着我期望在我的账户中请求Bender的购物车数据,然后执行,就会看到自己的购物车里显示的是Bender购物车里的数据
练习11 更改订单让自己钱包鼓起来
步骤1:在购物车中点增加商品数量,截获请求http://localhost.charlesproxy.com:3000/rest/basket/3
步骤2:修改返回的response,就可以看到总价变成了负数
练习12 重定向到指定网址
步骤1:将鼠标滑动到右上角的Fork me on Github, 在DevTools的页面中可以看到,a标签的href属性有个重定向地址
步骤2:将href的链接改为 redirect?to=https://google.ie, 然后点击页面的Fork me
步骤3:你会得到一个错误页面,但是如果你将值改为redirect?to=https://google.ie/?https://github.com/bkimminich/juice-shop,就会成功将网页带到Google去,成功
A6:2017 - 安全配置 错误
暂无
A7:2017 - 跨站脚本攻击
反射性XSS:APP和API都有未经过滤的用户输入作为网页的一部分输出
存储型XSS:APP或API会存储未经过任何处理的用户输入,这些数据在未来会被查看
DOM型XSS:JS框架或SPA会动态引入攻击者可操纵的数据
练习13 反射型XSS攻击
反射型攻击意思就是恶意的query直接来自受害者发送出去的请求。
步骤1:在启动了Juice Shop的网站,直接访问http://localhost:3000/#/search?q=%3Cscript%3Ealert(%22XSS1%22)%3C%2Fscript%3E,点击回车后会发现后边的部分已经变成<script>alert("XSS1")<%2Fscript>, 可以看到有popup弹出,尝试将尾部中%2F改成%2E,直接转义成了- 并且没有攻击成功,也尝试改为%2D,直接q=undefine了,也没有攻击成功,还不知道为什么?如果有知道的小伙伴欢迎补充
而且这是你可见的弹窗了,最担心的是它趁你不注意,做了不应该做的事
练习14 反射型XSS攻击
步骤1:
尝试访问下面的链接
http://localhost:3000/#/search?q=%3Cscript%3Edocument%2EquerySelector%28%22%2Enavbar%2Dlogo%22%29%2EsetAttribute%28%22src%22%2C%22%2Fpublic%2Fimages%2Fproducts%2Fapple_juice%2Ejpg%22%29%3B%3C%2Fscript%3E
其实它其中真正想表达的意思是执行这段code
document.querySelector(".navbar-logo").setAttribute("src", "/public/images/products/apple_juice.jpg");
它将你的主站logo改成了杯子和樱桃的图片,左上角
练习15 反射型XSS攻击
步骤1: 尝试下面的链接
http://localhost:3000/#/search?q=%3Cspan%3Ea%3C%2Fspan%3E
会发现 Search Results旁边多了一个a,这意味着不仅恶意的payload会被执行,同时页面中还有可能试图显示未经过任何处理的输入
练习16 持久化的XSS攻击
步骤1: 打开charles
步骤2:在注册界面,注册一个账号,charles中会看到一个API
步骤3:选中users下/,点击上边灰色的六边形框,Enable Breakpoints
步骤4:在注册页面再填写一个注册用户的信息,然后点击Register,Charles会捕捉到这个请求,然后断点在那里,这时,已经绕过了前端对Email的校验,准备发请求了
步骤5:在charles的断点中选择Edit Request Tab,以及底部的JSON Text,注意是JSON Text,如果你选了JSON会发现,在那里边编辑Email,会进行字符截断,但是选择JSON Text不会,将其中Email的值改为<script>alert("XSS2")</script>,然后点击底部的Execute,这个请求就会发出去,然后Response回来还会进到这里,继续点击Execute就行,这样注入信息就会被记录到数据库中持久化下来
步骤6:不知道大家还记得之前的/administration页面吗,尝试用任意一个账户登录,然后访问这个页面,就会看到有XSS2的弹窗,持久化XSS攻击成功
步骤7:因为在管理员页面,有显示所有账户的Email,当我们的注入被读取时,就会产生影响
练习17 持久化的XSS攻击
步骤1 - 步骤4 同上
步骤5:同样的方法,将Email 改为<script>document.body.style.background = 'pink';</script>,其他相同
步骤6:仍然是访问/administration页面,就会看到页面背景色变为粉色
练习18 根本不用前端的持久化XSS攻击
步骤1:在search页面里,点击某一个商品的logo,注意查看DevTools里有会有这样一个请求
步骤2:截取其中一部分,直接打开另一个Tab,粘贴进去
http://localhost.charlesproxy.com:3000/api/Products/1
步骤3:会看到如下的Response,而且这是一个Get请求
{
"status": "success",
"data": {
"id": 1,
"name": "Apple Juice (1000ml)",
"description": "test",
"price": 1.99,
"image": "apple_juice.jpg",
"createdAt": "2019-04-09T08:19:13.430Z",
"updatedAt": "2019-04-09T10:09:58.409Z",
"deletedAt": null
}
}
步骤4:猜测这个API也接受Post请求,那我们接下来用Curl命令在命令行里发一个Put请求
curl -X PUT "http://localhost:3000/api/Products/1" -H "Content-Type:application/json" --data-binary '{"description":"<script>alert(\"XSS3\")</script>"}'
步骤5:会看到Response 成功了,在search页面任何用户访问Products页面都会看到XSS3弹窗,攻击成功
A8:2017 - 不安全的反序列化
练习19 执行一个DoS攻击
步骤1:用人工检查或自动化URL发现工具,会找到一个Swagger API 文档,
步骤2:会看到一个Orders的Post请求,看到其中的Example中orderLinesData字段可以是任意的Json数据
步骤3:打开DevTools后点击Swagger中Try it Out,以及Execute,看到"No Authorization header was found"的Error
步骤4:回到刚才的search页面,打开DevTools,用任意账号登录,查看whoami这个API,找到Authorization
步骤5:将刚才找到的Authorization内容放到Swagger里右上角有一个Authorize的输入框里
步骤6:再Execute一下,看到正确的Response
步骤7:接下来我们执行一个DoS攻击,DoS即拒绝服务
步骤8:在Value中将orderLinesData那一行改为并Execute
"orderLinesData": "(function dos() { while(true); })()"
步骤9:看Response就发现死循环的代码已经在server里执行了,攻击成功
A9:2017 - 使用含有已知漏洞的组件
练习20 找到软件中使用的组件
步骤1:点菜单中About Us,在点击文字中唯一的链接,注意观察这个URL的地址,其中含有 /ftp/legal.md?md_debug=true
步骤2:截断ftp后边的部分,回车,会看到被程序员遗忘了的备份文件,点击其中的package.json.bak下载,看到Error提示,只有以md和pdf结尾的文件可以下载
步骤3:将package.json.bak改为package.json.bak%2500.pdf试一下,下载成功,检查这个json文件中有
"sanitize-html": "1.4.2"
接下来就可以利用1.4.2版本的sanitize-html中已知的安全漏洞去攻击网站了,查找成功
A10:2017 - 不足的日志记录和监控
练习21 记录不安全的尝试
步骤1:回想之前的下载尝试,如果有充分的Log记录,这样的行为是应该被记录的
步骤2:打开另一个命令行窗口,执行
docker ps
步骤3:找到你正在运行的Container, bkimminich/juice-shop:v7.5.1,执行
docker exec -it container_id sh
ls
步骤4:看到一个类似access.log.2018-10-25的文件
步骤5:执行
tail -f access.log.2018-10-25
步骤6:当你进入search页面的时候,记了很多Log,但再尝试下载上边的文件时,并没有相应的Log记录,其实有很多信息都是可以记录在Log里的,但结合之前的A3,又不应该记录太多敏感信息
总结
至此,大部分的情况都已经通过例子或练习share给大家了,这些只是我浅显的理解,但就这些东西如果我们能举一反三,也是可以发现不少问题或者预防不少问题的
参考:
https://www.owasp.org/images/6/67/OWASP_AppSec_Research_2010_OWASP_Top_10_by_Wichers.pdf