-
-
Save thevilledev/8fd0cab3f098320aa9daab04be59fd2b to your computer and use it in GitHub Desktop.
beego_xss_poc.go
This file contains hidden or 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 ( | |
| "fmt" | |
| "log" | |
| "os" | |
| "path/filepath" | |
| "time" | |
| "github.com/beego/beego/v2/server/web" | |
| ) | |
| // UserProfile represents a user profile with various fields | |
| type UserProfile struct { | |
| ID int `form:"-"` | |
| Username string `form:"username,text,Username:"` | |
| DisplayName string `form:"displayName,text,Display Name:"` | |
| Email string `form:"email,text,Email:"` | |
| Bio string `form:",textarea,Bio:"` | |
| JoinDate time.Time `form:"joinDate,text,Join Date:"` | |
| IsAdmin bool `form:"isAdmin,checkbox,Admin:"` | |
| } | |
| func main() { | |
| // Create a temporary directory for templates | |
| tempDir, err := os.MkdirTemp("", "beego-xss-poc") | |
| if err != nil { | |
| fmt.Println("Error creating temporary directory:", err) | |
| return | |
| } | |
| defer os.RemoveAll(tempDir) | |
| // Write templates to temporary directory | |
| templates := map[string]string{ | |
| "index.tpl": indexTemplate, | |
| "profile.tpl": profileTemplate, | |
| "admin.tpl": adminTemplate, | |
| "submit.tpl": submitTemplate, | |
| "submitted.tpl": submittedTemplate, | |
| } | |
| for name, content := range templates { | |
| err := os.WriteFile(filepath.Join(tempDir, name), []byte(content), 0644) | |
| if err != nil { | |
| fmt.Println("Error writing template:", err) | |
| return | |
| } | |
| } | |
| // Set view path to temporary directory | |
| web.BConfig.WebConfig.ViewsPath = tempDir | |
| // Register template functions | |
| err = web.AddFuncMap("renderform", web.RenderForm) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| // Register controllers | |
| web.Router("/", &MainController{}) | |
| web.Router("/profile", &ProfileController{}) | |
| web.Router("/admin", &AdminController{}) | |
| web.Router("/submit", &SubmitController{}) | |
| // Start the server | |
| fmt.Println("Starting server at http://localhost:8080/") | |
| fmt.Println("This application demonstrates the XSS vulnerability in Beego's RenderForm() function.") | |
| fmt.Println("Visit http://localhost:8080/ to see the demo.") | |
| web.Run() | |
| } | |
| // MainController handles the home page | |
| type MainController struct { | |
| web.Controller | |
| } | |
| func (c *MainController) Get() { | |
| c.TplName = "index.tpl" | |
| } | |
| // ProfileController handles the profile page | |
| type ProfileController struct { | |
| web.Controller | |
| } | |
| func (c *ProfileController) Get() { | |
| // Create a user profile with malicious data | |
| profile := &UserProfile{ | |
| ID: 1, | |
| Username: "johndoe", | |
| DisplayName: `" onmouseover="alert('XSS Attack via Display Name')" data-malicious="`, | |
| Email: "john@example.com", | |
| Bio: `</textarea><script>alert('XSS Attack via Bio')</script><textarea>`, | |
| JoinDate: time.Now(), | |
| IsAdmin: false, | |
| } | |
| c.Data["Profile"] = profile | |
| c.TplName = "profile.tpl" | |
| } | |
| // AdminController handles the admin page | |
| type AdminController struct { | |
| web.Controller | |
| } | |
| func (c *AdminController) Get() { | |
| // Simulate fetching user profiles from a database | |
| profiles := []*UserProfile{ | |
| { | |
| ID: 1, | |
| Username: "johndoe", | |
| DisplayName: "John Doe", | |
| Email: "john@example.com", | |
| Bio: "Regular user bio", | |
| JoinDate: time.Now(), | |
| IsAdmin: false, | |
| }, | |
| { | |
| ID: 2, | |
| Username: "attacker", | |
| DisplayName: `" onmouseover="alert('XSS Attack via Display Name')" data-malicious="`, | |
| Email: "attacker@example.com", | |
| Bio: `</textarea><script>alert('XSS Attack via Bio')</script><textarea>`, | |
| JoinDate: time.Now(), | |
| IsAdmin: false, | |
| }, | |
| } | |
| c.Data["Profiles"] = profiles | |
| c.TplName = "admin.tpl" | |
| } | |
| // SubmitController handles form submissions | |
| type SubmitController struct { | |
| web.Controller | |
| } | |
| func (c *SubmitController) Post() { | |
| // Create a new user profile | |
| profile := &UserProfile{} | |
| // Parse form data into the profile | |
| if err := c.ParseForm(profile); err != nil { | |
| c.Ctx.WriteString("Error parsing form: " + err.Error()) | |
| return | |
| } | |
| // Display the submitted profile | |
| c.Data["Profile"] = profile | |
| c.TplName = "submitted.tpl" | |
| } | |
| func (c *SubmitController) Get() { | |
| // Create an empty profile for the form | |
| profile := &UserProfile{} | |
| c.Data["Profile"] = profile | |
| c.TplName = "submit.tpl" | |
| } | |
| // Templates embedded directly in the code | |
| const ( | |
| indexTemplate = `<!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Beego XSS Vulnerability Demo</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| margin: 0; | |
| padding: 20px; | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| } | |
| h1 { | |
| color: #333; | |
| } | |
| ul { | |
| padding-left: 20px; | |
| } | |
| li { | |
| margin-bottom: 10px; | |
| } | |
| a { | |
| color: #0066cc; | |
| text-decoration: none; | |
| } | |
| a:hover { | |
| text-decoration: underline; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>Beego XSS Vulnerability Demo</h1> | |
| <p>This application demonstrates the XSS vulnerability in Beego's RenderForm() function.</p> | |
| <h2>Demonstration Pages:</h2> | |
| <ul> | |
| <li><a href="/profile">User Profile</a> - Shows a profile with malicious data</li> | |
| <li><a href="/admin">Admin Panel</a> - Shows multiple user profiles including one with malicious data</li> | |
| <li><a href="/submit">Submit Form</a> - Create your own profile with malicious data</li> | |
| </ul> | |
| <h2>Vulnerability Explanation:</h2> | |
| <p>The vulnerability exists in the <code>RenderForm()</code> function in Beego's <code>templatefunc.go</code> file. This function directly injects user-provided values into HTML without proper escaping, allowing for XSS attacks.</p> | |
| <h3>Vulnerable Code:</h3> | |
| <pre> | |
| // In renderFormField function: | |
| return fmt.Sprintf('%v<input%v%v name="%v" type="%v" value="%v"%v>', | |
| label, id, class, name, fType, value, requiredString) | |
| </pre> | |
| <p>None of the values (label, id, class, name, value) are properly HTML-escaped before being inserted into the HTML template.</p> | |
| </div> | |
| </body> | |
| </html>` | |
| profileTemplate = `<!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>User Profile - XSS Demo</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| margin: 0; | |
| padding: 20px; | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| } | |
| h1, h2 { | |
| color: #333; | |
| } | |
| .form-container { | |
| margin-top: 20px; | |
| padding: 20px; | |
| border: 1px solid #eee; | |
| border-radius: 5px; | |
| background-color: #f9f9f9; | |
| } | |
| .warning { | |
| color: #cc0000; | |
| font-weight: bold; | |
| padding: 10px; | |
| background-color: #ffeeee; | |
| border: 1px solid #ffcccc; | |
| border-radius: 5px; | |
| margin-bottom: 20px; | |
| } | |
| a { | |
| color: #0066cc; | |
| text-decoration: none; | |
| display: inline-block; | |
| margin-top: 20px; | |
| } | |
| a:hover { | |
| text-decoration: underline; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>User Profile</h1> | |
| <div class="warning"> | |
| <p>⚠️ Warning: This page demonstrates an XSS vulnerability. The profile contains malicious data that will be rendered unsafely.</p> | |
| <p>Hover over the Display Name field to see the XSS attack in action.</p> | |
| </div> | |
| <h2>Profile Information</h2> | |
| <div class="form-container"> | |
| <!-- This is where the vulnerability occurs - RenderForm doesn't escape user input --> | |
| {{renderform .Profile}} | |
| </div> | |
| <a href="/">Back to Home</a> | |
| </div> | |
| </body> | |
| </html>` | |
| adminTemplate = `<!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Admin Panel - XSS Demo</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| margin: 0; | |
| padding: 20px; | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| } | |
| h1, h2, h3 { | |
| color: #333; | |
| } | |
| .user-profile { | |
| margin-top: 20px; | |
| padding: 20px; | |
| border: 1px solid #eee; | |
| border-radius: 5px; | |
| background-color: #f9f9f9; | |
| margin-bottom: 20px; | |
| } | |
| .warning { | |
| color: #cc0000; | |
| font-weight: bold; | |
| padding: 10px; | |
| background-color: #ffeeee; | |
| border: 1px solid #ffcccc; | |
| border-radius: 5px; | |
| margin-bottom: 20px; | |
| } | |
| a { | |
| color: #0066cc; | |
| text-decoration: none; | |
| display: inline-block; | |
| margin-top: 20px; | |
| } | |
| a:hover { | |
| text-decoration: underline; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>Admin Panel</h1> | |
| <div class="warning"> | |
| <p>⚠️ Warning: This page demonstrates an XSS vulnerability. One of the profiles contains malicious data that will be rendered unsafely.</p> | |
| <p>Hover over the Display Name field in the second profile to see the XSS attack in action.</p> | |
| </div> | |
| <h2>User Profiles</h2> | |
| {{range $index, $profile := .Profiles}} | |
| <div class="user-profile"> | |
| <h3>User #{{$index}}</h3> | |
| <!-- This is where the vulnerability occurs - RenderForm doesn't escape user input --> | |
| {{renderform $profile}} | |
| </div> | |
| {{end}} | |
| <a href="/">Back to Home</a> | |
| </div> | |
| </body> | |
| </html>` | |
| submitTemplate = `<!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Submit Profile - XSS Demo</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| margin: 0; | |
| padding: 20px; | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| } | |
| h1, h2 { | |
| color: #333; | |
| } | |
| .form-container { | |
| margin-top: 20px; | |
| padding: 20px; | |
| border: 1px solid #eee; | |
| border-radius: 5px; | |
| background-color: #f9f9f9; | |
| } | |
| .info { | |
| color: #0066cc; | |
| padding: 10px; | |
| background-color: #e6f0ff; | |
| border: 1px solid #b3d1ff; | |
| border-radius: 5px; | |
| margin-bottom: 20px; | |
| } | |
| .example { | |
| font-family: monospace; | |
| background-color: #f5f5f5; | |
| padding: 10px; | |
| border: 1px solid #ddd; | |
| border-radius: 3px; | |
| margin: 10px 0; | |
| } | |
| input[type="submit"] { | |
| background-color: #0066cc; | |
| color: white; | |
| border: none; | |
| padding: 10px 20px; | |
| border-radius: 3px; | |
| cursor: pointer; | |
| margin-top: 20px; | |
| } | |
| input[type="submit"]:hover { | |
| background-color: #0052a3; | |
| } | |
| a { | |
| color: #0066cc; | |
| text-decoration: none; | |
| display: inline-block; | |
| margin-top: 20px; | |
| margin-right: 20px; | |
| } | |
| a:hover { | |
| text-decoration: underline; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>Submit Your Profile</h1> | |
| <div class="info"> | |
| <p>This form allows you to create a profile with potentially malicious data to test the XSS vulnerability.</p> | |
| <p>Try entering the following in the Display Name field:</p> | |
| <div class="example">" onmouseover="alert('XSS Attack via Display Name')" data-malicious="</div> | |
| <p>Or try entering the following in the Bio field:</p> | |
| <div class="example"></textarea><script>alert('XSS Attack via Bio')</script><textarea></div> | |
| </div> | |
| <h2>Create Profile</h2> | |
| <div class="form-container"> | |
| <form action="/submit" method="post"> | |
| Username:<br> | |
| <input name="username" type="text"><br> | |
| Display Name:<br> | |
| <input name="displayName" type="text"><br> | |
| Email:<br> | |
| <input name="email" type="text"><br> | |
| Bio:<br> | |
| <textarea name="Bio"></textarea><br> | |
| <input type="submit" value="Submit"> | |
| </form> | |
| </div> | |
| <a href="/">Back to Home</a> | |
| </div> | |
| </body> | |
| </html>` | |
| submittedTemplate = `<!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Submitted Profile - XSS Demo</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| margin: 0; | |
| padding: 20px; | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| padding: 20px; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| } | |
| h1, h2 { | |
| color: #333; | |
| } | |
| .form-container { | |
| margin-top: 20px; | |
| padding: 20px; | |
| border: 1px solid #eee; | |
| border-radius: 5px; | |
| background-color: #f9f9f9; | |
| } | |
| .success { | |
| color: #008800; | |
| font-weight: bold; | |
| padding: 10px; | |
| background-color: #eeffee; | |
| border: 1px solid #ccffcc; | |
| border-radius: 5px; | |
| margin-bottom: 20px; | |
| } | |
| .warning { | |
| color: #cc0000; | |
| font-weight: bold; | |
| padding: 10px; | |
| background-color: #ffeeee; | |
| border: 1px solid #ffcccc; | |
| border-radius: 5px; | |
| margin-bottom: 20px; | |
| } | |
| a { | |
| color: #0066cc; | |
| text-decoration: none; | |
| display: inline-block; | |
| margin-top: 20px; | |
| margin-right: 20px; | |
| } | |
| a:hover { | |
| text-decoration: underline; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>Submitted Profile</h1> | |
| <div class="success"> | |
| <p>✅ Your profile has been submitted successfully!</p> | |
| </div> | |
| <div class="warning"> | |
| <p>⚠️ Warning: If you submitted malicious data, you will see the XSS attack in action below.</p> | |
| <p>Hover over the Display Name field or check the Bio field to see if your XSS attack worked.</p> | |
| </div> | |
| <h2>Your Profile Information</h2> | |
| <div class="form-container"> | |
| <!-- This is where the vulnerability occurs - RenderForm doesn't escape user input --> | |
| {{renderform .Profile}} | |
| </div> | |
| <a href="/submit">Submit Another Profile</a> | |
| <a href="/">Back to Home</a> | |
| </div> | |
| </body> | |
| </html>` | |
| ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment