# [patch] abuse-proof zif_mail()

- Thread: https://externals.io/message/10186
- Original archive: https://news-web.php.net/php.internals/10186
- Started by Paul G on 2004-05-30T13:49:47+00:00
- Messages: 8
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #10186 — Paul G — 2004-05-30T13:49:47+00:00

URL: https://externals.io/message/10186#10186

folks,

first post/patch, please be gentle <g>.

hosting companies using mod_php have a *very* hard time preventing and
tracking abuse of `mail()`. when sendmail is invoked from a suexeced cgi
script, we get the username. with mod_php `mail()`, we get a big fat nothing,
a ton of spam in the spool and a bunch of abuse reports from ticked off
victims. we then go on a grepping witchhunt, which is hardly a workable
option on a busy production box.

the patch i am including below apends an X-AntiAbusePHP:
/path/to/script/which/is/spewing header to all messages sent through `mail()`.
while we will be actively parsing that header in our sendmail replacement
script, leaving the username only and throttling/limiting based on per-user
sending threshholds, those who do not go that far to be good netizens will
at least be able to identify the source of spewage post mortem.

we already have iptables ACLs in place to prevent unauthorized connections
to remotehost:25, but most people can not implement that, so the socket
calls may be my next mutilation target. with that said, it would be much
more intrusive (hence likely unsuitable for addition into the core) and i
thought it would be more prudent to test the waters with a trivial patch,
since i am likely to have done something wrong/contrary to the php way of
doing things.

i would think this {sh,c}ould be ifdefined, but being unfamiliar with the
status quo policy on that and considering that the patch has a fair chance
of being unwelcome, i did not pursue it.

cheers,
paul

diff -ru php-4.3.6/ext/standard/mail.c php-4.3.6.abuse1/ext/standard/mail.c
--- php-4.3.6/ext/standard/mail.c       2004-01-08 20:35:58.000000000 -0500
+++ php-4.3.6.abuse1/ext/standard/mail.c        2004-05-30
08:27:55.000000000 -0400
@@ -87,6 +87,8 @@
        int to_len, message_len, headers_len;
        int subject_len, extra_cmd_len, i;
        char *to_r, *subject_r;
+       char *exec_file=NULL;
+       int abuseh_len=0, got_headers=0;

        if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE
Restriction in effect.  The fifth parameter is disabled in SAFE MODE.");
@@ -103,6 +105,18 @@
                return;
        }

