赞
踩
本小节简要说明php数据库编程的一些基础概念,旨在更好的理解sql注入漏洞的产生原因和攻击方式;以mysql数据库为例;php自身并无数据库编程的能力,需要安装mysqli或PDO模块,以此来完成数据库编程的功能;这里以mysqli为例;
在php5.0版本之后,php使用面向对象的数据库编程方式;我们常用的sqli-libs靶场用的是过程式的mysqli函数来操作数据库的,两者并无太大区别。
创建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就是连接数据库资源的对象的引用变量
使用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>";
}
上述操作只适用于无返回值的增删改操作
若$con->query($sql)
执行了一个select语句,则会以mysqli_result
类的对象形式返回结果集;
结果集也是一张表;对于结果集的处理有以下四种方式,前三种方法可以看作从结果集中取出一条记录,以数组的形式返回,数组的下标分别对应每个字段,数组的值就是每个字段的值:
fetch_row()
:将普通数字索引数组形式返回结果集的记录,数字下标从0开始,分别对应表中的字段,记录的值就是数组各单元的值
fetch_assoc()
:以关联数组的形式返回结果集中的记录,关联数组的下标就是各字段名称,值与下标一一对应
fetch_array()
:以上面两种形式结合的数组返回,php支持一个数组的下标的由多种形式组成,只要不重复
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"]; // 循环输出结果集中每条记录的信息
}
对于结果集对象和数据库连接对象都要进行资源回收
$result->close(); // 回收结果集资源
$con->close(); // 断开数据库连接
总结:数据库编程的三大步骤
- 建立连接
- 执行sql命令并处理结果集
- 断开连接
本小节主要简单总结前端与后端的sql语句交互,可以简单理解sql注入漏洞的来源,以及如何做防范
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); // 对结果集进行处理,将记录以数字索引和关联两种形式的数组取出 // 之后就可以通过访问数组的方式对记录进行输出
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开源免费,因此是许多网站选择的数据库,并且它内置了好多功能函数,以及几个用来便于DBA管理的元数据库,这些函数和数据库都会成为我们进行sql注入时的兵器
version():输出数据库的版本
使用select <函数>;
来输出,下同
database():输出当前所在数据库
user():输出数据库用户名
currnet_user():输出当前用户名
system_user():输出系统用户名
@@datadir:数据库路径
@@version_compile_os:操作系统的版本
length():返回字符串的长度
substring()、substr()、mid():字符串截取函数
分别都有三个参数
截取的字符串
截取起始位置,从一开始计数
截取长度
left():从左侧开始取指定字符个数的字符串
concat():没有分隔符的字符串拼接函数
concat_ws():含有分隔符的字符串拼接函数
group_concat():连接一个组的字符串,通常用于将同一个字段的数据拼接为同一行输出
将id字段的数据拼接为一行输出
ord():以ascii码返回,同ascii()
hex():将字符串转为16进制
unhex():十六进制解码
md5():返回md5值
floor(x):返回不大于x 的最大整数
round():返回参数x 接近的整数
rand():返回0-1 之间的随机浮点数
sleep(s):睡眠时间为指定的秒数,睡眠期间数据库无法进行任何操作
该数据库同performance_schema(用于性能分析),是mysql自带的数据库
作用:用于存储元数据,关于所有数据库的一切对象几乎都包含在内,如数据库名、数据表名、列名及其类型、权限等
该数据库存储的数据都是所有数据库对象的视图,与原数据无关联
schemata表:存储所有数据库的名称,show tables
就是从该表获取数据的
重要字段:schema_name,即所有数据库名称
tables表:存储所有的表名
重要字段:
columns:存储所有的字段名称
重要字段:
掌握该数据库常用的表及其重要字段,可以在sql注入猜表名、字段名时提供帮助
使用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
使用phpstudy(新手推荐)
从GitHub下载靶场文件:https://github.com/Audi-1/sqli-labs
解压后放入phpstudy的WWW目录下
在小皮面板创建网站,填写域名等信息,并且要创建数据库,php版本一定要选择php5(因为该靶场使用的mysqli是过程式的函数,php5之后的都成了面向对象的mysqli)
可以修改本地hosts,然后就可以在浏览器使用域名访问靶场了
打开靶场文件db-creds.inc
,填写数据库密码,这步一定要正确,否则会建立数据库失败
浏览器进入靶场,如图所示,点击Setup/reset Database for libs初始化数据库
初始化成功后如下图所示,然后就可以开始练习sql注入啦
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。