Skip to content

Instantly share code, notes, and snippets.

@horsley
Created May 31, 2015 05:51
Show Gist options
  • Save horsley/e286276f83cae9b60d98 to your computer and use it in GitHub Desktop.
Save horsley/e286276f83cae9b60d98 to your computer and use it in GitHub Desktop.
ocserv auth hacking
// ocservFront project main.go
package main
import (
"bufio"
"bytes"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"regexp"
"strings"
)
const authFormOld = `<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="auth-request">
<version who="sg">0.1(1)</version>
<auth id="main">
<message>Please enter your username</message>
<form method="post" action="/auth">
<input type="text" name="username" label="Username:" />
</form></auth>
</config-auth>`
const authFormNew = `<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="auth-request">
<version who="sg">0.1(1)</version>
<auth id="main">
<message>Please enter your username</message>
<form method="post" action="/auth">
<input type="text" name="username" label="Username:" />
<input type="password" name="password" label="Password:" />
</form></auth>
</config-auth>`
var authUserPassRE = regexp.MustCompile("<auth><username>(.*?)</username><password>(.*?)</password></auth>")
var vpnCookieRE = regexp.MustCompile("webvpncontext=(.*?);")
func main() {
//@todo load config from file
cert, _ := tls.LoadX509KeyPair("/Users/horsley/Backup/ssl/ihorsley.com.crt", "/Users/horsley/Backup/ssl/ihorsley.com.key")
var cfg tls.Config
cfg.Certificates = []tls.Certificate{cert}
l, err := tls.Listen("tcp", ":15443", &cfg) //@todo load config from file
if err != nil {
log.Println("listen error:", err)
os.Exit(1)
}
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
log.Println("accept error:", err)
continue
}
go func(clientConn net.Conn) {
log.Println("conn process start")
defer clientConn.Close()
//@todo load config from file
remoteConn, err := tls.Dial("tcp", "vps9.ihorsley.com:443", nil) //remote can be unix cleartext socket of ocserv
if err != nil {
log.Println("connect upstream error:", err)
return
}
defer remoteConn.Close()
vpnCookie := make(chan string, 1)
go func() { //remote => client
hackRemoteResponse(clientConn, remoteConn, vpnCookie)
io.Copy(clientConn, remoteConn)
}()
//client => remote
hackClientRequest(clientConn, remoteConn, vpnCookie)
io.Copy(remoteConn, clientConn)
log.Println("conn process done")
}(conn)
}
}
//hackClientRequest
//hack auth by resend both user and pass form and cookie
func hackClientRequest(clientConn, remoteConn net.Conn, vpnCookie chan string) {
reader := bufio.NewReader(clientConn)
for { //client req hacking
req, err := http.ReadRequest(reader)
if err != nil {
log.Println("ReadRequest from client conn err:", err)
return
}
if req.URL.Path == "/auth" {
var buf bytes.Buffer
_, err = buf.ReadFrom(req.Body)
req.Body.Close()
if err != nil {
log.Println("read request body from client conn err:", err)
return
}
req.Body = ioutil.NopCloser(bytes.NewReader(buf.Bytes()))
log.Println("3. second req, auth req, do first sending")
req.Write(remoteConn)
//waiting for cookie
ck := <-vpnCookie
log.Println("5. got cookie, resend auth req with cookie")
req.Header.Set("Cookie", fmt.Sprintf("webvpncontext=%s;", ck))
req.Body = ioutil.NopCloser(bytes.NewReader(buf.Bytes()))
req.Write(remoteConn)
log.Println("6. resend done, hack finish, going to do regular io.Copy")
break
} else {
log.Println("1. first req, pass")
req.Write(remoteConn)
}
}
}
//hackRemoteResponse
//hack auth by change auth form and drop the first cookie resp
func hackRemoteResponse(clientConn, remoteConn net.Conn, vpnCookie chan string) {
reader := bufio.NewReader(remoteConn)
for { //remote resp hacking
resp, err := http.ReadResponse(reader, nil)
if err != nil {
log.Println("ReadResponse from remote conn err:", err)
return
}
if resp.ContentLength == len(authFormOld) { //hack auth form
log.Println("2. first resp, hack resp auth form")
resp.Body.Close()
resp.ContentLength = int64(len(authFormNew))
resp.Body = ioutil.NopCloser(strings.NewReader(authFormNew))
} else if ck := resp.Header.Get("Set-Cookie"); ck != "" && vpnCookieRE.MatchString(ck) { //get context cookie
log.Println("4. second resp, grep cookie, resp hacking finish")
if m := vpnCookieRE.FindStringSubmatch(ck); m != nil && m[1] != "" {
vpnCookie <- m[1]
//log.Println("get vpn cookie:", m[1])
break
}
}
err = resp.Write(clientConn)
if err != nil {
log.Println("write to client conn err:", err)
return
}
}
}
@alimp5
Copy link

alimp5 commented Mar 20, 2020

dear @horsley

how i can pentest below IPs on port 443:
https://31.47.37.228/
https://31.47.37.46/
https://www.shodan.io/host/31.47.37.46

This VPN service is hackable ?
Is this really a VPN service?
Because i couldn't find info about launched service behind of port 443.

I got this message in browser:
0.1(1) Please enter your username.

I wait for your response.

Tnx in advance.

@mstxq17
Copy link

mstxq17 commented Feb 12, 2021

how to use it, can you provide some link about this script?

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