变量
所有漏洞都来源于变量,因此变量首先要做的就是定义初始化。用任何一个变量前一定要先定义,初始化它
虽然现在Discuz!X来说,GPC不会被全局覆盖了,但是大家写插件的过程中也不要忽视了
因为在服务器php.ini的配置中 global on 时
所有的GET POST 都会变成变量
$_GET['xxx']  如果存在
就会变成 $xxx 而产生在程序里
因此,你自己要用的变量,一定要初始化

第一点,变量的初始化
无论你要怎么利用变量,一定要初始化
不管是Discuz!还是Discuz!X
由于PHP的历史原因
你不能相信任何一个服务器
只因为php有个global on 的参数
他会让GPC变量直接变成全局变量
因此,你自己的变量一定要初始化

第二点,认清变量的类型
整刚才说到,变量一定要初始化,那么初始化成什么类型
如果你要用于数组

初始化$a = array();
字串 $a ='';
数字 $a = 0

这样子,这里说说数组,这里又存在一个php历史问题,这历史延续至今。

$s = '123456';
echo $s[2];
等于什么?

[]大家都知,这是数组的用法,但php太自由了 $s[3] 的数组用法,竟然可以用在字串里,这个在大家认为很自然。
但是,很多漏洞会从此诞生,这就是认清自己的变量类型的道理所在。
$s[1] 是数组的用法,可以用在字串中,但是我不推荐大家用,黑客会这么用在GET中更改你的变量类型。

举例
echo $s[2];
简单这一句,你认为这是输出数组的一个项,还是字串?
大多数人会认为这明显是输出数组的一个项目,但是刚才也看到了,它输出字串的一个字节也可以。
那,我们反过来思考,如果程序的某逻辑需要输出字串的某字节,但是,如果你没明确告知变量类型。那么有可能会让这一个字节变成一个字串 xxx.php?s[2]=hello

初始化+认清自己的变量类型
特别是数组和字串,如果你要取字串的某一位,安全的方法,可能还是 substr($s, 2, 1)
切忌[]的用法,一定要$a = array() 不要让他和字串类型的变量产生互用理中

第三点、不要相信任何一个即将入库的变量
进很多SQL注入都是从变量开始,要仔细看每一个SQL语句中可能出现的变量,如,整数一定要intval;字串一定要addslashes处理,说到addslashes,说说Discuz!的特点,国外某些论坛是,所有变量都无需addslashes,addslashes只在SQL数据库类中统一处理,但Discuz!不是,Discuz!会统一给GPC变量自动addslashes。

注意,是只给GPC变量加addslashes,其他的都没加。所以,你要注意两件事:
1. GPC变量你想用于显示?
那么别忘记stripslashes 后在显示,否则万一遇到有带有 ' 的,那就会多一个\,I'm 变成 I\'m
htmlspecial只处理<>这些,和单引号无关

2. 再次,刚才说过DZ只处理GPC。因此,GPC之外的所有变量一定要自己addslashes,特别是有些时候时,把A库的东西读出来后,直接复制到B库的情况。有人说A库的东西都入进去了,直接入B库还不安全吗?这可不一定,I'm 被A读取出来后 直接入B库,肯定是sql error,必须addslashes。如果要 serialize ,那么 serialize前无需addslashes,serialize后要,从数据库中去出来的肯定是I'm,不是I'\m,serialize是好东西,但不要把addslashes后的也给serialize进去。

那么,我再继续深一步,刚才说到了数据库。
我们保证了入库前的所有变量必须是addslashes,但是,如果你不做下面的一件事。那么你再addslashes也是白搭
哪件事呢?
select * from table where id=$id
select * from table where id=I\'m
看,依然sql错误,而且还被注入

我举例子 
没错,单引号封闭,无论你是什么类型的字段
在Discuz!的规范里,必须都加单引号
select * from table where id='$id'
WHERE后面的所有条件
变量必须加单引号,这是规范。也许你少加一个,并不会产生漏洞,也只是也许。

