从零学网络安全 - Web 技术核心与安全风险(三)
一、PHP 基本语法
1. PHP 介绍
PHP(Hypertext Preprocessor,超⽂本预处理器)是⼀⻔开源的服务器端脚本编程语⾔,专⻔⽤于开发Web⽹站的后端逻辑。
PHP 特点
- PHP 可在不同的平台上运⾏(Windows、Linux、Mac OS X 等)。
- PHP 与⽬前⼏乎所有的正在被使⽤的服务器相兼容(Apache、IIS 等)。
- PHP 提供了⼴泛的数据库⽀持。
- PHP 易于学习,并可⾼效地运⾏在服务器端。
2. 学网安为什么必须学 PHP
- PHP 的市场占比极⾼,是漏洞重灾区。
- 不懂 PHP,就看不懂漏洞的底层原理。
- 不懂 PHP,就看不懂漏洞的利用方式。
- PHP 是网安入门最友好的后端语⾔。
3. PHP 基础语法
PHP 文件默认扩展名为 .php,通常包含 HTML 标签和⼀些 PHP 脚本代码。PHP 代码必须包含在 <?php ... ?>标签中。PHP 中的每⾏代码都必须以分号结束。
注释规则:
- //单行注释
- /*多行注释*/
变量规则:所有变量都必须以 $ 符号开头。
- 变量以 $ 符号开始,后面跟着变量的名称。
- 变量名必须以字母或者下划线字符开始。
- 变量名只能包含字母、数字以及下划线(A-z、0-9 和 _ )。
- 变量名不能包含空格。
- 变量名是区分大小写的($y 和 $Y 是两个不同的变量)。
示例1:输出 "hello world"
<?php
//echo 输出单⼀类型(数值,字符串,布尔)
echo "hello world";
?>
示例2:定义变量
<?php
//指定浏览器用UTF-8解析页面(必须放在所有输出之前,无前置空格/换行)
header("Content-Type: text/html; charset=utf-8");
$message = "欢迎学习 PHP!"; // 变量定义
echo $message; // 输出变量内容
// 使用点号(.)连接字符串
echo "<h1>" . $message . "</h1>"; // HTML 和 PHP 混合输出
?>
示例3:数组
数组元素的第一个下标为0.
<?php
$student = ["xiaoming", "xiaolin", "xixi", "xiaoai"];
//利用索引获取数组里数据
echo $student[0];
echo "<br>";
echo $student[1];
?>
示例4:条件语句
1. if 语句
语法:
if (条件){
条件成立时要执行的代码;
}
示例:
<?php
$score = 75;
if ($score >= 60) {
echo "成绩及格";
}
?>
2. if...else 语句
语法:
if (条件){
条件成⽴时执⾏的代码;
}else{
条件不成⽴时执⾏的代码;
}
示例:
<?php
$score = 55;
if ($score >= 60) {
echo "成绩及格";
} else {
echo "成绩不及格";
}
?>
3. if...elseif...else 语句
语法:
if(条件1){
条件1成⽴时执⾏的代码;
}else if(条件2){
条件2成⽴时执⾏的代码;
}else{
以上条件不成⽴时执⾏的代码;
}
示例:
<?php
$score = 75;
if ($score >= 90) {
echo "成绩优秀";
} elseif ($score >= 60) {
echo "成绩及格"; // 75 >= 60 成立
} else {
echo "成绩不及格";
}
?>
示例5:循环语句
知道循环次数通常用 for,不知道次数通常用 while
1. for 循环
语法:
for (初始值; 条件; 增量){
要执⾏的代码;
}
示例:
<?php
$student = ['xiaoming', 'xiaolin', 'xixi', 'xiaogao'];
for ($i = 0; $i <= 3 ; $i=$i+1) {
echo $student[$i].' ' ;
}
?>
2. while 循环
语法:
while (条件){
要执⾏的代码;
}
示例:
<?php
$count = 3;
$student = ['xiaoming', 'xiaolin', 'xixi', 'xiaogao'];
while ($count >= 0) {
echo $student[$count].' ' ;
$count=$count-1;
}
?>
示例6:PHP函数
PHP 函数准则:
- 函数的名称应该提示出它的功能
- 函数名称以字⺟或下划线开头(不能以数字开头)
语法:
PHP⾃定义函数
示例:
<?php
function func()
{
echo "This is a function.";
}
func();
?>
示例7:类
类是抽象的概念,类似一个模板,⽤来描述具有相同属性和⽅法的对象的集合,⽐如:“人”是⼀个类。对象是类的实例,是某⼀个具体的事物,比如 “张三”则是“人”类的⼀个对象。
<?php
header("Content-Type: text/html; charset=utf-8");
class student{
public $name;
public $age;
public function say() { //自定义函数
echo $this->name. " 你好!";
}
}
$stu1 = new student();
$stu1 -> name = "xiaoming";
echo $stu1->name;
$stu1 -> say();
?>
示例8:类的构造方法
PHP魔术方法(Magic Methods)在 PHP 中具有特定的命名和功能。
- 魔术方法不需要显式调用,而是由PHP解释器在特定时机自动触发。
- 通常用两个下划线(__)开头,后跟方法名称如构造方法__construct()。
<?php
class Person {
public function __construct() {
echo "construct is coming ~";
}
}
$p1 = new Person();
?>
示例9:超全局变量
- $_GET:收集通过 URL GET 方法提交的表单数据
- $_POST:收集通过 HTTP POST ⽅法提交的表单数据
- $_FILES:处理通过 HTTP POST 上传的⽂件
准备一个登录的页面
<!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="b.php" method="get">
姓名:<input type="text" name="name"><br>
年龄:<input type="number" name="age"><br>
<button type="submit">提交</button>
</form>
</body>
</html>
准备另一个获取数据的php页面
<?php
header("Content-Type: text/html; charset=utf-8");
$name = $_GET['name'] ;
$age = $_GET['age'] ;
echo "<h3>接收到的参数:</h3>";
echo "姓名:{$name}<br>";
echo "年龄:{$age}<br>";
echo "<a href='a.php'>返回填写表单</a>";
?>
在 a.php 中输入数据后提交

