CVE-2022-4823 (published 2022-12-28T21:15Z)

A vulnerability, which was classified as problematic, was found in InSTEDD Nuntium. Affected is an unknown function of the file app/controllers/geopoll_controller.rb. The manipulation of the argument signature leads to observable timing discrepancy. It is possible to launch the attack remotely. The name of the patch is 77236f7fd71a0e2eefeea07f9866b069d612cf0d. It is recommended to apply a patch to fix this issue. VDB-217002 is the identifier assigned to this vulnerability.

CVSS v3 base score: 5.9, MEDIUM (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N)

Weakness information:
cwe_id: CWE-203
cwe_name: Observable Discrepancy
description: The product behaves differently or sends different responses under different circumstances in a way that is observable to an unauthorized actor, which exposes security-relevant information about the state of the product, such as whether a particular operation was successful or not.
extended_description: Discrepancies can take many forms, and variations may be detectable in timing, control flow, communications such as replies or requests, or general behavior. These discrepancies can reveal information about the product's operation or internal state to an unauthorized actor. In some cases, discrepancies can be used by attackers to form a side channel.
         

Fix information:
repo_url: https://github.com/instedd/nuntium
commit_details: repo_url: https://github.com/instedd/nuntium
author: Matías García Isaía
author_date: 2022-11-23 19:35:07-03:00
msg: Detect GeoPoll AT's to: number (#88)

* Securely check GeoPoll incoming signature

This avoids timing attacks

* Log unknown GeoPoll requests parameters

To avoid losing data upon API changes

See #76

* Show GeoPoll channels in Interactions tab

* Detect GeoPoll AT's to: numbers

Fixes #76
repository: repo_url: https://github.com/instedd/nuntium
repo_name: instedd/nuntium
description: InSTEDD Messaging Platform
repo_language: Ruby
owner: instedd
file_changes: filename: geopoll_controller.rb
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,7 @@ require 'digest/md5'
 class GeopollController < ApplicationController
   skip_filter :check_login
 
-  # POST /:account_name/:channel_name/:secret_token/geopoll/incoming
+  # POST /:account_name/:channel_name/geopoll/incoming
   def incoming
     account = Account.find_by_id_or_name(params[:account_name])
     channel = account.geopoll_channels.find_by_name(params[:channel_name])
@@ -28,17 +28,24 @@ class GeopollController < ApplicationController
     identifier = params[:Identifier]
     signature = Digest::MD5.hexdigest(auth_token + identifier)
 
-    if signature != params[:Signature]
+    if !(ActiveSupport::SecurityUtils.secure_compare params[:Signature], signature)
       return render text: "Error", status: :unauthorized
     end
 
+    unknown_params = params.except(
+      'Identifier', 'Signature', 'SourceAddress', 'TargetAddress', 'MessageText', # GeoPoll API specification
+      'account_name', 'channel_name', 'controller', 'action' # Rails-generated parameters
+    )
+
     msg = AtMessage.new
     msg.from = "sms://#{params[:SourceAddress]}"
-    msg.to   = "sms://#{channel.configuration[:from]}"
+    msg.to   = "sms://#{params[:TargetAddress]}"
     msg.body = params[:MessageText]
     msg.channel_relative_id = params[:Identifier]
     account.route_at msg, channel
 
+    channel.logger.warning :channel_id => channel.id, :at_message_id => msg.id, :message => "Received unknown parameters for AT #{msg.id}: #{unknown_params.to_json}" unless unknown_params.empty?
+    
     render text: "Accepted"
   end
 
@@ -51,6 +58,11 @@ class GeopollController < ApplicationController
       return render text: "Error", status: :not_found
     end
 
+    unknown_params = params.except(
+      'MessageId', 'Status', # GeoPoll API specification
+      'account_name', 'channel_name', 'controller', 'action' # Rails-generated parameters
+    )
+
     status = params[:Status]
     case status
       when "SUCCESS"
@@ -63,8 +75,10 @@ class GeopollController < ApplicationController
     account.logger.info :channel_id => channel.id, :ao_message_id => ao.id,
       :message => "Recieved delivery notification with status #{status.inspect}"
 
-     ao.custom_attributes[:geopoll_status] = status if status
-     ao.save!
+    channel.logger.warning :channel_id => channel.id, :at_message_id => msg.id, :message => "Received unknown parameters for AO #{msg.id} Status: #{unknown_params.to_json}" unless unknown_params.empty?
+
+    ao.custom_attributes[:geopoll_status] = status if status
+    ao.save!
 
     render text: "Accepted"
   end

programming_language: Ruby
filename: show.html.erb
change_type: ModificationType.MODIFY
diff: @@ -110,6 +110,18 @@
     </ul>
   <%- end -%>
 
+  <%- if channels.any?{|c| c.kind == 'geopoll'} -%>
+    <div><b>Via <%= link_to 'GeoPoll', 'https://www.geopoll.com/', :target => '_blank' -%></b></div>
+    <ul>
+      <%- channels.select{|c| c.kind == 'geopoll'}.each do |channel| -%>
+        <li>Incoming Messages URL: <span class="url">POST <%= geopoll_incoming_url(:account_name => account.name, :channel_name => channel.name) -%></span>
+          create Application Terminated Messages in channel <%= channel.name %></li>
+        <li>Delivery Reports Receiver URL: <span class="url">POST <%= geopoll_status_url(:account_name => account.name, :channel_name => channel.name) -%></span>
+          receive delivery reports in channel <%= channel.name %></li>
+      <%- end -%>
+    </ul>
+  <%- end -%>
+
   <%- unless applications.empty? -%>
     <div><b>Via <%= link_to 'RSS', 'http://en.wikipedia.org/wiki/RSS', :target => '_blank' -%></b></div>
     Use <%= link_to 'Http Basic Authentication', 'http://en.wikipedia.org/wiki/Basic_access_authentication', :target => '_blank' -%> with application credentials (use "account/application" as username).

programming_language: Ruby