root 权限安全使用

配置 sudo

安装后只有仔细配置,sudo 才会安全和可靠。sudo 配置文件是 /etc/sudoers。可以编辑这个文件,以赋予特定用户只能够以 root 特权运行某些特定命令(而非任何命令)的能力。还可以限制这些用户只能使用某些特定的选项或参数运行命令。或者可以设置 sudo,使一个特定用户当以 root 特权运行命令时,不能使用一个特定的选项或参数。

编辑 sudoers 的最佳方法是在命令中这样使用 visudo:su -c visudo 命令或 sudo visudo。visudo 实用程序锁定、编辑和检查 sudoers 文件的语法。默认情况下,visudo 调用 vi 编辑器。可以设置 SUDO_EDITOR、VISUAL 或 EDITOR 环境变量,以使 visudo 调用不同的编辑器。以下命令使 visudo 调用 nano 编辑器(nano 包):

        $ export EDITOR=$(which nano) 
     

用所选择的文本型编辑器替换 nano。把这个命令放在启动文件中,以每次登录时自动设置此变量。值得注意的是,需要始终使用 visudo 编辑 sudoers 文件。

sudoers 文件中的一个语法错误,就会使无法使用 sudo 来取得 root 特权。如果直接编辑这个文件(不使用 visudo 命令),直到发现不能使用 sudo,才知道引入了语法错误。visudo 实用程序检查 sudoers 的语法后,才允许退出。如果它找到了一个错误,它给修复错误的选择,不保存对文件的更改并退出,或保存对文件的更改并退出。最后一个选择通常是较差的,所以 visudo 用 (DANGER!) 标记它。

在 sudoers 文件中,注释以 # 号开头,可以出现在一行的任何地方。除了注释,这个文件包含三种类型的条目:用户特权规范、别名和默认值。这些条目各占一行。可以通过使用反斜杠(\)来继续一行。

指定用户特权的行格式如下(等号两边的空白是可选的):

        user_list host_list = [(runas_list)] command_list 
     

其中,user_list 指定本规范行适用的用户。该列表可以包含用户名、组(% 前缀)以及用户别名(下一节)。可以使用内置命令 alias ALL 来使该行适用于所有用户;host_list 指定本规范行适用的主机。该列表可以包含一个或多个主机名、IP 地址或主机别名。可以使用内置命令 alias ALL 来使该行适用于所有系统,参考 sudoers 文件;runas_list 指定运行 command_list 中命令的用户,当带– u 选项调用 sudo 时。该列表可以包含用户名、组(% 前缀)以及使用 runas 别名(在下一节讨论)。它必须括在括号内。没有 runas_list,sudo 假定为 root。可以使用内置命令 alias ALL 来使该行适用于所有的用户和组;command_list 指定本规范行适用的实用程序。此逗号分隔的列表可以包含实用程序名、实用程序的目录名以及命令别名(在下一节讨论)。所有名称必须是绝对路径名;目录名必须以一个斜杠(/)结束。如果命令前面加上一个惊叹号(!),则是排除该命令。另外,可以使用内置命令 alias ALL 来使该行适用于所有的命令。在 command_list 中包含的字符串 sudoedit,赋予 user_list 中的用户使用 root 特权编辑文件的权限。如果对 command_list 中的命令用个双引号 (“”) 引起来,用户将无法指定任何命令行参数,其中包括该命令的选项。或者可以指定参数,包括通配符,来限制允许用户对该命令使用的参数。

以下用户特权规范允许 Sam 在所有系统(由 ALL 指定)上使用 sudo 来挂载和卸载文件系统(以 root 特权运行 mount 和 umount),参考包含本规范的 sudoers 文件:

        sam ALL=(root) /bin/mount, /bin/umount 
     

(root)runas_list 是可选的。如果省略它,sudo 允许用户以 root 特权运行 command_list 中的命令。在下面的例子中,Sam 要利用这些特权。他不能直接运行 umount,而是必须调用 sudo 来运行它。

        $ whoami 
        sam 
        $ umount /music 
        umount: only root can unmount /dev/sdb7 from /music 
        $ sudo umount /music 
        [sudo] password for sam: 
        $ 
     

如果用下面的一行替换上述 sudoers 中的该行,Sam 就无法卸载 /p03,虽然他仍然可以卸载其它任何文件系统,并可以安装任何文件系统:

        sam ALL=(root) /bin/mount, /bin/umount, !/bin/umount /p03 

     

