dede list.php漏洞如何防范?

99ANYc3cd6
预计阅读时长 21 分钟
位置: 首页 DEDE建站 正文

list.php 是 DedeCMS 中用于栏目列表页的动态脚本文件,它的主要作用是接收用户请求,从数据库中提取特定栏目的文章列表,然后调用相应的模板文件(通常是 list_article.htm)将数据渲染成 HTML 页面展示给用户。

dede list.php
(图片来源网络,侵删)

下面我将从几个方面为你全面解析这个文件。


文件位置与作用

  • 文件位置: /dede/list.php
  • 核心作用:
    1. 入口: 作为栏目列表页的动态入口,当你访问网站上一个“栏目”链接时,这个链接通常指向 list.php,并附带一个栏目 ID(如 list.php?tid=1)。
    2. 数据处理: 接收栏目 ID (tid),根据这个 ID 从数据库中查询该栏目下的所有文章(或子栏目)。
    3. 分页处理: 如果文章数量超过每页显示的数量,list.php 会负责生成分页链接,并获取当前页的文章数据。
    4. 模板渲染: 将查询到的文章数据、分页信息、栏目信息等变量传递给列表页模板文件。
    5. 输出: 执行模板引擎(通常是 dedecms 的 php.lib.php),将模板文件解析并最终输出 HTML 代码给浏览器。

代码结构与核心逻辑解析

list.php 的代码逻辑非常清晰,我们可以将其分为几个主要部分。

1. 初始化与安全检查

文件开头首先会加载 DedeCMS 的核心环境和安全检查。

require_once(dirname(__FILE__)."/config.php");
CheckRank(0, 0);
  • require_once(dirname(__FILE__)."/config.php");: 引入配置文件 config.php,这个文件包含了数据库连接信息、网站路径等全局设置,是所有 DedeCMS 动态页面的基础。
  • CheckRank(0, 0);: 检查用户权限,这里 0, 0 表示不检查会员等级,允许所有访客访问,如果后台设置了栏目需要登录才能查看,这里会进行相应的权限验证。

2. 获取并处理栏目ID (tid)

这是 list.php 最关键的一步,它决定了要显示哪个栏目的内容。

dede list.php
(图片来源网络,侵删)
if(!isset($tid))
{
    $tid = 0;
}
$tid = intval($tid);
  • if(!isset($tid)): 检查 URL 中是否存在 tid 参数(list.php?tid=10)。
  • $tid = intval($tid);: 使用 intval() 函数对 tid 进行强制类型转换,确保它是一个整数,这是非常重要的安全措施,可以防止 SQL 注入攻击。

3. 获取栏目信息并检查权限

根据 tid 从数据库中获取该栏目的详细信息,并检查是否可以访问。

$row = $dsql->GetOne("SELECT * FROM `#@__arctype` WHERE id='$tid' AND ishidden<>1");
if(!is_array($row))
{
    ShowMsg('栏目不存在或被禁用!', '-1');
    exit();
}
  • $dsql->GetOne(...): 执行一条 SQL 查询,从 #@__arctype 表(栏目表)中获取 ID 为 $tidishidden(是否隐藏)不等于 1 的栏目记录。
  • if(!is_array($row)): 如果查询结果不是一个数组(即栏目不存在或被隐藏),则调用 ShowMsg() 函数显示错误信息,并终止脚本执行。

4. 设置页面基本参数

这部分代码设置列表页的标题、关键词、描述等 SEO 相关信息。

$typename = $row['typename'];
$seotitle = $row['seo_title'];
$keywords = $row['keywords'];
$description = $row['description'];

这些变量通常来自栏目表中的字段,用于填充页面的 <title><meta name="keywords"><meta name="description">

5. 核心查询:获取文章列表

这是 list.php 的核心功能,从数据库中获取文章数据。

$channelid = $row['channel']; // 获取栏目绑定的模型ID
$addtable = $row['addtable']; // 获取附加表名
// 获取分页参数
$PageNo = isset($PageNo) ? intval($PageNo) : 1;
// 构建查询条件
$ismake = $row['isdefault']; // 是否生成静态
$tempfile = $row['tempindex']; // 模板文件名
// ... 省略了一些处理顶级栏目、栏目交叉引用的逻辑 ...
// 最终的SQL查询
$query = "SELECT arc.*,tp.typedir,tp.typename,tp.corank,tp.isdefault,tp.defaultname,
          tp.namerule,tp.namerule2,tp.ispart,tp.moresite,tp.siteurl,tp.sitepath
          FROM `#@__archives` arc
          LEFT JOIN `#@__arctype` tp ON arc.typeid=tp.id
          WHERE arc.arcrank > -1 AND arc.typeid='$tid'
          ORDER BY arc.sortrank DESC, arc.id DESC";
