Уловки безопасности командной строки

Командная строка и сценарии опасны. Сделайте небольшую опечатку с помощью команды rm -rf, и вы окажетесь в мире боли. Смешивайте prod с stage в имени базы данных во время выполнения сценария импорта, и вы окажетесь в тупике (если они находятся на одном сервере, что не очень хорошо, но бывает). То же самое для того, чтобы заметить слишком поздно, что имя сервера, на котором вы sshed, не соответствует тому, что вы думали, после того, как запомнили некоторые команды. Вы должны уважать Hole Hawg.

У меня есть несколько маленьких ритуалов перед выполнением рискованных команд - например, тройная проверка сервера, на котором я работаю. Вот интересная статья о безопасности полетов.

Какие маленькие ритуалы, инструменты и приемы защищают вас от командной строки? И я имею в виду объективные вещи, такие как "сначала запустите ls foo*, посмотрите на результат этого, а затем замените ls на rm -rf, чтобы избежать запуска rm -rf foo * или что-то в этом роде", а не "убедитесь, что вы знаете, что команда сделает ".

30 ответов

Решение

Хорошо работает использование различных цветов фона в вашей оболочке для серверов prod/staging/test.

Имейте в виду план возврата, прежде чем начать.

  • Заархивируйте файл / каталог вместо того, чтобы удалить его сразу
  • установите (cisco) маршрутизатор для перезагрузки через 'x' минут и не пишите сразу
  • убедитесь, что интерфейс, который вы меняете, не тот, в который вы вошли в систему. Это может быть интерфейс маршрутизатора, к которому вы telnet'd или порт Ethernet VNC'd к.
  • никогда не входите в систему как root
  • сделать резервную копию. проверь что это хорошо. сделать еще один.
  • спросите кого-то, кому вы доверяете: "Я собираюсь сделать что-то глупое здесь?"

У меня есть низкотехнологичное решение для некоторых из них.

Я разработал привычную привычку делать следующее (при планировании работы от имени root):

  • Сначала войдите как обычный пользователь, затем используя sudo su - root переключиться на root. Я делаю это как умственную подготовку, напоминание мне, что я мысленно вошел в очень опасную область и что я должен быть настороже и всегда настороже. Как ни странно, этот маленький ритуал спас меня от грусти, просто подкрепив, что я не могу быть небрежным.
  • Каждая команда набирается, но клавиша [Return] никогда не нажимается. Никогда
  • Ни одна команда никогда не выполняется без точного понимания того , что она делает. Если вы делаете это, не зная, что он делает, вы играете в русскую рулетку со своей системой.
  • Перед нажатием клавиши [Return] команда, которая была выведена на CLI, тщательно проверяется на глаз. Если есть какие-либо колебания, любой намек на потенциальную проблему, он снова пересматривается. Если это колебание не устранено, команда остается в строке, и я запускаю alt-F2 для другой консоли, чтобы просмотреть справочные страницы и т. Д. Если в графическом сеансе я запускаю браузер и выполняю поиск.
  • Ни один обычный пользователь никогда не передается sudo в моих системах, не потому что я BOFH, а потому что без подготовки и тренировки это все равно что дать обезьяну заряженный пистолет. Поначалу это забавно и весело, пока обезьяна не смотрит вниз на бочку и не сжимает...

При использовании rm я всегда cd сначала в каталог, затем используйте префикс ./ чтобы убедиться, что каталог правильный, т.е.

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

или я указываю полный путь к файлу

rm /usr/some/directory/targetfile

который является PITA, но... лучше, чем потом сожалеть.

Это специфично для Windows Powershell.

В качестве политики мы добавляем следующий файл profile.ps1 на каждом сервере. Это гарантирует, что следующее верно:

  1. Окна консоли PowerShell имеют темно-красный цвет фона
  2. Администратор добавлен в заголовок
  3. Сообщение "Предупреждение. Powershell работает от имени администратора". написано при запуске
  4. Строка заголовка имеет префикс "Администратор:"
  5. Стандартные утилиты (такие как скрипты корпоративной оболочки, vim и infozip) находятся в пути.
$ currentPrincipal = New-Object Security.Principal.WindowsPrincipal ([Security.Principal.WindowsIdentity]:: GetCurrent ())
& {
    if ($ currentPrincipal.IsInRole ([Security.Principal.WindowsBuiltInRole]:: Administrator))
    {
        (Получить-хост).UI.RawUI.Backgroundcolor="Darkred"
        ясно-хост
        write-host "Предупреждение. PowerShell работает от имени администратора. n"
    }

    $ utilities = $ null
    if ([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}"
    }
}

