网安导实验四

网安导实验四:“Web 安全”讲义

默认已经学会了网络基础、HTML、CSS、JavaScript。

HTTP

HTTP(Hypertext Transfer Protocol)是一种用于传输超文本的应用层协议。HTTP 是 Web 的基础,用于在 Web 浏览器和 Web 服务器之间传输数据。HTTP 是无状态的,即每个请求都是独立的,服务器不会保存任何关于客户端的信息。HTTP 使用 TCP 协议作为传输层协议,端口号为 80。

HTTP 协议内容主要包括请求报文和响应报文。请求报文由请求行、请求头和请求体组成,用于向服务器发送请求。响应报文由状态行、响应头和响应体组成,用于向客户端发送响应。

HTTP 请求方法有多种,如 GET、POST、PUT、DELETE 等。GET 方法用于请求数据,POST 方法用于提交数据,PUT 方法用于更新数据,DELETE 方法用于删除数据。

HTTP 状态码用于表示请求的处理结果,如 200 OK(请求成功)、404 Not Found(请求的资源不存在)、500 Internal Server Error(服务器内部错误)等。

HTTP 头部用于传输请求和响应的元数据,如 Content-Type(内容类型)、Content-Length(内容长度)、User-Agent(用户代理)等。

HTTP Cookie 用于在客户端存储会话信息,如用户 ID、用户名、购物车信息等。Cookie 由服务器发送给客户端,客户端在后续请求中携带 Cookie,服务器根据 Cookie 识别用户。

HTTP 缓存用于缓存 Web 页面,减少网络传输时间。HTTP 缓存分为强缓存和协商缓存,强缓存通过 Cache-ControlExpires 头部控制,协商缓存通过 Last-ModifiedETag 头部控制。

URL 和 URI

URL(Uniform Resource Locator,统一资源定位符)是 URI(统一资源标识符)的一种,用于标识 Web 资源的位置。URL 是互联网上资源的地址,通过 URL 可以访问特定的资源。

一个完整的 URL 由以下几部分组成:

  1. 方案(Scheme):指定访问资源所使用的协议,例如 http、https、ftp 等。
  2. 主机(Host):指定资源所在的服务器的域名或 IP 地址。
  3. 端口(Port):指定访问资源所使用的端口号(可选)。
  4. 路径(Path):指定资源在服务器上的具体位置。
  5. 查询字符串(Query):提供额外的参数,用于传递给服务器(可选)。
  6. 片段标识符(Fragment):指定资源中的某个部分(可选)。

例如:

1
2
3
Scheme :// hostname[:port] / path / [;parameters][?query]#fragment

http://www.example.com/path/to/resource;param1=value1;param2=value2?query1=value1&query2=value2#fragment

param 一般不用,或者用也是用 .htaccess 重写,一般不考虑。

URI 则是身份标识符,用于标识资源的位置。URI 包括 URL 和 URN(统一资源名称)两种。URL 用于定位资源,URN 用于命名资源(了解即可)。

PHP 介绍

PHP(Hypertext Preprocessor)是一种广泛使用的开源服务器端脚本语言,尤其适用于Web开发。它最初由Rasmus Lerdorf于1994年创建,旨在简化网页开发过程。PHP可以嵌入到HTML中,并与多种数据库集成,最常用的是MySQL。其灵活性、易学性和强大的社区支持使得PHP成为开发动态网页和Web应用程序的首选语言之一。PHP代码在服务器上执行,生成的HTML发送到客户端,从而实现网页的动态交互。它广泛应用于各种Web开发项目,包括内容管理系统、电子商务平台和社交媒体网站。

人们常说:

PHP 是世界上最好的语言。

最早出现在2001年7月的PHP文档中:"PHP is the best language for web programming, but what about other languages?"

随后变成了PHP的标志性语句,被广泛传播。

php是最好的语言

PHP特别适合于 Web 开发,并且可以嵌入到 HTML 中。PHP 语法借鉴了 C、Java 和 Perl,易于学习和使用。

