命令行安全技巧

命令行和脚本是危险的。 用rm -rf写一个错字,你处在一个受到伤害的世界里。 在运行导入脚本的同时,将数据库名称与数据库名称混淆起来,并将其绑定(如果它们位于同一台服务器上,这并不好,但会发生)。 同样的,注意到一些命令之后,服务器名称并不是你认为的那样。 你必须尊重孔霍克 。

在运行有风险的命令之前,我有一些小小的仪式 – 比如对我所在的服务器进行三重检查。 这里有一篇关于RM安全的有趣文章 。

什么小仪式,工具和技巧让你在命令行上安全? 我的意思是客观的事情,比如“先运行ls foo *,看看输出,然后用rm -rfreplacels以避免运行rm -rf foo *或类似的东西”,而不是“确定你知道什么命令会做“。

一个很好的方法就是在你的shell上使用不同的背景颜色来生成/登台/testing服务器。

在开始之前,请记住退出计划。

  • 压缩文件/目录,而不是立即删除它
  • 设置(cisco)路由器以“x”分钟数重新启动,不要立即“wr”
  • 确保你正在改变的界面不是你进入系统的界面。 这可能是您telnet到的路由器接口或VNC的以太网端口。
  • 从不以“root”身份login
  • 做一个备份。 检查它是好的。 再做一个。
  • 问一个你信任的人“我在这里做些什么愚蠢的事吗?

我有一些低技术解决scheme,其中一些。

我制定了一个习惯做以下事情(当计划以root身份工作时):

  • 首先,以普通用户身份login,然后使用sudo su - root切换到root用户。 我这样做是心理准备,提醒我,我已经精神上走进了一个非常危险的地区,我应该随时保持警惕和警惕。 听起来很有趣,这个小小的仪式本身通过强化我不能不小心 ,为节省了很多的痛苦。
  • 每个命令都是input的,但是从不按下[Return]键。 从来没有
  • 没有命令执行没有理解到底是什么。 如果你不知道它做了什么,你正在用你的系统玩俄罗斯轮盘赌 。
  • 按下[返回]键之前,请仔细检查CLI上触发的命令。 如果有任何犹豫,任何暗示的潜在问题,它都会重新审查。 如果犹豫不决,命令就留在线上,而我也可以用另一个控制台来查询手册页等。如果在graphics会话中,我启动一个浏览器并进行一些search。
  • 没有普通用户在我的系统上使用过sudo不是因为我是BOFH ,而是因为没有准备和训练,就像给猴子上了一个装满枪的枪。 开始的时候有趣有趣,直到猴子看到桶子,挤压…

当使用rm时,我总是先cd到目录,然后使用./的前缀来确保目录是正确的,即

cd /usr/some/directory ; rm ./targetfile

或者我指定文件的整个path

rm /usr/some/directory/targetfile

这是一个PITA,但是…比对不起更安全。

这一个是特定于Windows Powershell的。

作为一项政策,我们在每台服务器上添加以下机器profile.ps1。 这确保以下情况是正确的:

  1. pipe理PowerShell控制台窗口有一个深红色的背景色
  2. pipe理员被添加到标题
  3. “Warning:Powershell正在以pipe理员身份运行”消息。 在启动时写入
  4. 标题栏前面加上“Administrator:”
  5. 标准实用程序(如企业shell脚本,vim和infozip)在path中。
 $ currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity] :: GetCurrent())
 &{
     if($ currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole] :: Administrator))
     {
         (获取主机).UI.RawUI.Backgroundcolor =“暗红色”
        明确主机
        写主机“警告:PowerShell以pipe理员身份运行。
     }

     $ utilities = $ null
    如果([IntPtr] :: size * 8 -eq 64)
     {
         $ host.UI.RawUI.WindowTitle =“Windows PowerShell(x64)” 
         $ utilities =“$ {env:programfiles(x86)} \ Utilities”
     }
    其他
     {
         $ host.UI.RawUI.WindowTitle =“Windows PowerShell(x86)”
         $ utilities =“$ {env:programfiles} \ Utilities”
     }
     if((Test-Path $ utilities) -  and!($ env:path -match $ utilities.Replace(“\”,“\\”)))
     {
         $ env:path =“$ utilities; $ {env:path}”
     }
 }

function提示
 {
     if($ currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole] :: Administrator))
     {
        如果(!$ host.UI.RawUI.WindowTitle.StartsWith(“Administrator:”))
         {$ Host.UI.RawUI.WindowTitle =“Administrator:”+ $ host.UI.RawUI.WindowTitle}
     }
     'PS'+ $(if($ nestedpromptlevel -ge 1){'>>'})+'>'
 }

我可以同意所有上述的答案,但我必须强调这个非常非常重要的提示:

知道什么时候避免多任务。

我确定我所在系统的主机名在bash(或其他shell)提示符下。 如果我是chroot,我肯定也会以某种方式进入。

