·设为首页收藏本站📧邮箱修改🎁免费下载专区📒收藏夹👽聊天室📱AI智能体
返回列表 发布新帖

插件开发经验之安全风险.避免审核驳回

259 2
发表于 2022-8-14 10:51:26 | 查看全部 阅读模式

马上注册,免费下载更多dz插件网资源。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
交流探讨应是好事,但有些重复问题老是不断的问,弄的我都烦了。为此,整理一些开发者Q友常见的问题,在此一并回答如下:
常有开发者的作品因数据库SUID(SELECT、UPDATE、INSERT、DELETE)的操作涉及安全风险而无法审核通过,可又一时搞不清所说的“安全风险”到底是哪些代码,不知所措。我来讲解一下,希望能有所帮助(当初我也经常遇到这类问题,随着经验积累,慢慢有所悟了)。

此类“安全风险”,一般是指对$_GET和$_POST有没有进行安全过滤处理(addslashes)。
搞清这个概念,问题就好解决了。举个自定义C::t方法的例子

$name  = $_GET['name'];//从地址栏或表单获取
$query = C::t('#mp#common_member')->fetch_by_username($name);
这里用了$_GET,由于该值将用于数据库操作,那么该值是否安全呢?
我们来看DZ的技术文库是怎么说的,经查"Discuz! X2.5新版架构优化说明"—>"程序底层架构"—>"function_core.php 减肥之术"—>"用户输入数据的处理"中,有两句话是这样说的:
$_GET和$_POST的值默认不做addslashes处理;
$_GET为$_GET和$_POST数组的合并,代码中统一使用$_GET取值;
显然,上面参与数据库操作的$name变量是不安全的。但事实真这样吗?
下面看看与之相关自定义的C::T方法是怎么写的吧。
------------------------
……
public fetch_by_username($name){
  return DB::result_first('select * from %t where username=%s',array($this->_table,$name));
}
……
通过上面的代码,需要明白两件事:
①该方法调用了DB层封装的函数result_first;
②使用了%s对数组第二参数$name进行格式化处理;
对于①,我们再看DZ的技术文库,经查"Discuz! X2.5新版架构优化说明"—>"数据库DB层"—>"新增数据层:数据层的规范和约定"中,有句话是这样说的:
"DB层封装的函数实现了addslashes,个别直接写sql语句的需主意addslashes;"
通过查看source/discuz/discuz_database.php,我们可以找到该类定义的result_first方法,说明该方法是被封装在DB里的,所以基本确定$name是安全的。
至于为啥要查看discuz_database.php,而不是discuz_table.php,自己慢慢上下求索吧。
对于②,我们再看DZ的技术文库,经查"Discuz! X2.5新版架构优化说明"—>"数据库DB层"—>"原DB类的改进"—>"3、SQL语句format的支持"中,可以看到支持的格式化表,其中%s表示进行addslashes安全过滤处理。至此,我们可以完全确定上面的代码是安全可靠的了。
但是如果我将自定义函数修改如下:
……
public fetch_by_username($name){
  return DB::result_first('select * from %t where username=%i',array($this->_table,$name));
}
……
public fetch_by_username($name){
  return DB::query('select * from '.DB::table('xxx').' where username='.$name);
}
……
会怎样呢?留给大家思考。
------------------------

再看一个例子:
$query = DB::query('select * from '.DB::table('xxx').' where username='.$_GET['name']);
虽然DB封装了query函数,但该函数并未进行addslashes处理,而只是检验SQL语句里的每一个字符,严格的讲是不安全的。
另外,DZ的技术文库—>"Discuz! X2.5新版架构优化说明"—>"数据库DB层"—>"新增数据层:数据层的规范和约定"中规定:"不能使用$_G、$POST、$GET等全局变量;"
其实,除了不能使用规定的三个全局变量外,$_REQUEST变量也不应该在SQL中使用!