PHP 简介

PHP 是一种服务器端脚本语言,主要用于开发动态和交互性强的 Web 应用。PHP 可以与多种数据库系统(如 MySQL、PostgreSQL)集成,并且支持多种协议(如 HTTP、HTTPS、FTP)。

安装 PHP

在开始使用 PHP 之前,需要先安装 PHP 解释器。以下是安装 PHP 的步骤:

我们使用 Apache2 + PHP 的组合搭建本地环境。可选的还有 Nginx + PHP、Lighttpd + PHP 等。

Apache2 是一个开源的 Web 服务器,用于在本地搭建 Web 开发环境。PHP 是一种服务器端脚本语言,用于处理 Web 请求和生成动态内容。

安装 Apache2

1
2
3
4
sudo apt update # 更新软件包列表
sudo apt install apache2 # 安装 Apache2
sudo systemctl start apache2 # 启动 Apache2
sudo systemctl enable apache2 # 设置 Apache2 开机自启

安装 PHP

1
2
sudo apt install php libapache2-mod-php php-mysql php-cli php-curl php-gd php-mbstring php-xml php-zip # 安装 PHP 和相关扩展
sudo systemctl restart apache2 # 重启 Apache2

完成后,在浏览器中访问 http://localhost,如果看到 Apache2 的默认页面,则说明安装成功。

/var/www/html 目录下创建一个 PHP 文件,如 index.php,并输入以下内容:

1
2
3
<?php
phpinfo();
?>

然后在浏览器中访问 http://localhost/index.php,如果看到 PHP 的信息页面,则说明 PHP 安装成功。

.htaccess 文件

.htaccess 是 Apache2 的配置文件,用于配置网站的访问权限、重定向、错误处理等。我们可以通过修改 .htaccess 文件来配置 Apache2 的行为。

例如,我们可以通过 .htaccess 文件禁止目录列表、重定向 URL、设置错误页面等。

例如,我们可以禁止对 index.php 文件的访问:

1
2
3
4
<Files "index.php">
Order Allow,Deny
Deny from all
</Files>

配置 Apache2

Apache2 的配置文件位于 /etc/apache2 目录下,主要包括 apache2.confports.confsites-availablesites-enabled 等文件。

  • apache2.conf:Apache2 的主配置文件。
  • ports.conf:端口配置文件。
  • sites-available:站点配置文件目录。
  • sites-enabled:启用的站点配置文件目录。

我们可以通过修改配置文件来配置 Apache2 的虚拟主机、目录、模块等。

配置虚拟主机(不重要)

虚拟主机是 Apache2 的一个重要功能,用于在同一台服务器上托管多个网站。每个虚拟主机都有自己的域名、目录和配置。

我们可以通过配置虚拟主机来实现多个网站的托管,提高服务器的利用率。

同一主机解析不同链接的教程较多,本处我们只写怎么让不同端口对应不同虚拟主机。

配置多端口虚拟主机:

我们这里搞个例子,让 3000 端口和 3001 端口指向不同的目录。

首先,我们需要在 /etc/apache2/sites-available 目录下创建两个配置文件,如 site1.confsite2.conf

1
2
sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/site1.conf
sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/site2.conf

然后,我们需要编辑这两个配置文件,分别配置虚拟主机的域名、目录和日志。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# site1.conf
<VirtualHost *:3000>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/site1
ErrorLog ${APACHE_LOG_DIR}/site1-error.log
CustomLog ${APACHE_LOG_DIR}/site1-access.log combined
</VirtualHost>

# site2.conf
<VirtualHost *:3001>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/site2
ErrorLog ${APACHE_LOG_DIR}/site2-error.log
CustomLog ${APACHE_LOG_DIR}/site2-access.log combined
</VirtualHost>

接着,我们需要启用这两个虚拟主机,并重启 Apache2 服务。

1
2
3
sudo a2ensite site1.conf
sudo a2ensite site2.conf
sudo systemctl restart apache2

最后,我们需要在 /var/www 目录下创建 site1site2 目录,并在这两个目录下创建一个 index.html 文件。

