1. 任务
1.1.1.1.1.1. 知识部分
1.Linux的命令过一遍
2.自行学习http协议,了解http请求与响应,并理解浏览器与服务器是如何通信的,理解浏览器是如何访问网站的【之前有写过,这里简单把之前笔记再看一遍,请求头使用回忆】
3.php学习https://www.runoob.com/php/php-tutorial.html
4.代码执行函数rce
1.1.1.1.1.2. 题目(第一次一般直接抄或复现,这次看看能否独立完成)
- [MoeCTF 2021]Do you know HTTP
- [SWPUCTF 2024 秋季新生赛]http标头
- https://www.nssctf.cn/problem或者青少年CTF练习平台 (这个平台不需要金币)rce-labs level0-8靶场里面的引导是很详细的可以在nssctf上打(也可以自己用docker部署本地靶场 https://github.com/ProbiusOfficial/RCE-labs)【这个寒假 又自己打过了,所以这里就不打了先】
- [SWPUCTF 2021 新生赛]babyrce
2. 知识点学习
2.1. Linux再学习
【个人感觉Linux的命令得过一遍,我用思维导图的形式展出,感觉更清晰一点】
2.1.1. Linux终端命令格式

2.1.1.1.1.1. -man的使用操作键

2.1.2. 常用Linux命令的基本使用
2.1.2.1. 常用Linux命令的基本使用
|--------------|----------------------|-----------------|
| 命令 | 对应英文 | 作用 |
| ls | list | 查看当前文件夹下面内容 |
| pwd | print work directory | 查看当前所在文件夹 |
| cd[目录名] | changge directory | 切换文件夹 |
| touch[文件名] | touch | 如果文件不存在,新建文件 |
| mkdir[目录名] | make directory | 创建目录 |
| rm[文件名] | remove | 删除指定文件 |
| clear | clear | 清屏 |
2.1.2.2. 快捷方式
通过上下方向键 ↑ ↓ 来调取过往执行过的Linux命令;
命令或参数仅需输入前几位就可以用 Tab 键补全;
Ctrl + R :用于查找使用过的命令(history命令用于列出之前使用过的所有命令,然后输入!命令加上编号 (!2) 就可以直接执行该历史命令);
Ctrl + L:清除屏幕并将当前行移到页面顶部;
Ctrl + C:中止当前正在执行的命令;
Ctrl + U:从光标位置剪切到行首;
Ctrl + K:从光标位置剪切到行尾;
Ctrl + W:剪切光标左侧的一个单词;
Ctrl + Y:粘贴Ctrl + U | K | Y剪切的命令;
Ctrl + A:光标跳到命令行的开头;
Ctrl + E:光标跳到命令行的结尾;
Ctrl + D:关闭Shell会话;
ctrl + shift + =: 放大终端窗口的字体显示
ctrl + -: 缩小终端窗口的字体显示
2.1.3. 其他命令
2.1.3.1. 总出
思维导图展出,学习完后可以快速回忆,查询

2.1.3.2. 查找文件find
用来在 特定的目录下 搜索 符合条件的文件 【找文件】
find [路径] -name "文件名"
- 如果省略路径,表示在当前文件夹下查找
2.1.3.2.1.1. 栗子
1.搜索桌面目录下,文件名包含 1 的文件
find -name "*1*"
2.搜索桌面目录下,所有以 .txt 为扩展名的文件
find -name "*.txt"
3.搜索桌面目录下,以数字 1 开头的文件
find -name "1*"
2.1.3.3. 软链接和硬链接
2.1.3.3.1. 软链接
ln -s 被链接的源文件 链接文件
建立文件的软链接,用通俗的方式讲类似于 Windows 下的快捷方式
- 没有**-s 选项建立的是一个 硬链接文件,**两个文件占用相同大小的硬盘空间,工作中几乎不会建立文件的硬链接
- 源文件要使用绝对路径,不能使用相对路径,这样可以方便移动链接文件后,仍然能够正常使用
2.1.3.3.1.1. 栗子
-
- 将桌面目录下的 01.py 移动到 demo/b/c 目录下
mkdir -p ~/Desktop/demo/b/c
mv ~/Desktop/01.py ~/Desktop/demo/b/c/ # 把桌面上的01.py移动到目标目录
cd ~/Desktop # 回到桌面目录准备创建软链接 -
- 在桌面目录下新建 01.py 的 软链接 FirstPython分别使用 相对路径 和 绝对路径 建立 FirstPython 的软链接【一个是简略写法,一个是详细完整的写法】
1.相对路径创建(源文件只写相对于当前桌面的路径)
ln -s demo/b/c/01.py FirstPython_relative2.绝对路径创建(源文件写完整路径)
ln -s /home/你的用户名/Desktop/demo/b/c/01.py FirstPython_absolute
替换成你自己的用户名,比如如果是root就是/root/Desktop/...
-
- 将 FirstPython 移动到 demo 目录下,对比使用 相对路径 和 绝对路径 的区别
mv FirstPython* ~/Desktop/demo/ # 把两个软链接都移动过去
cd ~/Desktop/demo
- 👉 相对路径链接(FirstPython_relative) :打开会提示「No such file or directory」,链接失效,因为它存的路径是
demo/b/c/01.py,现在它自己在demo目录,找的就是demo/demo/b/c/01.py,这个文件不存在。 - 👉 绝对路径链接(FirstPython_absolute):可以正常打开、编辑源文件,因为它存的是完整固定路径,和自己在哪没关系。
2.1.3.4. 硬链接{用不到,知道即可}
ln 被链接的源文件 链接文件
在使用 ln 创建链接时,如果没有 -s 选项,会创建一个 硬链接,而不是软链接
2.1.3.4.1.1. 栗子
-
- 在 ~/Desktop/demo 目录下建立 ~/Desktop/demo/b/c/01.py 的硬链接 01_hard
- 使用 ls -l 查看文件的硬链接数(硬链接------有多少种方式可以访问文件或者目录)
cd ~/Desktop/demo
ln ~/Desktop/demo/b/c/01.py 01_hard
执行ls -l查看,你会看到源文件和硬链接的inode编号一样,硬链接数都变成了2。
-
- 删除 ~/Desktop/demo/b/c/01.py ,并且使用 tree 来确认 demo 目录下的三个链接文件文件软硬链接的示意图
rm ~/Desktop/demo/b/c/01.py
tree ~/Desktop/demo # 查看目录结构
- 现在demo目录里,你创建的两个软链接里,只有绝对路径那个能打开,但它也会提示找不到源文件;但硬链接 01_hard****依然可以 正常打开 ,内容和原来的01.py完全一样。
- 这就是硬链接的特性:删除源文件不影响硬链接,因为它们本来就是同一个文件的不同名字。
- 在 Linux 中,只有文件的 硬链接数 == 0 才会被删除
- 使用 ls -l 可以查看一个文件的硬链接的数量
文件软硬链接示意图

【在 Linux 中,文件名 和 文件的数据 是分开存储的】
2.1.4. 打包压缩
- 在不同操作系统中,常用的打包压缩方式是不同的选项 含义
Windows 常用 rar
Mac 常用 zip
Linux 常用 tar.gz
2.1.4.1. 打包 / 解包
tar 是 Linux 中最常用的 备份工具,
此命令可以 把一系列文件 打包到 一个大文件中,也可以把一个 打包的大文件恢复成一系列文件
2.1.4.1.1.1. 打包文件
打包文件
tar -cvf 打包文件.tar 被打包文件/路径
-c:--create,创建新的打包文件,这是打包操作的核心参数
-v:--verbose,显示打包过程的详细信息,
会把当前正在打包的每个文件/目录名打印在屏幕上,方便你看到打包进度
-f 文件名:--file,指定打包后输出的归档文件名,
这里就是指定输出为test.tar,-f必须放在所有参数的最后,因为它后面要紧跟文件名
如:
cd ~/Desktop
tar -cvf test.tar test_pack/
就是将test_pack/目录下所有文件都打包进test.tar里面
2.1.4.1.1.2. 解包文件
tar -xvf 打包文件.tar