我曾经在另外一个活的Linux发行版中安装了一个Gentoo系统,并且意外地在错误的shell中运行了一个非常具有破坏性的命令(无法回想一下它是什么样的ATM – 一些rm变体),导致一系列的活动系统被删除,而不是来自chroot内的东西。 从那时起,我一直这样做

 export PS1="(chroot) $PS1" 

每当我在一个chroot工作。

在更改服务器之前,有几件重要的事情需要注意:

  • 确保我在正确的服务器上

  • 注意**有多less人会受此行为的影响*(如果您犯了错误)

  • 在input“input”键之前,请注意撤消可能性

  • 问问你自己,这个命令是否有可能断开你的会话 (fw规则,坏的关机等)。 确保你有一个故障转移回来(特别是如果你是异地)

如果你还没有做到这一点别名rm -r -i

规则1 – 进行备份

规则2 – 切勿在标准命令中添加“保密”包装,制作自己的版本,但不要接pipe名称,当你在没有设置的系统上时,它会咬你。

像root和(部分)目录树等不同颜色的提示技巧是很好的帮手,但同样,确保你可以在没有它们的情况下工作。

这看起来可能与直觉相反,但是最好的命令行安全提示是: 如果一个GUI模式的select是可用的和实用的,则使用IT

为什么? 非常简单。 graphics用户界面模式通常有一个内置的安全网,forms是“警告 – 你要咆哮freeblefrop,你确定要这样做吗? 即使没有,也会让你放慢脚步,给予思考时间更多的空间。 它可以让你仔细检查选项之前,提交给他们,你可以截图之前和之后的状态,它可以保护你免受错别字; 所有好的,有用的和有益的东西。

在可怕的“rm -rf”的经典案例中,你是否认为从GUI或CLI意外发出它更容易?

最后,诉诸GUI并不是什么好事。 它不会完全防止重大灾害; 就像在CLI中一样,可以在GUI中触发快乐; 但是如果它能够拯救你,那么它一旦被certificate是值得的。

使用常识,不要运行你不明白的命令。 这是很好的build议。 如果你想要写出你传递给rm的所有东西的绝对path,或者通过sudo运行任何东西,那么就自由了。 那么我宁愿su -c。 至less它不会caching密码。 如果没有密码validation,任何普通用户都可以使用root权限运行,我感觉不太舒服。

有几件事情可以放在你的〜/ .bashrc中,让事情变得更安全一点,比如:

 alias srm='rm -i' 

让你有一个安全的替代rm,…

但最后,你可能会总是搞砸了。 有一天,我有一个已经失效的configuration脚本,我的整个/ usr / bin文件夹,打破了几件事情。 是的,一个简单的“安装”任何types的软件的错误,可能会打破你的系统。 无论你做什么,你永远不会安全。 我所得到的是,最重要的是:

保持定期备份。

而不是别名rm到rm -i,用别名说删除或saferemove(并将其用作首选删除工具)不是更好。 然后当你使用一个没有这个设置的盒子时,不会造成伤害。

确保你永远不会运行你在网上find的命令,除非你完全明白他们在做什么。

你的系统可能与海报有所不同,这可能会造成一个伤害的世界。

从Unix / Linux的angular度来看,一个明显的命令行安全就是正确使用root帐户。
rm -rf作为root通常比用户更危险,使用sudo等内置的东西而不是rootlogin是至关重要的。 一个不错的简单whoami通常会帮助精神分裂症或多重人格。

这和prepending对任何文件切换命令的回声,特别是如果你想确保你有一个glob或正则匹配的权利。

如果你杀了你的主要会话,或者做了一些愚蠢的事情来locking它,那么在你正在使用的机器上build立一个辅助连接可能会很方便。

这样你仍然可以进入机器,并可以杀死你的主要会话。

上面的大多数评论都是指rm,但是我也用其他命令做了一些愚蠢的事情。

ifconfig取下networking – 哎哟,这需要物理存在来解决。

至于脚本,我通常在两个窗口中工作。 第一个我用来写脚本,第二个testing每一行,因为我写它。 慢慢地仔细地做,我可以确保每一行都按我所期望的那样工作,当我编写代码时,注意保持相同的variables等等。

就个人而言,我并没有发现额外的提示,像rm -i真的有帮助。 当我厌倦,强调等等时,我会犯大部分的错误,而这些时候我只是一味地嘲笑你而忽视提示。 不好的做法也许。

如果你使用bash,试试这个:

 TMOUT=600 

/root/.bashrc或类似的。 它会在10分钟后自动将您注销,这样可以减less您不小心打开并input某些内容的根端子的机会。

是的,我知道你应该使用sudo来执行root命令 – 这只是一个额外的安全网,以防你决定玩一天冒险。

 # Allow only UPDATE and DELETE statements that specify key values alias mysql="mysql --safe-updates"` 

如果您曾经使用过mysql命令行,那么强烈推荐别名。

我不使用ls,而是使用echo,因此在shell扩展了所有内容后,我可以看到完整的命令。 此外,总是使用双引号variables来表示文件,以便您的文件可以使用可能具有制表符或空格的文件名。