1
2
3
4
sudo mkdir /var/www/site1
sudo mkdir /var/www/site2
sudo echo "Site 1" > /var/www/site1/index.html
sudo echo "Site 2" > /var/www/site2/index.html

完成后,在浏览器中访问 http://localhost:3000http://localhost:3001,分别看到 Site 1Site 2 的内容,则说明虚拟主机配置成功。

在 Windows 上安装 PHP 有多种方法,如使用 XAMPP、WampServer、EasyPHP 等。这些工具集成了 Apache、MySQL 和 PHP,可以一键安装。

我们这里只介绍手动安装 PHP 的方法:

  1. 下载 PHP 安装包:https://windows.php.net/download/
  2. 解压安装包到指定目录
  3. 配置环境变量

在 macOS 中安装 PHP 非常简单,只需要使用 Homebrew 即可:

1
brew install php

PHP 基础语法

PHP 标记

我们先得知道 HTML 是怎么传给用户并显示的。

  1. 用户输入 URL,浏览器向服务器发送请求。
  2. 服务器接收请求,解析 URL,返回对应的 HTML 文件。
  3. 浏览器接收 HTML 文件,解析 HTML 文件,显示页面。

而 PHP 是在服务器上执行的,所以我们可以在 HTML 文件中嵌入 PHP 代码,然后由服务器解析 PHP 代码,生成 HTML 文件,最后返回给浏览器。

PHP 脚本可以放在文档中的任何位置,但是 PHP 脚本会在服务器上解析之后再发送到浏览器。PHP 脚本以 <?php 开始,以 ?> 结束。

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
<title>PHP 示例</title>
</head>
<body>
<h1><?php echo "Hello, World!"; ?></h1>
</body>
</html>

PHP 文件的默认文件扩展名是 .php

在同一个文件中,多个 PHP 代码块将共享相同的作用域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
<title>PHP 示例</title>
</head>
<body>
<?php
// 第一个 PHP 代码块
$greeting = "Hello, World!";
?>

<h1><?php echo $greeting; ?></h1>

<?php
// 第二个 PHP 代码块
$greeting = "Hello, PHP!";
?>

<h2><?php echo $greeting; ?></h2>
</body>
</html>

变量和数据类型

PHP 是一种解释型语言,因此,它写起来和我们熟悉的 JavaScript 很像。

PHP 中的变量以 $ 符号开头,后跟变量名。变量名区分大小写。PHP 支持多种数据类型,包括字符串、整数、浮点数、布尔值、数组和对象。

请不要忘记变量名以 _ 开头也是合法的。否则会有不幸是事情发生。

PHP 中的变量不需要显式声明数据类型,PHP 会根据变量的值自动确定数据类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$array = array(1, 2, 3);
$string = implode(", ", $array); // 数组转换为字符串
echo $string; // 输出: 1, 2, 3

$array = explode(", ", $string); // 字符串转换为数组
print_r($array); // 输出: Array ( [0] => 1 [1] => 2 [2] => 3 )
?>
<?php
$true = true;
$false = false;

echo $true; // 输出: 1
echo $false; // 输出: (空)

$sum = $true + 10; // 布尔值自动转换为数字
echo $sum; // 输出: 11
?>

控制结构

PHP 支持多种控制结构,如条件语句(if...else)、循环语句(forwhile)、跳转语句(breakcontinue)等。

函数

PHP 内置了大量的函数,如字符串处理函数、数组处理函数、日期处理函数等。此外,PHP 还支持用户自定义函数。

常见函数有:

  1. 字符串处理函数:strlen()subpos()str_replace() 等。
  2. 数组处理函数:count()(统计元素数)、array_push()(向数组末尾添加元素)、array_merge()in_array(检查数组中是否存在某个值) 等。
  3. 日期处理函数:date()time()strtotime() 等。
  4. 文件处理函数:file_get_contents()file_put_contents()fopen()fclose() 等。
  5. 数据库处理函数:mysqli_connect()mysqli_query()mysqli_fetch_array() 等。
  6. 错误处理函数:die()trigger_error()set_error_handler() 等。
  7. 其他函数:var_dump()(打印变量的类型和值)、phpinfo()(显示 PHP 信息)、header()(发送原始 HTTP 头)、isset()(检查变量是否已设置)、empty()(检查变量是否为空)、unset()(销毁变量)等。