2.1.4.2. 压缩/解压缩
2.1.4.2.1. gzip【用来压缩tar打包的文件】
tar 与 gzip 命令结合可以使用实现文件 打包和压缩
- tar 只负责打包文件,但不压缩
- 用 gzip 压缩 tar 打包后的文件,其扩展名一般用 xxx.tar.gz
- 【在 tar 命令中有一个选项 -z可以调用 gzip ,从而可以方便的实现压缩和解压缩的】
2.1.4.2.1.1. 压缩文件
tar -zcvf 打包文件.tar.gz 被压缩的文件/路径...
栗子:
# 先切换到桌面目录
cd ~/Desktop
# 把test_pack目录压缩为test.tar.gz
tar -zcvf test.tar.gz test_pack/
2.1.4.2.1.2. 解压缩文件
tar -zxvf 打包文件.tar.gz
栗子:
cd ~/Desktop
tar -zxvf test.tar.gz
执行后会直接在当前桌面目录,重新生成 test_pack 文件夹及其内部所有文件,保持原有目录结构。
2.1.4.2.1.3. 解压缩到指定路径
tar -zxvf 打包文件.tar.gz -C 目标路径
-C解压缩到指定目录,注意:要解压缩的目录必须存在
栗子:
比如我们要解压到 /tmp/test_unpack/ 这个目录:
# 1. 先创建目标目录(如果不存在)
mkdir -p /tmp/test_unpack/
# 2. 执行解压,指定目标路径
tar -zxvf test.tar.gz -C /tmp/test_unpack/
参数说明:-C(大写)参数的作用是切换解压目标路径,必须放在压缩包文件名之后。
解压后可以用这条命令验证结果:
ls /tmp/test_unpack/
你会看到 test_pack 目录已经出现在这个指定路径下了。
2.1.4.2.2. bzip2(two)
【用法与gzip一致】
- 在 tar 命令中有一个选项**-j**可以调用 bzip2 ,从而可以方便的实现压缩和解压缩的功能
命令格式如下:
压缩文件
tar -jcvf 打包文件.tar.bz2 被压缩的文件/路径...
解压缩文件
tar -jxvf 打包文件.tar.bz2
|----------|----------------------------------------|-------------------------------------|
| 对比维度 | gzip | bzip2 |
| 压缩比 | 较低,对文本通常能压缩到原大小的30%-40%,比bzip2大10%-30% | 更高,相同文件通常比gzip再小10%-30%,对文本类数据优势更明显 |
| 压缩/解压速度 | 更快,计算开销小,实时性好 | 明显更慢,压缩速度通常是gzip的1/4左右 |
| 资源占用 | CPU和内存占用更低 | 内存和CPU消耗更高 |
| 文件后缀 | .gz | .bz2 |
2.1.5. 软件安装
通过 apt 安装/卸载软件
-
apt 是
Advanced Packaging Tool,是 Linux 下的一款安装包管理工具 -
可以在终端中方便的 安装/卸载/更新软件包
1. 安装软件
$ sudo apt install 软件包
2. 卸载软件
$ sudo apt remove 软件名
3. 更新已安装的包
$ sudo apt upgrade
2.1.6. 文件和目录常用命令
2.1.6.1. 查看目录内容
2.1.6.1.1. ls 命令说明
ls 是英文单词 list 的简写,其功能为列出目录的内容,是用户最常用的命令之一,类似于 DOS下的 dir 命令
2.1.6.1.2. Linux 下文件和目录的特点
Linux 文件 或者 目录 名称最长可以有 256 个字符参数 含义
- 以
.开头的文件为隐藏文件,需要用 -a 参数才能显示 .代表当前目录...代表上一级目录
2.1.6.1.3. ls 常用选项
|----|--------------------------|
| 参数 | 含义 |
| -a | 显示指定目录下所有子目录与文件,包括隐藏文件 |
| -l | 以列表方式显示文件的详细信息 |
| -h | 配合 -l 以人性化的方式显示文件大小 |
2.1.6.1.4. ls通配符的使用
|---------|-----------------------|
| 通配符 | 含义 |
| * | 代表任意个数个字符 |
| ? | 代表任意一个字符,至少 1 个 |
| [] | 表示可以匹配字符组中的任一一个 |
| [abc] | 匹配 a、b、c 中的任意一个 |
| [a-f] | 匹配从 a 到 f 范围内的的任意一个字符 |
2.1.6.1.4.1. 栗子
*代表任意个数(包含0个)的任意字符
*.log→ 匹配所有.log结尾的日志文件,比如access.log、error-2024.logdata*→ 匹配所有以data开头的文件,比如data、data.csv、database*2026*→ 匹配文件名中包含2026的任意文件,比如report-2026.txt、2026-04.tar.gz
?代表恰好1个任意字符(至少1个,只能是1个)
file?.txt→ 匹配file1.txt、fileA.txt,不匹配file.txt(少一个字符)或file12.txt(多一个字符)??→ 匹配文件名长度恰好为2个字符的文件/目录
[]匹配字符组中的任意一个字符
基础用法:
[abc].txt→ 只匹配a.txt、b.txt、c.txt,不匹配d.txt
范围用法:file[0-9].txt→ 匹配file0.txt~file9.txt任意一个img[a-z].png→ 匹配imga.png到imgz.png任意一个
取反用法(^开头表示不匹配):[^0-9].txt→ 匹配文件名第一个字符不是数字的.txt文件,比如a.txt、data.txt,不匹配1.txt
2.1.6.2. 切换目录
2.1.6.2.1. cd
cd 是英文单词 change directory 的简写,其功能为更改当前的工作目录,也是用户最常用的命令之一
【注意:Linux 所有的 目录 和 文件名 都是大小写敏感的,即大小写区分,tset与Tset不一样】
|-----------|-------------------------|
| 命令 | 含义 |
| cd | 切换到当前用户的主目录(/home/用户目录) |
| cd ~ | 切换到当前用户的主目录(/home/用户目录) |
| cd . | 保持在当前目录不变 |
| cd ... | 切换到上级目录 |
| cd - | 可以在最近两次工作目录之间来回切换 |
2.1.6.2.2. 相对路径和绝对路径
|--------|----------|--------------|----------------|
| 类型 | 开头特征 | 优点 | 适用场景 |
| 绝对路径 | /或~ | 不依赖当前位置,不会出错 | 脚本写固定路径、访问系统目录 |
| 相对路径 | 无斜杠开头 | 更简洁,项目迁移方便 | 日常操作同一项目内的文件 |
2.1.6.2.2.1. 绝对路径示例(以 / 或 ~ 开头)
绝对路径是从根目录/家目录开始的完整路径,不管你当前在哪个目录,它都指向唯一位置:
/home/yourname/Documents/note.txt:从根目录开始,完整定位到你的文档下的笔记~/project/ctf/web:~自动展开为当前用户的家目录,等价于/home/你的用户名/project/ctf/web/var/www/html/test.php:Apache默认网站根目录的完整绝对路径
回顾:上面的软链接使用绝对路径
ln -s /home/yourname/ctf/payload.php /var/www/html/shell.php
2.1.6.2.2.2. 相对路径示例(不以 / 开头,相对于当前工作目录)
相对路径是相对于你当前所在目录的位置,当前目录变了,同一个相对路径指向的位置也会变:
- 如果你当前在
/home/你的用户名/目录,那么:
-
./Documents:.代表当前目录 ,等价于/home/你的用户名/Documents../opt:..代表上级目录 ,等价于/home/optproject/ctf:从当前目录往下找,等价于/home/你的用户名/project/ctf
2.1.6.3. 创建和删除操作
2.1.6.3.1. touch**【创建文件或修改文件时间】**
- 如果文件 不存在,可以创建一个空白文件
- 如果文件 已经存在,可以修改文件的末次修改日期
2.1.6.3.2. mrdir【创建一个新的目录】
|--------|----------|
| 选项 | 含义 |
| -p | 可以递归创建目录 |
新建目录的名称 不能 与当前目录中 已有的目录或文件 同名
2.1.6.3.3. rm【删除文件或目录】
使用 rm 命令要小心,因为文件删除后不能恢复
|--------|-----------------------------------|
| 选项 | 含义 |
| -f | 强制删除,忽略不存在的文件,无需提示 |
| -r | 递归地删除目录下的内容,删除文件夹 时必须加此参数 |
2.1.6.4. 拷贝和移动文件
|--------------|----------|------------------------|
| 命令 | 对应英文 | 作用 |
| tree [目录名] | tree | 以树状图列出文件目录结构 |
| cp 源文件目标文件 | copy | 复制文件或者目录 |
| mv 源文件 目标文件 | move | 移动文件或者目录/文件或者目录重命名 |
2.1.6.4.1. tree
- tree 命令可以以树状图列出文件目录结构
|--------|-----------|
| 选项 | 含义 |
| -d | 只显示目录 |
2.1.6.4.1.1. 栗子
-
展示当前目录所有文件和子目录:
tree
-
只展示当前目录的子目录(忽略文件):
tree -d
示例效果:会只列出uploads、logs、config这类目录,不会列出目录里的脚本文件。
2.1.6.4.2. cp
- cp 命令的功能是将给出的 文件 或 目录 复制到另一个 文件 或 目录 中,相当DOS 下的 copy命令
|---------|----------------------------------------------------|
| 选 项 | 含义 |
| -i | 覆盖文件前提示 |
| -r | 若给出的源文件是目录文件,则 cp 将递归复制该目录下的所有子目录和文件, 目标文件必须为一个目录名 |
2.1.6.4.2.1. 栗子
-
复制单个文件:把当前目录的
test.php复制一份叫test_backup.phpcp test.php test_backup.php
-
复制整个目录 :把
dirsearch目录下所有内容,递归复制到/opt/dirsearchcp -r ./dirsearch /opt/dirsearch
-
覆盖前提示:复制
payload.txt到payloads目录,如果目标已经有同名文件,会先提示你确认cp -i payload.txt payloads/
2.1.6.4.3. mv
- mv 命令可以用来移动 文件 或 目录,也可以给 文件或目录重命名
|--------|---------|
| 选项 | 含义 |
| -i | 覆盖文件前提示 |
2.1.6.4.3.1. 栗子
-
重命名文件:把
old.php改名为new.php【文件对文件】mv old.php new.php
-
移动文件:把
shell.php移动到uploads目录下【文件移到目录下】mv shell.php uploads/
-
移动并覆盖 提示:把
test.txt移动到/tmp目录,如果目标已有同名文件,会提示确认mv -i test.txt /tmp/
2.1.6.5. 查看文件内容
|---------------|-------------|----------------------------|
| 命令 | 对应英文 | 作用 |
| cat 文件名 | concatenate | 查看文件内容、创建文件、文件合并、追加文件内容等功能 |
| more 文件名 | more | 分屏显示文件内容 |
| grep 搜索文本 文件名 | grep | 搜索文本文件内容 |
2.1.6.5.1. cat
cat 命令可以用来 查看文件内容、创建文件、文件合并、追加文件内容 等功能
cat 会一次显示所有的内容,适合 查看内容较少 的文本文件
|--------|-----------|
| 选项 | 含义 |
| -b | 对非空输出行编号 |
| -n | 对输出的所有行编号 |
2.1.6.5.1.1. 栗子
这个选项就是编号,
1 <?php
2 echo "this is webshell";
3 system($_GET['cmd']);
4 ?>
1 <?php
2
3 echo "this is webshell";
4
5 system($_GET['cmd']);
6
7 ?>
2.1.6.5.2. more
- more 命令可以用于分屏显示文件内容,每次只显示一页内容
- 适合于 查看内容较多的文本文件
使用 more 的操作键:
|---------|----------------|
| 操作键 | 功能 |
| 空格键 | 显示手册页的下一屏 |
| Enter键 | 一次滚动手册页的一行 |
| b | 回滚一屏 |
| f | 前滚一屏 |
| q | 退出 |
| /word | 搜索word 字符串 |
2.1.6.6. grep
Linux 系统中 grep 命令是一种强大的文本搜索工具
grep 允许对文本文件进行 模式查找,所谓模式查找,又被称为正则表达式。
【grep [选项] "匹配模式" [文件/目录路径]】
|--------|----------------------|
| 选项 | 含义 |
| -n | 显示匹配行及行号 |
| -v | 显示不包含匹配文本的所有行(相当于求反) |
| -i | 忽略大小写 |
2.1.6.6.1.1. 栗子
-
基础搜索:在指定文件中查找包含关键词的行
在error.log中查找包含"SQL"的行
grep "SQL" error.log
-
-i 忽略大小写:不区分大小写匹配,避免漏匹配
匹配Error、error、ERROR等各种形式
grep -i "error" access.log
-
-n 显示行号:输出匹配行在文件中的具体行号,方便快速定位
grep -n "eval" webshell.php
-
-v 反向匹配 :只输出不包含 关键词的行,用来过滤无用信息
筛选出日志中不是"success"的行(看异常)
grep -v "success" system.log
-
-c 统计匹配行数 :只输出匹配到的总行数,适合快速统计
统计访问日志里一共出现了多少次404错误
grep -c " 404 " /var/log/nginx/access.log
-
-r 递归搜索:遍历指定目录下所有子目录和文件搜索
在当前目录所有PHP文件里找包含"eval"关键词的一句话木马
grep -r "eval" . --include="*.php"
-
上下文显示(看报错前后内容很有用)
-
-
-A n:显示匹配行 + 后面n行 -
-B n:显示匹配行 + 前面n行 -
-C n:显示匹配行 + 前后各n行找日志里的fatal错误,并显示错误前后各1行上下文
grep -C 1 "fatal" /var/log/nginx/error.log
-
-
正则匹配:支持正则表达式实现精准匹配
查找以"[ERROR]"开头的行
grep "^\[ERROR\]" system.log
查找包含IP地址的行
grep -E "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" access.log
-
结合管道的常用技巧
grep经常和其他命令搭配做过滤,非常高效:
# 列出当前目录下所有log后缀的文件
ls | grep ".log"
# 实时监控日志,只输出带Timeout的新日志
tail -f service.log | grep "Timeout"
2.1.6.6.1.2. 常用的两种模式查找
|--------|----------------|
| 参数 | 含义 |
| ^a | 行首,搜寻以 a 开头的行 |
| ke$ | 行尾,搜寻以 ke 结束的行 |
2.1.7. 系统信息相关命令
2.1.7.1. 时间和日期
|--------|-----------------------------------|
| 命令 | 作用 |
| date | 查看系统时间 |
| cal | calendar 查看日历, -y 选项可以查看一年的日历 |
【突然想到黑神话悟空的那道题,要注意date的形式,可以去查日历?】
2.1.7.2. 磁盘信息
|---------------|---------------------------|
| 命令 | 作用 |
| df -h | disk free 显示磁盘剩余空间 |
| du -h [目录名] | disk usage 显示目录下的文件大小 |
2.1.7.3. 进程信息【 当前正在执行的一个程序】
|------------------|------------------------------|
| 命令 | 作用 |
| ps aux | process status 查看进程的详细状况 |
| top | 动态显示 运行中的进程并且排序 |
| kill [-9] 进程代号 | 终止 指定代号的进程,-9 表示强行终止 |
2.1.7.3.1. ps
ps 默认只会显示当前用户 通过终端启动 的应用程序
ps 选项说明
|--------|--------------------------|
| 选项 | 含义 |
| a | 显示终端上的所有进程,包括其他用户的进程 |
| u | 显示进程的详细状态 |
| x | 显示没有控制终端的进程 |
2.1.7.3.1.1. 栗子
ps aux | grep nginx
过滤出你想要找的进程,比如找nginx
2.1.7.3.2. top
打开一个交互式界面,实时刷新显示进程的CPU、内存使用率,适合排查服务器卡慢问题。
常用交互操作:
- 按
P:按CPU使用率排序,找出占CPU最高的进程 - 按
M:按内存使用率排序 - 按
q:退出top界面 - 直接输入top就可以启动了
2.1.7.3.3. kill
使用 kill 命令时,最好只终止由当前用户开启的进程,而不要终止 root 身份开启的进程,否则可能导致系统崩溃
2.1.7.3.3.1. 栗子
实用例子:
-
先找到占用端口的PHP-FPM进程PID:
ps aux | grep php-fpm
假设得到进程ID是 1234
-
强制杀死这个进程:
kill -9 1234
其他常见用法:如果要温和停止进程可以不用-9,用kill 进程PID发送默认终止信号,让进程正常退出。
2.1.8. 用户权限相关命令
2.1.8.1. 组管理
【创建组/删除组的终端命令都需要通过sudo执行】
{sudo 是Linux/Unix系统中临时获取管理员权限执行命令的工具}
|--------------------|-----------------------------|
| 命令 | 作用 |
| groupadd 组名 | 添加组 |
| groupdel 组名 | 删除组 |
| cat /etc/group | 确认组信息 |
| chgrp -R 组名 文件/目录名 | 递归修改 文件 /目录的所属组 |
- 组信息 保存在
/etc/group文件中 /etc目录是专门用来保存 系统配置信息 的目录
2.1.8.2. 用户管理
【创建用户 / 删除用户 / 修改其他用户密码 的终端命令都需要通过 sudo 执行】
2.1.8.2.1. 创建用户/设置密码/删除用户
|---------------------------|--------|------------------------------------------------------|
| 命令 | 作用 | 说明 |
| useradd -m -g组 新建用户名 | 添加新用户 | -m是自动建立用户家目录【如果忘记就删除用户重新建立】 -g指定用户所在的组,否则建立一个与用户同名的组 |
| passwd 用户名 | 设置用户密码 | 如果是普通用户,直接用passwd修改自己的密码 |
| userdel -r 用户名 | 删除用户 | -r是自动删除用户的家目录 |
| cat/etc/passwd |grep 用户名 | 确认用户信息 | 新建用户后,用户信息会保存在/etc/passwd |
2.1.8.2.1.1. 疑问?家目录是什么
Linux的家目录是每个用户专属的个人存储空间,是用户登录系统后的默认工作目录,用于存放用户的私人文件、配置文件和应用数据。
标准默认路径
- 普通用户 :默认存放在
/home/用户名,例如用户test的家目录是/home/test - 超级管理员root :家目录为独立的
/root,不在/home路径下
2.1.8.2.2. 查看用户信息
|------------|---------------------|
| 命令 | 作用 |
| id [用户名] | 查看用户UID 和 GID信息 |
| who | 查看当前所有登录的用户列表 |
| whoami | 查看当前登录用户的账户名 |
2.1.8.2.2.1. uid,gid是什么意思
UID(User ID,用户ID)和GID(Group ID,组ID)是Linux系统权限管理的核心数字标识符,系统通过它们而非用户名/组名来判断权限。
|---------|----------|---------------------------------|----------------------------------------------------------------------------------|
| 标识符 | 作用对象 | 核心作用 | 常见ID范围 |
| UID | 单个用户 | 唯一标识系统用户, 决定用户对系统资源(文件/进程)的访问权限 | <br>- 0:root超级用户(最高权限)<br>- 1~999:系统服务/守护进程专用(系统用户) <br>- ≥1000:普通用户 |
| GID | 用户组 | 唯一标识用户组, 简化同组用户的共享权限分配 | <br>- 0:root用户组 <br>- 1~999:系统预留组 <br>- ≥1000:普通用户组 |
2.1.8.2.2.2. uid,gid使用栗子
所有用户和组的UID/GID信息都明文存储在两个系统配置文件中:
-
/etc/passwd:存储所有用户信息,每行格式为:
用户名:密码占位符(x):UID:GID:用户说明:家目录:登录Shell
示例(root用户条目):
root:x:0:0:root:/root:/bin/bash
可以看到:root的UID=0、GID=0。
- /etc/group:存储所有用户组信息,包含组成员列表。
查看当前/指定用户的UID/GID:
# 查看当前登录用户
id
# 查看指定用户(比如test)
id test
输出示例:
uid=1000(test) gid=1000(test) groups=1000(test),4(adm)
其中gid是用户主组GID ,后面groups是用户加入的所有附加组。
2.1.8.2.2.3. uid,gid涉及到一个考点(漏洞)
权限提升风险 :只要用户的UID被设置为0,无论用户名是什么,都会被内核识别为root,获得最高权限。攻击者常会通过修改普通用户UID为0来实现提权。
可以用命令排查异常特权用户:
# 找所有UID为0的异常用户
awk -F: '$3 == 0 {print $1}' /etc/passwd
2.1.8.2.2.4. which
which命令可以查看执行命令所在位置,【注意,cd不行】
which ls
# 输出
# /bin/ls
which useradd
# 输出
# /usr/sbin/useradd
2.1.8.2.2.5. bin 和 sbin
在 Linux 中,绝大多数可执行文件都是保存在 /bin 、 /sbin 、 /usr/bin 、 /usr/sbin
/bin ( binary )是二进制执行文件目录,主要用于具体应用
/sbin ( system binary )是系统管理员专用的二进制代码存放目录,主要用于系统管理
/usr/bin ( user commands for applications )后期安装的一些软件
/usr/sbin ( super user commands for applications )超级用户的一些管理程序
2.1.8.2.3. 切换用户
|----------|-----------------|---------------------|
| 命令 | 作用 | 说明 |
| su - 用户名 | 切换用户,并且切换目录 | 可以切换到用户家目录,否则保持位置不变 |
| exit | 退出当前登录账户 | |
2.1.8.2.3.1. 注意有没有带-
|------------|--------------|--------------|------------------------|
| 命令 | 环境变量 | 工作目录 | 适用场景 |
| su - 用户名 | 加载目标用户的完整环境 | 自动切到目标用户家目录 | 需要以目标用户完整身份操作时(推荐标准用法) |
| su 用户名 | 保留当前原用户的环境变量 | 留在原用户的当前工作目录 | 只需要切换身份但保留当前环境时 |
- 普通用户切换到任何其他用户都需要输入目标用户的密码;
- root切换到任何用户都不需要密码。【我突然在思考一个问题,没别的意思,如果老大要看地下员工工作情况,可以直接切换账号进来吗】
2.1.8.2.4. 切换文件权限
|--------|--------|
| 命令 | 作用 |
| chown | 修改拥有者 |
| chgrp | 修改组 |
| chmod | 修改权限 |
命令:
# 修改文件|目录的拥有者
chown 用户名 文件名|目录名
# 递归修改文件|目录的组
chgrp -R 组名 文件名|目录名
# 递归修改文件权限
chmod -R 755 文件名|目录名
2.1.9. 远程管理常用命令
2.1.9.1. 关机/重启
|----------|----------------|---------|
| 命令 | 对应英文 | 作用 |
| shutdown | 选项 时间 shutdown | 关机/重新启动 |
命令
# 重新启动操作系统,其中 now 表示现在
$ shutdown -r now
# 立刻关机,其中 now 表示现在
$ shutdown now
# 系统在今天的 20:25 会关机
$ shutdown 20:25
# 系统再过十分钟后自动关机
$ shutdown +10
# 取消之前指定的关机计划
$ shutdown -c
- 不指定选项和参数,默认表示 1 分钟之后 关闭电脑
- 远程维护服务器时,最好不要关闭系统,而应该重新启动系统
2.1.9.2. 查看配置网卡信息
|-----------|-------------------------------|------------------------|
| 命令 | 对应英文 | 作用 |
| ifconfig | configure a network interface | 查看/配置计算机当前的网卡配置信息 |
| ping ip地址 | ping | 检测到目标 ip地址 的连接是否正常 |
2.1.9.2.1. ifconfig
ifconfig是Linux早期经典的网卡配置查看工具 ,全称是interface configuration ,属于net-tools工具包(部分新版系统默认不预装)。
2.1.9.2.1.1. 基础用法
-
查看全部网卡的完整配置信息
$ ifconfig
-
过滤提取所有IP地址
$ ifconfig | grep inet
2.1.9.2.1.2. ✅ 补充要点
- 网卡命名规则:一台计算机通常会包含多种网卡:
-
- 物理网卡:新版Linux(CentOS 7+/Ubuntu 15+)默认命名为
ensXX或enp0sX,老式命名为eth0/eth1; - 虚拟网卡:比如Docker的
docker0、VMware虚拟机的vmnet、本地环回lo;
- 物理网卡:新版Linux(CentOS 7+/Ubuntu 15+)默认命名为
- 本地回环地址 127.0.0.1:专门用于本机进程间网络通信,永远代表本机本身,通常用来测试本机TCP/IP协议栈是否正常工作。【一般用来测试本机网卡是否正常】
2.1.9.2.2. ping
ping命令用于检测本机到目标主机之间的网络连通性和延迟质量,它的命名取自声纳探测的回声,网络中也常用作动词:比如"ping一下这个IP看看有没有开机"。
【ping 一般用于检测当前计算机到目标计算机之间的网络 是否通畅,数值越大,速度越慢】
2.1.9.2.2.1. 基础用法
-
检测到目标主机的连通状态
$ ping <IP地址或域名>
示例:ping www.baidu.com
-
检测本地网卡/TCP协议栈是否正常
$ ping 127.0.0.1
2.1.9.2.2.2. ✅ 补充要点
- 工作原理 :ping基于ICMP协议,向目标主机发送
Echo Request(回声请求)数据包,如果目标主机在线且允许ICMP请求,就会回复Echo Reply(回声应答); - 延迟判断 :输出中的
time=xx ms就是本次请求往返的延迟,数值越大说明网络延迟越高,连接质量越差; - 常用参数 :默认Linux下
ping会一直发包,按Ctrl+C停止;如果只需要指定发包次数,可以加-c参数:ping -c 4 127.0.0.1(发送4个包后自动停止); - 排坑提示:ping不通不代表目标一定不在线,很多服务器会开启防火墙拦截ICMP数据包,此时需要结合其他端口检测方式(比如telnet、nc)进一步验证。
2.1.9.3. 远程登录和赋值文件
|--------------------|---------|
| 命令 | 作用 |
| ssh 用户@ip | 关机/重新开机 |
| scp 用户名 @ip:文件名或路径 | 远程复制文件 |
2.1.9.3.1. ssh
SSH 全称Secure Shell(安全外壳协议) ,是目前最主流的加密远程通信协议,专为解决传统远程工具的安全缺陷而生。
通过 SSH 客户端 我们可以连接到运行了 SSH 服务器 的远程机器

