目录
简介:
使用场景:
博主目前从事网络安全工作,有时候会遇到大量url目标需要漏洞测试,比如挖掘src等,这个时候我们就需要对目标进行存活性验证,这样可以减少一些无用的请求,提高我们的工作效率,博主从高效率出发,利用golang的协程高并发编写如下代码。
代码:
废话不多说,代码奉上:
/*
批量验证url存活性;
将需要验证url保存至target.txt中,按照一行一个url格式保存;
需要根据自身目录修改常量path值,例如const path string = "C:\Users\Administrator\Desktop\xx\";
最终输出文件为:urls.txt
*/
package main
import (
"bufio"
"fmt"
"log"
"net/http"
"os"
"strings"
"sync"
"time"
)
var wg sync.WaitGroup
const path string = "/xxx/xx/"
func main() {
// file: 打开URL链接文本{target.txt},file1: 创建保存结果{url.txt}
file, err := os.Open(path+"target.txt")
if err != nil {
log.Fatalf("Error when opening file:\n%s", err)
return
}
defer file.Close()
file1, err := os.OpenFile(path+"url.txt", os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0644)
if err != nil {
log.Fatalf("Error when opening file:\n%s", err)
return
}
defer file1.Close()
// 循环遍历target.txt
scanners := bufio.NewScanner(file)
for scanners.Scan() {
u := scanners.Text()
// 去除URL中的换行,包含taobao、jd、tb、alibaba等字符的url,可以根据自己需求自行添加规则{res}
oks := strings.Replace(u, "\n", "", -1)
res1 := strings.Contains(oks, "taobao")
res2 := strings.Contains(oks, "jd.")
res3 := strings.Contains(oks, "tb")
res4 := strings.Contains(oks, "alibaba")
res5 := strings.Contains(oks, "tmall")
res6 := strings.Contains(oks, "1688")
// 发现存在以上字符跳过开启下一轮循环
if res1 || res2 || res3 || res4 || res5 || res6 {
continue
}
res7 := strings.Contains(oks, "http://")
res8 := strings.Contains(oks, "https://")
// 部分URL缺少协议http://字段,go对没有协议字段的URL会引起恐慌
if res7 || res8 {
wg.Add(1)
go req(oks, file1)
continue
}
// 对缺少协议URL字符串拼接,采取多协程高效率对目标URL验证存活
okk := "http://" + oks
okks := "https://" + oks
wg.Add(1)
go req(okk, file1)
wg.Add(1)
go req(okks, file1)
}
wg.Wait()
quchong()
}
// 目标URL存活验证,传入URL和已经创建好并打开的等待写入的文本文件
func req(ur string, file1 *os.File) {
defer wg.Done()
// 有密码认证使用"http://username:password@xxx:8000"
//proxy := "http://127.0.0.1:8080"
//proxyAddress, _ := url.Parse(proxy)
//创建客户端,并添加请求超时时间为10秒
client := http.Client{
Timeout: 10 * time.Second,
}
// 创建访问http,添加请求头,client.Do执行请求
req, err := http.NewRequest("GET", ur, nil)
if err != nil {
fmt.Print("[err] ",ur," 连接错误: ")
fmt.Println(err)
return
}
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36")
htp, err := client.Do(req)
if err != nil {
fmt.Print("[err] ",ur," 连接错误: ")
fmt.Println(err)
return
}
status := htp.StatusCode
defer htp.Body.Close()
fmt.Print("[ok] ",ur, " 状态码:")
fmt.Println(status)
// 写入存活状态URL至打开的文本中
_, err = file1.WriteString(ur+"\n")
if err != nil {
fmt.Print("[err] 写入url.txt(一次写入)报错,")
log.Fatalf("Error when file writestring:\n%s", err)
return
}
}
func quchong(){
// 最后删除中转文件url.txt
defer remove()
// 创建切片和集合用于存储遍历url做为判断条件
a := make([]string, 0, 7)
b := make(map[string]bool)
// 打开需要去重文件{url.txt},创建新文件{urls.txt}
file, err := os.Open(path+"url.txt")
if err != nil {
log.Fatalf("Error when opening file:\n%s", err)
return
}
defer file.Close()
file1, err := os.OpenFile(path+"urls.txt", os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0644)
if err != nil {
log.Fatalf("Error when opening file:\n%s", err)
return
}
// 将需要去重文件整体赋值为字符串,用于判断url是否重复出现
defer file1.Close()
file2, err := os.ReadFile(path+"url.txt")
if err != nil {
log.Fatalf("Error when read file:\n%s", err)
return
}
str := string(file2)
// 循环遍历去除重复url
scanners := bufio.NewScanner(file)
for scanners.Scan() {
ur := scanners.Text()
res1 := strings.Contains(ur, "http://")
if res1 {
url := strings.Replace(ur,"http://","", -1)
num := strings.Count(str, url)
if num == 1 {
_, err = file1.WriteString(ur+"\n")
if err != nil {
fmt.Print("[err] 写入urls.txt(二次写入)报错,")
log.Fatalf("Error when file writestring:\n%s", err)
return
}
} else if num > 1 && ! b[url] {
a = append(a, url)
for _, v := range a {
b[v] = true
}
_, _ = file1.WriteString(ur+"\n")
if err != nil {
fmt.Print("[err] 写入urls.txt(二次写入)报错,")
log.Fatalf("Error when file writestring:\n%s", err)
return
}
} else {
continue
}
} else {
url := strings.Replace(ur,"https://","", -1)
num := strings.Count(str, url)
if num == 1 {
_, err = file1.WriteString(ur+"\n")
if err != nil {
fmt.Print("[err] 写入urls.txt(二次写入)报错,")
log.Fatalf("Error when file writestring:\n%s", err)
return
}
} else if num > 1 && ! b[url] {
a = append(a, url)
for _, v := range a {
b[v] = true
}
_, _ = file1.WriteString(ur+"\n")
if err != nil {
fmt.Print("[err] 写入urls.txt(二次写入)报错,")
log.Fatalf("Error when file writestring:\n%s", err)
return
}
} else {
continue
}
}
}
}
// 创建函数删除中转文件url.txt
func remove() {
err := os.Remove(path+"url.txt")
if err != nil {
fmt.Println("[err] 删除中转文件url.txt失败")
} else {
fmt.Println("[ok] 删除中转文件url.txt成功,最终存活URL文件为urls.txt")
}
}
使用非常简单,只需要修改代码中 const path string = "/xxx/xx/",将引号中修改为自己代码放置位置的绝对路径,例如:"C:\Users\Administrator\Desktop\xx\",注意最后\一定要有,将代码保存为xxx.go,根据个人喜好将文件放到刚刚指定的目录,,将需要测试存活性的url保存指同级目录,然后命名为target.txt,url没有格式要求随意即可,代码会自动分类处理。
以上完成后就可以愉快的运行脚本了
go run xxx.go
稍等片刻,存活验证成功的url将会被输出到同级目录为urls.txt。
当然golang也可以将代码打包成二进制文件,windows可以打包成exe,Mac/Linux同样可以打包成对应系统可执行文件,命令:
1.Mac
Mac下编译Linux, Windows平台的64位可执行程序:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build test.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go
2.Linux
Linux下编译Mac, Windows平台的64位可执行程序:
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build test.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go
3.Windows
Windows下编译Mac, Linux平台的64位可执行程序:
SET CGO_ENABLED=0
SET GOOS=darwin3
SET GOARCH=amd64
go build main.go
SET CGO_ENABLED=0
SET GOOS=linux
SET GOARCH=amd64
go build main.go
GOOS:目标可执行程序运行操作系统,支持 darwin,freebsd,linux,windows
GOARCH:目标可执行程序操作系统构架,包括 386,amd64,arm
说到这里不得不说golang配置国内源,这个在下载需要安装第三方库的时候会用上,本文代码用不上,提前配置以后难免会用到:
Mac/Linux
配置国内源
export GOPROXY=https://goproxy.cn
// 编辑配置文件永久配置
vim ~/.bashrc
export GOPROXY=https://goproxy.cn
source ~/.bashrc
windows
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
F&Q
欢迎使用过程出现的问题评论讨论,目前没有发现bug,如果有童鞋发现可以评论也可以私信。