安全的本质
安全问题的本质是信息问题,一切的安全方案设计的基础,都是建立在信任关系上的。
是否信任普通用户的输入-->前台漏洞
是否信任管理员用户的输入-->后台漏洞
是否信任升级包、离线升级、在线升级、自动化升级-->供应链攻击
不信任任何输入-->对输入进行检测(实际上就是把信任关系绑定到了对输入的检测逻辑上,一旦输入检测逻辑出现了问题,信任关系就被打破,很容易就出现了漏洞),例如:认为闭源很安全,就不做过多的安全防护,将安全寄托在代码闭源上,一旦代码被黑客拿到手,信任关系被打破后,漏洞就随之出现。
所有的安全模型都可以简化成一种最简易的模型
输入-->检测是否有安全风险-->输出
这也是所有安全方案能够抽象出来的最简化的模型
比如:
网络检测与响应(NDR):
输入:流量、pcap包
检测:waf、正则、流量解析、文件分析、威胁情报等
输出:正常流量无动作、恶意流量阻断
终端检测与响应(EDR):
输入:进程事件、文件事件、主机API调用
检测:父子进程关系异常、非常规API调用、敏感文件读取
输出:异常阻断杀死进程
WEB应用防火墙(WAF):
输入:api调用
检测:是否包含XSS、SQL注入等关键字(包括AI检测)
输出:中断此次异常连接
WEBSHELL查杀
输入:文本文件
检测:是否包含恶意关键字、数据进入敏感函数
输出:隔离、删除
在进行渗透过程中,我们能掌握的只有输入,挖掘漏洞最好的入口点,也只能是从输入去入手。
控制与数据
以一段代码为例
代码1:
<html>
<body>
Hello my name is:
<?php
echo $_GET["name"];
?>
</body>
</html>
代码2:
<html>
<script>
console.log("Hello my name is :" + "<?php echo $_GET['name'];?>")
</script>
</html>
将程序员的代码分割为两个部分,一部分是控制代码走向的控制流代码,一部分是用来被展示、被存储、被流转的数据流代码。
程序员希望用户输入的一定是数据流而不是控制流。
一旦输入的数据能够经过某种方式侵入到控制流时,漏洞就产生了。
例如:
SQL注入
<?php
$db = init_db();
$username = $_GET['username']; // input: fffff' and 1=1#
$db->query("select * from table where username = '$username'");
?>
该代码的输入流情况如下
输入-->php字符串变量-->sql语句-->数据库
在数据库层面,控制流是sql语句,整个控制流流程如下:
action(动作): select
object(对象): table
subject(目标客体): *
condition(条件):
key: username
value: $username //用户输入
在这里程序员应该通过编程保证用户的输入只能影响结构中的value位置,如果不能保障,就会出现漏洞
action(动作): select
object(对象): table
subject(⽬标客体): *
condition(条件):
expression: and(逻辑与)
key1: username
value1: $username // ⽤户输⼊ fffff
key2: 1
value2: 1
在代码层(PHP)的输入,导致数据库(mysql)层的数据流侵入到了控制流
服务器模板注入(SSTI)
以Twig为例,Twig是PHP的一套模板渲染的组件,但是不规范的渲染参数输入方式,可能会导致模板注入。
正确写法:
<?php
require_once dirname(__FILE__).'\twig\lib\Twig\Autoloader.php';
Twig_Autoloader::register(true);
$twig = new Twig_Environment(new Twig_Loader_String());
$output = $twig->render("Hello {{name}}", array("name" => $_GET["name"])); // 将⽤户输⼊作为模版变量的值
echo $output;
?>
输入流情况:
输入-->php字符串变量$_GET["name"]-->Twig模板渲染-->发现变量{{name}}-->找到变量name的绑定-->解析字符串-->渲染展示
Twig使用一个加载器loader(Twig_Loader_Array)来定位模板,以及一个环境变量environment(Twig_Environment)来存储配置信息。其中,render()方法通过其第一个参数载入模板,并通过第二个参数中的变量来渲染模板。
使用Twig模板引擎渲染页面,其中模板含有{{name}}变量,其模板变量值来自于GET请求参数$_GET["name"]。
由于模板引擎一般都默认对渲染的变量值进行编码和转义,所以即使通过name参数传递js代码进行XSS也是不会成功的。
但是如果渲染的模板内容收到用户的控制,那么情况就会不一样了:
<?php
require_once dirname(__FILE__).'/../lib/Twig/Autoloader.php';
Twig_Autoloader::register(true);
$twig=newTwig_Environment(newTwig_Loader_String());
$output=$twig->render("Hello {$_GET['name']}");// 将用户输入作为模版内容的一部分
echo $output;
?>
输入流情况:
输入-->php字符串变量$_GET["name"]-->拼接字符串"Hello {$_GET['name']}"作为新变量-->Twig模板渲染-->渲染展示
该段代码在构建模板时,拼接了用户输入作为模板的内容,现在如果再向服务端直接传递js代码,用户输入会原样输出
在代码层(PHP)的输入,导致了Twig模板层的数据流入侵到控制流
命令执行
<?php
$domain = $_GET["domain"]; //input:baidu.com";whoami;echo "xxx
echo system('ping "'.$domain.'"');
?>
这是一个路由器或者设备产品常有的功能,测试网络连通性的
程序员的原意,在bash程序中:
execute:
process:
exe: tracert --> /bin/tracert
arg: $domain
在这里程序员应该通过编程保证用户的输入只能够影响到结构中的arg位置,如果不能保障,就会出现漏洞
ping "baidu.com";whoami;echo "xxx
execute:
process1:
exe: tracert
arg: "baidu.com"
or-->
process2:
exe: whoami
arg: -
or-->
process3:
exe: echo
arg: "xxx"
在代码层(PHP)的输入,导致了bash程序的数据流入侵到了控制流
业务流程问题
过度信任用户输入
业务功能:输出当前用户的信息
<?php
$user_id = int($_GET['user_id']);
$db = init_db();
$data = $db->query("select * from user where user_id = $user_id");
echo parse_user_profile($data);
?>
这是典型的越权读取的原型了,虽然没有SQL注入漏洞,但是在业务逻辑上的校验有缺陷,信任了用户输入的user_id,导致漏洞的产生。
不信任用户输入-->信任检测逻辑
//login.php
<?php
session_start();
$password = "test";
$_SESSION['is_login'] = 0;
if ($_GET['password'] == $password){
$_SESSION['is_login'] = 1;
$_SESSION['user_id'] = $_GET["user_id"]; // 假定管理员user_id=0
header("location: /user.php?is_login=1");
exit();
}else{
echo "密码错误";
exit();
}
?>
// http://127.0.0.1/login.php?password=test&user_id=123
//user.php
<?php
header("content-type: text/html; charset=utf-8");
if ($_SESSION['is_login'] == $_GET['is_login']){ NULL == NULL
echo "你登录了";
if ($_SESSION['user_id'] == 0){ NULL == 0
echo "你是管理员,来吧";
}else{
echo "你不是管理员,不行";
}
}else{
echo "没登陆,滚";
}
?>
这是一个经典的逻辑绕过漏洞,在整个流程里面,开发者完全没有信任用户的输入,对密码进行了校验,校验通过才存session,并且用户id也是存储于session中的,没法通过cookie伪造绕过鉴权。
回顾之前的内容
不信任任何输入-->对输入进行检测(实际上就是把信任关系绑定到了对输入的检测逻辑上,一旦输入检测逻辑出现了问题,信任关系就被打破,很容易就出现了漏洞)
这段代码就是对输入的检测逻辑出现了漏洞
php是弱类型的语言,在php下,NULL == false == 0 == ""
而$_SESSION的取值来自于Cookie中的PHPSESSION的输入,如果我们不输入Cookie,这里就完全绕过了这个校验。
标签:审计,name,--,Day01,输入,信任,代码,模板 From: https://www.cnblogs.com/LeouMaster/p/18426599