1、sql注入漏洞中,常见的防护方案有哪些?请简述原理和用法
类型转换
将输入强制转换为整数/浮点用于整数/浮点类型的输入参数处理可防止SQL注入
常用函数:
- intval($input)
- floatval()
- floor()
- (int)$input
- $input + 0
以intval函数为例:
<?php
/*强制类型转换*/
$id=intval($_GET['id']); //因查询ID为整数 所以可以强制转换为整数
$id=$pdo->quote($_GET['name']);
/*预处理语句*/
$stmt =$pdo->prepare("SELECT id, name FROM users WHERE id=?;");
$stmt->execute([$_GET['id']]);
?>
特殊字符转义
原理:在单引号'、双引号"、反斜线\与 NULL前加上反斜线可用于防止SQL注入。
- addslashes函数以及magic_quotes_gpc选项具有该功能其中,当magic_quotes_gpc=On时,如果post、get、cookie过来的数据有单引号、双引号、反斜线与 NULL等字符,PHP解析器就会自动增加转义字符
\,如果这个选项为off,那么我们就必须调用addslashes函数来为字符串增加转义。 - PDO::quote() 转义特殊字符并添加引号
开启gpc,打开php.ini 找到 magic_quotes_gpc = Off 设置成On 重启服务,即可开启
<?php
var_dump(get_magic_quotes_gpc()); //查询gpc的值 1 是开启 0是关闭
在程序中通常是检测 gpc是否开启 如果没有开启则使用 addslashes 对传过来的字符进行过滤
<?php
function check_put($str){
if(!get_magic_quotes_gpc()){ //判断gpc是否开启
return addslashes($str); //没有开启 使⽤ addslashes 进行过滤
}
return $str;
}
echo check_put($_GET['id']);
2、针对常见的防护方案,哪些是可以绕过的?哪些又没法绕过?
可绕过
SQL语句中传参无单引号闭合:如数字型时,攻击者的SQL注入语句不需要单引号闭合,即addslashes函数不起作用,可以绕过。
宽字节注入(传入的参数会使用GBK编码,如:iconv()和 mb_convert_encodeing()函数等)
如:SQL语句为id=1%df'时,addslashes()函数会在单引号(%27)前面加⼀个反斜杠(%5c),在GBK编码中,%df%5c为汉字運,这就导致后面的单引号逃逸,实现绕过。
编解码绕过(urldecode、base64_decode、json_decode 编码注入)
以urldecode编码注入为例:对注入语句进行两次编码,首先前端会进行一次解码,然后将依旧是url编码的注入语句传递给后端,使得addslashes()过滤失效,最后urlencode函数进行解码还原注入语句
//%2527 第⼀次解码%25转换成% 再拼接27变成 %27在进行解码等于'所以会造成注入
$id= $_GET['id'];
$id = addslashes($id);
$id = urldecode($id);
echo "select * from news where id='$id'";
弱类型
在判断数据类型时,php有类型函数对其判断,php是⼀种弱类型,会自动转换类型。如果只是判断并没有赋值。可能会造成漏洞。
- intval,整型转换函数
- in_array 、array_search
- swith
- is_numeric
如果使用is_numeric,is_numeric会先对十六进制做类型判断,⼗六进制被判断为数字型为真,就进入了条件语句,如果再把这个代 入进入sql语句进入mysql数据库,mysql数据库会对hex进行解析成字符串存入到数据库中,如果这个字段再被取出来⼆次利用,就 可能造成⼆次注入漏洞。
二次注入
⼆次注入的原理,在第⼀次进行数据库插入数据的时候,仅仅只是使⽤了 addslashes 或者是借助 magic_quotes_gpc 对其中的特殊字符进行了转义,但是addslashes有⼀个特点就是虽然参数在过滤后会添加 “\” 进行转义,但是“\”并不会插入到数据库中,在写入数据库的时候还是保留了原来的数据。
http头信息注入
通常程序员会设置全局过滤防止SQL注入,开启之后 GET、POST、Cookie这些传入过来的值都会进行过滤。而http头信息是直接获取,不会对其进行过滤。通过http头信息注入,来实现绕过。
无法绕过
- 强制类型转换(如intval函数处理数字型参数)
- 参数化查询(预处理语句):SQL代码与数据分离,使得攻击者无法改变SQL命令的结构。
- 严格的输入白名单验证:非白名单字符(如
'、"、#)会被直接拒绝。 - 数据库权限最小化
3、请参考pikachu靶场,审计并利用宽字节注入漏洞
查询pikachu源码中set character_set_client=gbk语句,找到宽字节注入漏洞模块
// 设置客户端编码为GBK - 这是漏洞根源
$set = "set character_set_client=gbk";
execute($link,$set);
// 用户输入经过转义处理
$name = escape($link,$_POST['name']);
// 构建SQL查询 - 存在宽字节注入风险
$query="select id,email from member where username='$name'";
当MySQL客户端编码设置为GBK时,某些特殊字符(如0xbf27)会被解释为一个多字节字符,导致转义反斜杠被"吞掉"。
4、命令注入漏洞常见的函数有哪些?
system( ):能够将字符串作为OS命令执行,自带输出功能。
exec( ):能够将字符串作为OS命令执行,需要输出执行结果。返回结果是有限的。
shell_exec( ):通过 shell 执行命令并将完整的输出以字符串的方式返回。
passthru( ):执行外部程序并且显示原始输出。
pcntl_exec( ):pcntl是linux下的⼀个扩展,可以支持php的多线程操作。pcntl_exec函数的作用是在当前进程空间执行。
popen( ):打开⼀个指向进程的管道,该进程由派生给定的 command 命令执行产生。
proc_open( ):执行⼀个命令,并且打开用来输入/输出的文件指针。
反单引号``:在php中称之为执行运算符,PHP 将尝试将反引号中的内容作为 shell 命令来执行,并将其输出信息返。
ob_start( ): 是 PHP 中用于开启输出缓冲的函数
5、代码执行漏洞常见的函数有哪些?
eval( ):函数把字符串按照 PHP 代码来计算。该字符串必须是合法的 PHP 代码,且必须以分号结尾。
assert( ):功能是判断⼀个表达式是否成立,返回true or false,重点是函数会执行此表达式。
preg_replace( ):执行⼀个正则表达式的搜索和替换。
call_user_func( ): 把第一个参数作为回调函数调用。
call_user_func_array( ):调用回调函数,并把⼀个数组参数作为回调函数的参数。
create_function( ):PHP中的内置函数,用于在PHP中创建匿名(lambda-style)函数。
6、如何结合伪协议通过文件包含漏洞读取文件?请简述原理
| 1. 发现参数 | 找到可控的 include/require 参数。 |
|---|---|
| 2. 使用伪协议 | 构造 php://filter URL,指定 convert.base64-encode 过滤器。 |
| 3. 指定目标文件 | 通过 resource= 参数指向要读取的敏感文件(如源码、配置文件)。 |
| 4. 服务器处理 | PHP引擎读取目标文件,将其内容Base64编码后输出,而非执行。 |
| 5. 攻击者解码 | 获取输出的Base64字符串,解码后得到文件原始内容。 |
防御措施:
- 避免动态包含用户输入是根本解决方法。
- 如果必须动态包含,采用白名单机制,只允许包含预定义好的文件。
- 严格过滤输入,检查是否包含
../、php://、file://等危险协议或路径遍历字符。 - 配置
php.ini中的allow_url_fopen和allow_url_include为 Off(默认已是Off),这可以防止php://、http://等伪协议的使用,极大增加利用难度。
7、复习php常见漏洞
SQL注入漏洞
概述:未过滤的用户输入直接拼接 SQL 语句,导致恶意 SQL 语句执行。
修复方案:使用预编译语句和参数化查询,对所有用户输入进行严格的验证和过滤。
命令注入
概述:应用程序在执行系统命令时,未对用户输入进行适当的过滤或验证,导致攻击者能够注入恶意命令并在服务器上执行。
修复方案:使用过滤函数内置函数 escapeshellcmd(), escapeshellarg(),过滤和转义输入中的特殊字符,使用白名单限制输入,禁用危险函数。
代码执行
概述:在WEB中,PHP代码执行是指应用程序过滤不严,用户通过http请求将代码注入到应用中执行。
修复方案:严格对用户的输入进行验证与过滤、避免使用动态执行函数如eval()、create_function()、assert()、preg_replace()等、禁用危险函数,在php.ini中禁用不安全的函数,比如eval()、exec()、system()、passthru()等。
文件包含
概述:直接包含用户可控的文件路径,导致本地/远程代码执行。
修复方案:用户输入不能作为 include()的目标、限制 allow_url_include = Off(防止 RFI)、使用白名单验证文件路径。
文件上传
概述:未对上传文件的类型、内容、后缀名等进行严格校验,导致恶意代码上传并执行。服务端对上传的文件处理逻辑不够安全,则会导致上传漏洞。
修复方案:严格限制上传文件类型、文件名处理、限制文件上传目录。
变量覆盖漏洞
概述:变量覆盖即通过外部输入将某个变量的值给覆盖掉,通常将可以用自定义的参数值替换原有变量值的情况称为变量覆盖漏洞,攻击者通过用户输入覆盖 PHP 代码中的全局变量进而影响程序的正常逻辑,甚至执行恶意操作。
修复方案:避免 extract() 和 parse_str()覆盖全局变量、明确变量来源不依赖全局变量。
XSS漏洞
概述:未对用户输入的数据进行输出时的 HTML 实体编码,导致攻击者可以注入恶意 JavaScript。
修复方案:对所有输出到浏览器的内容进行适当的HTML实体编码。
SSRF漏洞
概述:是由于服务端提供了从其他服务器获取数据,但没有对地址或协议等进⾏过滤或限制造成的漏洞。
修复方案:校验用户输入的url,限制协议类型、使用白名单机制。
CSRF
概述:攻击者诱导用户在已认证的状态下向应用发送伪造请求。
修复方案:添加token/Referer校验,拒绝空Referer。
XXE
概述:攻击者通过自定义实体访问系统文件或远程资源。
修复方案:禁用XML解析器中的外部实体解析、使用安全的XML库(默认不支持外部实体)、验证和清理输入的XML内容,避免恶意内容被解析。
反序列化
概述:反序列化不可信数据导致代码执行或逻辑绕过。
修复方案:避免反序列化用户输入、使用 JSON 等安全格式替代
其他漏洞
逻辑漏洞
概述:越权访问、未授权访问、频率限制绕过、拒绝服务、URL跳转等
越权漏洞
拒绝服务
概述:通过特殊的用户输⼊ 消耗的服务器资源比如生成图片不限宽高(⼆维码、验证码、图片处理)
URL跳转