Экранирование специальных символов при замене паролей в нескольких файлах bash-скриптом - PullRequest
0 голосов
/ 05 ноября 2018

Я нашел много близких вопросов, но не совсем подходящих для моего варианта использования, поэтому пришлось открыть новый.

Предположим, система имеет пароль, состоящий из строчных и прописных букв, цифр и специальных символов (az, AZ, 0-9, #) в нескольких файлах конфигурации (один и тот же пароль используется веб-приложением на главной домен, его субдомены и все соответствующие базы данных). Пример такого файла с паролем:

$databases = array (
  'default' =>
  array (
    'default' =>
    array (
      'database' => 'database_name',
      'username' => 'datbase_user',
      'password' => 'yv[48k2)KMGx{g1b',
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',
      'collation' => 'utf8mb4_general_ci',
      'charset' => 'utf8mb4',
      'prefix' => '',
    ),
  ),
);

Я пытаюсь написать bash-код, который принимает автоматически сгенерированный новый пароль (с тем же алгоритмом - все строчные и прописные буквы, цифры и специальные символы), находит все вхождения старого пароля в домашнем каталоге соответствующего родителя. домен и его поддоменов и заменяет новым паролем. Следующая однострочная работает нормально:

grep -rlF "$old_pass" /path/to/directory | xargs sed -i "s/$old_pass/$new_pass/g"

для паролей, состоящих только из букв и цифр (например, qVYYgB5bRxUYpHg). Однако, хотя часть grep работает нормально, часть sed дает сбой, как только система добавляет специальные символы в сгенерированный пароль (например, aN#zDU>lve15Uwqn), давая:

sed -i "s/$old_pass/$new_pass/g" password.php
sed: -e expression #1, char 37: unterminated `s' command

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

Ответы [ 3 ]

0 голосов
/ 05 ноября 2018

Я думаю, что возможные перестановки автоматически сгенерированных паролей могут выходить за рамки того, что вы легко сможете согласовать с sed, но суть вопроса заключается в защите метасимволов. Для этого конкретного примера:

$: echo "$b"              # the desired string
aN#zDU>lve15Uwqn
$: echo "$a"              # the current string, with embedded metachars
yv[48k2)KMGx{g1b
$: echo "$a" |            # pipe it to a sed to clean it
>    sed 's/\W/\\&/g'     # backquote all non-word chars
yv\[48k2\)KMGx\{g1b
$: echo "$a" | sed 's/\W/\\&/g'>a # save to a file
$: cat a
yv\[48k2\)KMGx\{g1b
$: echo "sed -E 's/$(<a)/$b/g'">x # save the sed to be run to a file
$: cat x
sed -E 's/yv\[48k2\)KMGx\{g1b/aN#zDU>lve15Uwqn/g'
$: echo $a | . x          # source it
aN#zDU>lve15Uwqn

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

Итак, ваш настоящий сценарий:

 echo "$old_pass" | sed 's/\W/\\&/g'> old_pat
 echo "$new_pass" | sed 's/\W/\\&/g'> new_pat
 echo "sed -E 's/$(<old_pat)/$(<new_pat)/g'" > src # save the command to a file
 echo "$old_pass" | . src                        # source it

Я не включил -i для редактирования на месте, так как вы сначала захотите проверить процесс.

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

... вы не прописываете все эти пароли в этом php-файле? : D

0 голосов
/ 05 ноября 2018

Лучше использовать perl здесь, потому что он поддерживает /\Q...\E/ шаблон регулярного выражения, который обрабатывает все буквы в этих тегах буквально (без специального значения регулярного выражения).

Вот пример:

cat file

abc123
pass=yv[48k2)KMGx{g1b
foobar

Теперь используйте команду perl:

old_pass='yv[48k2)KMGx{g1b'
new_pass='aN#zDU>lve15Uwqn'

perl -pe "s~\\Q${old_pass}\\E~\\Q$new_pass~g" file

abc123
pass=aN\#zDU\>lve15Uwqn
foobar

Если у вас нет perl, то вы можете использовать этот awk, который использует поиск по sting без использования регулярных выражений:

awk -v old="$old_pass" -v new="$new_pass" 'n=index($0, old) { 
   $0 = substr($0, 1, n-1) new substr($0, n + length(old)) } 1' file
0 голосов
/ 05 ноября 2018

Ваше выражение sed неверно, потому что вам нужно убрать квадратную скобку [:

sed -i 's/yv\[48k2)KMGx{g1b/aN#zDU>lve15Uwqn/g' password.php

Чтобы избежать расширения параметров оболочки, используйте в кавычках выражение sed.

Если вы хотите сопоставить все буквы, цифры и специальные символы (при условии пунктуации), вы можете использовать символы класса:

sed 's/[[:punct:][:alnum:]]*/NEWPASSWORKD/g' password.php
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...