функция подсказка
{
    if ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
    {
        if(!$host.UI.RawUI.WindowTitle.StartsWith( "Администратор: "))
        { $Host.UI.RawUI.WindowTitle = "Администратор: " + $host.UI.RawUI.WindowTitle }
    }
    'PS' + $(if ($nestedpromptlevel -ge 1) { '>>' }) + '> '
}

Я могу согласиться со всеми приведенными выше ответами, но я должен подчеркнуть этот очень, очень важный совет:

Знайте, когда следует избегать многозадачности.

Я уверен, что имя хоста системы, в которой я работаю, находится в приглашении bash (или другой оболочки). Если у меня есть chroot, я тоже уверен, что это так и есть.

Однажды я устанавливал систему Gentoo из другого живого дистрибутива Linux и случайно выполнил довольно разрушительную команду (не могу вспомнить, что это был ATM - какой-то вариант rm) в неправильной оболочке, что приводит к удалению множества вещей в работающей системе, а не вещей из chroot. С тех пор я всегда делал

export PS1="(chroot) $PS1"

всякий раз, когда я работал в chroot.

Есть несколько важных вещей, о которых нужно знать, прежде чем вносить изменения в сервер:

  • Убедитесь, что я на правильном сервере

  • Знайте, ** сколько людей будет затронуто этим действием * (если вы допустили ошибку или нет)

  • Прежде чем вводить клавишу ввода, учтите возможность отмены

  • Спросите себя, может ли эта команда отключить ваш сеанс (правило fw, плохое завершение работы и т. Д...). Убедитесь, что у вас есть сбой, чтобы вернуться (особенно, если вы находитесь за пределами площадки)

Если вы еще этого не сделали, псевдоним rm-rm -i

Правило 1 - делайте резервные копии

Правило 2 - НИКОГДА не добавляйте обертки "molly guard" к стандартным командам, конечно, создавайте свою собственную версию, но не берите имя, оно просто укусит вас, когда вы находитесь в системе, которую вы не настроили.

Уловки подсказок, такие как разные цвета для корневого и (частичного) дерева каталогов, являются отличными помощниками, но, опять же, убедитесь, что вы можете работать без них.

Это может показаться нелогичным и менее "ardkore", но лучший совет по безопасности командной строки, который у меня есть: если альтернатива в режиме GUI доступна и практична, то используйте ее.

Зачем? Достаточно просто. GUI-режим обычно имеет встроенную систему безопасности в форме "предупреждение - вы собираетесь заморозить freeblefrop, вы уверены, что хотите это сделать?" Даже если это не так, это замедляет вас и дает больше времени для размышлений. Это позволяет вам проверять параметры перед их фиксацией, снимать скриншоты до и после состояний, защищает вас от опечаток; все хорошие, полезные и полезные вещи.

В классическом случае страшного "rm -rf", как вы думаете, проще ли случайно выпустить его из GUI или CLI?

В конце концов, нет ничего постыдного в использовании графического интерфейса. Это не будет безошибочно предотвратить крупные бедствия; в графическом интерфейсе настолько же возможно быть довольным триггером, как и в CLI; но если это спасет вас однажды, это доказало свою ценность.

Используйте здравый смысл и не запускайте команды, которые вы не понимаете. Это все хороший совет. Если вы чувствуете, что вам больно записывать абсолютный путь всего, что вы передаете в rm, или запускать что-либо через sudo, не стесняйтесь. Я бы предпочел Су-С тогда. По крайней мере, это не кэширует пароль. Мне было бы неудобно, если бы любому обычному пользователю разрешали запускать вещи с правами root без проверки пароля.

Есть несколько вещей, которые вы можете вставить в ~/.bashrc, чтобы сделать их немного более безопасными, например:

alias srm='rm -i'

Позволяя вам иметь безопасную альтернативу рм,...

Но, в конце концов, вы можете и всегда облажаться. На днях у меня был несуществующий скрипт настройки, прервавший всю мою папку /usr/bin, сломав несколько вещей. Да, простая "установка" любого программного обеспечения с ошибкой может привести к поломке вашей системы. Вы НИКОГДА не в безопасности, что бы вы ни делали. То, к чему я стремлюсь, это САМАЯ важная вещь:

Регулярно сохраняйте резервные копии.