可以在 b.php 中显示结果

示例10:序列化 serialize() 和反序列化 unserialize()
序列化是将⼀个 PHP 对象(包括它的类名、所有属性和属性值)转换为⼀个可存储、可传输的字符串的过程。
反序列化是将这个字符串还原回原来的 PHP 对象的过程。
准备一个登录的页面
<!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="b.php" method="get">
姓名:<input type="text" name="name"><br>
年龄:<input type="number" name="age"><br>
密码:<input type="password" name="pwd"><br>
<button type="submit">提交</button>
</form>
</body>
</html>
准备另一个获取数据的php页面
在 a.php 中输入数据后提交

可以在 b.php 中显示结果

二、WEB 交互实战
有一个php文件,index.php
<?php
error_reporting(0);
include "flag.php";
$KEY = "ZS";
$str = $_GET['str'];
if(unserialize($str)===$KEY){
echo "$flag" ."</br>";
}
show_source(__FILE__);
?>

有一个flag文件,flag.php
<?php
$flag = 'flag{this_is_flag_2026}';
?>
目的:得到 if 语句中的 flag
思路:
在 PHP 中,=== 被称为全等运算符,两个变量的值、类型、长度必须完全相同才能成为全等。既然要求反序列化后的 $str 全等于 $KEY,而 $KEY 又被赋值为 "ZS",所以我们可以序列化 $KEY (即“ZS”)来得到 flag。
执行这段测试代码来得到“ZS”序列化后的结果:
<?php
header("Content-Type: text/html; charset=utf-8");
$zs=serialize("ZS");
echo $zs;;
?>
我们得到:
s:2:"ZS";
所以我们可以在游览器中修改 url:http://127.0.0.1/fan/index.php?str=s:2:"ZS"
目标达成:
