UnixMountainSkiFun

Unix Горы Лыжи

02-06-2008 18:23

Обеспечиваем безопасность


Теперь мы переходим к следующей части этой главы, которую мы начнем с того, что напугаем вас. Шифрование и цифровая подпись это не новое понятие, однако когда вы попытаетесь использовать эту технологию, то скорее всего столкнетесь с новыми понятиями и наверняка будете не вполне понимать, что и как делается. Однако не паникуйте! Глава 10?, "Обеспечение безопасности E-Mail с помощью GPG", содержит все то, что необходимо знать о GnuPG.

Использование GnuPG для целей авторизации

Как мы уже говорили, у текущей версии e-mail-консоли есть одна маленькая проблемка, которая состоит в том, что всякий, кто способен отправить e-mail на вашу систему, сможет исполнять команды от имени вашей учетной записи. Чтобы не допустить такого безобразия, мы модифицируем Perl-скрипт таким образом, чтобы обеспечить поддержку обнаружения и проверки цифровой подписи. Когда e-mail поступает на e-mail-консоль, то сначала он будет проверен на наличие цифровой подписи (digital signature), а затем будет проверен снова, с помощью особого keyring-а, содержащегося в e-mail-консоли, на предмет того, имеет ли силу эта цифровая подпись. Это означает то, что пользоваться командами e-mail-консоли смогут только те люди, которым вы доверяете. Вы можете пользоваться и другими приемами для обеспечения безопасности. Однако, здесь, мы будем стараться излагать все как можно проще, а потому предполагаем, что ваши друзья вполне благонадежны, и не будут стараться стереть все файлы в вашем домашнем каталоге. Помимо авторизации, результаты работы команд e-mail-консоли также должны быть зашифрованы.

Использование GnuPG для шфирования результатов

После того, как цифровая подпись проверена, мы можем перейти к исполнению команд e-mail-консоли, содержащихся в e-mail, а затем поместить зашифрованные результаты в e-mail, и отправить его обратно. Мы будем пользоваться GnuPG, для того чтобы шифровать результаты выполнения команд.

Чтобы зашифровать результаты выполнения команд, мы будем использовать e-mail-адрес, содержащийся в полях From или Reply-to, в качестве идентификатора публичного ключа (public key identifier). Мне кажется, что я смог объяснить достаточно ясно.

Собираем все вместе

И проверка цифровой подписи, и шифрование результатов, потребуют модификации скрипта email_console.pl. Вот новая версия этого скрипта:

 #!/usr/bin/perl

 use IPC::Open3;
 use Symbol;

 #------------------------
 # set up vars for open3
 #------------------------
 $WTR = gensym();
 $RDR = gensym();

 #---------------------------
 # some handy variable defs
 #---------------------------
 $logfile = "/home/stmurphy/.email_console.log";
 $line_sep = 0;
 $separator = "\n" . "~" x 72 . "\n";
 $theOutput = "\n\n";
 $reply_subject = "Email Console Results";
 $signature_line =  "\n--\nOutput generated by the Email Console\n";
 $no_commands_mesg = "No commands found to execute.";
 $from = "";
 $reply_to = "";

 #---------------
 # open log file
 #---------------
 open LOG,">>$logfile";

 #-----------------------------
 # read in the entire file
 #-----------------------------
 @email = <>;

 #----------------------------
 # search for a sender to
 # put as out recipient for
 # the reply back
 #----------------------------
 foreach $_ (@email) {

     #------------------------
     # get the sender address
     #------------------------
     if ($_ =~ m/^From: (.*)/) {
         $from = $1;
     }

     #---------------------------------
     # get the sender address override
     #---------------------------------
     if ($_ =~ m/^Reply-To: (.*)/) {
         $reply_to = $1;
     }
 }
 $who = ($reply_to ne "") ? "F:$from R:$reply_to" : $from;

 #--------------------------------------
 # check message for a valid signature
 #--------------------------------------
 open GPG, "|/usr/bin/gpg -batch -verify -keyring ec-keyring -no-default-keyring
 foreach $_ (@email) {
     print GPG $_;
 }
 close GPG;
 $val = $? / 256;

 #-------------------------
 # valid signature found
 #-------------------------
 if ($val == 0) {
     #--------------------------
     # our parse/execution loop
     #--------------------------
     foreach $_ (@email) {

         #---------------------------
         # look for <exec>...</exec>
         # and process the command
         #---------------------------
         if ( $_ =~ m/^<exec>(.*)<\/exec>/ ) {
             undef $cmd_output;
             if ($line_sep) {
                 $theOutput .= $separator;
             } else {
                 $line_sep = 1;
             }
             print LOG scalar localtime() . " $who executed [$1]\n";
             $theOutput .= "Executing [$1]\n\n";

             #-----------------------
             # execute the command(s)
             #-----------------------
             open3($WTR, $RDR, "", $1);
             close($WTR);
             while (<$RDR>) {
                 $cmd_output .= $_;
             }
             $theOutput .= $cmd_output;
         }
     }
 }

 #-------------------------
 # invalid signature found
 #-------------------------
 elsif ($val == 1) {
     $theOutput .= "Invalid digital signature!";
     print LOG scalar localtime() . " $who - Invalid digital signature\n";
 }

 #-------------------------
 # some other problem
 # or not a signed message
 #-------------------------
 elsif ($val >= 2) {
     $theOutput .= "Not a valid Email Console email.\nA digital signature is required!";
     print LOG scalar localtime() . " $who - No digital signature found\n";
 }

 #-----------------------------
 # report if there were
 # no command executed at all
 #-----------------------------
 if (!$val && !$line_sep) {
     $theOutput .= $no_commands_mesg;
     print LOG scalar localtime() . " $who - No commands in email\n";
 }

 #---------------------------
 # tack on a handy dandy
 # signature line
 #---------------------------
 $theOutput .= $signature_line;

 #-----------------------------
 # override the from address
 # with the reply-to address
 #-----------------------------
 if ($reply_to ne "") {
     $from = $reply_to;
 }

 #----------------------
 # close the log file
 #----------------------
 close LOG;

 #----------------------
 # encrypt the results
 #----------------------
 open3($WTR, $RDR, "",  "gpg --armor --output - --recipient \"$from\ " -quiet --batch

 print $WTR $theOutput;
 close $WTR;

 undef $theOutput;
 while(<$RDR>) {
     $theOutput .= $_;
 }
 close $RDR;

 #-----------------------
 # send the reply email
 # with the execution
 # results
 #-----------------------
 exec "echo \"$theOutput\" | mailx -s \"$reply_subject\" \"$from\"";

 exit;

Чтобы упростить тестирование этих двух версий e-mail-консоли, я принял решение назвать вторую версию email_console_gpg.pl. Должно быть вы уже заметили некоторые изменения в этом скрипте, например, такие как журналирование запросов. Журнальный файл e-mail-консоли, я разместил в своем домашнем каталоге и сделал скрытым, -- .email_console.log. Другое более значительное изменение состоит в добавлении GPG-кода, для реализации проверки цифровой подписи и шифрования результатов исполнения команд.

И наконец, я изменил файл .procmail, -- включил в него дополнительный рецепт, который перенаправляет e-mail с строкой темы письма <gpg-console/>, на новый скрипт email_console_gpg.pl. Когда все будет готово, то не требуется включать в этот файл оба рецепта и скрипта, -- включайте только безопасную версию. Если же вы оставите обе версии, то ваша система будет открытой для внешних атак. Эти две версии приведены в файле, исколючительно лишь только для целей демонстрации внесенных нами изменений. Новый файл .procmailrc, с добавленным в него новым рецептом, приведен ниже:

 #------------------------
 # my .procmailrc file
 #-------------------------
 SHELL=/bin/bash
 MAILDIR=${HOME}/Mail
 LOGFILE=${MAILDIR}/procmail.log
 LOG--- Logging ${LOGFILE} for ${LOGNAME}, "

 #------------------------------------
 # Recipes
 #------------------------------------
 :0
 * ^Subject: <console/>
 |/usr/bin/perl ~/bin/email_console.pl

 :0
 * ^Subject: <gpg-console/>
 |/usr/bin/perl ~/bin/email_console_gpg.pl

 #---------------------------------------------
 # catchall recipe
 #---------------------------------------------
 :0:
 ${DEFAULT}

В результате внесенных нами изменений, мы обезопасили e-mail-консоль. Однако, это не все, что можно сделать, для обеспечения безопасности утилиты e-mail-консоли. Эту утилиту можно улучшать и улучшать, -- предоставляем вам эту возможность. Ну и наконец, если вы заинтересовались этим скриптом, то ниже приведены некоторые рисунки, иллюстрирующие работу безопасной e-mail-консоли. Рисунок 7-6 это e-mail, который содержит команды для e-mail-консоли. Рисунок 7-7 показывает e-mail на тот момент, когда он получен моей системой (я решил получить его не через Procmail, только для того, чтобы сделать "фотоснимок" экрана). И наконец, рисунок 7-8 иллюстрирует результаты выполнения e-mail-команд. Попутно заметим, что KMail автоматически дешифрует результат. Мне нравится такой функционал!

Рисунок 7-6. Создание e-mail.

Рисунок 7-7. Полученный e-mail.

Рисунок 7-8. Результаты выполнения команд.

<< Рецепты | Multi Tool Linux | Итоги >>


edit RightSideBar