此外,作为基础内容,我们还需要了解正则表达式。

表单处理

PHP 可以处理表单数据,包括获取表单数据、验证表单数据、过滤表单数据等。我们可以使用 $_GET$_POST$_REQUEST 全局数组来获取表单数据。

我们先介绍这三个全局数组:

$_GET

$_GET 是一个全局关联数组,包含 URL 参数的键值对。$_GET 变量用于收集表单数据,通过 URL 参数传递给页面。

get.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html>
<head>
<title>GET 示例</title>
<script>
function submitForm(event) {
event.preventDefault(); // 阻止表单默认提交行为

var xhr = new XMLHttpRequest();
var name = document.getElementById("name").value;
var age = document.getElementById("age").value;
var url = "process_get.php?name=" + encodeURIComponent(name) + "&age=" + encodeURIComponent(age);

xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById("result").innerHTML = xhr.responseText;
}
};
xhr.send();
}
</script>
</head>
<body>
<form onsubmit="submitForm(event)">
Name: <input type="text" id="name" name="name">
Age: <input type="text" id="age" name="age">
<input type="submit" value="Submit">
</form>

<div id="result"></div>
</body>
</html>
process_get.php
1
2
3
4
5
6
7
<?php
$name = $_GET['name'];
$age = $_GET['age'];

echo "Name: " . htmlspecialchars($name) . "<br>";
echo "Age: " . htmlspecialchars($age);
?>

上面的 PHP 脚本可以使用 ?name=a&age=13 的方式传递参数并获取返回值。

$_POST

$_POST 是一个全局关联数组,包含表单数据的键值对。$_POST 变量用于收集表单数据,通过 HTTP POST 方法传递给页面。

例子与 $_GET 类似,只是将 GET 改为 POST

$_REQUEST

$_REQUEST 是一个全局关联数组,包含 $_GET$_POST$_COOKIE 的内容。$_REQUEST 变量用于收集表单数据,通过 GETPOST 方法传递给页面。虽然它更加简单,但明确使用 $_GET$_POST 更安全、更清晰。

例如,在上面的例子中,我们可以使用 $_REQUEST 替换 $_GET

process_request.php
1
2
3
4
5
6
7
<?php
$name = $_REQUEST['name'];
$age = $_REQUEST['age'];

echo "Name: " . htmlspecialchars($name) . "<br>";
echo "Age: " . htmlspecialchars($age);
?>

数据库连接

PHP 可以连接多种数据库系统,如 MySQL、PostgreSQL、SQLite 等。PHP 提供了多种数据库操作函数,如 mysqli_connect()mysqli_query()mysqli_fetch_array() 等。

1
2
3
4
5
6
7
8
9
CREATE DATABASE example_db;

USE example_db;

CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
age INT NOT NULL
);
1
2
3
INSERT INTO users (name, age) VALUES ('dx3qOb', 19);
INSERT INTO users (name, age) VALUES ('jiuhao47', 46);
INSERT INTO users (name, age) VALUES ('mmm', 20);
db.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

$servername = "localhost";
$username = "root";
$password = "13754";
$dbname = "example_db";

// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);

// 检查连接
if ($conn->connect_error) {
die("连接失败: " . $conn->connect_error);
} else {
echo "连接成功<br>";
}

// 执行查询
$sql = "SELECT id, name, age FROM users";
$result = $conn->query($sql);

if ($result === false) {
die("查询失败: " . $conn->error);
}

if ($result->num_rows > 0) {
// 输出数据
while($row = $result->fetch_assoc()) {
echo "ID: " . $row["id"]. " - Name: " . $row["name"]. " - Age: " . $row["age"]. "<br>";
}
} else {
echo "0 结果";
}

