小迪安全系列笔记---12sql注入基础总结

XDSec—12SQL注入基础总结

一、php数据库编程

本小节简要说明php数据库编程的一些基础概念,旨在更好的理解sql注入漏洞的产生原因和攻击方式;以mysql数据库为例;php自身并无数据库编程的能力,需要安装mysqli或PDO模块,以此来完成数据库编程的功能;这里以mysqli为例;

在php5.0版本之后,php使用面向对象的数据库编程方式;我们常用的sqli-libs靶场用的是过程式的mysqli函数来操作数据库的,两者并无太大区别。

1.1、php数据库编程的三大步骤

1.1.1、连接数据库

创建mysqli这个类的对象。mysqli的构造方法大致如下:

mysqli::__construct(<host>,<username>,<passwd>,<database>,[port]);
// host为mysql的地址
// username和passwd分别为数据库的管理员账户和密码
// database为选择的数据库名称
// port一般默认3306,若自行修改了端口,则要添加该值
// 其中database也可用其他成员方法更换,具体自行了解

用例如下:

$con =new mysqli("localhost","root","root","phpDB");
// 连接localhsot下的phpDB,并将对数据库的引用返回为$con该变量
// $con就是连接数据库资源的对象的引用变量

1.1.2、执行sql命令

使用mysqli类中定义的query()方法,该方法若成功执行sql语句则返回true,反之false

$sql ="insert into users(user_id,user_passwd) values('admin','123456')";
// 定义sql语句
if($con->query($sql))   // 调用query()方法,并传入要执行的sql语句
{
    echo "改变的记录的数量:".$con->affected_rows."<br>";
}

上述操作只适用于无返回值的增删改操作

1.1.3、对于查询操作的处理

$con->query($sql)执行了一个select语句,则会以mysqli_result类的对象形式返回结果集;

结果集也是一张表;对于结果集的处理有以下四种方式,前三种方法可以看作从结果集中取出一条记录,以数组的形式返回,数组的下标分别对应每个字段,数组的值就是每个字段的值:

  1. fetch_row():将普通数字索引数组形式返回结果集的记录,数字下标从0开始,分别对应表中的字段,记录的值就是数组各单元的值

  2. fetch_assoc():以关联数组的形式返回结果集中的记录,关联数组的下标就是各字段名称,值与下标一一对应

  3. fetch_array():以上面两种形式结合的数组返回,php支持一个数组的下标的由多种形式组成,只要不重复

  4. fetch_object():以对象形式返回,对象的成员属性即为结果集的各个字段,调用成员属性即可输出该记录各字段对应的值

    示例如下:

    // 仍使用上述$con的连接
    $sql ="select * from users";
    $result =$con->query($sql);   // 执行了查询语句,返回一个结果集对象
    // 该对象可理解为指向结果集表的一个指针
    
    while($row =$result->fetch_assoc())  // 取出结果集中的记录,以关联数组形式返回
        // 该方法在成功返回一条记录后,会自动移动到下一条记录,全部结束则返回false
    {
        echo $row["user_id"];
        echo $row["user_passwd"];  // 循环输出结果集中每条记录的信息
    }
    

1.1.4、断开连接

对于结果集对象和数据库连接对象都要进行资源回收

$result->close();   // 回收结果集资源
$con->close();   // 断开数据库连接

总结:数据库编程的三大步骤

  1. 建立连接
  2. 执行sql命令并处理结果集
  3. 断开连接

1.2、数据库编程的一般应用

本小节主要简单总结前端与后端的sql语句交互,可以简单理解sql注入漏洞的来源,以及如何做防范

1.2.1、sqli-libs源码分析

Less-1的部分源码,及其简要分析

