CVE-2024-28892
An OS command injection vulnerability exists in the name parameter of GoCast 1.1.3. A specially crafted HTTP request can lead to arbitrary command execution. An attacker can make an unauthenticated HTTP request to trigger this vulnerability.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
GoCast 1.1.3
GoCast - https://github.com/mayuresh82/gocast
9.8 - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWE-78 - Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’)
Gocast does BGP route advertisements from a host using GoBGP.
In GoCast an injection was found when the name of an app is used to create the label of a new loopback interface. This injection has been demonstrated using the HTTP API, but could also be exploitable when the App is defined through the config file or if added due to Consul integration. Due to a lack of authentication, the HTTP API should be disabled in most environments or configured to only go through a proxy that adds authentication, but it should be noted that this API is enabled in the default config file.
Name triggers an injection in system.go:addLoopback but is limited to a string length of 12 characters due to the limited size of Linux Kernal network interfact labels.
func addLoopback(name string, addr *net.IPNet) error {
deleteLoopback(addr)
prefixLen, _ := addr.Mask.Size()
label := fmt.Sprintf("lo:%s", name)
// linux kernel limits labels to 15 chars
if len(label) > 15 {
label = label[:15]
}
cmd := fmt.Sprintf("ip address add %s/%d dev lo label %s", addr.IP.String(), prefixLen, label)
cmdList := getCmdList(cmd)
_, err := exec.Command(execCmd, cmdList...).Output()
Users of GoCast should disable the HTTP API or put it behind authentication if it can’t be. Disable Consul integration if possible. Check that the file permissions for the configuration file prevent users other than root and the GoCast user from modifying the file.
There are many ways to prevent command injections. For minimal changes to the codebase, a good method would be to surround the label argument that contains user input with single quotes and remove all single quotes from the label string before inserting it into the command.
Example:
label = strings.ReplaceAll(label,"'","") // replace all single quotes with nothing
cmd := fmt.Sprintf("ip address add %s/%d dev lo label '%s'", addr.IP.String(), prefixLen, label)
cmdList := getCmdList(cmd)
2024-04-02 - Initial Vendor Contact
2024-04-23 - Initial Vendor Contact - Second try
2024-04-25 - Vendor Disclosure
2024-05-27 - Status request sent to vendor
2024-05-27 - Vendor reply. Patch is upcoming
2024-06-24 - Status request sent to vendor
2024-07-02 - Status request sent to vendor
2024-11-13 - Impending release announcement sent to vendor
2024-11-21 - Public Release
Discovered by Matt Street and Edwin Molenaar of Cisco Meraki.