// 关闭连接
$conn->close();
?>

文件操作

PHP 可以打开、读取、写入、关闭文件。PHP 提供了多种文件操作函数,如 fopen()fread()fwrite()fclose() 等。

file.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$filename = "example.txt";
$content = "Hello, World!";
$handle = fopen($filename, "w");

if ($handle === false) {
die("无法打开文件");
}

if (fwrite($handle, $content) === false) {
die("无法写入文件");
}

fclose($handle);
echo "写入成功";
?>

错误处理

PHP 提供了多种错误处理函数,如 die()trigger_error()set_error_handler() 等。我们可以使用 error_reporting 配置指令来设置 PHP 错误级别。

知道了这些我们就可以了解一些常见的 WEB 攻击了。

常见 WEB 攻击

XSS 攻击

XSS(Cross-Site Scripting)跨站脚本攻击,是一种常见的 Web 攻击方式,攻击者通过在 Web 页面中插入恶意脚本,获取用户的敏感信息。其基于浏览器会解析并执行所有含有关键字的内容的特性。

例如:

xss.html
1
2
3
4
5
<script>
alert("XSS");
</script>

<img src="x" onerror="alert('XSS')">
xss.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html>
<html>
<head>
<title>XSS 攻击示例</title>
<script>
function submitForm(event) {
event.preventDefault(); // 阻止表单默认提交行为

var input = document.getElementById("userInput").value;
var xhr = new XMLHttpRequest();
xhr.open("POST", "xss.php", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById("result").innerHTML = xhr.responseText;
}
};
xhr.send("comment=" + encodeURIComponent(input));
}

function loadComments() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "comments.txt", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById("result").innerHTML = xhr.responseText;
}
};
xhr.send();
}

window.onload = loadComments;
</script>
</head>
<body>
<h1>XSS 攻击示例</h1>
<form onsubmit="submitForm(event)">
<label for="userInput">输入内容:</label>
<input type="text" id="userInput" name="userInput">
<input type="submit" value="提交">
</form>

<h2>结果:</h2>
<div id="result"></div>
</body>
</html>
xss.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$comment = $_POST['comment'];
// $comment = htmlspecialchars($comment); // 防止 XSS 攻击
$file = 'comments.txt';

// 追加评论到文件
file_put_contents($file, $comment . "\n", FILE_APPEND);

// 读取文件内容并返回
echo file_get_contents($file);
}

if ($_SERVER["REQUEST_METHOD"] == "GET") {
$file = 'comments.txt';
echo file_get_contents($file);
}
?>
xss_safe.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
<head>
<title>XSS 攻击示例</title>
<script>
function submitForm(event) {
event.preventDefault(); // 阻止表单默认提交行为

var input = document.getElementById("userInput").value;
var resultDiv = document.getElementById("result");
resultDiv.textContent = input; // 使用 textContent 防止 XSS 攻击
}
</script>
</head>
<body>
<h1>XSS 攻击示例</h1>
<form onsubmit="submitForm(event)">
<label for="userInput">输入内容:</label>
<input type="text" id="userInput" name="userInput">
<input type="submit" value="提交">
</form>

<h2>结果:</h2>
<div id="result"></div>
</body>
</html>
xss_safe.php
1
2
3
4
5
6
7
8
9
10
11
12
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$comment = $_POST['comment'];
$comment = htmlspecialchars($comment); // 防止 XSS 攻击
$file = 'comments.txt';

// 追加评论到文件
file_put_contents($file, $comment . "\n", FILE_APPEND);

// 读取文件内容并返回
echo file_get_contents($file);
}
clear.php
1
2
3
4
<?php
$file = 'comments.txt';
file_put_contents($file, '');
?>

PHP 攻击

PHP 比较

PHP 中的比较运算符有 ===== 两种,其中 == 用于比较值,=== 用于比较值和类型。在 PHP 中,== 会进行类型转换,=== 不会进行类型转换。