Вместо псевдонима от rm к rm -i, было бы лучше псевдонимом сказать удалить или безопасное удаление (и использовать их в качестве предпочитаемого инструмента удаления). Затем, когда вы используете ящик, который не был настроен, не наносится никакого урона.

Очевидным для безопасности командной строки с точки зрения Unix/Linux является правильное использование учетной записи root.
Rm -rf в качестве пользователя root обычно более опасен, чем пользователь, и использование встроенных средств, таких как sudo, а не вход в систему от имени пользователя root является жизненно важным. Хороший простой whoami обычно поможет от шизофрении или нескольких личностей.

Это и добавление эха к любым командам изменения файлов, особенно если вы хотите убедиться, что вы правильно выбрали глобальное или регулярное выражение.

Если вы используете bash, попробуйте это:

TMOUT=600

в вашем /root/.bashrc или похожие. Через 10 минут он автоматически выходит из системы, уменьшая вероятность того, что вы перейдете в корневой терминал, который вы случайно оставили открытым, и наберете что-нибудь глупое.

Да, я знаю, что вы должны использовать sudo для выполнения корневых команд - это просто дополнительная сеть безопасности на тот случай, если вы решите рисковать в один прекрасный день.

Убедитесь, что вы никогда не запускаете команду, найденную в Интернете, если вы не полностью понимаете, что они делают.

Ваша система может отличаться от системы плаката, и это может причинить боль.

Наличие вторичного соединения с машиной, на которой вы работаете, может быть полезно в случае, если вы прервете свой основной сеанс или сделаете что-то глупое, что блокирует его... тяжелая обработка и т. Д.

Таким образом, вы по-прежнему имеете доступ к компьютеру и можете прервать ваш основной сеанс.

Большинство вышеприведенных комментариев относятся к rm, но я сделал несколько глупостей и с другими командами...

ifconfig, чтобы отключить сеть - ой, это требует физического присутствия, чтобы исправить.

Что касается сценариев, я обычно работаю в двух окнах. Первое, которое я использую для написания сценария, второе - для проверки каждой строки при ее написании. Идя медленно и осторожно, я могу убедиться, что каждая строка работает так, как я ожидаю, когда я пишу код, заботясь о сохранении тех же переменных и т. Д.

Лично я не нахожу лишних подсказок для таких вещей, как rm -i, которые действительно помогают. Я делаю большую часть своих ошибок, когда я устаю, испытываю стресс и т. Д., И это именно то время, когда я просто буду бить тебя и все равно игнорировать подсказку. Плохая практика, возможно.

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

Настоятельно рекомендуется иметь псевдоним, если вы используете mysql CLI.

Если вы используете несколько вариантов операционной системы, помните о различиях в синтаксисе; то, что является достаточно безопасным в одном варианте unix, чрезвычайно опасно в другом.

Пример: killall

Linux / FreeBSD / OSX - убивает все процессы, соответствующие переданному параметру. Например: "killall apache" убивает всех apache, оставляя все остальные процессы в покое.

Солярис - убивает все процессы. Нет, правда. Со страницы man: killall используется shutdown(1M) для уничтожения всех активных процессов, не связанных напрямую с процедурой shutdown.

Пользователь root:
Не будь пользователем root, если тебе не нужно.
Если поставщик заявляет, что ему нужно запускать с правами root, скажите им, что вы являетесь клиентом и хотите запустить его без полномочий root.
Сколько программных пакетов с полки хотят получить root "просто потому, что это проще"?

привычка:
никогда не используйте '*' с remove, не глядя на него три раза. Лучше всего выработать привычку использовать ls -l TargetPattern, а затем использовать 'rm!$'. Самая большая угроза не в том, где ты думаешь. Я почти набираю 'имя хоста' так часто, как 'ls'!

костыли:
стандартная подсказка помогает, как и псевдонимы, такие как "alias rm='rm -i'", но я часто не имею полного контроля над машинами, на которых я работаю, поэтому я использую сценарий ожидаемой оболочки просто для установки вашего пути, подсказка и псевдонимы с '-i'

найти проблемы:
Использование полного пути помогает, но в тех случаях, когда это невозможно, перейдите в более безопасное место и ТАКЖЕ используйте "&&", чтобы убедиться, что "cd" завершится успешно, прежде чем вы выполните поиск, удаление, tar, untar и т. д.
пример: cd /filesystema && tar cf - | ( cd /filesystemb && tar vxf -)
использование '&&' может помешать извлечению tar-файла поверх самого себя в этом случае (хотя в этом случае лучше использовать 'rsync')

