百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

XSS注入我也不怕不怕啦--PHP从框架层面屏蔽XSS的思考和实践

myzbx 2025-03-24 18:31 60 浏览

本文由腾讯WeTest团队提供,更多资讯可直接戳链接查看:http://wetest.qq.com/lab/

微信号:TencentWeTest

对于新接触web开发的同学来说,XSS注入是一件非常头疼的事情。就算是web开发多年的老手,也不敢保证自己写的代码完全没有XSS注入的风险。

因为现在比较主流的XSS防治手段主要有两种,一种是在用户输入是将异常关键词过滤,另一种则是在页面渲染时将html内容实体化转义。

然而第一种方法一定程度上对业务数据要求相对较高,存在屏蔽数据和业务数据有冲突的情况,例如“程序类帮助文档的编辑保存”,“外站帖子爬虫”等等。都不能无差别将异常关键词过滤掉,必须保持原输入内容的完整性。

而另一种html内容实体化的方式,又非常的依赖开发的编程习惯。一个不小心漏写了就是一个安全工单,做web的前端同事应该深有体会。于是,我开始研究能不能不再依赖开发习惯,从框架层面上完全屏蔽XSS。

这里先介绍一下我的PHP web Server框架,是我自己从从事web开发开始就一直在维护更新的框架,链接在此,有兴趣的同学,可以看下。或者提出更多改进的建议。

首先来看下普通的PHP是怎么转义html实体的:

htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE) ENT_QUOTES 意思是需要转义双引号(”)和 单引号 (’)

ENT_SUBSTITUTE 意思是 把无效的编码替代成一个指定的带有 Unicode 替代字符

首先很容易想到的是把php模版中的字符串全部替换掉。

而熟悉smarty的同学应该知道,其实smarty的模版渲染也是用了转义字符串的方式。那我们渲染页面的代码可以这么写。

/**

* 获得模板渲染后的内容

* @return string

*/

public function getContent

{

//防XSS注入

foreach ([Math Processing Error]

[Math Processing Error][Math Processing Error]

}

unset($param);

    extract($this->params);
    ob_start;
    //include template
    $file = sprintf('%s/template/%s.tpl.php', TXApp::$app_root, $this->view);
    include $file;
    $content = ob_get_clean;
    return $content;
}

这样的话,传入的字符串类型的变量都会被替换掉了。但是问题也很明显。那就是如果是数组或者object对象,里面的内容就无法进行转义了。而这同样也是smarty的一个弊端,smarty是在assign方法里进行的实体化转义,如果是数组或者object就无视了。当然我们还需要更进一步的进行转义处理。

有同学看到这里肯定会有个想法,如果是数组的话,递归进行转义处理不就可以了吗。

事实上我一开始的确是这么做的,但是弊端也很明显。递归的层数越多,性能损耗就越大。而且并非所有进行转义的内容我们都会用到,这样就会造成性能的浪费。最优化的处理方式就是当需要用到的时候再做转义处理,没用到的时候该咋样还是咋样。

于是我开始着手自己写一个类,在我的框架里我命名为TXArray 继承了ArrayObject,也就是让其具备了array的部分性质。接下来开始进行array 方法重构。以下是部分代码

class TXArray extends ArrayObject

{

private [Math Processing Error]

public function __construct($storage=array)
{
    $this->storage = $storage;
}

public function getIterator
{
    foreach ($this->storage as $key => $value){
        $key = $this->encode($key);
        if (!isset($this->encodes[$key])){
 $this->encodes[$key] = $this->encode($value);
        }
    }
    return new ArrayIterator($this->encodes);
}

public function offsetGet($k)
{
    if (isset($this->storage[$k])){
        $key = $this->encode($k);
        if (!isset($this->encodes[$key])){
 $this->encodes[$key] = $this->encode($this->storage[$k]);
        }
        return $this->encodes[$key];
    }
    return null;
}

public function offsetExists($k)
{
    return isset($this->storage[$k]);
}

public function offsetUnset($k)
{        
    unset($this->storage[$k]);
    $k = $this->encode($k);
    unset($this->encodes[$k]);
}

public function offsetSet($k, $value)
{
    $this->storage[$k] = $value;
    $this->encodes[$k] = $this->encode($value);
}

public function count
{
    return count($this->storage);
}

private function encode($value)
{
    if (is_string($value)){
        $value = is_string($value) ? htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE) : $value
    } elseif (is_array($value)){
        $value = new self($value);
    }
    return $value;
}

} offsetGet 会在[Math Processing Error]

这样一个递归的转义模型就写好了。也实现了用到时才转义的目标。

但是还有个问题。并不是所有字段都需要转义的,例如我们平台的舆情监控数据,数据来源主要是各大贴吧论坛,数据本身包含了图片img,字体颜色等html元素。在展示时并不希望被模版转义。所以我在框架上继续优化。添加了PHP的魔法方法__get

public function __get($k)
{
    return isset($this->storage[$k]) ? $this->storage[$k] : null;
}

public function get($key)
{
    return $this->__get($key);
}

也就是说只要调用[Math Processing Error]

另外看业务也再需要加上一些对array的处理方法,例如array_key_exists,in_array, join等。或者直接使用__call 魔法方法

public function __call($method, $args)
{
    $args = &$this->storage;
    return call_user_func_array($method, $args);
}

public function serialize
{
    return serialize($this->storage);
}

public function __invoke
{
    return $this->storage ? true : false;
}

public function keys
{
    return array_keys($this->values(false));
}

然后我们在页面模版里就可以愉快的使用了

但是这个TXArray还是有个问题,就是如果需要转化成json全部下发给js使用的话,那里面的数据就无法被转义了。当然也可以递归先全转义一遍,但总觉得代码不够漂亮。这个问题我还会继续研究。有新的进展和优化我都会上传到我的 PHP开源组件框架 中,大家有什么好的建议都可以rtx跟我探讨沟通哈

相关推荐

如何设计一个优秀的电子商务产品详情页

加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...

怎么在JS中使用Ajax进行异步请求?

大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...

中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革

前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...

前端监控 SDK 开发分享_前端监控系统 开源

一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...

Ajax 会被 fetch 取代吗?Axios 怎么办?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...

前端面试题《AJAX》_前端面试ajax考点汇总

1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...

Ajax 详细介绍_ajax

1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...

6款可替代dreamweaver的工具_替代powerdesigner的工具

dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

福斯《死侍》发布新剧照 "小贱贱"韦德被改造前造型曝光

时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...

不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!

Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...

2025 年 Python 爬虫四大前沿技术:从异步到 AI

作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...

最贱超级英雄《死侍》来了!_死侍超燃

死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...

停止javascript的ajax请求,取消axios请求,取消reactfetch请求

一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...