Signing table allows cross-user signing
The SigningTable configuration allows users with authenticated access to some
OpenDKIM system to apply someone else’s signing configuration. A malicious user
could sign a message using someone else’s private signing key on that OpenDKIM
system.
This is possible because signing table entries are matched against a sender’s From header. The From header can be anything. It may be different from the envelope sender (MAIL FROM); the envelope sender is usually authenticated by a mail system, it may not be filled with an arbitrary address. As far as I am aware, From is usually not restricted in this way.
For example, if user mallory@example on some system learns that the same system
also signs messages for vip@important, they can first authenticate as the
mallory user. When composing the message, they then include the header
From: <vip@important> to sign using that account’s signing key and
configuration. Especially if that configuration includes the i= tag, the
resulting valid signature (d=important and i=vip@important) will look like a
legitimate signed message from the victim account.
To be clear, even when OpenDKIM is not involved the malicious user could send
mail with envelope MAIL FROM:<mallory@example> and message content
From: <vip@important>. The question is whether OpenDKIM should sign such
messages with the victim user’s key.
Perhaps this is banal, and working as designed, nevertheless it looks to me like it could be abused. Comments welcome, am I overlooking something?
A solution might be to require the extracted From address to match the (usually authenticated) envelope sender address.
Edit: This is a known issue, but the related discussions seem to have disappeared with the old mailing list (example). The SenderMacro parameter can be used as a mitigation.
A solution might be to require the extracted From address to match the (usually authenticated) envelope sender address.
I use setup lua script for it. With the script:
- If {auth_authen} is empty, don't request signing (our MTA checks that the smtp.from address is allowed to be used by the sasl user).
- If Sender: header is found, use it as originator header, else use From: header as originator header
- Parse originator header with RFC6854 syntax including
obs-syntaxes in RFC5322, then extract header originator address list - Compare smtp.from address extract by using
odkim.get_envfrom()and extracted originator address list, with local-part canonicalization (we use VERP like smtp.from). If one of extracted header originator address match smtp.from, then request signing, with their key.
If it could be done by only specified some options in opendkim.conf, I might not use lua script.