удаляет:
никогда не удаляйте рекурсивно, если вы можете помочь, особенно в сценарии. найти и удалить с -type f и -name 'pattern' Я до сих пор живу в страхе перед тем, как кормить xargs 'ничто'... tar и untar для перемещения (используйте вместо этого rsync)

Я избегаю * Glob в качестве собственного аргумента, когда это возможно. Даже если я действительно имею в виду "удалить все в этом каталоге", я пытаюсь быть более конкретным, т.е. rm *.php, Это упреждающий контроль повреждения в случае, если я случайно запустил ту же команду из истории в другом каталоге.

Немного мета к некоторым другим постам: сначала я использую обычные предложенные шаги echo/ls, чтобы убедиться, что команда выбирает набор файлов, которые я хочу, или интерпретируется оболочкой иным образом, как и предполагалось.

Но затем я использую функции редактирования истории команд оболочки, чтобы извлечь предыдущую команду и изменить только те части, которые необходимо изменить.

Совсем не помогает набирать каждую из этих команд независимо...

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

... потому что я случайно набрал пробел в последней строке и удалил все файлы. Я всегда получал предыдущую строку и просто удалял "эхо".

Отличный способ заставить вас задуматься о том, что вы делаете, - добавить что-то подобное в bashrc root (cshrc, что угодно):

unset PATH

Таким образом, вы должны сделать /bin/rm вместо просто "rm". Эти дополнительные персонажи могут заставить вас думать.

Вместо ls я использую echo, чтобы увидеть полную команду после того, как оболочка все расширила. Кроме того, всегда используйте двойные кавычки, представляющие файлы, чтобы ваши вещи работали с именами файлов, которые могут содержать символы табуляции или пробелы.

Для сложных регулярных выражений, особенно команды 'find', помещают echo впереди и записывают их в файл. Затем вы можете проверить, действительно ли вы удаляете / перемещаете / и т. Д. Именно то, что вы думаете, прежде чем выполнять файл с "источником".

Это также удобно для ручного добавления тех крайних случаев, которые регулярное выражение не подобрало.

Вместо

rm foo*

использование

rm -i foo*

Это практично с несколькими файлами, но не с, скажем, целым архивом. Вот почему псевдонимы rm встанет у вас на пути.

Выполнение команды сначала с помощью echo - хорошая идея, но она по-прежнему подвержена опечаткам.

Попробуйте использовать его с расширением, таким как!$.

echo foo*
rm -rf !$

! $ Расширяется до последнего слова последней команды, поэтому эквивалентно

echo foo*
rm -rf foo*

Также есть!*, Который распространяется на все аргументы последней команды.

Действительно, вы могли бы сделать это таким образом, если вы предпочитаете

echo rm -rf foo*
!*

(Если вы используете ksh, а не bash, вы можете ввести Esc+period, чтобы вставить последнее слово.)

Используйте bash и установите PS1='\u@\h:\w> '. Это расширяется до имени пользователя @ имя_хоста: / full / working / directory / path> Как упоминалось в других ответах, вы можете использовать ожидаемую настройку среды при каждом входе в систему, если не можете обновить файлы.profile или.bash_profile. Изменение цвета фона - лучший ответ:-)

В случае чего-то вроде:

ls *.php
echo rm *.php
рм *.php

Вы можете использовать оператор подстановки, например так:
$ ls *.php
<каталог dir>

$ ^ ls ^ echo rm (заменяет ls в предыдущей команде на echo rm, оставляя остальную часть командной строки такой же)

$ ^ echo rm ^ rm (замените echo rm на просто rm, поэтому вам не нужно повторно вводить *.php и выбрасывать пробел в неподходящее время)

^ = shift-6, для тех, кто не знаком с этим.

Вместо того, чтобы использовать rm -rf <dir> положить -rf в конце примерно так: rm <dir> -rf, Думайте об этом как о снятии безопасности после того, как вы прицелились и перед тем как выстрелить. Таким образом, вы защищены, если вы нажали клавишу ввода при вводе имени каталога (или с помощью дополнения табуляции) и у вас есть каталоги с одинаковыми именами.

О да. Эта старая уловка - отправка кому-то файла через IRC с именем "-rf", чтобы он оказался в каталоге ~. Один маленький "rm -rf" позже (вместо "rm - -rf") и большой смех последовали, когда они выучили суровый урок о том, что IRC не запускается от имени root.

Другие вопросы по тегам