if(isset($_GET['id'])){ // 该id变量即为通过URL传递的一个变量
$id=$_GET['id'];
// 在前端设计中,该id可以是前端的一个表单域中的控件的name值
// 用户在控件中填写值后,点击submit控件提交,整个表单域的内容就会以键值对的形式传递到action指定的后端文件中
// 如果表单采用get提交,则键值对会通过url传递;post则在请求报文的请求体中出现
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
// 该条sql语句通过用户传递的$id与数据库交互,查询到指定内容
// 分析这里便是sql注入的核心,可以发现如果不对$id进行严格检查,就会使发生sql注入的语句被数据库执行
echo '执行的sql语句为:'.$sql;
echo '<br>';
echo '<br>';
$result=mysql_query($sql);
// 采用过程式的函数传递sql语句,同对象式的成员方法query()
$row = mysql_fetch_array($result);
// 对结果集进行处理,将记录以数字索引和关联两种形式的数组取出
// 之后就可以通过访问数组的方式对记录进行输出

1.2.1、预处理与占位符

php还提供了另一种形式的sql语句交互方式,即通过mysqli_stmt这个类进行预处理,在sql语句中使用占位符?,并将占位符与自定义变量绑定,从而实现sql语句的交互

案例:

$sql ="select stu_num,stu_name from stus where stu_num=?";
// 使用占位符,占位符可以与前端传来的数值绑定,从而实现交互
$stmt =$con->prepare($sql);   // 获取预处理的sql语句对象
$stmt->bind_param("s",$num);   // 为占位符绑定变量并且指定类型为s,因为数据库是强类型的
// i(所有整型)、d(所有浮点值)、s(其他,包括字符串)、b(所有二进制类型)
// 若bind->param("sdsi",$v1,$v2,$v3,$4),即分别向四个变量指定类型
$num ="20220001";  // 给变量赋值
// 这个变量的值可以是前端控件传来的,实现前后端交互,并可对值进行严格性判断,防止sql注入
$stmt->execute();   // 执行预处理的SQL语句
// 此时就实现了交互式的sql语句
$stmt->store_result();// 取出结果集表
$stmt->bind_result($stu_num,$stu_name);   // 这两个变量是为了匹配返回结果集中的字段,不要和绑定占位符的变量混淆

$stmt->fetch();// 取出结果集表中的记录
echo $stu_num."----".$stu_name;

二、针对mysql的注入技巧总结

mysql开源免费,因此是许多网站选择的数据库,并且它内置了好多功能函数,以及几个用来便于DBA管理的元数据库,这些函数和数据库都会成为我们进行sql注入时的兵器

2.1、mysql常用函数

2.1.1、系统信息函数

  1. version():输出数据库的版本

    在这里插入图片描述

    使用select <函数>;来输出,下同

  2. database():输出当前所在数据库

  3. user():输出数据库用户名

  4. currnet_user():输出当前用户名

  5. system_user():输出系统用户名

  6. @@datadir:数据库路径

  7. @@version_compile_os:操作系统的版本

2.1.2、字符串操作函数

  1. length():返回字符串的长度

    在这里插入图片描述

  2. substring()、substr()、mid():字符串截取函数

    分别都有三个参数

    1. 截取的字符串

    2. 截取起始位置,从一开始计数

    3. 截取长度

      在这里插入图片描述

  3. left():从左侧开始取指定字符个数的字符串

  4. concat():没有分隔符的字符串拼接函数

    在这里插入图片描述

  5. concat_ws():含有分隔符的字符串拼接函数

    在这里插入图片描述

  6. group_concat():连接一个组的字符串,通常用于将同一个字段的数据拼接为同一行输出

    group_caoncat

    将id字段的数据拼接为一行输出

2.1.3、编码函数

  1. ord():以ascii码返回,同ascii()

    在这里插入图片描述

  2. hex():将字符串转为16进制

    在这里插入图片描述

  3. unhex():十六进制解码

  4. md5():返回md5值

    在这里插入图片描述

  5. floor(x):返回不大于x 的最大整数

  6. round():返回参数x 接近的整数

  7. rand():返回0-1 之间的随机浮点数

2.1.4、时间函数

  • sleep(s):睡眠时间为指定的秒数,睡眠期间数据库无法进行任何操作

    在这里插入图片描述

2.1.4、其他函数

  1. load_file():读取文件并返回文件内容为一个字符串
  2. if():判断函数
  3. find_in_set():返回字符串在字符串列表中的位置

2.2、information_schema数据库

2.2.1、基本了解

  1. 该数据库同performance_schema(用于性能分析),是mysql自带的数据库

  2. 作用:用于存储元数据,关于所有数据库的一切对象几乎都包含在内,如数据库名、数据表名、列名及其类型、权限等

    该数据库存储的数据都是所有数据库对象的视图,与原数据无关联

2.2.2、常用表及其字段组成

  1. schemata表:存储所有数据库的名称,show tables就是从该表获取数据的

    重要字段:schema_name,即所有数据库名称

  2. tables表:存储所有的表名

    重要字段:

    1. table_name,即所有的表名称
    2. table_schema,即表对应的数据库名称
  3. columns:存储所有的字段名称

    重要字段:

    1. table_schema,即字段名称对应的数据库名称
    2. table_name,即字段所在的表的名称
    3. columns_name,所有字段的名称

掌握该数据库常用的表及其重要字段,可以在sql注入猜表名、字段名时提供帮助

三、搭建sqli-libs靶场

  1. 使用docker容器

    # docker pull acgpiano/sqli-labs
    # docker run -dt --name sqli -p 80:80 -p 13306:3306 --rm acgpiano/sqli-labs
    # docker exec -it sqli /bin/bash
    

    第二句命令是为了把docker的端口映射到主机端口,详细教程请看https://blog.csdn.net/Alashan12/article/details/124027184

  2. 使用phpstudy(新手推荐)

    1. 从GitHub下载靶场文件:https://github.com/Audi-1/sqli-labs

    2. 解压后放入phpstudy的WWW目录下

    在这里插入图片描述

    1. 在小皮面板创建网站,填写域名等信息,并且要创建数据库php版本一定要选择php5(因为该靶场使用的mysqli是过程式的函数,php5之后的都成了面向对象的mysqli)

      在这里插入图片描述

    2. 可以修改本地hosts,然后就可以在浏览器使用域名访问靶场了

    3. 打开靶场文件db-creds.inc,填写数据库密码,这步一定要正确,否则会建立数据库失败

      在这里插入图片描述

    4. 浏览器进入靶场,如图所示,点击Setup/reset Database for libs初始化数据库

      在这里插入图片描述

    5. 初始化成功后如下图所示,然后就可以开始练习sql注入啦

      在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值