PHP-关于DZ最近出现的登录用户名限制问题?

PHP-关于DZ最近出现的登录用户名限制问题?

泛泛之交 发布于 2017-10-25 字数 821 浏览 1311 回复 2

最近好多家DZ论坛都突然出现了用户注册时出现用户名限制,
当用户在注册窗口注册,
输入的用户名是大于3个字符小于15个字符,
但是弹窗提示“”
请输入图片描述

虽然后来DZ通报了解决办法,
是由于后台防灌水功能中的注册表单使用默认导致
只要把注册表单设置为其他,只要没有关键字:username,password这些就没问题
改完以后问题就解决了,虽然解决,但是这个为什么?怎么导致的?
到现在我还是没弄明白,
由于本人虽懂一些DZ的知识,
但是对内部程序运行的机制很多都不明白,
所以特此请教大家解释这个DZ的漏洞是怎么发生的?

补充并强调一下:主要怕大家理解错我的题意,因为我的问题主要是想了解造成这次几家DZ论坛突然出现用户注册限制的触发原因在那里?(请大家注意一下黑体字部分)

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

灵芸 2017-11-10 2 楼

我来给你说一下,首先看后台注册表名设置:

if(!preg_match('/^[A-z]w+?$/', $settingnew['reginput']['username'])) {
$settingnew['reginput']['username'] = 'username';
}

如果你不设置(默认)的话程序会默认username为字段名,然后保存到数据库。
在dx入口程序class_core.php里开始会调用建立缓存的函数function _init_setting(),里面有这么一条语句

!empty($this->cachelist) && loadcache($this->cachelist);//如果缓存存在,就加载缓存。

而function loadcache($cachenames, $force = false)这个东东呢,又调用function cachedata($cachenames)。该函数是读缓存文件的,看下面一句:

 if(!@include_once(DISCUZ_ROOT.'./data/cache/cache_'.$cachename.'.php')) {
$lostcaches[] = $cachename;
}

当你第一次进入dx或着在后台清缓存的时候,程序会自动重新生成新缓存,而dx生成环境缓存的文件就是cache_setting.php,打开该文件你会看到首先一个函数function build_cache_setting()。哦,这东东就是建立dx环境缓存的函数呀!里面有这么一段代码引起了我的注意:

 $reginputbwords = array('username', 'password', 'password2', 'email');
if(in_array($data['reginput']['username'], $reginputbwords) || !preg_match('/^[A-z]w+?$/', $data['reginput']['username'])) {
$data['reginput']['username'] = random(6);
}
if(in_array($data['reginput']['password'], $reginputbwords) || !preg_match('/^[A-z]w+?$/', $data['reginput']['password'])) {
$data['reginput']['password'] = random(6);
}
if(in_array($data['reginput']['password2'], $reginputbwords) || !preg_match('/^[A-z]w+?$/', $data['reginput']['password2'])) {
$data['reginput']['password2'] = random(6);
}
if(in_array($data['reginput']['email'], $reginputbwords) || !preg_match('/^[A-z]w+?$/', $data['reginput']['email'])) {
$data['reginput']['email'] = random(6);
}

$data这个变量就是存的当前dx里缓存数据,分析上面代码不难知道,如果你没在后台设置注册表明而选择默认的话,它就会随机生成六位字符串给你注册信息字段。

再看注册模板:register.htm

 <td><input type="text" id="{$this->setting['reginput']['username']}" name="" class="px" tabindex="1" autocomplete="off" size="25" maxlength="15" required /></td>

耶,name值咋为空呢,id="{$this->setting['reginput']['username']}"又引起了我的注意,$this->setting变量是在入口程序里读的cache缓存,也就是上面的$data['reginput']['username'] = random(6);接着分析

当你填写完注册信息后register.js会ajaxpost调用addFormEvent(formid, focus),而这个函数里会把id赋给name

 if(formNode[i].name == '') {
formNode[i].name = formNode[i].id;
stmp[si] = i;
si++;
}

到这里我明白了,在点注册提交后js把$this->setting['reginput']['username']的值才赋给name值,然后再看class_member.php是如何处理的。

function on_register()函数开始有这几句代码:

 $_G['gp_username'] = $_G['gp_'.$this->setting['reginput']['username']];
$_G['gp_password'] = $_G['gp_'.$this->setting['reginput']['password']];
$_G['gp_password2'] = $_G['gp_'.$this->setting['reginput']['password2']];
$_G['gp_email'] = $_G['gp_'.$this->setting['reginput']['email']];

上面是接收注册信息数据,下面是判断用户名长度。

 $usernamelen = dstrlen($username);
if($usernamelen < 3) {
showmessage('profile_username_tooshort');
} elseif($usernamelen > 15) {
showmessage('profile_username_toolong');
}

到这里我明白了,dx搞这么复杂就是为了防止注册机的,你注册机每次给我传username、password、password2、email来,我靠,我每次都random(6),我看你咋搞!

不管你明不明白,反正我是明白了!

泛泛之交 2017-11-07 1 楼

我看了一下具体的文件:
文件:"/template/default/member/register.htm"里

 <div class="rfm">
<table>
<tr>
<th><span class="rq">*</span><label for="{$this->setting['reginput']['username']}">{lang username}:</label></th>
<td><input type="text" id="{$this->setting['reginput']['username']}" name="" class="px" tabindex="1" autocomplete="off" size="25" maxlength="15" required /></td>
<td class="tipcol"><i id="tip_{$this->setting['reginput']['username']}" class="p_tip">{lang register_username_tips}</i><kbd id="chk_{$this->setting['reginput']['username']}" class="p_chk"></kbd></td>
</tr>
</table>
</div>

文件:/static/js/register.js

 function addFormEvent(formid, focus){
var si = 0;
var formNode = $(formid).getElementsByTagName('input');
for(i = 0;i < formNode.length;i++) {
if(formNode[i].name == '') {
formNode[i].name = formNode[i].id;
stmp[si] = i;
si++;
}
if(formNode[i].type == 'text' || formNode[i].type == 'password'){
formNode[i].onfocus = function(){
showInputTip(!this.id ? this.name : this.id);
}
}
}
......

以上HTML这段代码是显示注册用户名的表单,可以发现name属性是空的,而id是可以后台配置的用户名ID,而在登录时/static/js/register.js这个脚本里的addFormEvent()函数会对注册表单进行检测,在检测时会对用户名、密码等name为空的属性,并把其ID的值赋给name属性,然后后台PHP就通过这个name属性来接收表单信息。而当改成弹窗注册时,应该是没有执行以上这段代码对name进行赋值,所以后台就没有接收到name为空,所以就会显示问题所示的提示。