OWASP TOP10靶场

OWASP TOP10靶场
JohnnyA01:2021 – 权限控制失效
Hijack a session
开发自己的会话 ID 的应用程序开发人员经常忘记合并安全性所需的复杂性和随机性。如果特定于用户的会话 ID 不复杂且随机,则应用程序极易受到基于会话的暴力攻击。
我觉得这方面可以使用JWT或者类似JWT的思想来解决,在后端对得到的敏感Cookie信息进行验签等动作
- 先对网页进行抓包,发送到Repeater方便观察规律
- 发送两次请求
可以看到他们的hijack_cookie不同,中间相差一个4796638040248218963-xxxxx
的Cookie,这也就是系统模拟的他人登录之后获得的Cookie,所以这个63就是我们需要进行劫持的对象。
同时通过观察看到最后几位数字17009253xxxxx
是固定的,但是后面四位数字是随机的。所以我们可以写一个脚本进行爆破就行。即hijack_cookie=4796638040248218963-17009253xxxxx
随机最后五位就行。
- 结果
Insecure Direct Object References
- 第一步按照提示输入账号密码就行。
- 点击按钮然后抓包,发现其实包里返回了userId和role的标识,只是不在前端显示而已,将这两个没显示的写入导下面的框中提交就行。
这让我想到在写登录后端接口的时候对于JAVA的一个user实体,他的passwd字段是要加一个@jsonignore的注解的,不然在序列化的时候会将这个字段给泄露出去。
- 得到具有这种漏洞的威胁之后,就开始猜测后端是如何接收字段的。最后使用
WebGoat/2342384
就可得到相应的返回结果,i.e.http://localhost:8080/WebGoat/2342384
得到这个规律之后点击view profile
,抓包之后进行重放爆破,发现userId=2342388的用户可以访问
- 下一个任务让我们修改别人的权限,并且高权限意味着低的数字,然后把用户的颜色改为红色。没抓包之前盲猜是个POST,抓包看看
通过更改userId可以成功的拿到Buffalo Bill’s profile
之后呢,提示让我们修改方法和路径去修改他的信息。想到常用的四个方法GET
POST
PUT
DELETE
肯定试试PUT
噻。
修改方法,修改Content-Type(好让后端识别噻), 修改payload,注意json格式
成功返回修改信息。
Missing Function Level Access Control
我目前来说理解是函数级别的访问控制,因为一个系统会存在很多的业务函数调用,所以访问控制必须在每一个函数里面执行。同时这种函数级别的访问控制和上面的IDOR(不安全的直接对象引用)不能归为一类,IDOR更像是一种横向的越权,即,这个用户可以访问和他权限相等的用户的信息。
- 第一个就是发现有没有通过前端直接进行隐藏的按钮,F12打开审查元素,用左上角的那个工具一个模块一个模块地搜索发现还真有,然后注释掉他的class就能看到隐藏的几个按钮,提交就行
通过之后给了个提示,所以把url保存一下
但是报错404,但是给了这个路径肯定有用,后面把他试出来了,真正的url应为http://192.168.52.133:8080/WebGoat/access-control/users
但是还是报错500,经典的Spring的内部错误。
这种情况无外乎是内部函数报错或者是我们传的参数不对。考虑到前后端基本都是json格式交互数据,所以改一个报头,content-type: application/json
,之后就正确返回数据了。
把userhash填进去这就过关了。
- 之后他说公司修复了这个漏洞,不仅管理员可以查看用户了,所以我们使用
http://192.168.52.133:8080/access-control/users-admin-fix
这个接口试试。
所以考虑如何提权,看到hint,使用POST方法可以更改权限,就更改我们当前的权限就行。
之后再Get一下,就可以得到信息了
Spoofing an Authentication Cookie
- 登录查看他们的差别
得到这两个:
NGY2ZTY3NTY3NjdhNDU3MDU3NjY2ZTY5NmQ2NDYx
NGY2ZTY3NTY3NjdhNDU3MDU3NjY3NDYxNmY2NzYyNjU3Nw==
很像base64编码,解码看看呢
4f6e6756767a457057666e696d6461
4f6e6756767a4570576674616f67626577
前面是一样的,但是就是后面有点区别,使用十六进制解码再看看
解码得到
发现OngVvzEpWf
是固定的,但是后面的就为username的镜像,所以tom
的spoof_auth=OngVvzEpWfmot
进行文本编码再base64得到:NGY2ZTY3NTY3NjdhNDU3MDU3NjY2ZDZmNzQ=
, 输入到包中进行登录就行
(A2) Cryptographic Failures
这一节基本都是对密码学的一个科普,基本上都学过所以没什么好说的。
- 首先是一个base64编码。
直接用base64解码就行
第二个是一个异或编码,但是要牵扯到密钥我就不知道这个怎么弄了。
Oz4rPj0+LDovPiwsKDAtOw==
我们知道流程就行,就是吧明文的每一位转为二进制,再与密钥的二进制进行异或,得到的结果再base64就好,所以在得知密钥为_
的情况下我们来进行解密
1 | import base64 |
- 第三个就是一个哈希的科普,具体哈希的内容可以看看seed的实验,我博客里也有。
这一节的作业就是使用hash碰撞找到他们的明文:
21232F297A57A5A743894A0E4A801FC3
2BB80D537B1DA3E38BD30361AA855686BDE0EACD7162FEF6A25FE97BF527A25B
看到哈希可以想到并不安全的MD5,网上都有做好的彩虹表,我们直接在线碰撞就行
第四个是一个对于对称加密和非对称加密的科普哈,都学过的,直接pass
第五个是一个签名的东西,首先要生成一个公钥,我们使用openssl进行生成
shell1
openssl pkey -in rsa.pem -pubout
生成的公钥通过:http://tool.chacuo.net/cryptrsakeyparse 去解析里面的模数
之后利用私钥,对这个模数进行签名:
有个BUG就是文中没有提到用的哈希算法是什么所以就用最常用的SHA-256试试,这个也是现在TLS里面用到的哈希算法
- 第六个说到了密钥管理的方面。
启动一个docker:
进入docker里
执行几个命令就行
(A3)Injection
SQL Injection (intro)
第二页
普通的sql语句,很简单
第三页
主要介绍数据操作语言
第四页
数据定义语言
第五页
数据控制语言
第九页
第十页
一个字符型注入,加一个条件就行
第十一页
发现可以拼接,加一个or 1=1的条件
第十二页
看到TAN,可能是字符型注入,试试注释掉后面的并且添加or 1=1,确实可以
拼接我们自己的update语句
1 | 3SL99A' or 1=1; update employees set salary=88888 where first_name='John' and last_name='Smith'; -- |
第十三页
1 | 1';DROP TABLE access_log;-- |
拼接语句 删库跑路
SQL Injection (advanced)
第三页
网页回显了sql语句,直接拼接就行
用union凭借另外一张表,注意字段数量不一样,所以添加1,2,3占位
1 | Dave' or 1=1 union select userid,user_name,password,cookie,'1','2',3 from user_system_data; -- |
但是显示不出来,可能是限制了显示的行宽
那就使用;
拼接SQL语句
1 | Dave' or 1=1; select * from user_system_data;-- |
输入dave的密码即可
第五页
让我们进行sql注入,并且没有提示sql语句,所以只能盲猜了
先猜这个语句,我们只要有值返回就可以登录
1 | select username.password from user where username ='Tom' and password ='passwd'; |
payload为
1 | username = tom |
失败了
还有一个注册页面,抓包注入试试,应该是个注入点
写个脚本跑跑
1 | import requests |
登录吧
SQL Injection (mitigation)
这一节说的是参数化传入的查询参数。让我想到seed实验的一张图
- mybatis如何防止sql注入的?
- 参数化查询工作原理?
第五页
第六页
第九页
前端就把空格给过滤了,用单行注释就行
1 | Dave'/**/or/**/1=1/**/union/**/select/**/userid,user_name,password,cookie,'1','2',3/**/from/**/user_system_data;/**/-- |
第十页
做了空格和and or过滤
使用
1 | Dave'/**/or/**/1=1/**/union/**/select/**/userid,user_name,password,cookie,'1','2',3/**/from/**/user_system_data;/**/-- |
但是发现select和from不见了,然后or还是可以用,但是要大写(一样的)
添加字符然后bypass
1 | Dave'/**/or/**/1=1/**/union/**/selselectect/**/userid,user_name,password,cookie,'1','2',3/**/frfromom/**/user_system_data;/**/-- |
第十二页
找到webgoat-prd的ip地址,通过order by漏洞,然后网页可以通过点击不同的标签来达到排序的效果,然后我们抓包看看传入的参数是什么。
一个get传入column按哪一行排列,试试可以在这个参数上可以做什么
猜测sql语句大概是
1 | select * from servers where xxxx order by ip; |
看看能不能拼接一下两个sql,报错500,看来不行
1 | select * from servers where xxxx order by ip; select ip from servers where hostname='webgoat-prd'; |
通过构造case when能不能找到注入点,可以看到我们的id被正确得到,也就是说1=1这个条件是可用的,所以通过修改这一段,就可以盲注。用前面我们的substr就可以得到想要的内容了
编写以下脚本
1 | import requests,json |
结合得到的信息,就可以拿到ip