首页 > 其他分享 >代码审计Day01——输入

代码审计Day01——输入

时间:2024-09-23 10:48:22浏览次数:1  
标签:审计 name -- Day01 输入 信任 代码 模板

安全的本质

安全问题的本质是信息问题,一切的安全方案设计的基础,都是建立在信任关系上的。

是否信任普通用户的输入-->前台漏洞
是否信任管理员用户的输入-->后台漏洞
是否信任升级包、离线升级、在线升级、自动化升级-->供应链攻击
不信任任何输入-->对输入进行检测(实际上就是把信任关系绑定到了对输入的检测逻辑上,一旦输入检测逻辑出现了问题,信任关系就被打破,很容易就出现了漏洞),例如:认为闭源很安全,就不做过多的安全防护,将安全寄托在代码闭源上,一旦代码被黑客拿到手,信任关系被打破后,漏洞就随之出现。

所有的安全模型都可以简化成一种最简易的模型

输入-->检测是否有安全风险-->输出

这也是所有安全方案能够抽象出来的最简化的模型

比如:

网络检测与响应(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

相关文章