// 执行查询并处理分页
$dsql->SetQuery($query);
$dsql->Execute('al');
$totalResult = $dsql->GetTotalResult('al'); // 获取总记录数
$totalpage = ceil($totalResult / $pagesize); // 计算总页数
// 获取当前页的数据
$artlist = array();
while($row = $dsql->GetArray('al'))
{
    // 处理文章URL
    $row['filename'] = GetFileUrl($row['id'],$row['typeid'],$row['senddate'],$row['title'],$row['ismake'],
                                  $row['arcrank'],$row['namerule'],$row['typedir'],$row['money'],
                                  $row['filename'],$row['moresite'],$row['siteurl'],$row['sitepath']);
    $artlist[] = $row;
}
  • SQL查询: 这条 SQL 语句从 #@__archives(文章主表)和 #@__arctype(栏目表)中联合查询符合条件的文章。WHERE arc.arcrank > -1 确保只审核通过的文章,arc.typeid='$tid' 确保只查询当前栏目的文章。
  • 分页逻辑: PageNo 表示当前页码。$totalResult 获取总文章数,$totalpage 计算总页数,虽然这里代码简化了,但完整的 list.php 会使用 GetPageList() 等函数来处理分页数据。
  • URL生成: GetFileUrl() 是一个极其重要的函数,它根据文章的发布设置(是否生成静态、动态规则等)来生成最终的文章访问链接。

6. 模板变量赋值与渲染

将所有准备好的数据传递给模板。

dede list.php
(图片来源网络,侵删)
// 将数据赋值给模板
$pv->SetTemplet($cfg_basedir.$cfg_templets_dir."/".$cfg_df_style."/list_article.htm");
$pv->SaveToHtml($typedir);
$pv->Display();
  • $pv = new PartView();: 创建一个 PartView(部分视图)对象,这是 DedeCMS 的模板引擎。
  • $pv->SetTemplet(...): 指定要使用的模板文件,这里的路径是 模板目录/默认风格/list_article.htm,如果栏目后台设置了使用独立模板,它会优先使用独立模板。
  • $pv->SaveToHtml(...): 如果开启了静态生成,这行代码会根据模板生成一个静态的 HTML 文件(/html/1/1.html)并保存到服务器上。
  • $pv->Display(): 如果是动态访问,这行代码会直接解析模板并输出 HTML 到浏览器。

如何修改 list.php 的行为?

我们不建议直接修改 list.php 的核心逻辑,因为 DedeCMS 的后台设置已经提供了足够的灵活性,但如果你有特殊需求,可以这样做:

1. 修改每页显示的文章数量

list.php 文件中找到 $pagesize 这个变量,修改它的值即可。

// 原始值可能是 20
$pagesize = 20; 
// 修改为 50
$pagesize = 50; 

2. 修改文章排序规则

在构建 SQL 查询的 ORDER BY 部分,你可以修改排序字段和顺序。

原始代码:

ORDER BY arc.sortrank DESC, arc.id DESC
  • sortrank: 后台设置的“置顶级别”,数值越大越靠前。
  • id: 文章 ID,通常是按发布时间倒序。

如果你想按“发布时间”排序,可以修改为:

ORDER BY arc.senddate DESC, arc.id DESC

3. 修改查询条件(只显示某一特定分类的文章)

在 SQL 的 WHERE 子句中添加条件。

原始代码:

WHERE arc.arcrank > -1 AND arc.typeid='$tid'

如果你想在这个栏目下只显示“图集”类型的文章,可以添加一个对 channeltype 的判断(假设图集模型的 channeltype 是 2):

WHERE arc.arcrank > -1 AND arc.typeid='$tid' AND arc.channeltype = 2

常见问题与调试

问题1:列表页空白或显示错误

  • 检查: list.phpShowMsg 函数是否被触发了?查看源代码或浏览器开发者工具,看是否有报错信息。
  • 排查:
    1. tid 参数是否正确传递?URL 中的 tid 是否对应数据库中存在的栏目 ID?
    2. 该栏目是否在后台被设置为“隐藏”或“不生成”?
    3. 数据库连接是否正常?

问题2:分页不正确

  • 检查: 查看生成的分页链接是否正确,点击第二页后,PageNo 参数是否增加?
  • 排查:
    1. $totalResult(总记录数)是否正确?可以手动在代码中输出这个值看看。
    2. $pagesize(每页显示数)是否被正确设置?
    3. 检查模板文件 list_article.htm 中分页标签 {dede:pagelist} 的写法是否正确。

问题3:文章链接错误

  • 检查: 点击文章,链接是否指向了正确的页面?
  • 排查:
    1. GetFileUrl() 函数需要很多参数来生成链接,检查文章的“是否生成HTML”、“文章命名规则”等后台设置。
    2. 检查栏目设置的“命名规则”是否与文章的“命名规则”冲突。

list.php 是 DedeCMS 动态网站架构的基石,理解它的运作原理,对于排查网站问题、进行二次开发以及优化网站性能都至关重要,记住它的核心流程:接收参数 -> 安全验证 -> 数据查询 -> 模板渲染,在修改它之前,请务必备份,并优先考虑通过后台设置和模板文件来实现你的需求。

-- 展开阅读全文 --
头像
织梦友情链接为何只显示一行?
« 上一篇 昨天
C语言如何实现十进制与二进制转换?
下一篇 » 昨天
取消
微信二维码
支付宝二维码