sudoers 中前面行的结果随后显示。sudo 程序不提示输入密码,因为 Sam 在最后五分钟内输过自己的密码。

        $ sudo umount /p03 
        Sorry, user sam is not allowed to execute '/bin/umount /p03' as root on localhost. 
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
     

以下行限制 Sam 挂载和卸载已挂载在 /p01、 /p02、/p03 和 /p04 上的文件系统:

        sam ALL= /bin/mount /p0[1-4], /bin/umount /p0[1-4] 
     

以下命令显示的结果是:

        $ sudo umount /music 
        Sorry, user sam is not allowed to execute '/bin/umount /music'
        $ sudo umount /p03 
        $ 
     

在 sudoers 中的以下行允许 wheel 组成员的用户使用 sudo 来取得 root 特权:

        ## Allows people in group wheel to run all commands 
        %wheel ALL=(ALL) ALL 

        # Members of the admin group may gain root privileges 
        %admin ALL=(ALL) ALL 

     

此用户特权规范适用于所有系统(由等号左边的 ALL 表示)。如注释所表明的,此行允许 wheel 组的成员(组名前面加一个百分号指定:%wheel)以任何用户(括号内的 ALL)运行任何命令(最右边的 ALL)。当不带– u 选项调用 sudo 实用程序,sudo 以 root 特权运行指定的命令,大部分时间是这样使用 sudo 的。

如果将前面 sudoers 中的行按如下修改,它会允许 wheel 组的成员以任何用户运行任何命令,但有一个例外:不允许他们运行 passwd 来更改 root 密码(虽然他们可以获得 root 特权并能手动编辑它)。

        %wheel ALL=(ALL) ALL, !/usr/bin/passwd root 
     

别名可让重命名和 / 或对用户、主机或命令进行分组。以下是别名定义的格式。其中 alias_type 是别名的类型(包括 User_Alias, Runas_Alias, Host_Alias, Cmnd_Alias),alias_name 是别名的名称(约定为全部大写字母),alias_list 是一个逗号分隔的构成别名的一个或多个元素的列表。别名元素前面的感叹号 (!) 是对它的否定。

        alias_type alias_name = alias_list 
     

以下给出一些常用的选项。

User_Alias

用户别名的 alias_list 与用户特权规范(在上一节讨论)的 user_list 相同。来自 sudoers 文件的下面的几行定义了三个用户别名:OFFICE、ADMIN 和 ADMIN2。第一行别名定义的 alias_list 包括用户名 zach、sam 和 sls;第二行包括两个用户名和 admin 组的成员;第三行包括除 Max 外的 admin 组的所有成员。

        User_Alias OFFICE = zach, sam, sls 
        User_Alias ADMIN = max, zach, %admin 
        User_Alias ADMIN2 = %admin, !max 
     

Runas_Alias

unas 别名的 alias_list 与用户特权规范(在上一节讨论)的 runas_list 相同。下面的 SM runas 别名包括 sam 和 sls 用户名:

        Runas_Alias SM = sam, sls 
     

Host_Alias

主机别名仅在 sudoers 文件被运行多个系统的 sudo 引用时才有意义。主机别名的 alias_list 与用户特权规范(在上一节讨论)的 host_list 相同。以下行定义的 LCL 别名包括名为 guava 和 plum 的系统:

        Host_Alias LCL = guava, plum 
     

如果想在此列表中使用完全合格的主机名(hosta.example.com 而不只是 hosta),必须设置 fqdn 标志。但是,这样做可能会降低 sudo 的性能。

Cmnd_Alias

命令别名的 alias_list 与用户特权规范的 command_list 相同。下面的命令别名包括三个文件,包含在尾部以 / 表示的目录中,该目录包括所有这样的文件:

        Cmnd_Alias BASIC = /bin/cat, /usr/bin/vi, /bin/df, /usr/local/safe/ 
     

Defaults (Options)

通过使用 Defaults 关键字,可以更改配置选项的默认值。在此列表中的大部分值是隐式布尔型(on 或 off)或字符串型的标志。在一个默认行上命名一个标志以打开它,在其前面加上一个 ! 以关闭它。下面的 sudoers 文件中的一行将关闭 lecture 和 fqdn 标志,并打开 tty_tickets:

        Defaults !lecture,tty_tickets,!fqdn 
     

env_reset

使 sudo 来重置环境变量使之仅包含 LOGNAME、SHELL、USER、USERNAME、MAIL 和 SUDO_* 变量。缺省是 on。更多信息,请参阅 sudoers 手册页。

fqdn