那么,凡是$_GET都要进行add...处理吗?不一定,要看用在什么地方,一般来讲,参与数据库SUID操作的DB::query中都要进行处理。例如:
$name  = addslashes($_GET['name']);
$query = DB::query('select * from '.DB::table('xxx').' where username='.$name);
但要注意避免重复过滤,如
$name  = addslashes($_GET['name']);
$query = DB::query('select * from '.DB::table('xxx').' where username='.addslashes($name));

综上:
1、使用C::t方法的,要注意相关参数是否用%s进行了格式化
2、无论是否C::t方法,使用DB::query(...)的,必须进行add...处理
3、避免重复过滤
4、尽量避免在SQL中使用禁用的全局变量,因为有时获取的变量值有违初衷,不是想要的结果
5、建议使用C::t方法
6、尽量了解、熟知、掌握DZ技术文库
7、尽量了解、熟知、掌握discuz_database.php、discuz_table.php等文件内容

有同行曾问我,为啥X2.5以后不再支持$_G['gp_xx'],我也不知道,这个要问官方。但既然不支持,最好就不要用,否则你还得写个说明,告知用户开启兼容的方法,这不是给自己找麻烦嘛。

还有同行问我,C::t方法有啥好处?我认为好处就是对象清楚、对SQL进行了格式化处理、降低了安全风险,并且有利于维护。

也有一些用户问我为啥不再开发X2的插件了,这个很简单,DZ的技术文库—>"Discuz! X2.5新版架构优化说明"—>"程序底层架构"—>"function_core.php 减肥之术"—>"用户输入数据的处理"中,第一句话是这样说的:"Discus! X2.5之前版本对$_GET和$_POST的值默认是进行addslashes处理,函数在使用此值时信任外部数据的安全性,但这样处理的弊端是容易生产二次注射的漏洞,为了防止此类漏洞的产生,函数必须不信任任何数据外部数据的安全性"。因此,我对X2及以前的版本安全性是不信任的,出于对用户负责,所以不再开发X2的插件了。

另外,忠告开发者,尤其是新手,要想提高插件审核通过率,应做到以下几点:
①养成良好规范的代码书写习惯,可读性强。那种一大堆乱码似的代码,人见人烦
②从审核者的角度着想,该注释的地方加注释,便于审核者理解此处用意,避免引起误解而被踢回。与人方便与己方便
③清理垃圾文件和代码,让审核者省时省力,提高审核进度。只有好处没有坏处
④没事就多看看“开发文档”,尤其是“Discuz! 应用中心应用审核规范”,避免违规。否则,遭罪的是自己
以上是个人经历及经验之谈,有不当之处请指正。

本篇属教程类,希望版主能移动到“插件教程”子版块中。
我要说一句 收起回复
一花一世界,一叶一追寻。一曲一场叹,一生为一人。

评论2

AI智能体Lv.7 发表于 2025-3-17 20:34:28 | 查看全部
在Discuz插件开发中,安全风险是一个非常重要的问题,尤其是在涉及到数据库操作时。以下是一些常见的安全风险及其避免方法,帮助你提高插件的审核通过率:

### 1. **输入数据的安全过滤**
   - **$_GET 和 $_POST 的处理**:在Discuz中,`$_GET` 和 `$_POST` 的值默认不会进行 `addslashes` 处理。因此,如果你直接使用这些变量进行数据库操作,可能会导致SQL注入等安全问题。
   - **解决方法**:在使用 `$_GET` 或 `$_POST` 时,建议使用 `addslashes` 进行安全过滤,或者使用Discuz提供的 `C::t` 方法,该方法会自动对输入数据进行安全处理。

  
  1. $name = addslashes($_GET['username']);
  2.    $query = DB::query('SELECT * FROM '.DB::table('common_member').' WHERE username='.$name);
复制代码


### 2. **使用C::t方法**
   - **C::t方法的优势**:`C::t` 方法是Discuz提供的一个封装好的数据库操作方法,它会对SQL语句进行格式化处理,并且自动对输入数据进行安全过滤,从而降低安全风险。
   - **示例**:

  
  1. $name = $_GET['username'];
  2.    $query = C::t('#mp#common_member')->fetch_by_username($name);
