立即注册找回密码

草根资源吧

 

官方指定联系方式

工作时间: 周一到周五早上09:00-11:00, 下午03:00-05:00, 晚上08:30-10:30(周六、日休息)
点击这里给我发消息 点击这里给我发消息
QQ: 280520150地址:河南郑州金水区  邮箱: lianxun888@163.com

[Discuz!二次开发] Discuz! 插件安全开发

[复制链接]
  • TA的每日心情
    开心
    2018-7-1 22:44
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    发表于 2017-12-20 10:31:10 | 显示全部楼层 |阅读模式
    基础PHP开发安全Part 1: addslahes/daddslashes
    addslahes是PHP自带的一个函数,其转换规则为
           \  => \\
           '  => \'
    "   => \"
           NUL => \0
           其中关键在 ' 和 " 上,这两个过滤非常重要,从某种角度说,这个过滤已经回避了很多SQL注入和PHP入侵。
           在最新的Discuz!X系列中,$_GET等都未经过addslashes,如果在程序中直接用DB::query执行SQL查询,并且没有使用%s,那么您需要进行必要的检测。
    example 1: Intval
    <?php
    ...
    $num=intval($_GET[‘num’]);
    DB::query(“UPDATE%t SET `text`=’{$num}’ WHERE uid=’{$_G[‘uid’]’}”, array(‘pluginx_test’));
    ?>
    example 2:String
    <?php
    $str=addslashes($_GET[‘str’]);
    DB::query(“UPDATE %t SET `text`=’{$str}’ WHERE uid=’{$_G[‘uid’]}’”,array(‘pluginx_test’));
    ?>
    example 3: Intval via %d
    <?php
    DB::query(“UPDATE %t SET `text`=%d WHERE uid=%d”, array(‘pluginx_test’,$_GET[‘num’], $_G[‘uid’]));
    ?>
    example 4: String via %s
    <?php
    DB::query(“UPDATE %t SET `text`=%s WHERE uid=%d”, array(‘pluginx_test’,$_GET[‘str’], $_G[‘uid’]));
    ?>
    但通过数据库/数据表类的入库方法(::insert, ::update)入库时,这些函数会进行必要的处理,所以,请不要进行重复处理。
    example 5:::insert
    <?php
    $str=$_GET[‘str’];
    $str=addslashes($_GET[‘str’]);
    DB::insert(‘pluginx_test’,array(‘uid’=>$_G[‘uid’], ‘text’=>$_GET[‘str’]));
    ?>
    example 6: ::insert
    <?php
    DB::insert(‘pluginx_test’,array(‘uid’=>$_G[‘uid’], ‘text’=>$_GET[‘str’]));
    DB::insert(‘pluginx_test’,array(‘uid’=>$_G[‘uid’], ‘text’=>addslashes($_GET[‘str’])));
    ?>
    同时补充,如果您的插件中使用了iconv等编码转换函数,特别是从UTF-8转成GBK这类情况,并且您需要addslashes,请记得先转换编码,再进行addslashes过滤。因为在UTF-8中的/, \, ‘, “”等敏感符有七八种表示方式,大多不会被addslashes处理,只有先转换编码后才能开始安全处理。此外,urldecode等也在此列。
    Part 2: 从引号开始一般来说,ASP常常比PHP容易入侵,很大程度是因为很多ASP初学者,对数据库的安全过滤一概不知,我们常常可以看到下面的这种语句(假设members有三列, id username password,实际需要时可以穷举列数尝试攻击)。
    example 7:Without a quote
    <?php
    $query=DB::query(“SELECTusername FROM members where id=$id”);
    ?>
           如果$id可以为人为构造的string,则可能有以下语句:令 string $id = 9999999999 union (all/distinct) select password FROM members where id = 1 SELECT username FROM members where id = 9999999999 union select password as username FROM members where id = 1 理论上可以获得id=1(常常是管理员)的密码,虽然打开 Discuz!的SQL安全机制后,以上攻击失效。 于是,非常重要的,你必须加上一个引号,并且保证 $id 是int类型,或者已经被有效的addslashes,包括数字类型。
    example 8:With a quote
    <?php
    $query=DB::query(“SELECTusername FROM members where id=’$id’”);
    ?>
    目前所知,并没有有效的办法攻破上述安全处理。 国内安全组织80vul特别提醒,in()/limit/order by/group by 这四个地方都是容易忘记加引号的,在本审核员两个月中的审核中,有一款插件因为in()轻信了dimplode的addslashes处理,忽视了此处仍容易被注入,而被打回。
    timestamptime() date()
    以后遇到这类回复可见的插件可以一律打回了,打印版没有可靠的嵌入点
    Part 3. 引用PHP代码文件
    首先我们引入一段令人非常无语的代码作为例子。
    example 10:
    <?php
    require $_GET['path'].'.php';
    ?>
    简直太容易了,如果可以打开URL,我就可以执行远程脚本了。
    http%3A%2F%2Fwww.example.com%2Fx.txt%00
    http%3A%2F%2Fwww.example.com%2Fx.txt?
    http%3A%2F%2Fwww.example.com%2Fx.txt#
    %00(NUL) ? # 都可以做URL的截断符,使得后面的.php不影响。
    在此特别重要的警示,绝对不要写出这样的代码,否则可能会发生非常多的情况,在此建议几种可行的方法
    example 11:
    <?php
    if(!in_array($_GET['path'], array('zip','bond','download')))exit;
    require $_GET['path'].'.php';
    ?>
    example 12:
    <?php
    if(!in_array($_GET['mod'],array('index', 'add'))) $_GET['mod']='index';
    ?>
    另外,一些插件需要引用一些PHP文件,这些PHP文件的名字并不确定,例如7ree的某漫画插件中,需要引用某名字的PHP文件,这个文件记载了漫画的信息,而这个名字由客户端提供,不能保证安全性。几次打回,分别是由于没有处理../和%00,最后要求使用白名单的方法来解决,即只容许某个范围的字符输出。preg_match的\w一般可以满足要求,建议大家参考。
    Part 4. GPC过滤
    大概的情况就是,对于一个外部变量,你必须有准确的限制。该是数字的,保证它是数字。该是正常文字的,保证它是正常文字。这里很大程度上是为了防止数据库注入及XSS。
    intval 整数
    特别注意,用intval处理一个非数字的字符串,仍然可以得出一个数字的结果, 比如intval("abcdefg+123456abcdefg-1111");结果为123456。   
    因为intval的原理是:从左边第一个数字(或正负号)开始,一直读到数字结束。
    还有特别要注意的,intval不会解决负数的问题,建议再进行 > 0 的检查
    is_numeric 数字
    请特别注意,如果你只允许正数的话,就不要使用这个函数,因为他可能产生好长好长的一个数字串,好像造成了PHPWind的一次银行漏洞。
    addslashes 可能要进库的字符串
    addslashes是非常重要的一个过滤,尤其要注意,不要重复过滤。
    strip_tags 对于不应该有HTML的文本
    这主要是 XSS 的要求,避免被 XSS ,重点就是避免用户的HTML标签直接输出到浏览器上。
    htmlspecialchars 对于可能有HTML的文本,但是不希望这些代码被解析。
    同strip_tags(),有区别的是,他不会去掉标签,而是变成可阅读的样式。
    MySQL的安全问题Part 5. 涉及搜索的插件,使用LIKE匹配时的注意
    许多涉及搜索的程序都会忘记下面这两个字符的过滤:
           % _
    % 相当于 .*    _ 相当于 .+
    Discuz!的过滤代码: addcslashes($keyword,'%_')
    Part 6. 加减法问题,防止积分暴涨
    对于一个unsigned int,如果你把0再减去1会怎样呢?是的,他会变成四十二亿多(1 << 32 -1)
                  UPDATE test set num=num-1                     (此时ccc=0)
                         num=4294967295
    该漏洞曾经发生在 PHPWind 的天使宠物插件上,用户现金为零时,打怪遇到惩罚事件掉金钱,结果直接获得高额的奖励。
                  UPDATE test set ccc=ccc+(-1)              (此时ccc=0)
                         num=4294967295
    再次变成四十二亿多
    对可能为负数的数字,加一个引号,可以解决这个问题:
                  UPDATE test set ccc=ccc+'-1'              (此时ccc=0)
                         ccc=0 没有发生变化
    著名插件作者 虾米:对于mysql建表的时候,数字不代表你使用的数字最大的位数,例如 timestampint(10) unsigned,这一个大家应该非常熟悉了,这一个括号中的10并不代表timestamp这个数字最多只能十位(具体的意思自己查手册吧,不知道也无妨),如果不知道是否应该用unsigned的时候就不要用unsigned的,涉及到积分的字段全部不要使用unsigned的(安全起见,宁可让用户负分也不能是正的无穷大)
    Part 7. 复杂的MySQL问题(来源于80vul)
    两个MySQL截断问题,第一个是超长截断,第二个是加一个0xc1截断(UTF8)。
    我们用例子来说
    example9:MySQL Problem #1
    MySQL:
    CREATE TABLEIF NOT EXISTS `pre_test` (
      `uid` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(13) NOT NULL,
      `password` char(32) NOT NULL,
      PRIMARY KEY (`uid`),
      UNIQUE KEY `username` (`username`)
    )ENGINE=MyISAM  DEFAULT CHARSET=utf8AUTO_INCREMENT=2;
    INSERT INTO`pre_test` (`uid`, `username`, `password`) VALUES
    (1, 'admin','aeb0908baa5b97e574c5b1825d8f4b92');
    <?php
    if(!DB::fetch_first(“SELECT* FROM pre_test WHERE username=%s”, array($_GET[‘username’]))){
    DB::query(“REPLACEINTO pre_test set username=%s, password=%s”, array($_GET[‘username’],md5($_GET[‘password’])));
    }
    ?>
    我现在用username=” admin                            lalala”
    password=’123456’来注册,那么fetch_first处执行的查询是
    SELECT * FROMpre_test WHERE username='admin                            lalala'
    查询结果: MySQL 返回的查询结果为空 (即零行)。
    零行的原因:因为数据库中的username不可能那么长!肯定找不到对应的!
    下面DB::query得以执行,
    REPLACE INTOpre_test set username='admin                            lalala',password='e10adc3949ba59abbe56e057f20f883e'                                    
    查询结果:影响了 2 行。插入的行 id: 2 ( 查询花费 0.0003 秒 )
    当长长的username进入数据库时,超长部分自动被截去,空格又被忽略,使得username与admin相同。
    当然这种方法并非完美,admin的uid已经发生了变化,这意味着创始人身份无法延续,版主的身份也会丢失,但该用户可以是管理员,至少已经拥有了管理员的名字。
    其实,如果你不用REPLACE INTO,这个问题就可以小很多,这样顶多造成MySQL Erro因为一般情况下username是UNIQUE索引的,INSERTINTO不会正常执行。
    PHPWind就曾经在这件事上摔跤过,当时是用第二个方法,也就是我们即将介绍的,0xc1截断修改任意用户密码(0xC1不是四个字,而是一个字符)。在UTF-8中,0xC1会使MySQL截断后面的数据。当我们请求的用户名“甜橙”后面加上0xC1,那么包括这个字符,及其之后的,在插入时都会被忽略。我们来模拟下。
    SELECT * fromtest where username='甜橙'
    查询结果:     甜橙        864411
    SELECT * fromtest where username=concat('甜橙', 0xc1)
    查询结果:MySQL 返回的查询结果为空 (即零行)。
    REPLACE INTOtest set username=concat('甜橙', 0xc1), password='123456'
    (模拟PHPWind早期的注册)
    甜橙密码被修改:         甜橙        123456
    简单说,执行一个查询,可能结果为空,但是一会插入信息时,却实际覆盖了原有的数据。使用REPLACE INTO时,开发者要特别小心。
    高级PHP开发安全Part 8. 字符串可能是数组
    非常少见的一个问题,但提出来吸引眼球。
    example 13:
    <?php
    $s='gnaojgapjhpajgpa';
    ?>
    此时 $s[1]=='n'
    example 14:
    <?php
    $s=array('nbaohpas','gkhaopjgpaj');
    ?>     
    此时 $s[1]=='gkhaopjgpaj'
    如果你要获得用户请求的数据的某一个字节,并且你考虑用[1]这样的方法来取,而不是substr,那么一定要用户给的数据是不是一个字符串,否则,你可能「拿」到一个字符串、一个数组等等……
    解决方法:检查是不是字符串,或者干脆就变成字符串好了。也可以用{1}来取。
    example 15:
    <?php
    $s=array('nbaohpas','gkhaopjgpaj');
    $s=(string)$s;
    ?>
    此时 $s{1}=='r',因为$s=='Array'
    也可以直接拒绝这类非法的信息
    example 16:
    <?php
    if(!is_string($s))exit('xxxxx');
    ?>
    Part 9. 随机数的可靠性
    由于rand函数可能只有三万多种变化,一般不适合用于有认证性的场合,首先,我们建议无论如何使用mt_rand代替rand.
    不要用随机函数去创造你认为安全的随机数,一个简单的原因,随机数的产生是根据种子的,种子相同时,从生成种子到第n次求随机数的结果都是完全相同的。考虑到PHP的多个版本存在随机数问题,Discuz!某版本后,决定采用md5散列函数来进行随机,random()函数回避了许多问题,建议替换:
    string random(int $length, bool $numeric= 0)
    在产生安全认证级别的密串时,这可能是一个大问题。某版本的Discuz!论坛的找回密码功能曾被破解,用于重设任意用户的密码。
    如果你要获得用户请求的数据的某一个字节,并且你考虑用[1]这样的方法来取,而不是
    Part 10. CSRF
    CSRF有两个特点:普遍、有害。绝大多数的插件,刚注意到CSRF的情况时,往往有许多作品需要大范围地改写,而且它具有有害性,即凡是CSRF攻击,往往都大大小小有利用价值,但是往往不会造成数据库一类的严重安全问题。
    首先,我们先讲CSRF在普通用户范围的存在意义,我们先举一个例子,假设有一个版主投票插件,每个人点击“支持“按钮,该版主获得一票,也可以投“反对”票。
    <ahref="plugin.php?id=test:index&vote=225290&op=support"class="btn">支持</a>
    <ahref="plugin.php?id=test:index&vote=225290&op=against"class="btn">反对</a>
    该版主为了争取选票,他可以在帖子(甚至签名)中嵌入以下的代码:
             
    一旦访问这个帖子,img中的链接即被访问一次,用户在“不知不觉”中投给了他一票。
    反对这个版主的人也有办法,他可以在帖子(甚至签名)中嵌入以下的代码:
             
    一旦访问这个帖子,同理,用户在“不知不觉”中投给了他一票反对。
    我们当然知道,这种问题并不会造成非常大的影响,但当我们关注了足够多的严重安全漏洞后,这些小小的漏洞是否值得注意呢?它们的确影响到了插件的初衷。
    我们接着讲一种面向管理员的CSRF,这种方法往往需要一定的运气,后台程序也有可能,但是后攻击难度太大。
    假设刚才的投票插件,有一个前台管理面板,里面自然应该有一个“删除该候选人”的功能,我们假设一下。
             225290     xxx   xxx票支持 xxx票反对  查看投票数据 | 删除该候选人
    我们假设“删除该候选人”是这样的一个链接
    <ahref="plugin.php?id=test:cp&action=del&uid=225290">删除该候选人</a>
    假设前台面板是这样的执行代码:
             if($_GET['action']=='del' &&$_G['adminid']==1 && ($uid=intval($_GET['uid']))>0){
                       ……
             }
    这样的话,有一种非常需要运气的方法,只要让有权限的用户访问到“plugin.php?id=test:cp&action=del&uid=225290”这个链接,即可将225290这个候选人删除掉,这里对管理员权限有要求,但是这是可以实现的,实战中有一个例子:
    版块:站务管理
    标题:管理员进来!网页有错位!
    内容:…….
    一般稍有管理的论坛,都会有管理员级用户访问。管理员可能永远不知道攻击是如何发生的,但是他已经实施了删除操作。这就是典型的面向管理员的CSRF攻击。
    特别是删除操作,往往判断不足,使这个便成了高热度的情况。
    修补建议:
    1. 使用formhash
    formhash是比较简单有效的一种方法,比如在链接中加一个formhash={FORMHASH}就有效果,在模板语法中,我们可以这样写
    <ahref="plugin.php?id=test:cp&action=del&uid=225290&formhash={FORMHASH}}">删除该候选人</a>
    Discuz!0629补丁所修复的一个安全问题涉及security key的取出,formhash的安全性被降低,在了解指定用户的情况下可能制造formhash,但是利用0629漏洞的例子还比较少,这个漏洞有远古性,0day工具也没有释出,了解对方环境有一定难度,所以formhash还是可信的。请放心使用这个方法!
    2. 使用submitcheck()
    submitcheck有两种好处,一种是确定通过POST的方式提交了一个变量,另一种是对来源地址有审查,也就避免了站外的访问威胁。这在表单中,我认为是有必要添加的。submitcheck同时也会检查formhash,并且防止FLASH攻击。
    一般是在添加/删除表单使用的。例如有一个添加候选人的表单,提交按钮的name="addsubmit"。
    PHP代码中可以这样写:
             if(submitcheck('addsubmit')){
                       ….
             }
           这样,提交时我可以肯定四个要点:POST提交,有FORMHASH,来源有限,不是FLASH,安全性能提高很多。如果要对删除操作进行这个检查,通常是通过弹出窗口进行confirm,用formhash的安全性也能满足一般需要。
    Part 11. ceil round floor的区别
    一般是针对积分兑换的插件,我举一个例子,如果规定50积分可以换一个某奖品。
                  $a['奖品']=$func($a['积分']);
                  使用 ceil 函数,我可以支付51个积分,换两个(进一法)
                  使用 round 函数,我可以支付75个积分,换两个(四舍五入)
                  使用 floor 函数,我只能至少支付100个积分,换两个(舍去法)
    这是三个取整函数,特别注意根据实际需要,使用适当的函数,避免让一些用户破坏了积分兑换的公平。或者,你的程序应该自己判断,使用户提供的积分中不足额的部分不被扣减。
    在此处,intval相当于 floor,也可以。
    Part 12. 不要上传SWF
    FLASHCSRF已经成为非常恐怖的攻击力量,在这里的建议是 不要允许用户上传SWF格式的文件,一旦这种文件上传到论坛上,就可以引发FLASH CSRF攻击。
    这种攻击的威胁非常巨大,如果普通用户访问,可以攻破FORMHASH和submitcheck(),如果管理员访问,可以攻破!defined('IN_ADMINCP') && die;
    原理就是利用FLASH请求数据,并且发出getURL的请求,或者javascript到浏览器上进行攻击,FLASH可以实施的攻击比较强。若自己的网页有必要展示swf时,请审慎控制allowScriptAccess参数。
    Part 13. 不要Foreach空值、数字、字符串
    foreach一个空值或一个数字时,会报一个错误,这可能暴露路径,但新版中已对PHP错误报告做了处理。开发者需要在不引用Discuz来初始化的一些文件中注意。万一foreach一个不合格的内容时,会中断程序运行,使得程序执行不正常,这要注意。
    Part 14. SESSION认证的验证码常见问题
           并不推荐使用SESSION来做验证码,经过加密的cookie可以符合要求(例如使用Discuz!的authcode函数)。但SESSION也有其独特的优点,在这里我对用SESSION进行验证时,一种容易忽略的情况进行说明:
    example17:<?php
    ...
    if(submitcheck(....)){
    if($_SESSION['code']!=$_GET['seccode'])showmessage(...);
    ...
    }else{
    ...
    session_start();
    $_SESSION['code']=random(4,1);
    ...
    ?>
           这里出现一个问题,若用户不接受SESSION,那么在submitcheck时,$_SESSION['code']为空,seccode为空时绕过。即是,如果你用SESSION进行验证,一定要检查SESSION是否真的存在并且有效,避免直接使用SESSION的存储值而忽视SESSION是否存在的问题,使得攻击者可以轻易绕过验证。
    DX论坛及插件机制特色Part 15. 伪造IP
    伪造IP是从很久以前就有的一个安全问题了,绝大多数的网站都不能正确处理,使得该伪造方法可以畅通无阻。如果有需要发敏感文章,那么通过伪造IP,甚至可以让人做替罪羊。
    我们来看一下 Discuz! X 判断用户IP的方法。
    privatefunction _get_client_ip() {
                       $ip =$_SERVER['REMOTE_ADDR'];
                       if(isset($_SERVER['HTTP_CLIENT_IP']) &&preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
                                $ip =$_SERVER['HTTP_CLIENT_IP'];
                       }elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR'])AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s',$_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
                                foreach ($matches[0]AS $xip) {
                                         if(!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
                                                   $ip= $xip;
                                                   break;
                                         }
                                }
                       }
                       return $ip;
             }
    我们可以看到, 获得IP的优先级是 CLIENT-IP、X-FORWARDED-FOR, 这两个是在 HTTP 头特别指定的量,相当于“识别真实IP”,这是在中国应用非常广泛的代码。
    但是,逆向过来看,你如果提交 X-FORWARDED-FOR: 127.0.0.1 ,Discuz就会认为你是来自 127.0.0.1 的用户,难道我说什么,DZ就信什么?你还真说对了。已确定 Discuz! 除了限制代理访问之外,没有其它方法阻止此类假IP。此方法可用于刷Discuz!的访问推广的积分。
           开发者编写投票插件,建议使用以下的代码进行判断,使得有代理迹象的投票全部无效。
                                if($_SERVER['HTTP_X_FORWARDED_FOR']||
                                         ERVER['HTTP_VIA']|| $_SERVER['HTTP_PROXY_CONNECTION'] ||
                                         ERVER['HTTP_USER_AGENT_VIA']|| $_SERVER['HTTP_CACHE_INFO'] ||
                                         ERVER['HTTP_PROXY_CONNECTION']){
                                                   这是代理投票,在此填你的处理代码
                                }
    Part 16. 后台模块为什么一定要加IN_ADMINCP
    在X版本中,在插件目录下的任意以 .inc.php 结尾的文件都可以通过 plugin.php?id=xxxx:xxxx 的形式访问,不管这个文件有没有登记为模块,以及是否是后台模块,也可以通过这种方法被访问。
    我们假使有这样的一个插件,它的目录分布如下:
           template                    模版目录
           admincp.inc.php              后台管理文件(包括修改、结单、删除等功能)
           index.inc.php             主程序(包括插件数据的初始化,cp.inc.php的权限判断)
           install.inc.php            安装文件(在XML中已登记)
           uninstall.inc.php              卸载文件(在XML中已登记)
           cron_payrecord_bakup.inc.php     计划任务文件(由install.inc.php在安装时复制到cron文件夹中,请注意这种做法已经不再允许
    登记的插件模块
           管理中心       admincp.inc.php       支付管理
           主导航项目    index.inc.php      主导航项目
    我下面给出几个链接
           plugin.php?id=xxxx:admincp
           在admincp.inc.php没有IN_ADMINCP或者强制权限判断的情况下,我可以通过这个程序进行一些关键的操作(修改、结单、删除),其中的formhash和submitcheck都可以被绕过。除非碰到showformheader等函数被迫终止。
           plugin.php?id=xxxx:cp
           该程序的一些变量没有经过index.inc.php初始化,可能功能失常。当权限判断由index.inc.php承担时,权限判断被绕过。
           plugin.php?id=xxxx:index
           正常访问的连接
           plugin.php?id=xxxx:install
           插件进入安装过程,但因为runquery函数是在function/plugin中定义的,平时不被引用,反而很难清空数据库。提议安装文件严格命名为install.php
           plugin.php?id=xxxx:uninstall
           同xxxx:install,一般不能进行卸载攻击,但是也可能造成其他风险。
           plugin.php?id=xxxx:cron_payrecord_bakup
           运行计划任务程序,咋看问题不大,但是有两点。一些计划任务有明确的时间性,这个连接可能使计划任务在短时间内被重复运行,类似定期发奖类的可能混乱。第二,计划任务很多比较消耗资源,通过计划任务实施DDOS或者CC攻击,达到的效果会快而且好。
           重申不再允许插件安装时复制/移动文件到论坛程序文件夹,X3应该直接放在插件的cron目录下,X2.5应该同时“合并安装”一个计划任务扩展。
    建议:后台管理文件一定要记得加 IN_ADMINCP,无需前台访问的文件不要加.inc.php
    Part 17. 敏感词过滤
    大家对Discuz! 的那个敏感词过滤不应太有信心的,至少对于 共*产*党 就无法过滤,防水墙解决了这个问题,但是真的无法输入“共产党”吗?
    举例,我想输入:共产党
    不少论坛进行屏蔽或替换处理,例如显示为“××”或者“我党”
    你完全可以这样输入,这种方法目前还是非常先进的:
                  共产党
                  共产党
    可正常看到“共产党”三个字,较新版本的Discuz!中都不屏蔽。
    插件中,如果有推广类信息,并且附带有敏感词过滤功能的,建议作考虑,不允许用户使用统一码表示汉字。
    Part 18. 手机版和打印版改变了局面
    近年出现很多验证类的插件,经过调查,多数没有抵御灌水机的能力。因为较新的灌水机都会优先使用wap手机版页面进行灌水,这样可以绕掉验证类插件的电脑版嵌入点。
    由于有用户投诉,后期统一对没有针对手机版设计嵌入点,又声称用于防灌水的验证类插件全部给予打回处理。只是用于检查用户提供的手机是否有效的这一类验证,都放宽。
    之前有很多回复限制类插件,限制用户需要达到一定的条件才能访问帖子。有登陆看全文的,也有回复看全文的。暂不提其中一些产品严重影响了搜索引擎的收录,并且可能被指出是欺骗。这些插件很多在打印版/手机版/archiver下失败了,显然嵌入点少了,难以实现这些功能。
    我们建议这类插件能设法showmessage来屏蔽打印版,同时在$postlist里面先下功夫,这样在archiver下应该可行。
    Part 19. 网址路径书写不合理
           近期有多款插件/风格因此被打回,开发者具体的测试环境可能有所不同,使得开发者debug时的显示效果和全部用户网站上的显示效果有差异,网址路径书写不合理是其中的一种。
    第一种情况是:路径使用反斜杠
           正确:<imgsrc="source/plugin/test/static/test.jpg" />
           错误:<imgsrc="source\plugin\test\static\test.jpg" />
    并非所有的服务器都接受反斜杠,请不要用反斜杠书写路径。
    第二种情况是:路径前加一个/,使路径从根目录开始
           正确:<imgsrc="source/plugin/test/static/test.jpg" />
           错误:<img src="/source/plugin/test/static/test.jpg"/>
    当用户的BBS并非安装在根目录时,图片文件不能被正确引用。
    Part 20. 调用远程信息的可靠性过滤
           开发一些插件时,我们会通过客户端的页面向我们插件的服务器端发送一些信息,例如站长信息,信息调用,或者功能请求。一个常见的例子便是更新信息。诚然,我们放心自己不会往自己的服务器端挂马,但是如果域名被劫持,或者发生这一类的事故,那么利用者就可能通过这个插件后台端向使用者发送攻击信息。Discuz!某版本的挂马,同时利用了后台的一个执行脚本的漏洞,以及custom.discuz.net的劫持。
           因此,尽管向用户端发送的信息由我们控制,我们依然希望里面没有有害代码。这是一个提议,建议服务器端发送的代码,尽可能由不需HTML标记的代码组成,以便htmlspecialchars处理。或者,直接使用iframe的方式引用,较新的浏览器都有良好的权限控制,使得框架内的代码无法控制框架外的主页面。请用iframe而不要用javascript,后者可以跨站。
    Part 21. IN_DISCUZ的必要性
           至今仍有不少插件由于缺少必要的IN_DISCUZ而被打回,缺少IN_DISCUZ的程序被单独执行时,往往由于没有初始化函数,而报出fatal error泄露服务器路径。实际操作中,确可无需IN_DISCUZ的类文件和函数文件并不做强制性要求,但建议只要是可以加这项限制的,都应该加,这样比较合理。
    Part 22. 认证类密串的生成问题
           有时,为了校验用户的身份,或者验证用户的权限,我们会通过网址传递一个hash,hash正确的才执行相关代码。
             plugin.php?id=xxx:xxx&ac=openimg&id=1893&hash=b95970a598bc1da9af743f988d9b0ee0
           其hash的生成算法是
    <?php
    ...
    $hash=md5('*cOpYRight*'.$imgid.'|'.$_G['uid'].'|'.$_G['siteurl']);
    ...
    ?>
           从生成的md5来反推原文基本是不可能的,但是生成这样一个md5却容易。即使你的插件使用了Zend加密,至今依然有各种方法可以反编译,并了解到你生成hash的算法。由于算法与论坛相关的部分只有siteurl,而siteurl很容易得到,所以这个hash实际上可以由客户端自行生成。
           显然,要解决这样的问题,我们要让这个hash不容易生成,即使知道加密算法。我们可以在md5的参数中增加$_G['authkey'],或者直接用formhash($imgid) 也是可以的。
           一般的认证场合中,直接使用FORMHASH也可以,除非这个hash不止需要与用户的身份有关,例如还与附件的ID有关,等等。
    Part 23. 多编码版本的程序编码问题
           目前,大多数的插件都使用语言包编写,并且支持多编码。这就要求汉字和汉字符号,都应该写在语言包内。最近有不少插件,在php文件中仍然有非注释部分的汉字和汉字符号,都让作者拿回去改,或者用统一码&#xxxx;这样的来解决。这样,不同编码的用户才可以真正看到相同的效果。
    Part 24. SWF决定奖励的抽奖插件
           许多抽奖插件给论坛带来了许多娱乐享受,这些插件有很大的缺口,我觉得有兴趣的开发者可以试试看。有不少的抽奖插件由swf抽奖,决定奖品后发送给服务端,由服务端发奖。这就涉及到了解swf与服务端的通讯方式后,恶意刷奖品。我们提醒,swf发奖插件应该由php决定奖品,swf仅负责显示奖品。
    Part 25. 时间安全问题
           在TIMESTAMP常量产生后,Discuz!会进行timezone_set,此后用date(),time(),gmdate(),dgmdate()获得的时间由系统及用户共同决定,除非你使用date(..., TIMESTAMP) gmdate(...,TIMESTAMP)等。其中,用户设置的时区可以远远超过24小时。如果插件中用于判断时间的代码没有考虑到这个问题,就可以使用户穿越时空。例如一款签到插件,在早期某版本中,许多非开发者用户已经知道通过调整时差,就可以向前一天或者向后一天。而实际上,如果该用户通过DOM编辑器等方式,提交了一个超过24小时的时差,那么该用户可以穿越到任何一天,这就使得签到用户可以补签之前任何一天的记录,也可以签到未来的日子。
           同样的问题如果出现在银行插件,那么后果会更加严重。可喜的是应用中心唯一一款银行插件,使用TIMESTAMP之间的对比,这样就回避了这类问题。

    本帖最近访客
    回复

    使用道具 举报

    该用户从未签到

    发表于 2017-12-21 09:10:25 | 显示全部楼层
    学习了,不错,
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2018-1-28 17:27
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2017-12-21 09:16:41 | 显示全部楼层
    学习了,不错,
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-21 23:42:53 | 显示全部楼层
    帮帮顶顶功能强大!!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-22 10:14:42 | 显示全部楼层
    谢谢谢谢下载了
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-12-20 20:03
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2017-12-22 12:34:20 | 显示全部楼层
    谢谢分享、、、
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2018-1-28 17:24
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2017-12-22 13:52:07 | 显示全部楼层
    百度了好久。。。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-23 01:30:29 | 显示全部楼层
    顶.........好资源
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-23 07:06:28 | 显示全部楼层
    学习了,不错,
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-12-20 20:03
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2017-12-23 15:09:33 | 显示全部楼层
    找到好贴不容易,我顶你了,谢了
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-23 19:24:47 | 显示全部楼层
    没看完~~~~~~ 先回复,好同志
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-23 20:45:53 | 显示全部楼层
    提示: 作者被禁止或删除 内容自动屏蔽
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-24 12:35:00 | 显示全部楼层
    支持一下
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-12-20 20:03
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2017-12-24 19:00:35 | 显示全部楼层
    下载来了
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-25 16:29:05 | 显示全部楼层
    有竞争才有进步资源不错
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2018-7-1 22:44
  • 签到天数: 16 天

    [LV.4]偶尔看看III

     楼主| 发表于 2017-12-26 12:51:41 | 显示全部楼层
    我抢、我抢、我抢沙发~
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-27 10:33:09 | 显示全部楼层
    顶.........好资源
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-28 16:24:44 | 显示全部楼层
    我抢、我抢、我抢沙发~
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-28 21:36:51 | 显示全部楼层
    好网站
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2017-12-29 18:18:16 | 显示全部楼层
    我抢、我抢、我抢沙发~
    回复 支持 反对

    使用道具 举报

    使用高级回帖 (可批量传图、插入视频等)

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则   Ctrl + Enter 快速发布  

    发帖时请遵守我国法律,网站会将有关你发帖内容、时间以及发帖IP地址等记录保留,只要接到合法请求,即会将信息提供给有关政府机构。
    Powered by Discuz! X3.2 豫ICP备17024477号-1   
    Copyright © 2008-2016 www.sxpxb.net All Rights Reserved.
    快速回复 返回顶部 返回列表