使用:ssh [-p port] user@remote
- user 是在远程机器上的用户名,如果不指定的话默认为当前用户
- remote 是远程机器的地址,可以是 IP/域名,或者是 后面会提到的别名
- port 是 SSH Server 监听的端口,如果不指定,就为默认值 22
栗子:
如:远程登录服务器
# 标准用法:用户名@服务器IP/域名
ssh user@192.168.1.100
# 指定非默认端口
ssh -p 2222 user@your-server.com
2.1.9.3.2. scp
它的地址格式与 ssh 基本相同,需要注意的是,在指定端口时用的是大写的 -P 而不是小写的
scp [参数] 源路径 目标路径
【第一个参数永远是要复制的文件/目录,第二个参数是保存位置,不需要刻意区分本地和远端,只需要按照规则写路径即可。】
2.1.9.3.2.1. 常用参数说明
|--------|--------------------------------------------------------------------|
| 参数 | 作用 |
| -r | 递归复制,传输目录时必须加 【若给出的源文件是目录文件,则 scp 将递归复制该目录下的所有子目录和文件,目标文件必须为一个目录名】 |
| -P | 大写P,指定远程 SSH 端口(默认22),非默认端口必须指定 |
| -p | 小写p,保留源文件的修改时间、访问时间和权限 【保留文件的属性】 |
| -C | 启用压缩传输,大文件、慢网络下可节省带宽 |
| -v | 显示详细传输过程,适合调试连接问题 |
| -q | 静默模式,隐藏传输进度条 |
| -l | 限制传输带宽,单位为 kbit/s,避免占满整个网络 |
| -i | 指定密钥文件,适合基于公钥免密登录的场景 |
2.1.9.3.2.2. 常见场景使用示例
-
本地 → 远程:上传文件
上传单个文件
scp /本地路径/test.txt root@192.168.1.100:/远程目标路径/
上传整个目录(必须加 -r)
scp -r /本地路径/项目目录 root@192.168.1.100:/远程目标路径/
远程SSH端口非默认(如2222)的情况
scp -P 2222 ./test.txt root@192.168.1.100:/data/
-
远程 → 本地:下载文件
只需要调换源路径和目标路径的顺序即可:
# 下载单个文件到本地当前目录(. 代表当前目录)
scp root@192.168.1.100:/var/log/nginx.log .
# 下载整个目录到本地
scp -r root@192.168.1.100:/var/log/nginx ~/本地备份目录/
- 远程 → 远程:直接中转(本地当跳板)
如果需要在两台远程服务器之间直接传文件,本地同时能连通两台的情况下可以直接传输,不需要先下载再上传:
scp user1@主机1IP:/源文件路径 user2@主机2IP:/目标路径
2.2. http请求头
-
HTTP Request Header 请求头
Accept:指定客户端能够接收的内容类型。Accept-Charset:浏览器可以接受的字符编码集。
Accept-Encoding:指定浏览器可以支持的web服务器返回内容压缩编码类型。
Accept-Language:浏览器可接受的语言。
Accept-Ranges:可以请求网页实体的一个或者多个子范围字段。
AuthorizationHTTP:授权的授权证书。
Cache-Control:指定请求和响应遵循的缓存机制。
Connection:表示是否需要持久连接。(HTTP 1.1默认进行持久连接)
CookieHTTP:请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。
Content-Length:请求的内容长度。
Content-Type:请求的与实体对应的MIME信息。
Date:请求发送的日期和时间。
Expect:请求的特定的服务器行为。
From:发出请求的用户的Email。
Host:指定请求的服务器的域名和端口号。
If-Match:只有请求内容与实体相匹配才有效。
If-Modified-Since:如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码。
If-None-Match:如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变。
If-Range:如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。
If-Unmodified-Since:只在实体在指定时间之后未被修改才请求成功。
Max-Forwards:限制信息通过代理和网关传送的时间。
Pragma:用来包含实现特定的指令。
Proxy-Authorization:连接到代理的授权证书。
Range:只请求实体的一部分,指定范围。
Referer:先前网页的地址,当前请求网页紧随其后,即来路。
TE:客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息。
Upgrade:向服务器指定某种传输协议以便服务器进行转换(如果支持。
User-AgentUser-Agent:的内容包含发出请求的用户信息。
Via:通知中间网关或代理服务器地址,通信协议。
Warning:关于消息实体的警告信息
2.2.1.1.1. Host【域名】
Host: xxx.com
-
作用:告诉服务器访问哪个域名/站点
-
考点:虚拟主机、绕过限制、子域名探测
2.2.1.1.2. User-Agent(UA)【浏览器,设备】
User-Agent: Mozilla/5.0...
-
作用:告诉服务器你是什么浏览器/设备
-
考点:- 过滤禁止爬虫/特定浏览器
-
伪造手机端、爬虫、绕过WAF
-
CTF常考:UA写入漏洞、UA过滤
2.2.1.1.3. Referer【网页.com,本站访问】
Referer: https://www.baidu.com
-
作用:记录你从哪个页面跳转过来
-
考点:- 防盗链检测(只允许本站访问)
-
伪造来路绕过权限校验
2.2.1.1.4. Cookie【键值对】
Cookie: username=admin; token=123456
-
核心重点!
-
作用:存用户登录身份、凭证、权限、自定义参数
-
考点最多:- 改Cookie伪造管理员
-
Cookie注入、越权、session劫持
-
题目: isadmin=0 改成 isadmin=1 直接通关
2.2.1.1.5. X-Forwarded-For(XFF)【IP地址限制】
X-Forwarded-For: 127.0.0.1
-
作用:伪造客户端IP地址
-
万能考点:- 服务器限制本地访问(仅127.0.0.1可看)
-
直接加这个头伪装成内网/本地IP绕过
2.2.1.1.6. X-Real-IP【同X-Forwarded-For】
- 和XFF类似,也是伪造真实IP,部分服务器优先读这个
2.2.1.1.7. Content-Type【数据类型,如图片。。】
Content-Type: application/x-www-form-urlencoded
-
作用:告诉服务器提交的数据是什么格式
-
常用:- 表单普通提交: x-www-form-urlencoded
-
JSON提交: application/json
-
文件上传: multipart/form-data
-
考点:格式不对403/报错,改格式绕过检测
2.2.1.1.8. Accept / Accept-Language
- 一般不常考,部分题目用来过滤地区、语言
2.2.1.1.9. Authorization
- 基础认证登录,用来爆破、伪造账号密码
2.2.1.1.10. Origin
- 跨域请求源头,配合CSRF漏洞使用
2.2.1.1.11. Cache-Control
- 控制缓存,部分源码泄露、缓存漏洞用到
2.3. php学习
https://www.runoob.com/php/php-variables.html
2.3.1. php语法
2.3.1.1. 基础语法
-
PHP 脚本以 <?php 开始,以 ?> 结束
<?php ?> -
PHP 文件的默认文件扩展名是 .php
-
PHP 文件通常包含 HTML 标签和一些 PHP 脚本代码
-
每条语句末尾要加 ;
-
有两种在浏览器输出文本的基础指令:echo 和 print 【注意区分,后面细说】
2.3.1.2. 注释
|----------|-----------------------|--------------------|
| 用途 | 推荐注释形式 | 示例 |
| 简单说明一行代码 | // 或 # | // 输出信息 |
| 说明一段代码块 | /* ... */ | 用于逻辑分块的注释 |
| 函数/类文档说明 | /** ... */ DocBlock | 用于描述参数、返回值、用途等 |
2.3.2. php变量
变量是用于存储数据的容器
2.3.2.1.1.1. PHP 变量规则:
- 变量以**$** 符号开始,后面跟着变量的名称
- 变量名必须以字母或者下划线字符开始
- 变量名只能包含字母、数字以及下划线(A-z、0-9 和 _ )
- 变量名不能包含空格
- 变量名是区分大小写的(y 和 Y 是两个不同的变量)
2.3.2.1. 创建(声明)变量
-
变量在您第一次赋值给它的时候被创建
-
PHP 会根据变量的值,自动把变量转换为正确的数据类型【因为是弱类型】
<?php $txt="Hello world!"; $x=5; $y=10.5; ?>
当您赋一个文本值给变量时,请在文本值两侧加上引号
2.3.2.2. 变量作用域
变量的作用域是脚本中变量可被引用/使用的部分
PHP 有四种不同的变量作用域:
- local
- global
- static
- parameter
|---------------------|-----------------------------------------|----------------------------------------------------------------------|
| 概念 | PHP中的核心含义 | 作用域 |
| local(局部变量) | 在函数/类方法内部声明的变量 | 仅当前函数/方法内部可访问,外部无法读取或修改 |
| global(全局变量) | 在函数外部 声明的变量,或在函数内用global 关键字修饰的变量 | - 直接声明在函数外:默认整个脚本全局可访问<br>- 在函数内用global 修饰:可以引入函数外的同名全局变量到函数作用域内 |
| static(静态变量) | 在函数/类内部用static 关键字修饰的变量 | 和局部变量一致,仅函数/类内部可访问 |
| parameter(参数变量) | 函数定义时声明的输入参数,本质也是局部变量 | 仅当前函数内部可访问 |
补充:
【注意:全局与局部

】
【局部变量,只作用于该函数内】
【如果要在一个函数中访问一个全局变量,需要使用 global 关键字】
2.3.2.2.1. PHP global 关键字
在函数内调用函数外定义的全局变量,我们需要在函数中的变量前加上 global 关键字:

2.3.2.2.2. Static 作用域
当一个函数完成时,它的所有变量通常都会被删除。然而,有时候您希望某个局部变量不要被删除。
要做到这一点,请在您第一次声明变量时使用 static 关键字:
2.3.2.2.2.1. 栗子:
举一个普通局部变量和静态变量的对比
-
普通局部变量
function countVisitor(){
num = 0; // 普通局部变量 num = num + 1; echo "当前计数:".num."
";
}// 连续调用3次
countVisitor();
countVisitor();
countVisitor();
输出结果:
当前计数:1
当前计数:1
当前计数:1
为什么每次都是1?因为普通局部变量$num:
- 每次调用函数都会重新 创建、重新赋值为0
- 函数运行完就销毁,根本不会保留上次的结果
- 静态变量(点出核心区别)
把代码改成static:
function countVisitor(){
static $num = 0; // 静态变量
$num = $num + 1;
echo "当前计数:".$num."<br>";
}
// 同样连续调用3次
countVisitor();
countVisitor();
countVisitor();
输出结果:
当前计数:1
当前计数:2
当前计数:3
这就是静态变量的核心特点:
只初始化一次,值会一直保留,整个脚本运行周期都不会销毁,下次调用会沿用上次修改后的值。
而且它还是局部变量:只有这个函数内部能访问它,外部改不了它,既保留了数据,又不会污染全局,非常适合做计数这类场景。
2.3.2.3. 参数作用域
【专门用来接收函数输入的局部变量】
参数是通过调用代码将值传递给函数的局部变量。
参数是在参数列表中声明的,作为函数声明的一部分:

外部不可访问、用完销毁,接收外部输入**【前俩者局部变量也是】**
2.3.3. PHP 5 echo 和 print 语句
2.3.3.1. echo 和 print 区别:
|------------|--------------|-------------|
| 对比维度 | echo | print |
| 返回值 | 无返回值 | 总是固定返回整数1 |
| 参数数量 | 支持多个参数,用逗号分隔 | 仅支持1个参数 |
| 执行性能 | 略快(不需要处理返回值) | 稍慢 |
| 表达式中使用 | 不可以 | 可以(因为有返回值) |
2.3.3.2. 栗子
-
参数数量差异
// echo支持多参数输出
echo "Hello", " ", "World", "!"; // 正常输出:Hello World!// print只能传一个参数,这么写会报错
// print "Hello", "World"; // 语法错误
print "Hello World!"; // 正确写法 -
返回值和表达式用法差异
因为print固定返回1,所以可以把它放在条件判断这类表达式里:// 这种写法是合法的,print输出内容后返回1,条件恒成立
if (print "检查输出") {
echo "会执行这里";
}
// echo就不能这么用,语法直接报错
2.3.4. php数据类型
PHP 支持以下几种数据类型:
- String(字符串)
- Integer(整型)
- Float(浮点型)
- Boolean(布尔型)
- Array(数组)
- Object(对象)
- NULL(空值)
- Resource(资源类型)
2.3.4.1. php字符串
一个字符串是一串字符的序列,就像 "Hello world!"。
你可以将任何文本放在单引号和双引号中:
<?php
$x = "Hello world!";
echo $x;
echo "<br>";
$x = 'Hello world!';
echo $x;
?>
2.3.4.2. PHP 整型
整数是一个没有小数的数字。
整数规则:
- 整数必须至少有一个数字 (0-9)
- 整数不能包含逗号或空格
- 整数是没有小数点的
- 整数可以是正数或负数
- 整型可以用三种格式来指定:十进制, 十六进制( 以 0x 为前缀)或八进制(前缀为 0)。

【var_dump是输出这个变量的信息,如数值和数据类型】
2.3.4.3. PHP 浮点型
浮点数是带小数部分的数字,或是指数形式。
2.3.4.4. PHP 布尔型
布尔型可以是 TRUE 或 FALSE
布尔型通常用于条件判断。
$x=true;
$y=false;
2.3.4.5. PHP 数组
数组可以在一个变量中存储多个值。
<?php
$cars=array("Volvo","BMW","Toyota");
var_dump($cars);
?>

结果,会具体写出长度5,类型string,数值"volvo"
2.3.4.6. PHP 对象
对象数据类型也可以用于存储数据。
在 PHP 中,对象必须声明。
首先,你必须使用class关键字声明类对象。类是可以包含属性和方法的结构。
然后我们在类中定义数据类型,然后在实例化的类中使用数据类型:
<?php
class Car
{
var $color;
function __construct($color="green") {
$this->color = $color;
}
function what_color() {
return $this->color;
}
}
?>
以上实例中PHP关键字this就是指向当前对象实例的指针,不指向任何其他对象或类。
2.3.4.7. PHP NULL 值
NULL 值表示变量没有值。NULL 是数据类型为 NULL 的值。
NULL 值指明一个变量是否为空值。 同样可用于数据空值和NULL值的区别。
可以通过设置变量值为 NULL 来清空变量数据
<?php
$x="Hello world!";
$x=null;
var_dump($x);
?>
2.3.4.8. PHP 资源类型
PHP 资源resource是一种特殊变量,保存了到外部资源的一个引用。
常见资源数据类型有打开文件、数据库连接、图形画布区域等。
由于资源类型变量保存有为打开文件、数据库连接、图形画布区域等的特殊句柄,因此将其它类型的值转换为资源没有意义。
使用 get_resource_type() 函数可以返回资源(resource)类型:
get_resource_type(resource $handle): string
2.3.5. PHP 类型比较
虽然 PHP 是弱类型语言,但也需要明白变量类型及它们的意义,因为我们经常需要对 PHP 变量进行比较,包含松散和严格比较。
- 松散比较:使用两个等号 == 比较,只比较值,不比较类型。
- 严格比较:用三个等号 === 比较,除了比较值,也比较类型。
2.3.5.1. 栗子
<?php
if(42 == "42") {
echo '1、值相等';
}
echo PHP_EOL; // 换行符
if(42 === "42") {
echo '2、类型相等';
} else {
echo '3、类型不相等';
}
?>
结果:
1、值相等
3、类型不相等
2.3.5.2. PHP中 比较 0、false、null
<?php
echo '0 == false: ';
var_dump(0 == false);
echo '0 === false: ';
var_dump(0 === false);
echo PHP_EOL;
echo '0 == null: ';
var_dump(0 == null);
echo '0 === null: ';
var_dump(0 === null);
echo PHP_EOL;
echo 'false == null: ';
var_dump(false == null);
echo 'false === null: ';
var_dump(false === null);
echo PHP_EOL;
echo '"0" == false: ';
var_dump("0" == false);
echo '"0" === false: ';
var_dump("0" === false);
echo PHP_EOL;
echo '"0" == null: ';
var_dump("0" == null);
echo '"0" === null: ';
var_dump("0" === null);
echo PHP_EOL;
echo '"" == false: ';
var_dump("" == false);
echo '"" === false: ';
var_dump("" === false);
echo PHP_EOL;
echo '"" == null: ';
var_dump("" == null);
echo '"" === null: ';
var_dump("" === null);
结果:
0 == false: bool(true)
0 === false: bool(false)
0 == null: bool(true)
0 === null: bool(false)
false == null: bool(true)
false === null: bool(false)
"0" == false: bool(true)
"0" === false: bool(false)
"0" == null: bool(false)
"0" === null: bool(false)
"" == false: bool(true)
"" === false: bool(false)
"" == null: bool(true)
"" === null: bool(false)
2.3.5.3. 一些些



2.3.6. php常量
-
- PHP 中的常量是指一旦定义后其值不能被改变的标识符。
- 常量值被定义后,在脚本的其他任何地方都不能被改变。
- 常量可以用
define()函数或const关键字来定义。 - 全局作用域 : 常量在定义后,可以在整个脚本的任何地方使用,无需使用
global关键字。
【在函数内调用函数外定义的全局变量,我们需要在函数中的变量前加上 global 关键字】
-
- 一个常量由英文字母、下划线、和数字组成,但数字不能作为首字母出现。 (常量名不需要加 $ 修饰符)。
2.3.6.1. 设置 PHP 常量【define】
设置常量,使用 define() 函数,函数语法如下:
bool define ( string $name , mixed $value [, bool $case_insensitive = false ] )
该函数有三个参数:
- name**:** 必选参数,常量名称,即标志符。
- value**:** 必选参数,常量的值。
- case_insensitive:可选参数,如果设置为
TRUE,该常量则大小写不敏感,默认是大小写敏感的。
栗子:
<?php
// 区分大小写的常量名
define("GREETING", "欢迎访问 Runoob.com");
echo GREETING; // 输出 "欢迎访问 Runoob.com"
echo '<br>';
echo greeting; // 输出 "greeting",但是有警告信息,表示该常量未定义
?>
2.3.6.2. 设置PHP常量【const】
const CONSTANT_NAME = "value";
以下是一个使用 const 关键字定义常量的实例:
const SITE_URL = "https://www.runoob.com";
echo SITE_URL;
// 输出 "https://www.runoob.com"
2.3.6.3. 预定义常量
PHP 提供了一些预定义常量,可以在脚本中直接使用。
这些常量通常用于获取 PHP 的配置信息、版本信息等。常见的预定义常量有:
PHP_VERSION:当前 PHP 解析器的版本。PHP_OS:服务器的操作系统。PHP_INT_MAX:最大的整数值。E_ERROR、E_WARNING、E_PARSE等:错误报告级别。
【直接echo就行了,echo PHP_VERSION ; // 输出 PHP 版本,例如 "7.4.1"】
2.3.6.4. 常量数组

define是用的("#",[]); const是用的 #=[,];
2.3.7. PHP的字符串
字符串变量用于存储并处理文本。
【字符串变量用于包含有字符的值。】
对应的函数有特别多,https://www.runoob.com/php/php-ref-string.html
这里提三个
- 创建字符串
$text="hello word";
- PHP 并置运算符
使用.进行连接
如:$text1." ".$text2;
- PHP
strlen()函数
echo strlen("Hello world!");
- PHP
strpos()函数
strpos() 函数用于在字符串内查找一个字符或一段指定的文本。
echo strpos("Hello world!","world");
注意,从字符0开始算,找"world"第一个字符,即为6(不是7)
2.3.8. PHP运算符
在 PHP 中,赋值运算符 = 用于给变量赋值。
在 PHP 中,算术运算符 + 用于把值加在一起。
2.3.8.1. PHP算术运算符
|-------------|------------|-----------------------------------------|----------------------------|-------|
| 运算符 | 名称 | 描述 | 实例 | 结果 |
| x + y | 加 | x 和 y 的和 | 2 + 2 | 4 |
| x - y | 减 | x 和 y 的差 | 5 - 2 | 3 |
| x * y | 乘 | x 和 y 的积 | 5 * 2 | 10 |
| x / y | 除 | x 和 y 的商 | 15 / 5 | 3 |
| x % y | 模 [除法余数] | x 除以 y 的余数 | 5 % 2 10 % 8 10 % 2 | 1 2 0 |
| intdiv(x,y) | 整除 | 返回值为第一个参数除于第二个参数的值并取整(向下取整) | 10%3 | 3 |
| -x | 设置负数 | 取 x 的相反符号 | <?php $x = 2; echo -$x; ?> | -2 |
| ~x | 取反 | x 取反,按二进制位进行"取反"运算。 运算规则: ~1=-2; ~0=-1; | <?php $x = 2; echo ~$x; ?> | -3 |
| a . b | 并置 | 连接两个字符串 | "Hi" . "Ha" | HiHa |
2.3.8.1.1. 取反【进一步解释栗子】
- 正数的补码 = 原码(本身的二进制)
- 负数的补码 = 原码符号位不变,其余位取反后加1
- 按位取反
~操作是:把二进制的所有位0变1、1变0,包括符号位 - 通用公式:::对整数 n****按位取反,结果永远是 ~n = -(n+1)

2.3.8.1.2. 加减乘除
<?php
$x=10;
$y=6;
echo ($x + $y); // 输出16
echo '<br>'; // 换行
echo ($x - $y); // 输出4
echo '<br>'; // 换行
echo ($x * $y); // 输出60
echo '<br>'; // 换行
echo ($x / $y); // 输出1.6666666666667
echo '<br>'; // 换行
echo ($x % $y); // 输出4
echo '<br>'; // 换行
var_dump(intdiv($x, $y));
//输出int(1)
echo -$x;
?>
2.3.8.2. PHP赋值运算符
基本的赋值运算符是 =。它意味着左操作数被设置为右侧表达式的值。
|---------|------------|-----------------|
| 运算符 | 等同于 | 描述 |
| x = y | x = y | 左操作数被设置为右侧表达式的值 |
| x += y | x = x + y | 加 |
| x -= y | x = x - y | 减 |
| x *= y | x = x * y | 乘 |
| x /= y | x = x / y | 除 |
| x %= y | x = x % y | 模(除法的余数) |
| a .= b | a = a . b | 连接两个字符串 |
2.3.8.2.1. 栗子
上面运算符使用
<?php
$x=10;
echo $x; // 输出10
$y=20;
$y += 100;
echo $y; // 输出120
$z=50;
$z -= 25;
echo $z; // 输出25
$i=5;
$i *= 6;
echo $i; // 输出30
$j=10;
$j /= 5;
echo $j; // 输出2
$k=15;
$k %= 4;
echo $k; // 输出3
?>
不同运算符可以得到相同的结论
<?php
$a = "Hello";
$b = $a . " world!";
echo $b; // 输出Hello world!
$x="Hello";
$x .= " world!";
echo $x; // 输出Hello world!
?>
2.3.8.3. PHP递增/递减运算符【已忘,易混】
【符号在变量前面,就先处理符号再返回值】
|------|-----|---------------|
| 运算符 | 名称 | 描述 |
| ++ x | 预递增 | x 加 1,然后返回 x |
| x ++ | 后递增 | 返回 x,然后 x 加 1 |
| -- x | 预递减 | x 减 1,然后返回 x |
| x -- | 后递减 | 返回 x,然后 x 减 1 |
2.3.8.3.1. 栗子
<?php
$x=10;
echo ++$x; // 输出11
$y=10;
echo $y++; // 输出10
$z=5;
echo --$z; // 输出4
$i=5;
echo $i--; // 输出5
?>
2.3.8.4. PHP比较运算符
|----------|-------|-------------------------------|------------------|
| 运算符 | 名称 | 描述 | 实例 |
| x == y | 等于 | 如果 x 等于 y,则返回 true | 5==8 返回 false |
| x === y | 绝对等于 | 如果 x 等于 y,且它们类型相同,则返回 true | 5==="5" 返回 false |
| x != y | 不等于 | 如果 x 不等于 y,则返回 true | 5!=8 返回 true |
| x <> y | 不等于 | 如果 x 不等于 y,则返回 true | 5<>8 返回 true |
| x !== y | 不绝对等于 | 如果 x 不等于 y, 或它们类型不相同,则返回 true | 5!=="5" 返回 true |
| x > y | 大于 | 如果 x 大于 y,则返回 true | 5>8 返回 false |
| x < y | 小于 | 如果 x 小于 y,则返回 true | 5<8 返回 true |
| x >= y | 大于等于 | 如果 x 大于或者等于 y, 则返回 true | 5>=8 返回 false |
| x <= y | 小于等于 | 如果 x 小于或者等于 y, 则返回 true | 5<=8 返回 true |
2.3.8.4.1. 栗子

2.3.8.5. PHP逻辑运算符
|----------|----|---------------------------------|---------------------------------------|
| 运算符 | 名称 | 描述 | 实例 |
| x and y | 与 | 如果 x 和 y 都为 true,则返回 true | x=6 y=3 (x < 10 and y > 1) 返回 true |
| x && y | 与 | 如果 x 和 y 都为 true,则返回 true | x=6 y=3 (x < 10 && y > 1) 返回 true |
| x or y | 或 | 如果 x 和 y 至少有一个为 true, 则返回 true | x=6 y=3 (x==6 or y==5) 返回 true |
| x || y | 或 | 如果 x 和 y 至少有一个为 true, 则返回 true | x=6 y=3 (x==5 || y==5) 返回 false |
| x xor y | 异或 | 如果 x 和 y 有且仅有一个为 true, 则返回 true | x=6 y=3 (x==6 xor y==3) 返回 false |
| ! x | 非 | 如果 x 不为 true,则返回 true | x=6 y=3 !(x==y) 返回 true |
2.3.8.6. PHP数组运算符【与算数运算符区分】
|----------|-----|---------------------------------------|
| 运算符 | 名称 | 描述 |
| x + y | 集合 | x 和 y 的集合 |
| x == y | 相等 | 如果 x 和 y 具有相同的键/值对,则返回 true |
| x === y | 恒等 | 如果 x 和 y 具有相同的键/值对,且顺序相同类型相同,则返回 true |
| x != y | 不相等 | 如果 x 不等于 y,则返回 true |
| x <> y | 不相等 | 如果 x 不等于 y,则返回 true |
| x !== y | 不恒等 | 如果 x 不等于 y,则返回 true |
2.3.8.6.1. 栗子
<?php
$x = array("a" => "red", "b" => "green");
$y = array("c" => "blue", "d" => "yellow");
$z = $x + $y; // $x 和 $y 数组合并
var_dump($z);
var_dump($x == $y);
var_dump($x === $y);
var_dump($x != $y);
var_dump($x <> $y);
var_dump($x !== $y);
?>
结果:
array(4) { ["a"]=> string(3) "red" ["b"]=> string(5) "green" ["c"]=> string(4) "blue" ["d"]=> string(6) "yellow" }
bool(false)
bool(false)
bool(true)
bool(true)
bool(true)
2.3.8.7. 三元运算符【在C也常见】
(expr1) ? (expr2) : (expr3)
对 expr1 求值为 TRUE 时的值为 expr2,在 expr1 求值为 FALSE 时的值为 expr3。
2.3.8.7.1. 栗子
<?php
// 普通写法
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
echo $username, PHP_EOL;
// PHP 5.3+ 版本写法
$username = $_GET['user'] ?: 'nobody';
echo $username, PHP_EOL;
?>
PHP_EOL 是一个换行符
通过判断 _GET 请求中含有 user 值,如果有返回 _GET['user'],否则返回 nobody
2.3.8.8. 组合比较符(PHP7+)
组合比较符 也称之为太空船操作符 ,符号为 <=>。
组合比较运算符可以轻松实现两个变量的比较,当然不仅限于数值类数据的比较。
语法格式如下:
$c = $a <=> $b;
解析如下:
- 如果**a \> b** , 则 $c 的值为 1。
- 如果 a == b , 则 $c 的值为 0。
- 如果 a \< b , 则 $c 的值为 -1。
2.3.8.8.1. 栗子
<?php
// 整型
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// 浮点型
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// 字符串
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>
2.3.8.9. 运算符优先级
下表按照优先级从高到低列出了运算符。同一行中的运算符具有相同优先级,此时它们的结合方向决定求值顺序。
|------|-----------------------------------------------------------|--------------|
| 结合方向 | 运算符 | 附加信息 |
| 无 | clone new | clone 和 new |
| => | [ | array() |
| <= | ++ -- ~ (int) (float) (string) (array) (object) (bool) @ | 类型和递增/递减 |
| 无 | instanceof | 类型 |
| <= | ! | 逻辑运算符 |
| => | * / % | 算术运算符 |
| => | + -- . | 算术运算符和字符串运算符 |
| => | << >> | 位运算符 |
| 无 | == != === !== <> | 比较运算符 |
| => | & | 位运算符和引用 |
| => | ^ | 位运算符 |
| => | | | 位运算符 |
| => | && | 逻辑运算符 |
| => | || | 逻辑运算符 |
| => | ? : | 三元运算符 |
| <= | = += -= *= /= .= %= &= |= ^= | 赋值运算符 |
| => | and | 逻辑运算符 |
| => | xor | 逻辑运算符 |
| => | or | 逻辑运算符 |
| => | , | 多处用到 |
2.3.8.9.1. 补充:与,或
运算符优先级中,or 和 ||,&& 和 and 都是逻辑运算符,效果一样,但是其优先级却不一样。
<?php
// 优先级: && > = > and
// 优先级: || > = > or
$a = 3;
$b = false;
$c = $a or $b;
var_dump($c); // 这里的 $c 为 int 值3,而不是 boolean 值 true
$d = $a || $b;
var_dump($d); //这里的 $d 就是 boolean 值 true
?>
$c = $a or $b;
因为or的优先级比=低,所以执行顺序是:
- 先执行赋值操作:
$c = $a,此时$a是3,所以$c直接被赋值为整数3 - 再执行
or运算:计算$c or $b,但这个运算结果没有被赋值给任何变量,直接被丢弃了
$d = $a || $b;
因为||的优先级比=高,所以执行顺序刚好反过来:
- 先执行逻辑运算:
$a || $b,$a=3在PHP中是真值,所以运算结果是布尔true - 再把运算结果赋值给
$d
2.3.8.10. 括号的使用
我们通过括号的配对来明确标明运算顺序,而非靠运算符优先级和结合性来决定,通常能够增加代码的可读性。
// 括号优先运算
3. 题目
3.1. [MoeCTF 2021]Do you know HTTP
3.1.1. 题目
https://www.nssctf.cn/problem/3408
检查一下你的学习成果吧
仅仅学习了HTTP请求头相关内容,你可能会发现浏览器已经不足以让你便利的去解决问题了,试试burpsuite!
https://github.com/XDSEC/moeCTF_2021

3.1.2. 解题
题目已经提示,使用bp来解题
3.1.2.1. 第一步
【1】误区:题目要求,用HS请求,我以为是?HS=
实际上是像get这种的请求方式
用bp对请求方式进行修改

将GET改为HS

【2】误区:
【注意,我发现我在拦截的时候,出现了很多的请求,导致我不知道哪一个是我要修改的】如下面的错误示范

HS/collect/pvoriginFrom=http%3A%2F%2Fnode5.anna.nssctf.cn%3A24911%2F&id=nGp0ycKWRnaOEGGwQW&uin=4746391841&version=1.41.10&aid=dad1ffcb-3dfa-4986-86ed-8f3ed69c9d4b&env=production&platform=3&netType=4&vp=954%20*%20512&sr=1440%20*%20900&sessionId=session&from=http%3A%2F%2Fnode5.anna.nssctf.cn%3A24911%2F&referer= HTTP
这是站点埋点的上报统计请求
- 请求路径里的
collect、pv都是固定的统计上报关键词 - 里面的
originFrom、from、referer都是用来记录页面来源,id、sessionId是用户标识,version是SDK版本------这些全是统计用的参数,和你要做操作的业务功能无关
3.1.2.2. 第二步
改完这个请求方式后,他要求只有本地ip才可以,所以继续在reapter里面修改

可以在右侧修改,也可以直接在左侧修改,然后send


3.1.2.3. 第三步
希望我从这个地点过来

Referer一下就好了
3.1.2.4. 第四步

User-Agent改一下
3.1.3. 总结:
这题其实就是在考察http请求头的修改应用,本人卡在了第一步这个HS这个请求方式没见过,不知道是请求方式,在修改时,因为很多的请求过来,不知道哪一个是我需要修改的,同时其他的请求头内容有点生疏。
3.2. [SWPUCTF 2024 秋季新生赛]http标头
3.2.1. 题目
https://www.nssctf.cn/problem/5942
web签到

3.2.2. 解题
3.2.2.1. 第一步

要在出售第一时间,注意date形式,我们可以去网络这里找到date的格式

Tue, 20 Aug 2024 00:00:00 GMT【这个我是查的,出售时间和几月几号星期几我不知道】
星期缩写, 日 月份缩写 年 时:分:秒 GMT,其中日固定为两位数,不足补前导零。
3.2.2.2. 第二步

浏览器,就用User-Agent
3.2.2.3. 第三步
按他的提示,可以很快写出来

3.3. [SWPUCTF 2021 新生赛]babyrce
3.3.1. 题目
<?php
error_reporting(0);
header("Content-Type:text/html;charset=utf-8");
highlight_file(__FILE__);
if($_COOKIE['admin']==1)
{
include "../next.php";
}
else
echo "小饼干最好吃啦!";
?> 小饼干最好吃啦!
3.3.2. 解题
3.3.2.1. 第一步
if else很容易看出要使得COOKIE中admin=1

3.3.2.2. 第二步
访问这个.php文件,发现新的代码
<?php
error_reporting(0);
highlight_file(__FILE__);
error_reporting(0);
if (isset($_GET['url'])) {
$ip=$_GET['url'];
if(preg_match("/ /", $ip)){
die('nonono');
}
$a = shell_exec($ip);
echo $a;
}
?>
就是用get的方式输入url来求值,注意有这个过滤(空格)

将空格用%09过滤,发现不报错了,但是无结果?

自以为是,注意flag不一定在/flag里头,你要去寻找
ls查找当前目录下

ls查找主目录下

找到flag在目录fllllllaaaaaagggggggg里头

3.3.3. 总结
注意:不要下意思以为flag在哪里,要去查找,一大坑点之一
4. 补充

发现电脑关闭后仍有轰鸣声,是因为S3模式 没有开,但是我不知道要不要打开,学长要是有看到帮帮忙~~❤️❤️❤️
5. 总结本周
5.1.1.1.1.1. 发牢骚
主要是看这个理论知识,了解基础的命令,真的是很枯燥,看的脑袋晕晕的,无数次想要放弃。。。一直在给自己打气,想说再看一点再看一点,争取把所有的命令的过一遍呀呀呀。。而且我尽量让这些命令在大脑里留下点痕迹,而非只是单纯的看,
5.1.1.1.1.2. 学了个啥知识呢?
- linux的命令全部过了一遍【非常久!!!】
- http请求头知识在做题时发现有点遗忘,回顾了一下,同时看了以前的Http的笔记【从协议,连接互联网开始】
- php的学习,但是没有完全学完,学到运算符【里头运算符种类还挺多】【下周将继续学习这一部分内容】
- 两道http题目
5.1.1.1.1.3. 下周要补充:
- rce这周没有时间看,下周将继续
- php的知识点学习继续
- 下周看看能不能把vscode搞好,上学期没有把Php配置弄好