网安导实验四
网安导实验四:“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-Control
和
Expires
头部控制,协商缓存通过 Last-Modified
和 ETag
头部控制。
URL 和 URI
URL(Uniform Resource Locator,统一资源定位符)是 URI(统一资源标识符)的一种,用于标识 Web 资源的位置。URL 是互联网上资源的地址,通过 URL 可以访问特定的资源。
一个完整的 URL 由以下几部分组成:
- 方案(Scheme):指定访问资源所使用的协议,例如 http、https、ftp 等。
- 主机(Host):指定资源所在的服务器的域名或 IP 地址。
- 端口(Port):指定访问资源所使用的端口号(可选)。
- 路径(Path):指定资源在服务器上的具体位置。
- 查询字符串(Query):提供额外的参数,用于传递给服务器(可选)。
- 片段标识符(Fragment):指定资源中的某个部分(可选)。
例如:
1 | Scheme :// hostname[:port] / path / [;parameters][?query]#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特别适合于 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 | sudo apt update # 更新软件包列表 |
安装 PHP
1 | sudo apt install php libapache2-mod-php php-mysql php-cli php-curl php-gd php-mbstring php-xml php-zip # 安装 PHP 和相关扩展 |
完成后,在浏览器中访问 http://localhost
,如果看到
Apache2 的默认页面,则说明安装成功。
在 /var/www/html
目录下创建一个 PHP 文件,如
index.php
,并输入以下内容:
1 |
|
然后在浏览器中访问 http://localhost/index.php
,如果看到
PHP 的信息页面,则说明 PHP 安装成功。
.htaccess
文件
.htaccess
是 Apache2
的配置文件,用于配置网站的访问权限、重定向、错误处理等。我们可以通过修改
.htaccess
文件来配置 Apache2 的行为。
例如,我们可以通过 .htaccess
文件禁止目录列表、重定向
URL、设置错误页面等。
例如,我们可以禁止对 index.php
文件的访问:
1 | <Files "index.php"> |
配置 Apache2
Apache2 的配置文件位于 /etc/apache2
目录下,主要包括
apache2.conf
、ports.conf
、sites-available
和 sites-enabled
等文件。
apache2.conf
:Apache2 的主配置文件。ports.conf
:端口配置文件。sites-available
:站点配置文件目录。sites-enabled
:启用的站点配置文件目录。
我们可以通过修改配置文件来配置 Apache2 的虚拟主机、目录、模块等。
配置虚拟主机(不重要)
虚拟主机是 Apache2 的一个重要功能,用于在同一台服务器上托管多个网站。每个虚拟主机都有自己的域名、目录和配置。
我们可以通过配置虚拟主机来实现多个网站的托管,提高服务器的利用率。
同一主机解析不同链接的教程较多,本处我们只写怎么让不同端口对应不同虚拟主机。
配置多端口虚拟主机:
我们这里搞个例子,让 3000
端口和 3001
端口指向不同的目录。
首先,我们需要在 /etc/apache2/sites-available
目录下创建两个配置文件,如 site1.conf
和
site2.conf
。
1 | sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/site1.conf |
然后,我们需要编辑这两个配置文件,分别配置虚拟主机的域名、目录和日志。
1 | # site1.conf |
接着,我们需要启用这两个虚拟主机,并重启 Apache2 服务。
1 | sudo a2ensite site1.conf |
最后,我们需要在 /var/www
目录下创建 site1
和 site2
目录,并在这两个目录下创建一个
index.html
文件。
1 | sudo mkdir /var/www/site1 |
完成后,在浏览器中访问 http://localhost:3000
和
http://localhost:3001
,分别看到 Site 1
和
Site 2
的内容,则说明虚拟主机配置成功。
在 Windows 上安装 PHP 有多种方法,如使用 XAMPP、WampServer、EasyPHP 等。这些工具集成了 Apache、MySQL 和 PHP,可以一键安装。
我们这里只介绍手动安装 PHP 的方法:
- 下载 PHP 安装包:https://windows.php.net/download/
- 解压安装包到指定目录
- 配置环境变量
在 macOS 中安装 PHP 非常简单,只需要使用 Homebrew 即可:
1 | brew install php |
PHP 基础语法
PHP 标记
我们先得知道 HTML 是怎么传给用户并显示的。
- 用户输入 URL,浏览器向服务器发送请求。
- 服务器接收请求,解析 URL,返回对应的 HTML 文件。
- 浏览器接收 HTML 文件,解析 HTML 文件,显示页面。
而 PHP 是在服务器上执行的,所以我们可以在 HTML 文件中嵌入 PHP 代码,然后由服务器解析 PHP 代码,生成 HTML 文件,最后返回给浏览器。
PHP 脚本可以放在文档中的任何位置,但是 PHP
脚本会在服务器上解析之后再发送到浏览器。PHP 脚本以 <?php
开始,以 ?>
结束。
1 | <!DOCTYPE html> |
PHP 文件的默认文件扩展名是 .php
。
在同一个文件中,多个 PHP 代码块将共享相同的作用域。
1 | <!DOCTYPE html> |
变量和数据类型
PHP 是一种解释型语言,因此,它写起来和我们熟悉的 JavaScript 很像。
PHP 中的变量以 $
符号开头,后跟变量名。变量名区分大小写。PHP
支持多种数据类型,包括字符串、整数、浮点数、布尔值、数组和对象。
请不要忘记变量名以 _
开头也是合法的。否则会有不幸是事情发生。
PHP 中的变量不需要显式声明数据类型,PHP 会根据变量的值自动确定数据类型。
1 |
|
控制结构
PHP
支持多种控制结构,如条件语句(if...else
)、循环语句(for
、while
)、跳转语句(break
、continue
)等。
函数
PHP 内置了大量的函数,如字符串处理函数、数组处理函数、日期处理函数等。此外,PHP 还支持用户自定义函数。
常见函数有:
- 字符串处理函数:
strlen()
、subpos()
、str_replace()
等。 - 数组处理函数:
count()
(统计元素数)、array_push()
(向数组末尾添加元素)、array_merge()
、in_array
(检查数组中是否存在某个值) 等。 - 日期处理函数:
date()
、time()
、strtotime()
等。 - 文件处理函数:
file_get_contents()
、file_put_contents()
、fopen()
、fclose()
等。 - 数据库处理函数:
mysqli_connect()
、mysqli_query()
、mysqli_fetch_array()
等。 - 错误处理函数:
die()
、trigger_error()
、set_error_handler()
等。 - 其他函数:
var_dump()
(打印变量的类型和值)、phpinfo()
(显示 PHP 信息)、header()
(发送原始 HTTP 头)、isset()
(检查变量是否已设置)、empty()
(检查变量是否为空)、unset()
(销毁变量)等。
此外,作为基础内容,我们还需要了解正则表达式。
表单处理
PHP
可以处理表单数据,包括获取表单数据、验证表单数据、过滤表单数据等。我们可以使用
$_GET
、$_POST
、$_REQUEST
全局数组来获取表单数据。
我们先介绍这三个全局数组:
$_GET
$_GET
是一个全局关联数组,包含 URL
参数的键值对。$_GET
变量用于收集表单数据,通过 URL
参数传递给页面。
1 |
|
1 |
|
上面的 PHP 脚本可以使用 ?name=a&age=13
的方式传递参数并获取返回值。
$_POST
$_POST
是一个全局关联数组,包含表单数据的键值对。$_POST
变量用于收集表单数据,通过 HTTP POST 方法传递给页面。
例子与 $_GET
类似,只是将 GET
改为
POST
。
$_REQUEST
$_REQUEST
是一个全局关联数组,包含
$_GET
、$_POST
和 $_COOKIE
的内容。$_REQUEST
变量用于收集表单数据,通过
GET
或 POST
方法传递给页面。虽然它更加简单,但明确使用 $_GET
或
$_POST
更安全、更清晰。
例如,在上面的例子中,我们可以使用 $_REQUEST
替换
$_GET
。 1
2
3
4
5
6
7
$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 | CREATE DATABASE example_db; |
1 | INSERT INTO users (name, age) VALUES ('dx3qOb', 19); |
1 |
|
文件操作
PHP 可以打开、读取、写入、关闭文件。PHP 提供了多种文件操作函数,如
fopen()
、fread()
、fwrite()
、fclose()
等。
1 |
|
错误处理
PHP 提供了多种错误处理函数,如
die()
、trigger_error()
、set_error_handler()
等。我们可以使用 error_reporting
配置指令来设置 PHP
错误级别。
知道了这些我们就可以了解一些常见的 WEB 攻击了。
常见 WEB 攻击
XSS 攻击
XSS(Cross-Site Scripting)跨站脚本攻击,是一种常见的 Web 攻击方式,攻击者通过在 Web 页面中插入恶意脚本,获取用户的敏感信息。其基于浏览器会解析并执行所有含有关键字的内容的特性。
例如:
1 | <script> |
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
PHP 攻击
PHP 比较
PHP 中的比较运算符有 ==
和 ===
两种,其中
==
用于比较值,===
用于比较值和类型。在 PHP
中,==
会进行类型转换,===
不会进行类型转换。
1 |
|
因此,若比较哈希值时使用 ==
运算符,可能会导致哈希碰撞攻击。
1 |
|
不仅是比较,PHP 中几乎所有的函数都有涉及到类型自动转换的问题,所以不规范的代码能造成的问题很多。
switch
语句会进行松散比较。1
2
3
4
5
6
7
8
9
10
11
12
switch ("0") {
case 0:
echo "匹配到 0\n"; // 这行会被执行
break;
case "0":
echo "匹配到 '0'\n";
break;
default:
echo "没有匹配到\n";
}intval()
函数会在没有指定基数时进行自动识别,并且会忽略字符串中的非数字字符。1
2
3
4
5
6
7
echo intval("47"); // 输出: 47
echo intval("47jiuhao"); // 输出: 47
echo intval("jiuhao47"); // 输出: 0
echo intval("47", 8); // 输出: 39
echo intval("0x47", 16); // 输出: 71strpos()
函数会返回字符串的位置,如果没有找到则返回false
。1
2
3
4
5
6
7
8
9
10
$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 中的 include
和 require
函数用于包含文件,可以包含本地文件或远程文件。如果用户可以控制包含的文件名,可能会导致文件包含漏洞。
1 |
|
1 |
|
PHP 反序列化
PHP 中的 serialize()
和 unserialize()
函数用于序列化和反序列化对象。如果用户可以控制序列化的数据,可能会导致反序列化漏洞。
1 |
|
PHP 伪协议
PHP
中的伪协议是一种特殊的协议,用于访问不同的资源。如果用户可以控制伪协议的参数,可能会导致伪协议漏洞。包括
file://
、php://
、data://
等。
例如,若服务器上存在这样的代码:
1 |
|
则用户可以通过 file://
伪协议包含任意文件。
1 | http://example.com/index.php?file=php://filter/convert.base64-encode/resource=index.php |
防止它的办法是过滤输入:
1 |
|
SQL 注入
SQL 注入是一种常见的 Web 攻击方式,攻击者通过在 Web 表单中输入恶意 SQL 语句,获取数据库中的敏感信息。SQL 注入通常发生在用户输入的数据未经过验证和过滤的情况下。
不会这个。