(fully qualified domain name:完全合格域名)在 sudoers 文件中的 FQDN 上执行 DNS 查找。当设置了这个标志,可以在 sudoers 文件中使用 FQDN,但这样做可能会对 sudo 的性能产生负面影响,特别是如果 DNS 不能正常工作时。当设置了这个标志,必须使用本地主机的官方 DNS 名称,不能用别名。如果 hostname 返回一个 FQDN,则不需要设置这个标志。默认是 on。

insults

当用户输入一个错误密码时,显示温和、幽默的 insults。默认是 off。另见 passwd_tries。

lecture=freq

控制 sudo 在密码提示之前显示提醒消息的频率。freq 可能的值是 never、once 和 always。指定 !lecture 与指定为 never 的 freq 是相同的。默认是 once。

mail_always

每当用户运行 sudo 时,给 mailto 用户发送电子邮件。默认是 off。

mail_badpass

当用户运行 sudo 时输入一个错误的密码时,给 mailto 用户发送电子邮件。默认是 off。

mail_no_perms

当用户的用户名在 sudoers 文件中,但没有权限运行被请求命令(运行 sudo)的,给 mailto 用户发送电子邮件。默认是 off。

mail_no_host

当一个用户的用户名在 sudoers 文件中,但在本地主机上没有运行命令的特权时运行 sudo 的,给 mailto 用户发送电子邮件。默认是 off。

mail_no_user

当其用户名不在 sudoers 文件中的用户运行 sudo 的,给 mailto 用户发送电子邮件。默认是 on。

mailsub=subj

(mail subject)将用于警告和错误消息的默认电子邮件主题从默认的 *** SECURITY information for %h *** 更改为 subj。sudo 实用程序在 subj 内将 %h 扩展到本地系统的主机名。如果 subj 包含 shell 特殊字符,把它放在引号之间。

mailto=eadd

给 eadd(电子邮件地址,默认是 root)发送 sudo 的警告和错误消息。如果 eadd 包含 shell 特殊字符,把它放在引号之间。

passwd_timeout=mins

mins 是 sudo 密码超时的分钟数。值为 0(零)表示密码不会超时。默认值为 5。

passwd_tries=num

num 是为响应 sudo 密码提示并在 sudo 退出之前,用户可以输入错误密码的次数。默认为 3。另见 insults 和 lecture。

rootpw

使 sudo 只接受 root 密码以响应其提示符。因为无论是要求的密码或 root 密码,sudo 都发布相同的提示符,开启这个标志可能会混淆用户。默认是 off,使 sudo 提示运行 sudo 的用户输入密码。

shell_noargs

当不带任何参数调用时,会使 sudo 无需改变环境就派生一个 root shell。默认是 off。此选项与 sudo 的– s 选项是相同的。

timestamp_timeout=mins

mins 是 sudo 时间戳有效的分钟数。设置 mins 为– 1 会使时间戳永远有效;设置为 0(零)会使 sudo 始终提示输入密码。默认值为 5。

tty_tickets

使 sudo 基于每个 tty 验证用户,而不是基于每个用户。默认是 on。

umask=val

val 是 sudo 用来运行该用户指定命令的 umask 值。将 val 设置为 0777,以保留用户的 umask 值。默认值是 0022。

锁定 root 帐户(删除 root 密码)

如果决定要锁定 root 帐户,执行 su -c ‘ passwd – l root ’命令。通过在其前面加两个惊叹号(!!),此命令将在 /etc/shadow 中的加密密码设置为无效。可以通过删除惊叹号来解锁该帐户或执行下面示例中所示的命令。

解锁 root 帐户

如果决定解锁锁定的 root 帐户,执行下面的命令。此命令假定可以使用 sudo 来取得 root 特权,并通过给它分配一个密码来解锁 root 帐户:

        $ sudo passwd root 
        [sudo] password for sam: 
        Changing password for user root. 
        New password: 
        Retype new password: 
        passwd: all authentication tokens updated successfully. 
     

允许普通用户运行特权命令

consolehelper 实用工具使得通常只能由 root 特权用户运行的系统程序更容易由普通用户运行。PAM 对用户进行身份验证,可以设置信任所有控制台用户,要求输入用户密码(非 root 密码),或在授予信任之前输入 root 密码。consolehelper 的概念基础是,可能要把对控制台有访问权限的任何人看作是值得信赖的。例如,Sam 可以用自己的身份在控制台上登录,无须知道 root 密码就可以运行 reboot。

要了解 consolehelper 的工作原理,可以参考这两个 halt 文件:

        $ file /sbin/halt /usr/bin/halt 
        /sbin/halt: symbolic link to '../bin/systemctl'
        /usr/bin/halt: symbolic link to 'consolehelper'

     