+       got_headers = headers ? 1 : 0;
+       exec_file= zend_get_executed_filename(TSRMLS_C);
+       /* add 2 [strlen("\r\n")] _if_ we are appending to preexisting
headers */
+       abuseh_len = (got_headers*2) + strlen(ABUSE_HEADER_TAG) +
strlen(ABUSE_HEADER_SRC) + strlen(exec_file);
+       headers = got_headers ? erealloc(headers, headers_len + abuseh_len +
1) : emalloc(abuseh_len + 1);
+       if(got_headers) strcat(headers, "\r\n");
+       strcat(headers, ABUSE_HEADER_TAG);
+       strcat(headers, ABUSE_HEADER_SRC);
+       strcat(headers, exec_file);
+       headers_len += abuseh_len;
+
+
        if (to_len > 0) {
                to_r = estrndup(to, to_len);
                for (; to_len; to_len--) {
diff -ru php-4.3.6/ext/standard/php_mail.h
php-4.3.6.abuse1/ext/standard/php_mail.h
--- php-4.3.6/ext/standard/php_mail.h   2002-12-31 11:35:33.000000000 -0500
+++ php-4.3.6.abuse1/ext/standard/php_mail.h    2004-05-30
08:26:59.000000000 -0400
@@ -24,6 +24,9 @@
 PHP_FUNCTION(mail);
 PHP_MINFO_FUNCTION(mail);

+#define ABUSE_HEADER_TAG        "X-AntiAbusePHP: Added to track PHP abuse,
please include with any abuse report\r\n"
+#define ABUSE_HEADER_SRC        "X-AntiAbusePHP: This message was sent
through "
+
 #if HAVE_SENDMAIL

 PHP_FUNCTION(ezmlm_hash);

---

## #10188 — Jeremy Johnstone — 2004-05-30T17:29:54+00:00

URL: https://externals.io/message/10186#10188 · In reply to: #10186

I have no say or pull around here, but I am +1 on the idea, but unsure on the 
implementation from below. 

-Jeremy



> folks,
>
> first post/patch, please be gentle <g>.
>
> hosting companies using mod_php have a *very* hard time preventing and
> tracking abuse of `mail()`. when sendmail is invoked from a suexeced cgi
> script, we get the username. with mod_php `mail()`, we get a big fat nothing,
> a ton of spam in the spool and a bunch of abuse reports from ticked off
> victims. we then go on a grepping witchhunt, which is hardly a workable
> option on a busy production box.
>
> the patch i am including below apends an X-AntiAbusePHP:
> /path/to/script/which/is/spewing header to all messages sent through
> `mail()`. while we will be actively parsing that header in our sendmail
> replacement script, leaving the username only and throttling/limiting based
> on per-user sending threshholds, those who do not go that far to be good
> netizens will at least be able to identify the source of spewage post
> mortem.
>
> we already have iptables ACLs in place to prevent unauthorized connections
> to remotehost:25, but most people can not implement that, so the socket
> calls may be my next mutilation target. with that said, it would be much
> more intrusive (hence likely unsuitable for addition into the core) and i
> thought it would be more prudent to test the waters with a trivial patch,
> since i am likely to have done something wrong/contrary to the php way of
> doing things.
>
> i would think this {sh,c}ould be ifdefined, but being unfamiliar with the
> status quo policy on that and considering that the patch has a fair chance
> of being unwelcome, i did not pursue it.
>
> cheers,
> paul
>
> diff -ru php-4.3.6/ext/standard/mail.c php-4.3.6.abuse1/ext/standard/mail.c
> --- php-4.3.6/ext/standard/mail.c       2004-01-08 20:35:58.000000000 -0500
> +++ php-4.3.6.abuse1/ext/standard/mail.c        2004-05-30
> 08:27:55.000000000 -0400
> @@ -87,6 +87,8 @@
>         int to_len, message_len, headers_len;
>         int subject_len, extra_cmd_len, i;
>         char *to_r, *subject_r;
> +       char *exec_file=NULL;
> +       int abuseh_len=0, got_headers=0;
>
>         if (PG(safe_mode) && (ZEND_NUM_ARGS() == 5)) {
>                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE
> Restriction in effect.  The fifth parameter is disabled in SAFE MODE.");
> @@ -103,6 +105,18 @@
>                 return;
>         }
>
> +       got_headers = headers ? 1 : 0;
> +       exec_file= zend_get_executed_filename(TSRMLS_C);
> +       /* add 2 [strlen("\r\n")] _if_ we are appending to preexisting
> headers */
> +       abuseh_len = (got_headers*2) + strlen(ABUSE_HEADER_TAG) +
> strlen(ABUSE_HEADER_SRC) + strlen(exec_file);
> +       headers = got_headers ? erealloc(headers, headers_len + abuseh_len
> + 1) : emalloc(abuseh_len + 1);
> +       if(got_headers) strcat(headers, "\r\n");
> +       strcat(headers, ABUSE_HEADER_TAG);
> +       strcat(headers, ABUSE_HEADER_SRC);
> +       strcat(headers, exec_file);
> +       headers_len += abuseh_len;
> +
> +
>         if (to_len > 0) {
>                 to_r = estrndup(to, to_len);
>                 for (; to_len; to_len--) {
> diff -ru php-4.3.6/ext/standard/php_mail.h
> php-4.3.6.abuse1/ext/standard/php_mail.h
> --- php-4.3.6/ext/standard/php_mail.h   2002-12-31 11:35:33.000000000 -0500
> +++ php-4.3.6.abuse1/ext/standard/php_mail.h    2004-05-30
> 08:26:59.000000000 -0400
> @@ -24,6 +24,9 @@
>  PHP_FUNCTION(mail);
>  PHP_MINFO_FUNCTION(mail);
>
> +#define ABUSE_HEADER_TAG        "X-AntiAbusePHP: Added to track PHP abuse,
> please include with any abuse report\r\n"
> +#define ABUSE_HEADER_SRC        "X-AntiAbusePHP: This message was sent
> through "
> +
>  #if HAVE_SENDMAIL
>
>  PHP_FUNCTION(ezmlm_hash);

---

## #10189 — Ilia Alshanetsky — 2004-05-30T17:33:34+00:00

URL: https://externals.io/message/10186#10189 · In reply to: #10186

Strong -1.

Ilia

---

## #10190 — Paul G — 2004-05-30T17:56:21+00:00

URL: https://externals.io/message/10186#10190 · In reply to: #10189

----- Original Message ----- 
From: "Ilia Alshanetsky" <ilia@prohost.org>
To: <internals@lists.php.net>
Sent: Sunday, May 30, 2004 1:33 PM
Subject: Re: [PHP-DEV] [patch] abuse-proof zif_mail()


> Strong -1.
>
> Ilia

ilia,

out of curiosity, what are the arguments against the idea and the
implementation respectively? you seem to be with a hosting company - how do
you handle the situation i described? not trying to be defensive, i am
genuinely interested in everyone's thoughts on this.

my thoughts on this are: *if* we agree that at least in certain situations
being able to track the source of abuse is a Good Idea, then we agree that
having a feature (for lack of a better word) that provides a way to identify
the source is a Good Idea as well. it need not be enabled by default, mind
you. however, i would venture a guess that sysadmins running *amp boxes with
untrusted users (a large portion of *amp boxes) would find this useful. if
there is something wrong with the way i've done it, which is entirely and
even likely possible, then there is a good chance that there is also a
better way of doing it. the worth of the idea and the implementation are
obviously decoupled and i am open to education through cluebat as it may
pertain to reworking the patch to be correct, as opposed to just working.

thoughts?

paul

---

## #10191 — Ilia Alshanetsky — 2004-05-30T18:07:19+00:00

URL: https://externals.io/message/10186#10191 · In reply to: #10190

First of all if you have people abusing the mail function one solution is to 
disable it via the disable_functions directive inside your php.ini file.

If you must append headers then you could easily specify a path to a sendmail 
using a configuration that would append any header that you like to outgoing 
e-mails. There are plenty of other solutions available.

Ilia

---

## #10192 — Paul G — 2004-05-30T18:29:53+00:00

URL: https://externals.io/message/10186#10192 · In reply to: #10191

ilia,

----- Original Message ----- 
From: "Ilia Alshanetsky" <ilia@prohost.org>
To: <internals@lists.php.net>; "Paul G" <paul@rusko.us>
Sent: Sunday, May 30, 2004 2:07 PM
Subject: Re: [PHP-DEV] [patch] abuse-proof zif_mail()


> First of all if you have people abusing the mail function one solution is
to
> disable it via the disable_functions directive inside your php.ini file.

depending on the function in question, this may or may not be a viable
option.

we already have `system()` and all of its bretheren disabled and have not had
any complaints from any legitimate users - those functions are not commonly
used in software typical users want to run and the collateral from disabling
them is negligible.

when it comes to `mail()`, it is a whole different story. if i disabled `mail()`
on just one box today, a *lot* of people would complain and with good
reason - the collateral inflicted by something that drastic (ie disabling a
very popular function to protect against a relative edge case) is way out of
line. i am not an anti-spam fanatic, the clients' requirements come first.

> If you must append headers then you could easily specify a path to a
sendmail
> using a configuration that would append any header that you like to
outgoing
> e-mails.

are you saying i can have sendmail append an identifier that would tell me
which script or user generated the email (given that it was invoked from
 `mail()` in mod_php)? if so, i (stupidly) missed it and would love to get it
done that way rather than mucking with php's internals.

> There are plenty of other solutions available.

i would love to hear abut them. obviously, if there is a simpler solution,
it is vastly preferable. closer inspection reveals that $PWD is the only
thing i can get at from within sendmail and it is obviously user-supplied
(most of my trophy captured scripts did their deed from cd /tmp).

thanks for your input, much appreciated.

paul

---

## #10225 — Sara Golemon — 2004-06-01T17:06:24+00:00

URL: https://externals.io/message/10186#10225 · In reply to: #10192

> when it comes to `mail()`, it is a whole different story. if i disabled
 `mail()`
> on just one box today, a *lot* of people would complain and with good
> reason - the collateral inflicted by something that drastic (ie disabling
a
> very popular function to protect against a relative edge case) is way out
of
> line. i am not an anti-spam fanatic, the clients' requirements come first.
>
The whole matter is moot because no matter how aggressively you block access
to `mail()`, sendmail, et. al.  The user can still make socket calls directly
using SMTP commands.  The protocol is not hard to understand and it's the
neerdowells that you're talking about stopping not the innocent accidentals.

-Sara

"Locks are to keep the honest people honest."

---

## #10226 — Paul G — 2004-06-01T17:38:36+00:00

URL: https://externals.io/message/10186#10226 · In reply to: #10225

sara,

----- Original Message ----- 
From: "Sara Golemon" <pollita@php.net>
To: <internals@lists.php.net>
Sent: Tuesday, June 01, 2004 1:06 PM
Subject: Re: [PHP-DEV] [patch] abuse-proof zif_mail()

--- snip ---

> The whole matter is moot because no matter how aggressively you block
access
> to `mail()`, sendmail, et. al.  The user can still make socket calls
directly
> using SMTP commands.  The protocol is not hard to understand and it's the
> neerdowells that you're talking about stopping not the innocent
accidentals.

i disagree. first off, at least on our setup, users can *try* to make socket
calls directly but it won't get them too far - we have iptables ACLs
preventing that. second off, the direct socket connections take more time
than calling sendmail and dumping it all in our spool and the abuser would
have to keep reloading the page (i know this can be automated) because of
the 30 second exec time limit. additionally, you could say that i care less
about them spewing directly than i care about them dumping twenty thousand
messages into our spool, when the relative effects on other clients' service
are considered. third off, this patch does not *stop* them per se, it just
helps us identify who is responsible so we can act on the abuse reports fast
enough not to get baclklisted by some maniac.

i am not arguing for making this the default, but quite honestly i do not
see a substantive reason not to make this a compile-time or a run-time
option. if there is a problem with the *how* of it, i will be glad to
correct the patch. i am also willing to produce a patch that will make it an
option, whether a compile or a run time one, if people tell me it is going
to be included. since we will always want this turned on, there is no point
in me mucking about with that if the patch is not going to be accepted.

cheers,
paul