复制代码


   在 `fetch_by_username` 方法中,`%s` 会自动对 `$name` 进行 `addslashes` 处理,确保SQL语句的安全性。

### 3. **避免直接使用DB::query**
   - **DB::query的风险**:虽然 `DB::query` 是Discuz提供的数据库操作方法,但它并不会自动对输入数据进行安全过滤。如果你直接使用 `$_GET` 或 `$_POST` 作为参数,可能会导致SQL注入。
   - **解决方法**:在使用 `DB::query` 时,务必对输入数据进行安全过滤,或者使用 `C::t` 方法来替代。

  
  1. $name = addslashes($_GET['username']);
  2.    $query = DB::query('SELECT * FROM '.DB::table('common_member').' WHERE username='.$name);
复制代码


### 4. **避免重复过滤**
   - **重复过滤的问题**:如果你已经对输入数据进行了 `addslashes` 处理,那么在SQL语句中就不需要再次进行过滤,否则可能会导致数据被多次转义,影响数据的正确性。
   - **示例**:

  
  1. $name = addslashes($_GET['username']);
  2.    $query = DB::query('SELECT * FROM '.DB::table('common_member').' WHERE username='.addslashes($name)); // 错误示例
复制代码


   正确的做法是只进行一次过滤:

  
  1. $name = addslashes($_GET['username']);
  2.    $query = DB::query('SELECT * FROM '.DB::table('common_member').' WHERE username='.$name);
复制代码


### 5. **避免使用禁用的全局变量**
   - **禁用变量**:在Discuz中,`$_G`、`$_POST`、`$_GET` 等全局变量不应该直接用于SQL语句中,因为这些变量可能会被恶意篡改,导致安全问题。
   - **解决方法**:尽量使用 `C::t` 方法,或者对输入数据进行严格的安全过滤。

### 6. **代码规范和注释**
   - **代码规范**:良好的代码规范和注释不仅有助于提高代码的可读性,还能帮助审核人员更好地理解你的代码逻辑,从而提高审核通过率。
   - **清理垃圾代码**:在提交插件之前,务必清理掉无用的代码和文件,确保插件的整洁性。

### 7. **熟悉Discuz技术文档**
   - **技术文档**:熟悉Discuz的技术文档,尤其是数据库操作相关的部分,能够帮助你更好地理解如何安全地进行数据库操作。
   - **开发文档**:建议经常查阅Discuz的开发文档,了解最新的开发规范和审核标准,避免因违规而被驳回。

### 8. **避免使用X2及以前版本的插件开发**
   - **X2版本的安全问题**:Discuz X2.5之前的版本对 `$_GET` 和 `$_POST` 的值默认进行了 `addslashes` 处理,但这种处理方式容易导致二次注入漏洞。因此,建议开发者尽量使用X2.5及以后的版本进行开发,以确保插件的安全性。

### 总结
在Discuz插件开发中,安全风险是一个需要高度重视的问题。通过合理使用 `C::t` 方法、对输入数据进行安全过滤、避免使用禁用的全局变量以及保持良好的代码规范,你可以有效降低插件的安全风险,提高审核通过率。同时,熟悉Discuz的技术文档和开发规范也是非常重要的。

希望这些经验对你有所帮助,祝你在Discuz插件开发中取得成功!
-- 本回答由 人工智能 AI智能体 生成,内容仅供参考,请仔细甄别。
我要说一句 收起回复
AI智能体Lv.7 发表于 2025-3-17 20:35:18 | 查看全部
在Discuz插件开发中,安全性是一个非常重要的考虑因素,尤其是在处理用户输入数据时。以下是一些关键点,帮助你避免常见的安全风险,提高插件审核通过率:

### 1. 用户输入数据的安全处理
用户输入数据(如`$_GET`、`$_POST`、`$_REQUEST`等)必须进行安全过滤,以防止SQL注入等安全漏洞。Discuz提供了多种方法来处理这些数据:

- **使用`addslashes`函数**:对用户输入的数据进行转义处理,防止SQL注入。
- **使用DB层的格式化参数**:在DB层的SQL语句中使用`%s`、`%d`等格式化参数,这些参数会自动进行安全处理。

例如:
  1. $name = $_GET['username'];
  2. $query = DB::query('SELECT * FROM '.DB::table('common_member').' WHERE username=%s', array($name));
复制代码


### 2. 避免直接使用全局变量
在SQL语句中直接使用`$_GET`、`$_POST`、`$_REQUEST`等全局变量是不安全的。应该先对这些变量进行安全处理,然后再使用。

例如:
  1. $name = addslashes($_GET['username']);
  2. $query = DB::query('SELECT * FROM '.DB::table('common_member').' WHERE username='.$name);
复制代码


### 3. 使用C::t方法
C::t方法是Discuz提供的一种更安全的数据库操作方式。它封装了数据库操作,并自动处理SQL语句中的格式化参数,降低了安全风险。

例如:
  1. $name = $_GET['username'];
  2. $query = C::t('#mp#common_member')->fetch_by_username($name);
复制代码


### 4. 避免重复过滤
在进行安全处理时,避免对同一数据进行多次过滤。例如:
  1. $name = addslashes($_GET['username']);
  2. $query = DB::query('SELECT * FROM '.DB::table('common_member').' WHERE username='.addslashes($name));
复制代码

上面的代码中,`$name`已经被`addslashes`处理过一次,再次使用`addslashes`会导致重复过滤。

### 5. 清理垃圾文件和代码
在提交插件时,确保清理掉不必要的文件和代码。这不仅有助于提高审核效率,还能减少潜在的安全风险。

### 6. 注释和代码规范
良好的代码注释和规范的代码书写习惯有助于审核者理解你的代码意图,减少误解和驳回的可能性。

### 7. 熟悉Discuz技术文档
熟悉Discuz的技术文档,尤其是数据库操作和安全处理相关的部分,可以帮助你编写更安全的代码。

### 8. 避免使用不推荐的方法
例如,`$_G`全局变量在Discuz X2.5以后不再推荐使用,应该尽量避免使用这些不推荐的方法。

### 9. 使用DB层的封装函数
尽量使用DB层封装的函数,如`DB::query`、`DB::result_first`等,这些函数已经进行了安全处理。

### 10. 避免直接拼接SQL语句
直接拼接SQL语句容易导致SQL注入漏洞,应该使用DB层的格式化参数来构建SQL语句。

### 总结
在Discuz插件开发中,安全性是首要考虑的因素。通过合理使用`addslashes`、DB层的格式化参数、C::t方法等,可以有效避免常见的安全风险。同时,良好的代码规范和注释也能提高插件的审核通过率。希望这些建议能帮助你更好地开发安全的Discuz插件。

如果你有更多问题,欢迎继续交流探讨!
-- 本回答由 人工智能 AI智能体 生成,内容仅供参考,请仔细甄别。
我要说一句 收起回复

回复

 懒得打字嘛,点击右侧快捷回复【查看最新发布】   【应用商城享更多资源】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

AI智能体
投诉/建议联系

discuzaddons@vip.qq.com

未经授权禁止转载,复制和建立镜像,
如有违反,按照公告处理!!!
  • 联系QQ客服
  • 添加微信客服

联系DZ插件网微信客服|最近更新|Archiver|手机版|小黑屋|DZ插件网! ( 鄂ICP备20010621号-1 )|网站地图 知道创宇云防御

您的IP:18.216.116.226,GMT+8, 2025-4-20 20:25 , Processed in 0.511351 second(s), 82 queries , Gzip On, Redis On.

Powered by Discuz! X5.0 Licensed

© 2001-2025 Discuz! Team.

关灯 在本版发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表