接上一次的继续整理。
3.3 回调漏洞
0x01 漏洞背景
在 PHP 一些回调函数中,如果函数输入可控,可以利用回调 assert 等方法进行命令执行漏洞
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
call_user_func($_REQUEST['fun'], $_REQUEST['pass']);
?>
- 漏洞代码 2 :
<?php
array_map($_REQUEST['fun'], $_REQUEST['pass']);
?>
在 fun 传递可控的情况下,会引起代码执行漏洞
- 修复建议:
第一个参数不让用户可控 - 建议修复代码:
array_map('addslashes', $_REQUEST['pass']);
参考文章:
https://www.leavesongs.com/penetration/php-callback-backdoor.html
4.1 命令执行漏洞
0x01 漏洞背景
exec 、 system 、 shell_exec 、 passthru 等命令执行函数,在传入的命令过滤不严,可导致任意命令执行漏洞,危及服务器。
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
$url = $_GET['url'];
$content = system("curl $url");
echo $content;
?>
直接将可控内容带入命令执行中,导致产生漏洞
- 漏洞代码 2 :
<?php
if (isset($_REQUEST['ip'])) {
$target = trim($_REQUEST['ip']);
$substitutions = array(
'&' => '',
';' => '',
'|' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
$target = str_replace(array_keys($substitutions) , $substitutions, $target);
$cmd = shell_exec('ping -c 4 ' . $target);
echo $target;
echo "<pre>{$cmd}</pre>";
} ?>
虽然进行了一些过滤,但是过滤不严, %0a 可绕过命令执行
- 修复建议:
不要让用户可控的内容带入命令执行中
参考文章:
http://www.freebuf.com/articles/web/137923.html
5.1 普通注入漏洞
0x01 漏洞背景
SQL 注入是攻击者通过把恶意 SQL 命令插入到 Web 表单的输入域或页面请求的查询字符串中,来达到欺骗服务器执行恶意的 SQL 命令的一种攻击方式
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
$mysqli = new mysqli('localhost', 'root', 'root', 'code'); // 数据库连接
$id = !empty($_GET['id']) ? $_GET['id'] : '1';
$data = $mysqli->query("select content from test where id=$id");
if ($data->num_rows !== '0') {
$arr = $data->fetch_all();
foreach ($arr as $a) {
echo ' 内容: ' . $a[0] . '<br>';
}
}
?>
对于传入的内容未过滤,且 SQL 拼接的时候没有单引号保护
- 修复建议:
使用单引号保护并过滤内容 - 建议修复代码:
$id = !empty($_GET['id']) ? addslashes($_GET['id']) : '1';
$data = $mysqli->query("select content from test where id='$id'");
- 漏洞代码 2 :
<?php
$mysqli = new mysqli('localhost', 'root', 'root', 'code'); // 数据库连接
$id = !empty($_GET['id']) ? $_GET['id'] : '1';
$data = $mysqli->query("select content from test where id='$id'");
if ($data->num_rows !== '0') {
$arr = $data->fetch_all();
foreach ($arr as $a) {
echo ' 内容: ' . $a[0] . '<br>';
}
}
?>
即使使用了单引号保护,但是传入内容未过滤,导致 SQL 注入
-修复建议:
参考代码 1 修复
- 漏洞代码 3 :
<?php
$mysqli = new mysqli('localhost', 'root', 'root', 'code'); // 数据库连接
if (!empty($_POST['content'])) {
$name = $_POST['name'];
$content = $_POST['content'];
if ($mysqli->query("insert into test (content)values('$name','$content')")) {
echo ' 发言成功 ';
} else {
echo ' 发言失败 ';
}
}
?>
nsert 型注入,差不多的注入方式。
- 修复建议: 对 SQL 拼接时一定要单引号保护,整数型也不例外,并且传入的值要经过 addslashes 函数过滤。不过最好的方案还是用 PDO 预处理
- 修复代码:
$name = addslashes($_POST['name']);
$content = addslashes($_POST['content']);
if($mysqli->query("insert into test (content)values('$name','$content')"))
5.2 宽字节注入漏洞
0x01 漏洞背景
宽字节注入发生的位置就是 PHP 发送请求到 MYSQL 时字符集使用 charactersetclient 设置值进行了一次编码
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
$mysqli = new mysqli('localhost', 'root', 'root', 'code'); // 数据库连接
$id = !empty($_GET['id']) ? addslashes($_GET['id']) : '1';
$mysqli->query("SET NAMES 'gbk'");
$data = $mysqli->query("select content from test where id='$id'");
if ($data->num_rows !== '0') {
$arr = $data->fetch_all();
foreach ($arr as $a) {
echo ' 内容: ' . $a[0] . '<br>';
}
}
?>
执行 SET NAMES 'gbk' 之后会引起宽字节注入漏洞,绕过单引号达到注入效果
- 修复建议:
字符集编码设置成 utf8 - 建议修复代码:
$mysqli->query("SET NAMES 'utf8'");
5.3 字符集漏洞
0x01 漏洞背景
默认情况下, Mysql 的字符集就是 latin1 , Mysql 字段的字符集和 php mysqli 客户端设置的字符集不相同导致可能绕过登录等情况
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
$mysqli = new mysqli('localhost', 'root', 'root', 'code'); // 数据库连接
if (!empty($_POST['username']) && !empty($_POST['password'])) {
$username = addslashes($_POST['username']);
$password = addslashes($_POST['password']);
$data = $mysqli->query("select * from user where username='$username' and password='$password'");
if ($data->num_rows !== '0') {
$arr = $data->fetch_row();
session_start();
$_SESSION['username'] = $arr[1];
echo ' 登录成功 ';
}
}
?>
例如管理员账号是 admin ,注册 admin%c2 ,登录之后就是管理员权限了
- 修复建议:
将数据库字符集修改为 utf8 - 参考文章:
https://www.leavesongs.com/PENETRATION/mysql-charset-trick.html
6.1 hash 比较绕过
0x01 漏洞背景
=== 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较
== 在进行比较的时候,会先将字符串类型转化成相同,再比较
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
if (isset($_GET['Username']) && isset($_GET['password'])) {
$logined = true;
$Username = $_GET['Username'];
$password = $_GET['password'];
if (!ctype_alpha($Username)) {
$logined = false;
}
if (!is_numeric($password)) {
$logined = false;
}
if (md5($Username) != md5($password)) {
$logined = false;
}
if ($logined) {
echo "successful";
} else {
echo "login failed!";
}
}
?>
0e 在比较的时候会将其视作为科学计数法,所以无论 0e 后面是什么, 0 的多少次方还是 0 。导致弱类型比较绕过
- 修复建议: 将 == 换成 ===
- 建议修复代码:
if (md5($Username) !== md5($password)) {
6.2 json 绕过
0x01 漏洞背景
=== 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较
== 在进行比较的时候,会先将字符串类型转化成相同,再比较
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
if (isset($_POST['message'])) {
$message = json_decode($_POST['message']);
$key = "*********";
if ($message->key == $key) {
echo "flag";
} else {
echo "fail";
}
} else {
echo "~~~~";
}
?>
json_decode 之后可以解析成布尔型,可以传入 true 绕过比较
- 修复建议:
将 == 换成 === - 建议修复代码:
if ($message->key === $key) {
6.3 array_search 绕过
0x01 漏洞背景
=== 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较
== 在进行比较的时候,会先将字符串类型转化成相同,再比较
如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
0x02 漏洞代码及分析
- 漏洞代码 1 :
<?php
if (!is_array($_GET['test'])) {
exit;
}
$test = $_GET['test'];
for ($i = 0; $i < count($test); $i++) {
if ($test[$i] === "admin") {
echo "error";
exit;
}
$test[$i] = intval($test[$i]);
}
if (array_search("admin", $test) === 0) {
echo "flag";
} else {
echo "false";
}
?>
传入数组 test[]=0 可以绕过
- 修复建议:
将 array_search 第三个参数为 true 则就不能绕过 - 建议修复代码:
if (array_search("admin", $test, true) === 0) {
版权属于:ic翼
本文链接:https://bingyishow.top/Technical-article/156.html
您必须遵守 署名-非商业性使用-相同方式共享 CC BY-NC-SA 使用这篇文章