基础网页开发和漏洞寻找
前言: 放寒假了,之前一直在准备期末,没什么时间学技术和写博客,最近有空了会写一些。
本篇博客将接着之前的内容介绍利用php搭建网站的一些步骤,从网页开发角度分析一些常用漏洞的产生。
学安全首先要会开发。
1.1操作数据库
php作为一门编程语言,是无法直接与数据库进行交互的,想要进行该操作需要使用php提供的数据库拓展,Php
提供了许多的数据库拓展,比较常见的有mysql拓展,mysqli拓展,下文将介绍mysqli拓展的使用。
想要使用该拓展首先需要在php.ini文件中打开
想要在php中操作数据库,分三个部分,1 连接数据库,2 操作数据库,3 断开连接
<?php
$link = mysqli_connect("localhost", "root", "root");
mysqli_select_db($link, "mysql");
$sql = "select * from help_topic";
$query = mysqli_query($link, $sql);
while ($row = mysqli_fetch_array($query)) {
echo $row['name'];
echo "</br>";
}
mysqli_close($link);
?>
1. mysqli_connect()
函数用于与数据库建立连接,传入的分别是服务器地址(可以是ip地址或者域名),数据库账
号,不光能连接本地的mysql服务器,也可以连接远程的mysql服务器。
数据库密码,数据库名(可省略),操作选项(可省略) 该函数的返回值是一个 MySQLi 连接对象,用于后续的数据库
操作和数据库关闭过程。
**2. **mysqli_select_db()
该函数用于选择数据库,分别传入连接对象和数据库名两个参数。
**3. ** mysqli_query()
该函数用于执行mysql语句,对数据库进行操作,传入的值分别是连接对象和mysql操作语
句,该函数在查询成功后返回一个mysqli对象,查询失败则返回false. 查询完成后,如果想要输出结果,则需要用到
mysqli_fetch_array
,该函数在结果集中取一行作为关联数组,每次执行后向下一行,直到结果集末尾。
数组的索引就是表的栏名,比如id,name,等
4. mysqli_close()
用于关闭连接,传入的值是连接对象。
通过上述的四个的步骤,就完成了一次数据库操作。
如果每次进行数据库操作都要来一遍这四种操作就未免过于麻烦,可以利用数据库配置文件进行简化
即,将连接数据库的语句单独放在另一个创建的config.php中,然后再在原文件中包含config.php即可
由于数据库配置文件中往往包含数据库的账号和密码,所以可以在此方向进行攻击
如果我们要根据条件选择不同的内容,可以这样做
<?php
include("config.php");
$sql = "select * from help_topic where help_topic_id= '" . $_GET['id'] . "'limit 1;";
$query = mysqli_query($link, $sql);
while ($row = mysqli_fetch_array($query)) {
echo $row['name'];
echo "</br>";
}
mysqli_close($link);
?>
通过get传参然后进行查询,有没有觉得很眼熟,没错,这就构成了最基础的sql注入。
在过去,无论是关于sql注入还是前文的操作,只用了Mysql中的select操作,我们对数据库还存在其他的操作,以
后再继续补充。
1.2 文件上传的实现
之前学习过文件上传漏洞,今天从开发角度分析一下该漏洞的产生。
之前再前端部分我们学习过文件的上传,但上传后怎么办没有提及,例如
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>upload</title>
</head>
<body>
<form action="" method="get">
<input type="file" name="myfile" />
<input type="submit" name="myfile" />
</form>
</form>
</body>
</html>
这就是一个简单的表单提交,先回顾一下以前的内容,通过action属性设置提交目标,可以是本地文件也可以是远
程服务器上的文件,如果想要提交给当前文件的php部分,只需要提交地址留空即可,method指明提交方法
下方input标签的name属性用于区分不同的数据,使用对应提交方式的变量以name为键可以获得其提交的值.
如果我们想要获取文件的其他信息,则需要使用$_FILES
超级全局变量了,使用方法为
$_FILES["传入数据的name值"]["需要用到的键"]
其中常用的键如下
1 name 获取上传文件的原始名称
2 type 获得上传文件的MIME类型
3 tmp_name 上传文件在服务器上的临时路径 比如我们上传一个a.txt,输出该键下的值,有
C:\Windows\php16DE.tmp,可以看到之前的文件是以临时文件形式存储的
4 error 上传文件时的错位代码
5 size 上传文件的大小(以字节为单位)
注意,上传后我们看到的并不是原始的文件,而是进行编码过的临时文件。
文件上传到临时文件夹后,我们需要将其移动到对应的文件夹,此时需要使用move_uploaded_file
函数,需要
注意的是,此函数只能用于移动上传的临时文件,因为只有这种情况下php会对上传的文件进行临时存储。
用法如下
move_uploaded_file("临时文件地址","移动后的地址");
注意,这个地址要包含文件本身,可以使用相对地址也可以使用绝对地址,移动之后的文件就成了上传前的文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>upload</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" />
</form>
<?php
$tmp = $_FILES["myfile"]["tmp_name"];
$nam = $_FILES["myfile"]["name"];
move_uploaded_file($tmp, './' . $nam);
?>
</body>
</html>
具体操作如上,multipart/form-data 。 指定传输数据为二进制类型传输。 最后的目标地址我们可以不使用上传
的原文件的名,自己更改地址给个新名也是可以的,这时
候在看目标文件夹,就发现之前上传的文件已经出现了,而且并不是tmp文件格式,此时说明上传成功。如果不加
护,是不是绝对也很熟悉,没错,这就又构成了文件上传漏洞。
想要实现文件上传,我们不光可以像这样手写功能实现,还可以使用编辑器,即我们在使用论坛或者博客网站时进
行评论那个文本栏,想要使用编辑器需要在服务器端下载编辑器并进行配置,常见的编辑器有ueditor等,当我们
使用网上的编辑器时,验证环节就完全交给编辑器负责了,这时候寻找文件上传漏洞就需要去寻找编辑器漏洞了,
同理,如果此时使用框架进行实现,则也需要去寻找框架的漏洞。
1.3 文件下载的实现
下载方式分为直连下载和传参下载,直连下载指直接访问对应文件的地址进行下载,传参下载指通过传入查询字符
串,然后在后台进行处理下载。
首先我们看一下直连下载。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<?php
function down()
{
$filepath = getcwd();
$filename = scandir($filepath . '\dow');
foreach ($filename as $value) {
if ($value != "." && $value != "..") {
echo $value . "</br>";
}
}
}
down();
?>
<form action="" method="post">
<input type="text" name="fname">
<input type="submit">
</form>
<?php
if ($_POST["fname"]) {
$url = "http://" . $_SERVER['HTTP_HOST'] . "/file/dow/" . $_POST["fname"];
header("location:$url");
}
?>
</body>
</html>
getcwd()
函数为获取当前文件地址,注意,在windows操作系统下,绝对地址用的是\
,但也可以识别/
在linux
或者html下,地址只能使用/
scandir()
的作用是获取指定目录下文件名称,并将其存储在数组中返回。
接下来我们来看传参下载,这种下载方式的实现是通过header函数,通过构造对客户机发送的响应报文来实现对
文件的下载
<?php
if ($_POST["fname"]) {
$filesiz = filesize("./dow/" . $_POST["fname"]);
$type = filetype($_POST['fname']);
header("Disposition;filename = " . $_POST["fname"]);
header("Accept-ranges:bytes");
header("Accept-length: " . $filesiz);
readfile("./dow/" . $_POST["fname"]);
}
?>
就是模拟了http响应报文,但是需要注意的是要将显示和下载分开,该方法就是将文件放在相应体中传回去,所以
本页面的内容也会包含进去,所以要分开。
1.4 文件及文件夹删除。
if ($_POST["fname"]) {
function delfile($name)
{
$file = "./dow/" . $name;
unlink($file);
}
function delfiledir($name)
{
$file = "./dow/" . $name;
rmdir($file);
}
}
实现文件夹删除功能非常的简单,只需要删除文件使用unlink函数,删除文件夹使用rmdir函数即可
1.5 文件读取与文件写入
首先我们来看读入
<?php
if ($_POST["fname"]) {
function fileread()
{
$filename = "./dow/" . $_POST['fname'];
$filesiz = filesize($filename);
$file = fopen($filename, "r") or die("无法打开");
echo fread($file, $filesiz);
fclose($file);
}
}
fileread();
?>
在php中fope()函数用于打开一个文件或url,并返回一个文件资源句柄,该函数接受两个参数,第一个是文件路
径,第二个是模式,fopen函数有以下几个模式:
1 r 以只读方式打开文件,文件必须存在,否则会打开失败。
2 w 以写入方式打开文件,如果文件不存在,则创建一个新文件,如果文件存在。则将原文件内容清除
3 a 以追加方式打开文件,如果文件不存在,则创建一个新文件,如果文件存在,则在文件末尾追加数据。
4 x 以独占方式打开文件进行写入,如果文件不存在,则会创建一个新文件,如果文件存在,则会打开失败。
5 r+ 以读写方式打开文件,文件必须存在,否则会打开失败,写入时是在文件头部继续进行。
6 w+ 以读写方式打开文件。如果文件不存在,则创建一个新文件,如果文件存在,则将其截断为零长度。
7 a+ 以读写方式打开文件进行追加,如果文件不存在,则创建一个新文件,如果文件存在,则在文件的末尾追加
数据
我们需要注意的是,通过此方式直接读取的html代码和js代码会被执行,php代码则会触发浏览器的容错机制,从
而被注释,这也就是之前我们在命令执行漏洞时使用tac而不是使用cat的原因。
关于写入
<?php
if ($_POST["fname"]) {
function filewrite()
{
$filename = "./dow/" . $_POST['fname'];
$file = fopen($filename, "a+") or die("无法打开");
fwrite($file, $_POST["txt"]);
fclose($file);
}
filewrite();
}
?>
1.6 搜索框功能的实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>搜索功能</title>
</head>
<body>
<form action="" method="post">
<label for="sea">搜索框</label>
<input type="search" name="sea" />
<input type="submit">
</form>
<?php
include("../config.php");
$name = $_POST["sea"];
$sql = "select * from fir where content like '%$name%';";
$quer = mysqli_query($link, $sql);
while ($row = mysqli_fetch_array($quer)) {
echo $row["id"] . "</br>";
echo $row["content"] . "</br>";
}
mysqli_close($link);
?>
</body>
</html>
搜索框可能存在sql注入漏洞和xss漏洞
1.7 留言板功能
实现留言板功能需要我们对数据库进行查询和修改,查询之前我们已经学习过了现在来学习一下inset操
作
insert into tablename (colunm1,column2 ....) value (value1,value2 ....);
学会了insert
就可以实现该功能了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="" method="post">
<label for="1">id:</label>
<input type="text" name="id" id="1">
</br>
<label for="2">内容</label>
<input type="text" name="content" id="2">
</br>
<input type="submit">
</form>
<?php
$link = mysqli_connect("localhost", "root", "root");
mysqli_select_db($link, "test");
$id = $_POST["id"];
$content = $_POST["content"];
$sql1 = "insert into con (id,content) value('$id','$content')";
mysqli_query($link, $sql1);
$sql2 = "select * from con";
$query = mysqli_query($link, $sql2);
while ($row = mysqli_fetch_array($query)) {
echo $row['id'] . "</br>";
echo $row['content'];
echo "</br>";
}
mysqli_close($link);
?>
</body>
</html>
1.8 获取用户信息功能
我们现在在访问网页时,时常会看见自己的地址显示以及一些信息,那么该功能是怎么实现的呢?这
时‘候就需要我们使用$_SERVER
超级全局变量了
$_SERVER["REMOTE_ADDR"]
//获取客户IP地址
$_SERVER["REMOTE_PORT"]
//获取客户访问的端口号
$_SERVER["SERVER_ADDR"]
//获取服务器地址
$_SERVER["SERVER_PORT"]
获取服务器端口
$_SERVER["QUERY_STRING"]
获取第一个?后所有内容
$_SERVER["REQUEST_METHOD"]
获取get或post方法
$_SERVER["DOCUMENT_ROOT"]
获取网站根目录
$_SERVER["REQUEST_URI"]
获取当前正在访问的网址
__DIR__
是获取当前访问地址所在磁盘目录名称
$_SERVER['HTTP_USER_AGENT'];
获取用户ua头
利用此变量可以防范CSRF漏洞
1.9 服务器端的cookie和session验证以及登录功能的实现
很多网页的内容要根据不同的用户显示不同的内容,此时需要用户进行登录操作,但每个页面都进行登
录未免不是很显示,所以我们使用cookie或者session来解决这个问题
cookie:身份验证,存储到客户端浏览器中
session:身份验证,存储到服务器内
很明显,存储在客户端的cookie相较而言更容易被泄露,设计cookie的问题由cookie修改,伪造,盗取
session相对来说要安全不少,设计session的安全问题一般是session劫持问题。举个例子
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录</title>
</head>
<body>
<form action="" method="post">
<label for="1">用户名:</label>
<input type="text" id="1" name="username">
</br>
<label for="2">密码:</label>
<input type="password" id="2" name="password">
</br>
<input type="submit">
</form>
<?php
include("config.php");
$username = $_POST["username"];
$password = $_POST["password"];
$sql = "select * from usr where username='$username' and password='$password';";
$que = mysqli_query($link, $sql);
if ($username) {
if (mysqli_num_rows($que)) {
echo "登录成功";
setcookie("user", $username);
header("location: admin.php");
} else
echo "登录失败";
}
?>
</body>
</html>
我们利用setcookie函数来设置cookie,在后台页面通过cookie来判断登录状态
<?php
$user = $_COOKIE["user"];
if (!$user)
header("location:login.php");
当用户首次访问某个Web应用程序时,服务器会在响应中发送一个cookie给客户端浏览器。这个cookie包
含了一个由服务器生成的唯一的标识符,称为session ID。客户端浏览器会将这个cookie保存起来。
当用户再次访问该Web应用程序时,浏览器会自动将存储的cookie发送回服务器。服务器接收到请求和附
带的cookie后,会检查session ID是否存在。如果存在,服务器就知道该请求来自已登录的用户,并根据
该session ID检索用户的会话数据。这样,服务器就可以根据用户的身份提供个性化的内容或执行其他与
身份验证相关的操作
我们只需要每个页面包含一个cookie验证代码即可实现自动判断,cookie是存储在客户端的浏览器中的,
所以如果我们有管理员的cookie,就可以干很多东西了。
我们再看一下基于session的判断。
<?php
include("config.php");
$username = $_POST["username"];
$password = $_POST["password"];
$sql = "select * from usr where username='$username' and password='$password';";
$que = mysqli_query($link, $sql);
if ($username) {
while ($row = mysqli_fetch_array($que)) {
$_SESSION["user"] = $row["username"];
header("location: admin.php");
}
}
?>
每次在进行session操作前,首先要开启session ,需要加上session_star()
如果不想这样,可以开启
session 自启动。在对应版本的php.ini文件中配置然后重启php服务器即可。
Session验证的原理是,当用户登录成功后,服务器会为该用户创建一个唯一的Session ID,并将该
Session ID与用户的登录状态等相关信息保存在服务器端。服务器通过在响应中设置一个名为“Set-
Cookie”的HTTP头部字段,将Session ID发送给客户端浏览器。客户端浏览器在接收到Session ID后,会
将其保存在Cookie中。当客户端再次向服务器发送请求时,会自动将保存的Session ID通过Cookie发送给
服务器端。服务器端会根据接收到的Session ID查找对应的Session信息,以判断该用户的登录状态。通过
这种方式,服务器可以在客户端访问时验证用户的身份,保持用户的登录状态,并提供个性化的服务。
2.0 利用ajax实现登录操作
我们不仅可以利用php实现登录,也可以使用ajax在前端进行登录操作
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS</title>
</head>
<body>
<label for="1">账号</label>
<input type="text"class="user">
<label for="2">密码</label>
<input type="password"class="pass">
<button>提交</button>
<script src="../jquery-3.7.1.min.js"> </script>
<script>
$('button').click(function () {
$.ajax({
type: 'post',
url: 'ajax.php',
dataType: 'json',
data: {
myusernam: $('.user').val(),
myupass: $('.pass').val()
},
success: function (res) {
if (res.infocode == 1) {
alert("登录成功");
}
else
alert("登录失败");
}
})
})
</script>
</body>
</html>
对于ajax.php
<?php
$username = $_POST["myusernam"];
$password = $_POST["myupass"];
$success = array("msg" => "ok");
if (1) {
$success["infocode"] = 1;
} else {
$success["infocode"] = 0;
}
echo json_encode($success);
用于判断登录,实际使用过程中1要换成数据库查询语句。
我们要树立起前后端分离的思想,第一个html文件是在客户端执行的,第二个php文件是在服务器端执行
的,echo的内容作为服务器响应结果传递给ajax中的res,因此会得到对于的值
第一个代码中success
是一个回调函数,用于处理服务器响应。当AJAX请求成功完成时,这个回调函数会
被调用。
具体来说,当用户点击提交按钮时,会触发一个AJAX POST请求到'ajax.php'。这个请求中包含了从输入框
中获取的用户名和密码。当服务器响应返回时,success
回调函数会被执行。
在success
回调函数中,代码检查服务器返回的数据中的infocode
属性。如果infocode
的值为1,则显
示一个提示框告诉用户"登录成功"。如果infocode
的值不是1,则显示一个提示框告诉用户"登录失败"。
简单来说,success
回调函数是用来处理和响应服务器返回的数据的。在这个例子中,它用于处理登录操
作的结果。
我们在提交数据过程中使用到了dataType 在此我对其进行解释: 其用来指定请求返回的数据类型,在请求报
文中放在ACCEPT字段中,需要与contentType 进行区分,contentType用于表明发送的数据类型。
2.1 商店购买页面实现
2.1.1 以前端设计价格为准,数据接受价格后运算
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商店</title>
</head>
<body>
<img src="https://wx3.sinaimg.cn/mw690/905502ccgy1hmhpnwickzj20u0140n7g.jpg" width="270" height="270">
<div>价格 100</div>
<label for="1">数量</label>
<input id="1" class="number">
</br>
<button>购买</button>
<script src="../jquery-3.7.1.min.js"> </script>
<script>
$('button').click(function () {
$.ajax({
type: 'post',
url: 'shop.php',
dataType: 'json',
data: {
price: 100,
number: $('.number').val()
},
success: function (res) {
if (res.infocode == 1) {
alert("购买成功");
}
else
alert("购买失败");
}
})
})
</script>
</body>
</html>
至于shop.php
<?php
$price = $_POST["price"];
$number = $_POST["number"];
$success = array("msg" => "ok");
$money = 1000; //获取的账户总金钱
if ($price * $number <= $money) {
$success["infocode"] = 1;
//对账户金钱进行操作。
} else {
$success["infocode"] = 0;
//购买失败
}
echo json_encode($success);
和我们之前写的代码差不多,这种价格是在前端设定的,所以给了我们更改的机会,其次,对输入的数据不
加判断也构成了标准的购买逻辑,如果我们输入个负数就会加钱
2.1.2 在前端以数据库价格为基准
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商店</title>
</head>
<body>
<?php
//我们此时获取的id是通过查询字符串获取的,取决于客户点击的页面
include("config.php");
$sql = "select * from pri where id=1;";
$pri = mysqli_query($link, $sql);
while ($row = mysqli_fetch_array($pri)) {
$price = $row["price"];
$src = $row["src"];
echo "<img src='$src' width=270 height=270>" . "</br>";
echo "价格:" . $price . "</br>";
}
?>
<label for="1">数量</label>
<input id="1" class="number">
</br>
<button>购买</button>
<script src="../jquery-3.7.1.min.js"> </script>
<script>
$('button').click(function() {
$.ajax({
type: 'post',
url: 'shop.php',
dataType: 'json',
data: {
price: <?php echo $price; ?>,
number: $('.number').val()
},
success: function(res) {
if (res.infocode == 1) {
alert("购买成功");
} else
alert("购买失败");
}
})
})
</script>
</body>
</html>
只不过是通过数据库获取了数据然后传到后端,但实际上还是可以抓包修改,没有什么卵用。
通过上述的几个实际例子,我们发现在前端发送价格或者判断是否购买成功是不可行的,实际中要把一系列
操作都放在后端去,真正做到前后端分离。
除了上述问题,还存在后端返回状态码在前端验证的问题,想要验证成功我们直接抓包改判断码,也算是比
较严重的漏洞。
2.2 php框架的基础使用
首先我们得先明白什么是框架:软件框架通常指的是一组模块化组件,这些组件遵循特定的接口和协议,以
实现某种业界标准或完成特定基本任务的软件组件规范。它不仅提供了规范所需的基础功能,而且还可以通
过扩展机制支持未来的需求变化。软件框架可能包含一系列库、工具和模板,旨在为开发人员提供一个快速
构建应用程序的途径。
也就是我们之前实现的一些功能就不用自己写了,直接用框架里写好的接口即可。
我们以thinkphp 5.0为例子
首先我们在官方网站下载thinkphp5框架,以public文件夹作为网站的根目录。
先了解一下thinkphp的url访问规则:
http://serverName/index.php(或者其它应用入口文件)/模块/控制器/操作/[参数名/参数值...]
比如我们将方法写在thinkphp/application/index/controller/Test.php
下
Test.php的内容如下
<?php
namespace app\index\controller;
use think\Controller;
class Test extends Controller
{
public function ec()
{
echo 123;
}
}
注意设置命名空间和引入控制器类
我们想要访问该ec方法时需要使用的url为:http://tp.com/index.php/index/Test/ec
也可为http://tp.com/index.php?s=index/Test/ec
注意: 文件名首字母得大写而且类名得和文件名保持一致。
我们遇到 页面错误! 请稍后再试 的报错时
在config.php文件下将 show_error_msg=false 改为true即可
由于thinkphp 5.0比较老,所以使用了getclass方法,但php8.0向上丢弃了该方法,所以需要更换版本或者
更改配置文件
2.3 thinkphp传递参数
如果想要传递参数,也有多种写法
比如http://tp.com/index.php?s=index/Test/ec&x=1
或者http://tp.com/index.php/index/Test/ec?x=1
我们在程序中除了典型的get,post,request超级全局变量获取内容,还可以使用input来获取传递的内容
在thinkphp中,使用方式如下
input('?get.id')
或者input('?post.name')
这两种是thinkphp的官方获取数据的写法,可以过滤掉很多的sql注入。
由于使用了thinkphp,导致了这与常规情况下php中input函数的使用不同,需要注意
当我们使用http://tp.com/index.php/index/Test/ec/x/1
的方式来传递参数时,
此时即不是通过get方式传递也不是通过post方式传递参数,所以获取传递参数时要这样写
input("x")s
对于官方写法对sql注入的过滤,我们进行进一步解释
$id =$_GET["x"];
$sql = "select * from pri where id=$id;";
对于这种写法,我们使用万能密码 qwewq of 1=1;
直接就可以获得表中的所有信息,但我们如果使用以下方法
$id = input("?get.x");
$sql = "select * from pri where id=$id;";
万能密码部分就会被过滤掉。
2.4 thinkphp 数据库操作
thinkphp有其提供的一套数据库操作方式,想要使用首先要配置thinkphp的config.php文件
配置好后我们在使用过程中就不需要连接数据库了,直接进行操作即可
首先我们来看查询的方式
我们可以这样查询
Db::query('select * from think_user where id=?',[8]);
具体使用如下
<?php
namespace app\index\controller;
use think\Db;
use think\Controller;
class Test extends Controller
{
public function ec()
{
$userId = 2;
$result = Db::query('select * from pri where id=?', [$userId]);
if ($result) {
foreach ($result as $row) {
echo $row['id'] . '<br>';
}
}
}
}
使用时需要引入Db类
返回的值是一个关联数组,即一个数组中套了另一个数组,这个关联数组存储了查询的所有信息,第一种方
式是原生的数据库查询方式,我们再来看另一种方式。
Db::table('think_user')->where('id',1)->find();
等价于
select * from think_user
<?php
namespace app\index\controller;
use think\Db;
use think\Controller;
class Test extends Controller
{
public function ec()
{
$userId = $_GET["x"];
$result = Db::table('pri')->where('id', $userId)->select();
if ($result) {
foreach ($result as $row) {
echo $row['id'] . '<br>';
}
}
}
}
使用find()是查询第一个数据,使用select()是查询数据集,上述这
我们需要注意的是,thinkphp中官方写法是第二中,在框架中进行sql注入过滤的写法也是第二种。
我们在实际进行渗透测试时,想要判断对方是否是thinkphp搭建的服务器,如果是白盒就直接看thinkphp文
件夹下的base.php文件。
如果是黑盒,就通过网络空间引擎,或者通过报错,返回数据包,url地址对其进行判断。
或者我们可以下载wappalyzer对其进行判断。