但,有些隐形的漏洞就是在七拐八拐中产生的。你少写一个,那些黑客就会用七拐八拐的方式去分析,看看可否利用行中。
intval是必须的,规则也是必须遵守的,然后是html的问题,不要漏掉任何一个字串类型。
所有字串类型,如果你不希望他们显示html,入库前一定要htmlspecialchars后再入库,或者strip_tags下

数字类型
大家都知道intval,字串是htmlspecialchars,当然,后台无所谓!后台比较安全,但是,最好也有,一个习惯,仅作参考。

$a = '12345';
$a_en = htmlspecialchars($a)
$a_ad = addslashes($a);

这样,入库的时候sql查询语句里应该都是_ad结尾的
html模版中的应该都是_en结尾的
我说不出很多黑客的那些漏洞属于
但是刚才说的那些如果都做到了,代码安全不成问题

然后说说Discuz!内置的一些变量

Discuz!X中,理论上你要用 $_G ($_G['gp_*'] 除外) 里的变量,都要考虑htmlspecialchars和addslashes
$_G['gp_*'] 是DX里的GPC
GP
GET POST 都经过了 addslashes后存放到了$_G['gp_*]中
但_G中的其他,均没addslashes
GPC都addslashes过
dhtmlspecialchars 支持数组
其他同理
如果你有一个良好的代码规范,也会让代码安全性提高
很多规范大家可以给自己定,像刚才的$a_en $a_ad

第四点,下面简单说说代码规范
大家阅读代码的时候也许都看到了
$a = 1;
赋值语句前后空格
if(.........
if后面没空格,这些细节涉及不到安全,但有一点,这些也有安全影响?

SQL
良好的代码规范可增加自己的可读性
DB::query("UPDATE ".DB::table('common_member_count')." set $giftunit = $remaining where uid = $_G[uid]");

Discuz!规定sql语句中的SQL关键词必须大写
DB::query("UPDATE ".DB::table('common_member_count')." SET $giftunit='$remaining' WHERE uid='$_G[uid]'");
修正过的

$giftunit = $remaining 
没引号,而且大小写不明,阅读起来很累,规范的不规范的写在一起
虽然站长,不会看代码。但是,一个漂亮代码文档,就像一篇好作文。

有一个SQL上的细节 notifications=notifications+1
这种SQL语句,理论上我们不推荐,虽然这么写本身是正确的
如果a字段是unsigned类型,那么会产生数暴增
产生溢出

a=a+'-1'
就不会

mysql好奇怪的
这点大家通过pma试试就知道了

插件如有减分操作的时候
当a=0的时候
1、a=a-1
2、a=a+'-1'
3、a=a+(-1)
三种方法,你看哪个ok

下面说最后一点
涉及安全的,代码的流程,你的程序,如果只在你的流程下运作
允许100、1000次也许都不会出错。但是,在别人那里,不一定

举例
foreach($array as $k => $v)
嗯,$array是数组,并且存在的时候。。。

没错,是,你自己调试的时候,这数组肯定有
但是在用户那里,有可能就没了
这时候,这语句有错

如果$array不是数组的情况下,这句就错了
你可以if(is_array($array))
也可以(array)$array

类似影响流程的不仅仅是foreach
如rawurlencode
echo rawurlencode('sss');
谁都知没问题
但!!回到刚才我曾说过的,认清变量类型
echo rawurlencode(array('11'));

肯定出错,大家可以测试下
因此 rawurlencode($s) 的时候
一定要确保$s是字串还是数组

用php的每一个函数的时候都要看清接受参数的类型
如果是字串,切记刚才说的
php很傻,有时候字串、数组不分
这是最后一点,爆路径,爆路径后能干啥,黑客最清楚

Discuz!基础的代码安全和代码规范的更多相关文章

  1. iOS开发:代码通用性以及其规范 第一篇(附带,自定义UITextView\进度条\双表显示\瀑布流 代码设计思路)

    在iOS团队开发中,我见过一些人的代码,也修改过他们的代码.有的人的代码写的非常之规范.通用,几乎不用交流,就可以知道如何修改以及在它基础上扩展延生.有的人的代码写的很垃圾,一眼看过去,简直会怀疑自己 ...

  2. 调用discuz编辑器发布帖子显示html代码的解决办法

    <!--{echo htmlspecialchars_decode(discuzcode($post[message], , , , , , , , , , ));}--> 在discuz ...

  3. JNI技术基础(2)——从零开始编写JNI代码

    书接上文: <JNI技术基础(1)——从零开始编写JNI代码> 2.编译源程序HelloWorld.java并生成HelloWorld.class 3.生成头文件HelloWorld.h ...

  4. Verilog HDL基础语法讲解之模块代码基本结构

    Verilog HDL基础语法讲解之模块代码基本结构   本章主要讲解Verilog基础语法的内容,文章以一个最简单的例子"二选一多路器"来引入一个最简单的Verilog设计文件的 ...

  5. Pycharm配置autopep8让Python代码更符合pep8规范

    一.何为pep8? PEP 8官方文档 -- Style Guide for Python Code PEP8中文翻译(转) 二.Pycharm中配置pep8 Pycharm本身是有pep8风格检测的 ...

  6. java基础8 构造函数和构造代码块

    一.构造函数 1 构造函数的作用 给对应的对象进行初始化. 2 构造函数的格式 修饰符 函数名(形式参数){ //函数名就是类名 函数体 } 举例说明: class Perosn{ private i ...

  7. 菜鸟笔记 -- Chapter 4.7 代码注释与编码规范

    4.7 代码注释与编码规范 在程序代码中适当的添加注释可以提高程序的可读性和可维护性.好的编码规范可以使程序更易阅读和理解.下面我们将介绍几种代码注释,以及应该注意的编码规范. 4.7.1 代码注释 ...

  8. VsCode写Python代码!这代码简直和大神一样规范!太漂亮了!

    VsCode写Python代码!这代码简直和大神一样规范!太漂亮了!    转 https://www.jianshu.com/p/636306763d89 VsCode虽然没有Pycharm的功能齐 ...

  9. 夯实Java基础系列7:Java 代码块和执行顺序

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

随机推荐

  1. git cherry-pick 命令,解决冲突后没有 commit 变更,再次pull 时出错

    Git : You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists). 解决方法:(1)使用git status 命令查看当前 ...

  2. Lua table的remove函数

    [1]remove函数简介 table.remove(table, pos): 返回table数组中位于pos位置的元素,其后的元素会被前移. pos参数可选, 默认为table长度, 即从最后一个元 ...

  3. C++完全二叉树的权值

    #include<stdio.h> #include<stdlib.h> #include<math.h> #include<string.h> int ...

  4. Matlab数据标准化——mapstd、mapminmax

    Matlab神经网络工具箱中提供了两个自带的数据标准化处理的函数——mapstd和mapminmax,本文试图解析一下这两个函数的用法. 一.mapstd mapstd对应我们数学建模中常使用的Z-S ...

  5. python利用kruskal求解最短路径的问题

    python利用kruskal算法求解最短路径的问题,修改参数后可以直接使用 def kruskal(): """ kruskal 算法 ""&quo ...

  6. Ubuntu中的两套网络连接管理方式

     版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/haifeng_gu/article/details/78286895 Linux里面有两套管理网络 ...

  7. 为什么要用 redis 而不用 map 做缓存?

    缓存分为本地缓存和分布式缓存.以 Java 为例,使用自带的 map 或者 guava 实现的是本地缓存,最主要的特点是轻量以及快速,生命周期随着 jvm 的销毁而结束,并且在多实例的情况下,每个实例 ...

  8. SAP CO-PA(盈利能力分析)

    为了在这个现代和动态的环境中保持和发展,快速和及时的决策对于做出正确的决策更为重要.组织盈利能力是评估设计组织目标,目标和实现目标的核心参数.在本博客中,我将讨论SAP ERP中包含的工具,以分析组织 ...

  9. pandas-17 关于nan的处理

    pandas-17 关于nan的处理 在pandas中有个另类的存在就是nan,解释是:not a number,不是一个数字,但是它的类型确是一个float类型.numpy中也存在关于nan的方法, ...

  10. 【开发笔记】-Tomcat启动时设置Jdk版本

    1. Window版本Tomcat 到bin下的setclasspath.bat文件,在文件的开始处添加如下代码: set JAVA_HOME=D:\Program Files\Java\jdk1.8 ...