Re: [Off-Topic] GMime and MIME misuse by attackers

Albrecht Dreß <[email protected]>
Newsgroups gmane.comp.gnome.apps.balsa
Message-ID <[email protected]>
Hi Jeff:

Am 16.10.17 16:01 schrieb(en) Jeffrey Stedfast via balsa-list:
> Ah, yes, okay – now I understand better. Different software interprets things differently so when writing software that attempts to filter out viruses and other types of attacks, it might not interpret things exactly the same as the user’s email client.

Exactly.  As I mentioned earlier, it's not limited to security appliances, though.  Some of my users usually read messages on the iPhone first.  If a message looked sane there, [s]he will probably open it carelessly later with Outlook, but the message might be interpreted differently there.

>> The NUL byte inserted by GMime when decoding base64 content with “=” inside the block (slide 32) looks like a bug to me, though.
> 
> It might be, I’ll have to look into it a bit more.

See the attached little test code and feed the TEST.txt file into it…

>> This leads to the question if it would be possible to extract this information from the GMime parser.  Although Balsa is probably not a target (due to the regrettably small number of installations and the robustness of Linux), it should be able to display a warning as mentioned above, just in case the user reads the messages using different MUA's (think of IMAP, plus Outlook/iOS/Android/…).  But it would be an *extremely* helpful feature for writing some kind of “security scanner”.
> 
> I think it would be possible, I think the question is mostly how to surface this information in a usable way.

The information about one issue detected by the parser could be a simple set of numerical values, e.g. something like
- offset: position within the input stream
- scope: e.g. as enum: message header; part header; part body; embedded message header; …
- classification: e.g. as enum: rfc violation (like unencoded 8-bit chars in a header, or duplicated boundary parameter, …plus all the stuff g_mime_parser_options_set_*_compliance_mode() controls); strange content (like “=” inside base64 block, unnecessary line folding in headers, …); …
- issue code: number

Maybe the latter two could be glued together, as to make the approach less complex.  Sometimes it is not clear anyway how to classify an issue:  Two contradictory Content-Transfer-Encoding headers for one part are against the intentions of RFC 2045, but not explicitly forbidden iirc.

For passing the issues to the caller:  As GMimeParser is derived from GObject, the most simple way might be a signal the caller can connect to.  The callback would receive the three or four values above.  This leaves the existing API unchanged and does not introduce any extra memory requirements (like an error stack).  The performance penalty (which only applies to messages containing any issues anyway) should be small.  And the approach is easily extensible – as to notify about an other issue, just define the enum code, and emit the signal.

If you could give me a hint where I should start within your sources, I could try to implement a small (I hope…) example patch for one of the issues addressed by the g_mime_parser_options_set_*_compliance_mode() options as to illustrate the approach.

Cheers,
Albrecht.

_______________________________________________
balsa-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/balsa-list
base64_test.c (text/x-csrc, 860 B)
#include <gmime/gmime.h>


int main(int argc, char **argv)
{
	gchar *filebuf;
	gsize inlen;
	guchar *out_data;
	gsize out_len;
	gchar *out_name;
	GMimeEncoding state;

	g_assert(argc >= 2);
	g_file_get_contents(argv[1], &filebuf, &inlen, NULL);
	out_data = g_base64_decode(filebuf, &out_len);
	out_name = g_strconcat(argv[1], "_GLIB", NULL);
	g_file_set_contents(out_name, (const gchar *) out_data, out_len, NULL);
	g_free(out_data);
	g_free(out_name);

	g_mime_encoding_init_decode(&state, GMIME_CONTENT_ENCODING_BASE64);
	out_data = g_malloc(g_mime_encoding_outlen(&state, inlen) + 1U);
	out_len = g_mime_encoding_flush(&state, filebuf, inlen, (char *) out_data);
	out_name = g_strconcat(argv[1], "_GMIME", NULL);
	g_file_set_contents(out_name, (const gchar *) out_data, out_len, NULL);
	g_free(out_data);
	g_free(out_name);

	g_free(filebuf);
	return 0;
}
TEST.txt (text/plain, 15 B)
Vkk=
UlVTIQ==
signature.asc (application/pgp-signature, 473 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQEcBAABCAAGBQJZ5Q15AAoJEEypbw5n59n4Q2EIANZUBmVvUxQZjj7MqnkuFrpv
LR+N8p2yhAaXRsvgONdFNkLVgwvy9FX2bNae04RdNbtdW08I/LNjoC30XJBDASpL
ck6NGnbXauTwku4ejK03aVz2FXKLXZYgpHiIovqDX165NJvsci0wiHSCXzp2UzMa
YNEYEfoYJZbcg42RElqBpR4w8kvs4so8aA7TBN26lScSQ8hoLI0fFswU6D/H8GKd
Cmj2yw9nMy1hIhM8Ydob1R+HUpJyWUZoBuWPhbUsbbP7nMgPeCt/bK+QH+x+tsUo
kVy0iRakaV7OmV1cdXHldxhfRnC4odJOOTnBs2Dfpd4flJ0aHPbtLMaRE3VGEX0=
=J56B
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.