尽可能避免* glob作为自己的参数。 即使我的意思是“删除这个目录中的所有东西”,我也试图更具体一点,也就是说。 rm *.php 。 如果我不小心将另一个目录中的相同命令从历史logging中删除,那么这是先发制人的损坏控制。

让你思考你在做什么的一个好方法是把这样的东西添加到root的bashrc(cshrc,whatever):

 unset PATH 

那样,你必须做/ bin / rm而不是“rm”。 那些额外的angular色可能会让你思考。

对于复杂的正则expression式,特别是“查找”命令把echo放在前面,并将它们捕获到一个文件中。 然后你可以检查你是否真正删除/移动/等到你认为你是什么之前执行文件与“源”。

手动添加正则expression式没有select的边界情况也很方便。

对其他一些post稍微meta:我使用首先build议的通常的echo / ls步骤,以确保该命令是select我想要的文件集或由shell解释为预期的。

但是之后我使用shell的命令历史编辑function来检索以前的命令,并且只修改需要改变的部分。

单独input每个命令都无济于事

 $ ls *.bak $ echo rm *.bak $ rm * .bak 

…因为我意外地在最后一行input了空格,并删除了所有的文件。 我总是检索前一行,只是删除'回声'。

根用户:
除非必须,否则不要成为根。
如果供应商表示需要以root身份运行,请告诉他们您是客户,并且您希望以非root身份运行它。
现成的软件包有多less只是因为它更容易?

习惯:
永远不要用“*”删除而不去查看三次最好是build立使用ls -l TargetPattern的习惯,然后使用“rm!$”。 最大的威胁不在于你认为自己在哪里。 我经常像'ls'一样input'hostname'!

拐杖:
一个标准提示可以帮助很多人,比如“alias rm ='rm -i'”这样的别名,但是我经常没有完全控制我所在的机器,所以我只用一个expect包装脚本来设置你的path,提示,并用'-i'

发现问题:
使用完整path有助于,但是在不可能的情况下,请进入更安全的位置,并使用'&&'确保'cd'成功,然后再进行查找,删除,tar,untar等操作:
例如: cd /filesystema && tar cf - | ( cd /filesystemb && tar vxf -) cd /filesystema && tar cf - | ( cd /filesystemb && tar vxf -)
在这种情况下,使用'&&'可以防止tar文件被提取出来(尽pipe在这种情况下'rsync'会更好)

删除:
如果可以帮助,请不要recursion删除,特别是在脚本中。 find并删除-type f和-name'模式'我仍然生活在恐惧喂养'没有'xargs …焦油和untar移动的东西周围(使用rsync代替)

如果您使用操作系统的多个变体,请注意语法上的差异; 一个unix变体的安全性是非常危险的。

例如:killall

Linux / FreeBSD / OSX – 杀死所有匹配参数的进程。 例如:“killall apache”杀死所有的apaches,只留下所有其他进程。

Solaris – 杀死所有进程。 不完全是。 从手册页 :killall被shutdown(1M)用来终止所有与closures过程没有直接关系的活动进程。

代替

rm foo*

使用

rm -i foo*

这对less数文件来说是实用的,但是与整个压缩包不同。 这就是为什么别名会妨碍你的方式。

首先使用echo运行命令是一个好主意,但仍然容易出现拼写错误。

尝试使用扩展名,例如!$。

 echo foo* rm -rf !$ 

!$扩展到最后一个命令的最后一个单词,所以它相当于

 echo foo* rm -rf foo* 

还有!*,扩展到最后一个命令的所有参数。

事实上,如果你愿意,你可以这样做

 echo rm -rf foo* !* 

(如果您使用的是ksh,而不是bash,则可以inputEsc +句点来代替最后一个单词。)

在类似的情况下:

ls * .php
回声rm * .php
rm * .php

您可以使用replace运算符,如下所示:
$ ls * .php
<dir listing>

$ ^ ls ^ echo rm(用前面的命令中的ls代替echo rm,保持命令行的其余部分一致)

$ ^ echo rm ^ rm(用rmreplaceecho rm,因此你不必重新input* .php并在错误的时间input空格)

对于那些不熟悉的人,^ = shift-6。

使用bash并设置PS1 ='\ u @ \ h:\ w>'。 这扩展到用户名@主机名:/完整/工作/目录/path>正如其他答案中所提到的,你可以使用期望设置环境,无论你login,如果你不能更新.profile或.bash_profile文件。 虽然改变背景颜色很容易是最好的答案:-)

是啊。 通过IRC发送给某人一个文件的这个古老的技巧命名为“-rf”,所以它最终在他们的目录中。 稍后有一个“rm -rf”(而不是“rm -rf”),随着他们学习一个关于不以root身份运行IRC的严峻教训,随之而来的是大笑声。

而不是使用rm -rf <dir>-rf放在最后,如下所示: rm <dir> -rf 。 把它瞄准之后,在你开火之前,把它看作是安全的。 这样,如果您在input目录名称(或使用制表符完成)的同时有一个input键,并且具有类似命名的目录,那么您将受到保护。