更多精彩内容,请访问云邮科技官方网站:http://www.yunrelay.com
现在位置:首页 » LINUX技术 »

EMOS和Extmail用的增强脚本

作者:山坛兄弟 ⁄ 时间:2015年09月17日 ⁄ 分类: LINUX技术 评论:0 在管理extmail的过程中,管理员开通的邮箱账号都是使用初始密码。懒惰的用户往往不做修改就直接使用。时间一长,管理员初始密码就容易被暴力破解。然后某一个账户就变成垃圾中转站了。

下面的三个脚本,是在不会改Perl代码的情况下,用bash加固一下服务器。
====================第一个脚本:用来强制用户24小时之内修改密码======================
复制内容到剪贴板
代码:
#!/bin/bash
#
#
# 脚本名:extmail-change-your-password.sh 
# 功能简介:一个强制用户修改密码的小脚本。使用cron安排在每天晚上24点之后执行。
#            禁用掉没有登录webmail修改密码的用户
#
# 作者: 刘西洋
#              <xiyangliu1987@gmail.com>
#              http://www.xiyang-liu.com
#
# 脚本自由,版权没有
#
# 创建时间:2012年11月27日一个阳光明媚的上午
#
#------程序设计思路-------------------
#    用户第一次使用webmail登录时,extmail在用户的Maildir文件夹下面
#创建一个maildirsize文件,用来记录磁盘限额信息。管理员邮箱收到的
#磁盘使用汇总报告显示,部分用户Maildir目录下没有maildirsize文件。
#这说明,这部分用户从没有登录过webmail界面,也没有修改过密码。
#    为了便于管理用户的磁盘限额信息,用户邮箱使用情况。以用户没有修改
#密码的名义,强制用户登录webmail界面。否则在当日24时后,禁用用户邮箱。
#--------结束-----------------------------
##设置全局变量
DB_HOSTNAME="localhost"
DB_PORT="3306"
DB_USERNAME="root"
DB_PASSWORD=""
DB_NAME="extmail"
COUNT_FILE="/var/log/extmail-passwd-check-count.txt"
LOG_FILE="/var/log/extmail-passwd-change.log"
TEMP_FILE=/tmp/extmail-count-tmp.tmp
SEND_SMS_EXEC=/var/password-manager/send-mas-sms.sh
declare domains=( `mysql -sN -h $DB_HOSTNAME -P $DB_PORT -u $DB_USERNAME -p$DB_PASSWORD $DB_NAME -e "select domain from domain;" | xargs` )
dlen=${#domains[@]}
di=0
while [ $di -lt "$dlen" ]
do
  declare users=( `mysql -sN -h $DB_HOSTNAME -P $DB_PORT -u $DB_USERNAME -p$DB_PASSWORD $DB_NAME -e "select uid from mailbox where active='1' and domain='${domains[$di]}'; " | xargs` )  
ulen=${#users[@]}
  ui=0  
  while [ $ui -lt "$ulen" ]
    do
    MAILDIRPATH=/home/domains/${domains[$di]}/${users[$ui]}/
    if [ -f $MAILDIRPATH/Maildir/maildirsize ];then
      echo USER ${users[$ui]}@${domains[$di]} OK!
    else 
      COUNT=`grep ${users[$ui]} $COUNT_FILE | cut -d ":" -f 2`
      if [ -z $COUNT ];then 
         COMM_MESSAGE="尊敬的企业邮箱用户,您好!您已开通用户名为${users[$ui]}@${domains[$di]}的企业邮箱账号,但是您还未登录修改密码.请您在24小时内登录企业邮箱,并修改密码.超过7天未修改密码的账户,将被自动注销.企业邮箱登录地址http://mail.xiyang-liu.com" 
         $SEND_SMS_EXEC "${users[$ui]}" "$COMM_MESSAGE"      
         echo User ${users[$ui]}@${domains[$di]} do not change password in 24 hours!
       else
         mysql -sN -h $DB_HOSTNAME -P $DB_PORT -u $DB_USERNAME -p$DB_PASSWORD $DB_NAME -e "update mailbox set active=0 where username='${users[$ui]}@${domains[$di]}'; "
         let COUNT++
         echo "${users[$ui]}@${domains[$di]}:$COUNT" >>$TEMP_FILE
         echo User ${users[$ui]}@${domains[$di]} keep DEFAULT password for $COUNT times now!
      fi
    fi
  let ui++
  done
let di++
done
cat $TEMP_FILE> $COUNT_FILE
> $TEMP_FILE
##程序结束
笔者运行的环境有多个域。同时,有多个域管理员。被禁用后的用户的激活问题可以交给域管理员。
====================第二个脚本:用于提醒用户60天修改一次密码============================
这个脚本的本意,是防止用户长时间不修改密码,如果凑巧了,用户的密码再比较简单。被不怀好意的人猜透的可能性就大增。指不定哪天邮件服务器负载飙到8-9了,疯狂的往外发垃圾邮件,处理倒是不难。可,企业邮箱声誉降下来了,或者被RBL加黑了,申诉就灰常折磨人了。
复制内容到剪贴板
代码:
#!/bin/bash
#
#本脚本需要一个密码权值对应文件。文件内容为:用户名@域名#密码#权值
#先将用户账号#密文#初始权值1 导出到一个文件中。
#通过mysql查询最新的密码,和文件中的旧密码进行比对,如果密码相同,则说明未修改密码。将权值加1。
#如果密码不同,则将新的密码更新到文件中,同时将权值重置为1。
#本脚本每周一执行,如果权值超过8,则短信提醒用户修改密码。同时将权值重置为4,以保证仅每个月提醒一次。
#                              刘西洋 <xiyangliu1987@163.com>
#                                      http://www.xiyang-liu.com

DB_HOSTNAME="localhost"
DB_PORT="3306"
DB_USERNAME="root"
DB_PASSWORD=""
DB_NAME="extmail"
#指定初始化密码文件
USER_PASSWD_FILE=/var/password-manager/user-password-file.txt
SEND_SMS_EXEC=/var/password-manager/send-mas-sms.sh
TEMP_FILE=/tmp/extmail-passwd-check-tmp.tmp
#如果不存在密码文件,则导出现有用户名密码,来创建一个新的密码文件
if  [ ! -s $USER_PASSWD_FILE ] ; then 
  mysql -sN -h $DB_HOSTNAME -P $DB_PORT -u $DB_USERNAME -p$DB_PASSWORD $DB_NAME -e "select username,password from mailbox;" | sed -e  's/\t/#/g' -e 's/$/&#1/g' > $USER_PASSWD_FILE
fi
#查询域名,创建数组
declare domains=( `mysql -sN -h $DB_HOSTNAME -P $DB_PORT -u $DB_USERNAME -p$DB_PASSWORD $DB_NAME -e "select domain from domain;" | xargs` )
#初始化指针
dlen=${#domains[@]}
di=0
#进入循环,每次处理一个域的用户
while [ $di -lt "$dlen" ]
do
  #查询域下用户,创建数组
  declare users=( `mysql -sN -h $DB_HOSTNAME -P $DB_PORT -u $DB_USERNAME -p$DB_PASSWORD $DB_NAME -e "select uid from mailbox where domain='${domains[$di]}';" | xargs` )
  #初始化指针
  ulen=${#users[@]}
  ui=0
  #进入子循环,逐个处理用户
  while [ $ui -lt "$ulen" ]
    do
    #分别查询密码文件和数据库中的密文密码
    FILE_PASSWD=`grep "^${users[$ui]}@${domains[$di]}#" $USER_PASSWD_FILE | cut -d "#" -f 2`
    SQL_PASSWD=`mysql -sN -h $DB_HOSTNAME -P $DB_PORT -u $DB_USERNAME -p$DB_PASSWORD $DB_NAME -e "select password from mailbox where username='${users[$ui]}@${domains[$di]}';" | xargs`
    #如果两个密码不同,则将新密码追加到临时文件中。否则将计数器加1
    if [ "$FILE_PASSWD" != "$SQL_PASSWD" ];then
      echo "${users[$ui]}@${domains[$di]}#$SQL_PASSWD#1" >> $TEMP_FILE
    else 
      COUNT=`grep "^${users[$ui]}@${domains[$di]}#" $USER_PASSWD_FILE | cut -d "#" -f 3`
      #如果记录不存在,初始化此记录
   if [ -z $COUNT ];then
         echo "${users[$ui]}@${domains[$di]}#$SQL_PASSWD#1" >> $TEMP_FILE 
      #如果计数器大于8,发送短信提醒用户修改密码
      elif [ $COUNT -gt 8 ];then
         COMM_MESSAGE="尊敬的企业邮箱用户,您好!您用户名为${users[$ui]}@${domains[$di]}的企业邮箱账号已经超过60天没有修改密码.为了您账户的安全.请您在24小时内登录企业邮箱修改密码.企业邮箱登录地址http://mail.xiyang-liu.com" 
         $SEND_SMS_EXEC "${users[$ui]}" "$COMM_MESSAGE"
         #将计数器置4,并将密码追加到临时文件
         echo "${users[$ui]}@${domains[$di]}#$SQL_PASSWD#4" >> $TEMP_FILE
       else
         #否则计数器加1,并将密码追加到临时文件,并输出调试信息。
         let COUNT++
         echo "${users[$ui]}@${domains[$di]}#$SQL_PASSWD#$COUNT" >> $TEMP_FILE
         echo User ${users[$ui]}@${domains[$di]} does not change password for $COUNT times now!
      fi
    fi
  let ui++
  done
let di++
done
#用临时文件内容覆盖密码文件内容
cat $TEMP_FILE > $USER_PASSWD_FILE
#清空临时文件
> $TEMP_FILE
上面脚本中,用了一个发短信的脚本。这个每个公司的情况都不一样。我的脚本不具有普适性。
脚本功能:接受用户邮箱账号和短信内容为输入变量,根据账号从一个账号手机号对应文件中提取用户的手机号。然后给用户发送一条短信。
需要借鉴发短信的脚本,请访问:http://www.xiyang-liu.com/2013/1 ... s-through-cmcc-mas/
============================第三个脚本:用户暴力破解用户简单密码=========================

通过前几个脚本,禁止了用户使用默认密码,禁止了用户不更改密码。如果用户改了一个符合规则的弱密码怎么办?或者如果用户两个密码反复用该如何办?

与其被别人破解,还不如自己破解!

破解思路:extmail系统使用了md5crypt加密用户密码,然后存放在数据库中。php的crypt函数可以将明文加上一个salt值声称密文密码。通过md5crypt加密弱密码后,与数据库中的密码进行比对。如果相同,则表示密码已经破解。用户密码被破解后,系统使用12位伪随机数重置用户密码。并短信告知用户新的密码。
复制内容到剪贴板
代码:
#!/bin/bash

DB_HOSTNAME="localhost"
DB_PORT="3306"
DB_USERNAME="extmail"
DB_PASSWORD=""
DB_NAME="extmail"

WEAK_PASS_FILE=/var/sysmgmt-script/password-manager/weak-passwd-dict.txt
SEND_SMS_EXEC=/var/sysmgmt-script/password-manager/send-mas-sms.sh
LOG_FILE=/var/log/reset-password-xiyang-liu.com.log

function F_RESET_PASS()
{
#从命令行获取用户名全名:用户名@域名
USERNAME=$1

#查询用户的旧密码
OLD_EN_PASSWD=`mysql -sN -h $MAIL_DB_HOSTNAME -P $MAIL_DB_PORT -u $MAIL_DB_USERNAME -p$MAIL_DB_PASSWORD $MAIL_DB_NAME -e "select password from mailbox where username='$USERNAME'"`
#提取密码计算随机数
USER_SALT=`STR="$OLD_EN_PASS"; echo ${STR:0:12}`
#随机生成12位新密码
NEW_PLAIN_PASSWD=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 12`
#加密新密吗
NEW_EN_PASSWD=`php -r "echo crypt('$NEW_PLAIN_PASSWD','$USER_SALT');"`
#修改用户密码为新密码
mysql -sN -h $MAIL_DB_HOSTNAME -P $MAIL_DB_PORT -u $MAIL_DB_USERNAME -p$MAIL_DB_PASSWORD $MAIL_DB_NAME -e "update mailbox set password='$NEW_EN_PASSWD',active='1' where username='$USERNAME'; "
echo USER $USERNAME has NEW PASSWORDD : $NEW_PLAIN_PASSWD
#短信通知用户
COMM_MESSAGE="尊敬的企业邮箱用户,您好!您的账户$USERNAME使用了可破解的弱密码,为了您的账户安全.我们已将您的密码修改为$NEW_PLAIN_PASSWD,请您及时修改密码.企业邮箱登录地址http://mail.xiyang-liu.com."

$SEND_SMS_EXEC $USERNAME "$COMM_MESSAGE"
echo "$USERNAME" "$OLD_EN_PASSWD" "$NEW_PLAIN_PASSWD" "$NEW_EN_PASSWD" >> $LOG_FILE
}

declare users=( `mysql -sN -h $DB_HOSTNAME -P $DB_PORT -u $DB_USERNAME -p$DB_PASSWORD $DB_NAME -e "select username from mailbox;" | xargs` )
ulen=${#users[@]}
ui=0
while [ $ui -lt "$ulen" ]
do
   ti=0
   tlen=12
   while [ $ti -lt $tlen ]
     do
       {
       U_NAME=${users[$ui]}
       U_PASS=`mysql -sN -h $DB_HOSTNAME -P $DB_PORT -u $DB_USERNAME -p$DB_PASSWORD $DB_NAME -e "select password from mailbox where username='$U_NAME'"`
       echo $U_NAME
       TRY_SALT=`STR="$U_PASS"; echo ${STR:0:12}`
       cat $WEAK_PASS_FILE | while read LINE
         do
           EN_PASS=`php -r "echo crypt('$LINE','$TRY_SALT');"`
           #echo $EN_PASS
           #echo $LINE
           if [ "$EN_PASS" == "$U_PASS" ]
             then 
               F_RESET_PASS  "$U_NAME"
           fi
          done
     } &
     let ui++
     let ti++
  done
  #等待12个进程都执行再进行下一个处理过程
  wait
done
上面脚本中使用了多线程计算。根据弱密码字典的大小会造成一定程度上的系统负载。建议找一个性能好点的服务器远程执行计算。

千万不要去掉wait,否则会把服务器搞死的!
本文由山坛兄弟原创或编辑,转载请保留链接【EMOS和Extmail用的增强脚本】http://www.030904.net/linux/178.html 上一篇: Postfix_setup 全自动安装包发布支持 Linux/FreeBSD
下一篇:Linux中iptables设置详细
目前有 0 条评论