在 Fedora 下,/sbin 中的文件链接到 /bin/systemctl;在 RHEL 下它链接到 /sbin/reboot。在这两个系统上,/usr/bin 中的文件都是到 /usr/bin/consolehelper 的一个链接。这些链接文件都是可执行文件:

        $ file /bin/systemctl /usr/bin/consolehelper 
        /bin/systemctl: ELF 32-bit LSB executable, Intel 80386 ... 
        /usr/bin/consolehelper: ELF 32-bit LSB executable, Intel 80386 ... 

     

在 root 的 PATH 变量中,/sbin 通常先于 /usr/bin。因此,当用户以 root 特权运行在 root 登录环境中执行 halt 命令,shell 将执行 Fedora 下的 /bin/systemctl reboot 或 RHEL 下的 /sbin/reboot。在一个普通用户的 PATH 变量中,/usr/bin 通常先于 /sbin(如果 PATH 包含 /sbin)。因此,当一个普通用户执行一个 reboot 命令,shell 将执行 /usr/bin/consolehelper(consolehelper 实用程序)。

consolehelper 做什么取决于如何设置 PAM。默认情况下,consolehelper 并不需要 root 密码;任何用户都可以执行 reboot 命令来重启系统。

root 帐户密码安全管理

密码安全管理原则

目前密码破解程序大多采用字典攻击以及暴力攻击手段,而其中用户密码设定不当,则极易受到字典攻击的威胁。很多用户喜欢用自己的英文名、生日或者账户等信息来设定密码,这样,黑客可能通过字典攻击或者是社会工程的手段来破解密码。所以建议用户在设定密码的过程中,应尽量使用非字典中出现的组合字符,并且采用数字与字符相结合、大小写相结合的密码设置方式,增加密码被黑客破解的难度。而且,也可以使用定期修改密码、使密码定期作废的方式,来保护自己的登录密码。具体列出几条设定安全密码的参考原则如下(几个需要遵循):

  • 口令长度至少为八个字符:口令越长越好。若使用 MD5 口令,它应该至少有 15 个字符。若使用 DES 口令,使用最长长度(8 个字符)。
  • 混和大小写字母:Linux 区分大小写,因此混和大小写会增加口令的强健程度。
  • 混和字母和数字:在口令中添加数字,特别是在中间添加(不只在开头和结尾处)能够加强口令的强健性。
  • 包括字母和数字以外的字符:$、和 > 之类的特殊字符可以极大地增强口令的强健性(若使用 DES 口令则不能使用此类字符)。
  • 挑选一个自己可以记住的口令:如果自己记不住自己的口令,那么它再好也没有用;使用简写或其它记忆方法来帮助自己记忆口令。
另外,还有一些原则需要牢记(几个不要):
  • 不要只使用单词或数字,决不要在口令中只使用单词或数字。
  • 不要使用现成词汇:像名称、词典中的词汇、甚至电视剧或小说中的用语,即使在两端使用数字,都应该避免使用。
  • 不要使用外语中的词汇:口令破译程序经常使用多种语言的词典来检查其词汇列表。依赖外语来达到保护口令的目的通常不起作用。
  • 不要使用黑客术语。
  • 不要使用个人信息:千万不要使用个人信息。如果攻击者知道自己的身份,推导出自己所用口令的任务就会变得非常容易。以下是自己在创建口令时应该避免使用的信息类型。
  • 不要倒转现存词汇:优秀的口令破译者总是倒转常用词汇,因此倒转薄弱口令并不会使它更安全。
  • 不要笔录自己的口令:决不要把口令写在纸上。把它牢记在心才更为安全。
  • 不要在所有机器上都使用同样的口令:在每个机器上使用不同的口令是及其重要的。这样,如果一个系统泄密了,所有其它系统都不会立即受到威胁。

使用密码分析工具验证

John the Ripper 是一个工具软件,用于在已知密文的情况下尝试破解出明文的破解密码软件。主要支持对 DES、MD5 两种加密方式的密文进行破解工作。它可以工作于多中不同的机型以及多种不同的操作系统之下,目前已经测试过能够正常运行的操作系统有:Linux x86、freeBSD、x86、Solaris、SPARC、OSF/1 Alpha、DOS、WinNT/WinXP 系列等。John the Ripper 1.7 是目前比较好的破解密码工具,在解密过程中会自动定时存盘,用户可以强迫中断解密过程(使用 Ctrl+C 组合键),下次还可以从中断的地方继续进行下去(john-restore 命令)。任何时候敲击键盘,用户都可以看到整个解密的进行情况,所有已经被破解的密码会被保存在当前目录下的 JOHN.POT 文件中,SHADOW 中所有密文相同的用户会被归成一类,这样 JOHN 就不会进行无谓的重复劳动了。在程序的设计中,关键的密码生成的条件被放在 JOHN.INI 文件中,用户可以自行修改设置,不仅支持单词类型的变化,而且支持自己编写 C 的小程序限制密码的取值方式。

在使用该软件前,我们可以从网上 http://www.openwall.com/john/ 下载其最新版本 john-1.7.9 for Linux 版本,它包含 DOC、SRC 和 RUN 三个目录,在 SRC 目录下,在 x86 机器上执行如下命令即可:

        #make 
        #make clean linux-x86-any 

     

安装好后,可以切换到 RUN 目录下,进行测试,如下所示:

        #cd ../run 
        #./john – test 

     

安装好后,我们可以灵活使用如下几种方式来对自己的账户密码进行测试。通常情况下,许多用户的密码命名方式非常简单,比如 foo、hello、world 等,或者很多都是与用户名相同的密码口令,那么我们一般可以先采用简单解密方式来对系统中的密码进行简单的初步试探,如果发现能够成功破解,那么就需要对这些密码口令的强度进行加强,如下所示:

        // 使用简单解密方式对系统账户进行测试
        #./john – single /etc/shadow 
        Loaded 3 password hashes with 3 different salts (FreeBSD MD5 [32/32]) 
        test             (test) 
        guesses: 1  time: 0:00:00:00 100%  c/s: 6975  trying: 999991900 

     

在上述命令中,我们发现系统存在一个 test 用户,其用户名和密码均为 test,因而通过最简单的方式便能将其发现和利用,如果为黑客破解则将造成不可设想的后果,因而我们的用户应该立即根据此种情况进行口令加强。

其次,用户可以使用字典文件来对系统用户的恶密码强度进行试探和测试。人们常用 hello、superman、cooler、asdfgh、123456 等作为自己的密码。而 -rules 参数则在此基础上再加上些变化,如字典中有单词 cool,则 JOHN 还会尝试使用 cooler、CoOl、Cool 等单词变化进行解密。一般视 SHADOW 中的用户多少及自己的字典大小、自己的机器速度,解密时间从几小时到几天不等。下面给出使用该方式进行解密的例子,假设我们已经生成了一个 password.lst 文件,其中包含了常用的以字典单词为依据的密码,那么我们对系统中的用户密码使用该方式进行试探破解,由于字典中保留了 duango 这样一个单词,因而用户 test 的密码所以也被试探出来,网络管理员同样需要对该密码进行加固,比如添加适当的后缀、字母和数字等:

        // 使用字典解密方式对系统账户进行测试
        # ./john --wordlist=password.lst /etc/shadow 
        Loaded 3 password hashes with 3 different salts (FreeBSD MD5 [32/32]) 
        duango           (test) 
        guesses: 1  time: 0:00:00:01 100%  c/s: 7065  trying: duango 

     

当然,上述两种只是非常直观和简单的方法,但是如果字典足够完整和实用的话,那么就能够查出绝大多数的脆弱口令,在实践中,我们还可以综合使用如下的一些选项,来对系统密码强度进行更为充分的检查和验证:

  • rules:在解密过程中使用单词规则变化功能。如将尝试 cool 单词的其他可能,如 COOLER、Cool 等,详细规则可以在 JOHN.INI 文件中的 [List.Rules:Wordlist] 部分查到。
  • incremental:使用遍历模式,就是组合密码的所有可能情况,同样可以在 JOHN.INI 文件中的 [Incremental:*****] 部分查到。
  • external:使用自定义的扩展解密模式,用户可以在 john.ini 中定义自己需要的密码组合方式。JOHN 也在 INI 文件中给出了几个示例,在 INI 文件的 [List.External:******] 中所定义的自动破解功能。
  • restore:继续上次的破解工作,JOHN 被中断后,当前的解密进度情况被存放在 RESTORE 文件中,自己可以复制这个文件到一个新的文件中。如果参数后不带文件名,JOHN 默认使用 RESTORE 文件。

参考资料

学习

讨论

关于作者

李洋,博士,现任某大型金融公司信息安全顾问,多年来一直从事信息安全方面的研发和管理工作,具有丰富的互联网、电信网和金融行业信息安全管理、咨询和研发经验。目前关注开源系统安全、云安全、虚拟化安全等。

posted on 2022-07-05 18:14  我在全球村  阅读(160)  评论(0编辑  收藏  举报