1
2
3
4
5
6
7
8
9
10
<?php
$number = 0;
$string = '0';

if ($number == $string) {
echo "相等";
} else {
echo "不相等";
}
?>

因此,若比较哈希值时使用 == 运算符,可能会导致哈希碰撞攻击。

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$hash1 = md5('240610708');
$hash2 = md5('QNKCDZO');

if ($hash1 == $hash2) {
echo "相等\n";
echo $hash1 . "\n";
echo $hash2 . "\n";
} else {
echo "不相等";
}
?>

不仅是比较,PHP 中几乎所有的函数都有涉及到类型自动转换的问题,所以不规范的代码能造成的问题很多。

  1. switch 语句会进行松散比较。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php
    switch ("0") {
    case 0:
    echo "匹配到 0\n"; // 这行会被执行
    break;
    case "0":
    echo "匹配到 '0'\n";
    break;
    default:
    echo "没有匹配到\n";
    }
    ?>
  2. intval() 函数会在没有指定基数时进行自动识别,并且会忽略字符串中的非数字字符。
    1
    2
    3
    4
    5
    6
    7
    <?php
    echo intval("47"); // 输出: 47
    echo intval("47jiuhao"); // 输出: 47
    echo intval("jiuhao47"); // 输出: 0
    echo intval("47", 8); // 输出: 39
    echo intval("0x47", 16); // 输出: 71
    ?>
  3. strpos() 函数会返回字符串的位置,如果没有找到则返回 false
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    $haystack = "jiuhao47";
    $needle = "j";

    if (strpos($haystack, $needle) != false) {
    echo "Found!";
    } else {
    echo "Not found!";
    }
    ?>

PHP 注入

PHP 注入是一种常见的 Web 攻击方式,攻击者通过在 Web 表单中输入恶意 PHP 代码,获取服务器的敏感信息。PHP 注入通常发生在用户输入的数据未经过验证和过滤的情况下。

PHP 代码执行

PHP 中的 eval() 函数用于执行字符串中的 PHP 代码。如果用户可以控制 eval() 函数的参数,可能会导致代码执行漏洞。

PHP 变量覆盖

PHP 中的 extract() 函数用于将数组中的键值对转换为变量。如果用户可以控制数组的键值对,可能会导致变量覆盖漏洞。 #### PHP 文件包含

PHP 中的 includerequire 函数用于包含文件,可以包含本地文件或远程文件。如果用户可以控制包含的文件名,可能会导致文件包含漏洞。

1
2
3
4
<?php
$file = $_GET['file'];
include $file;
?>
1
2
3
4
<?php
$file = $_GET['file'];
require $file;
?>

PHP 反序列化

PHP 中的 serialize()unserialize() 函数用于序列化和反序列化对象。如果用户可以控制序列化的数据,可能会导致反序列化漏洞。

1
2
3
4
<?php
$data = $_GET['data'];
$object = unserialize($data);
?>

PHP 伪协议

PHP 中的伪协议是一种特殊的协议,用于访问不同的资源。如果用户可以控制伪协议的参数,可能会导致伪协议漏洞。包括 file://php://data://等。

例如,若服务器上存在这样的代码:

1
2
3
4
<?php
$file = $_GET['file'];
include "file://$file";
?>

则用户可以通过 file:// 伪协议包含任意文件。

1
http://example.com/index.php?file=php://filter/convert.base64-encode/resource=index.php

防止它的办法是过滤输入:

1
2
3
4
5
6
7
8
9
10
<?php
$allowed_files = array('file1.txt', 'file2.html', 'file3.jpg');
$file = $_GET['file'];

if (in_array($file, $allowed_files)) {
include $file;
} else {
die("文件不存在");
}
?>

SQL 注入

SQL 注入是一种常见的 Web 攻击方式,攻击者通过在 Web 表单中输入恶意 SQL 语句,获取数据库中的敏感信息。SQL 注入通常发生在用户输入的数据未经过验证和过滤的情况下。

不会这个。