├── .idea
├── .gitignore
├── CodeScan-master.iml
└── modules.xml
├── CommonVul
├── Rce
│ └── Rce.go
├── Rule
│ ├── MatchFileNameRule.go
│ ├── MatchFileReadRule.go
│ ├── MatchLineRule.go
│ ├── MatchPathRule.go
│ ├── MatchRceRule.go
│ ├── MatchUploadRule.go
│ ├── MtachSqlRule.go
│ ├── ReStaticVar.go
│ └── Utils.go
└── Upload
│ └── Upload_check.go
├── EvilJarList.txt
├── Filter
└── FilterFile.go
├── FilterResult.txt
├── FindFile
├── Common.go
├── FindFile_Java.go
└── FindFile_PHP.go
├── Java-Code
├── AMF
│ └── AmfCheck.go
├── Auth_Bypass
│ └── Authcheck.go
├── El
│ └── Elcheck.go
├── Fastjson
│ └── parsecheck.go
├── Frame_Analysis
│ └── Frame_Analysiser.go
├── JDBC
│ └── FindJDBC.go
├── JNDI
│ └── Jndi.go
├── JS
│ └── Jseval.go
├── JarStatic
│ └── Jarstaticer.go
├── JavaSrciptShell
│ └── FindJavaSrciptShell.go
├── Log4j
│ └── Log4j2.go
├── ReadObject
│ └── readobject.go
├── Reflect
│ └── Reflect.go
├── SSTI
│ └── FreeMarker
│ │ └── FreeSsti.go
├── Sql
│ ├── FindSqlByCode.go
│ ├── FindSqlByXml.go
│ └── Sql.go
└── Zip
│ └── Zipsilp.go
├── PHP-Code
├── FileRead
│ └── Read.go
├── FileWrite
│ └── Write.go
├── Include
│ └── Include.go
├── PHPSql
│ ├── FindSqlByCode.go
│ └── Sql.go
├── SSRF
│ └── SSRF.go
└── Unserialize
│ └── ser.go
├── README.md
├── Utils
├── JavaScanUtil.go
├── PHPScanUtil.go
├── common.go
└── flag.go
├── build.sh
├── go.mod
├── go.sum
├── jarFiles.txt
└── main.go
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 | # 基于编辑器的 HTTP 客户端请求
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/CodeScan-master.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/CommonVul/Rce/Rce.go:
--------------------------------------------------------------------------------
1 | package Rce
2 |
3 | import (
4 | "CodeScan/CommonVul/Rule"
5 | "CodeScan/FindFile"
6 | "fmt"
7 | )
8 |
9 | func JavaRce(dir string) {
10 | FindFile.FindFileByJava(dir, "rce.txt", Rule.JavaRceRuleList)
11 | fmt.Println("RCE分析完成")
12 | }
13 |
14 | func PHPRce(dir string) {
15 | FindFile.FindFileByPHP(dir, "rce.txt", Rule.PHPRceRuleList)
16 | fmt.Println("RCE分析完成")
17 | }
18 |
--------------------------------------------------------------------------------
/CommonVul/Rule/MatchFileNameRule.go:
--------------------------------------------------------------------------------
1 | package Rule
2 |
--------------------------------------------------------------------------------
/CommonVul/Rule/MatchFileReadRule.go:
--------------------------------------------------------------------------------
1 | package Rule
2 |
3 | var PHPFileReadList = []string{
4 | "file_get_contents(", "file(", "readfile(", "fopen(",
5 | }
6 |
--------------------------------------------------------------------------------
/CommonVul/Rule/MatchLineRule.go:
--------------------------------------------------------------------------------
1 | package Rule
2 |
3 | var LineBlack = []string{
4 | "import ",
5 | "log.",
6 | "loaded from",
7 | "//",
8 | "document.write(",
9 | "getWriter().write(",
10 | "writer.write(",
11 | ".write()",
12 | }
13 |
--------------------------------------------------------------------------------
/CommonVul/Rule/MatchPathRule.go:
--------------------------------------------------------------------------------
1 | package Rule
2 |
3 | var PathBlackJava = []string{
4 | "apache", "lombok", "microsoft", "solr",
5 | "amazonaws", "c3p0", "jodd", "afterturn", "hutool",
6 | "javassist", "alibaba", "aliyuncs", "javax", "jackson",
7 | "bytebuddy", "baomidou", "google", "netty", "redis", "mysql",
8 | "logback", "ognl", "oracle", "sun", "junit", "reactor", "github",
9 | "mchange", "taobao", "nimbusds", "opensymphony", "freemarker", "java", "apiguardian", "hibernate", "javassist", "jboss", "junit", "mybatis",
10 | "springframework", "slf4j", "aspectj",
11 | }
12 |
13 | var PathBlackPhp = []string{
14 | "think", "vendor",
15 | }
16 |
--------------------------------------------------------------------------------
/CommonVul/Rule/MatchRceRule.go:
--------------------------------------------------------------------------------
1 | package Rule
2 |
3 | var JavaRceRuleList = []string{
4 | "Runtime.getRuntime().exec", "ProcessBuilder.start",
5 | "RuntimeUtil.exec(", "RuntimeUtil.execForStr(",
6 | }
7 |
8 | var PHPRceRuleList = []string{
9 | "System(", "shell_exec(", "exec(", "eval(", "passthru(", "proc_open(", "popen(",
10 | "assert(", "call_user_func(", "call_user_func_array(", "create_function(",
11 | }
12 |
--------------------------------------------------------------------------------
/CommonVul/Rule/MatchUploadRule.go:
--------------------------------------------------------------------------------
1 | package Rule
2 |
3 | var JavaUploadRuleList = []string{
4 | "Streams.copy(",
5 | ".getOriginalFilename(", ".transferTo(",
6 | "UploadedFile(", "FileUtils.copyFile(", "MultipartHttpServletRequest", ".getFileName(", ".saveAs(", ".getFileSuffix(", ".getFile", "MultipartFile file",
7 | }
8 |
9 | var PHPUploadRuleList = []string{
10 | "move_uploaded_file(", "file_put_contents(", "$_FILE[", "copy(", "->move(", "request()->file(",
11 | }
12 |
--------------------------------------------------------------------------------
/CommonVul/Rule/MtachSqlRule.go:
--------------------------------------------------------------------------------
1 | package Rule
2 |
3 | var XmlSqlBlack = []string{
4 | "", "id=\"dataSource\"", "", "",
7 | " 0 {
56 | writeToFile("sql.txt", selectList)
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Java-Code/Sql/FindSqlByXml.go:
--------------------------------------------------------------------------------
1 | package Sql
2 |
3 | import (
4 | Rule2 "CodeScan/CommonVul/Rule"
5 | "bufio"
6 | "fmt"
7 | "io/fs"
8 | "os"
9 | "path/filepath"
10 | "strings"
11 | )
12 |
13 | // findKeywordsInXMLFiles 函数用于检查 XML 文件中的关键字
14 | func findSqlByXml(dir string) {
15 | xmlList := []string{}
16 | var lastFile string // 记录上一次输出的文件,用于控制输出格式
17 |
18 | // 使用 Walk 函数遍历目录,查找所有的 .xml 文件
19 | err := filepath.Walk(dir, func(path string, f fs.FileInfo, err error) error {
20 | if !f.IsDir() && strings.HasSuffix(f.Name(), ".xml") {
21 | // xml黑名单匹配
22 | if Rule2.MatchRule(f.Name(), Rule2.XmlBlack) {
23 | return nil
24 | }
25 | xmlList = append(xmlList, path)
26 | }
27 | return nil
28 | })
29 | check(err)
30 |
31 | // 定义需要搜索的关键字
32 | keywords := []string{"${", "like '%${", "order by ${"} // 这里可以添加更多关键字
33 |
34 | // 遍历 XML 文件列表
35 | for _, file := range xmlList {
36 | foundKeywords := []string{}
37 |
38 | lineNumber := 1
39 | // 打开 XML 文件
40 | f, err := os.Open(file)
41 | check(err)
42 | defer f.Close()
43 |
44 | // 逐行扫描文件内容
45 | scanner := bufio.NewScanner(f)
46 | for scanner.Scan() {
47 | line := strings.TrimSpace(scanner.Text())
48 | // 检查每一行是否包含关键字,并且不包含黑名单中的关键字
49 | if Rule2.MatchRule(line, Rule2.XmlSqlBlack) {
50 | continue
51 | }
52 | // 检查每一行是否包含需要搜索的关键字
53 | for _, keyword := range keywords {
54 | if strings.Contains(line, keyword) {
55 | if lastFile != f.Name() {
56 | foundKeywords = append(foundKeywords, fmt.Sprintf("====================================================================\n"))
57 | foundKeywords = append(foundKeywords, fmt.Sprintf("file [%s]\n%d: %s", f.Name(), lineNumber, line))
58 | lastFile = f.Name()
59 | } else {
60 | foundKeywords = append(foundKeywords, fmt.Sprintf("====================================================================\n"))
61 | foundKeywords = append(foundKeywords, fmt.Sprintf("%d : %s", lineNumber, line))
62 | }
63 | }
64 | }
65 | lineNumber++
66 | }
67 |
68 | // 如果找到关键字,则将相关信息写入到 sql.txt 文件中
69 | if len(foundKeywords) > 0 {
70 | writeToFile("sql.txt", foundKeywords)
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Java-Code/Sql/Sql.go:
--------------------------------------------------------------------------------
1 | package Sql
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | )
7 |
8 | // check 函数用于检查错误,如果错误不为 nil 则触发 panic
9 | func check(e error) {
10 | if e != nil {
11 | panic(e)
12 | }
13 | }
14 |
15 | // Sqlcheck 函数是我们的主函数,负责执行 SQL 检查的逻辑
16 | func Sqlcheck(dir string) {
17 | // 检查是否存在 @Select 注解
18 | findSqlByCode(dir)
19 |
20 | // 检查 XML 文件中的关键字
21 | findSqlByXml(dir)
22 |
23 | fmt.Println("sql分析完成")
24 | }
25 |
26 | // writeToFile 函数用于将信息写入文件
27 | func writeToFile(filename string, lines []string) {
28 |
29 | // 创建或打开输出文件,以追加模式写入
30 | basedir := "./results/"
31 |
32 | // 检查目录是否存在
33 | if _, err := os.Stat(basedir); os.IsNotExist(err) {
34 | // 如果目录不存在,则创建
35 | err := os.MkdirAll(basedir, os.ModePerm)
36 | if err != nil {
37 | fmt.Println("Error creating directory:", err)
38 | return
39 | }
40 | }
41 |
42 | outputfile := basedir + filename // 打开文件,如果文件不存在则创建,如果存在则追加写入
43 | outputFile, err := os.OpenFile(outputfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
44 | check(err)
45 | defer outputFile.Close()
46 |
47 | // 将每一行信息写入文件
48 | for _, line := range lines {
49 | _, err = outputFile.WriteString(fmt.Sprintf("%s\n", line))
50 | check(err)
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Java-Code/Zip/Zipsilp.go:
--------------------------------------------------------------------------------
1 | package Zip
2 |
3 | import (
4 | "CodeScan/FindFile"
5 | "fmt"
6 | )
7 |
8 | func Zipsilp(dir string) {
9 | FindFile.FindFileByJava(dir, "zip.txt", []string{"zipEntry.getName(", "ZipUtil.unpack(", "ZipUtil.unzip(", "entry.getName()", "AntZipUtils.unzip(", "zip.getEntries()"})
10 | fmt.Println("Zipsilp分析完成")
11 | }
12 |
--------------------------------------------------------------------------------
/PHP-Code/FileRead/Read.go:
--------------------------------------------------------------------------------
1 | package FileRead
2 |
3 | import (
4 | "CodeScan/CommonVul/Rule"
5 | "CodeScan/FindFile"
6 | "fmt"
7 | )
8 |
9 | func Read(dir string) {
10 | FindFile.FindFileByPHP(dir, "FileRead_Phar.txt", Rule.PHPFileReadList)
11 | fmt.Println("PHP文件读取分析完成")
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/PHP-Code/FileWrite/Write.go:
--------------------------------------------------------------------------------
1 | package FileWrite
2 |
3 | import (
4 | "CodeScan/FindFile"
5 | "fmt"
6 | )
7 |
8 | func Write(dir string) {
9 | FindFile.FindFileByPHP(dir, "FileWrite.txt", []string{
10 | "file_put_contents(",
11 | })
12 | fmt.Println("PHP文件写入分析完成")
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/PHP-Code/Include/Include.go:
--------------------------------------------------------------------------------
1 | package Include
2 |
3 | import (
4 | "CodeScan/FindFile"
5 | "fmt"
6 | )
7 |
8 | func Include(dir string) {
9 | FindFile.FindFileByPHP(dir, "Include.txt", []string{
10 | "include(",
11 | })
12 | fmt.Println("PHP文件包含分析完成")
13 | }
14 |
--------------------------------------------------------------------------------
/PHP-Code/PHPSql/FindSqlByCode.go:
--------------------------------------------------------------------------------
1 | package PHPSql
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "io/fs"
7 | "os"
8 | "path/filepath"
9 | "strings"
10 | )
11 |
12 | // 函数用于检查是否存在java代码内容,并将相关信息写入 sql.txt
13 | func findSqlByCode(dir string) {
14 | selectList := []string{}
15 | var lastFile string // 记录上一次输出的文件,用于控制输出格式
16 |
17 | keywords := []string{"like '%\" +", "mysql_query(", "->where(", "->order(", "mysqli_query("}
18 |
19 | err := filepath.Walk(dir, func(path string, f fs.FileInfo, err error) error {
20 | if !f.IsDir() && strings.HasSuffix(f.Name(), ".php") {
21 | // 打开文件
22 | lineNumber := 1 // 行号,用于标识匹配行的位置
23 | file, err := os.Open(path)
24 | check(err)
25 | defer file.Close()
26 |
27 | // 逐行扫描文件内容
28 | scanner := bufio.NewScanner(file)
29 | for scanner.Scan() {
30 | line := strings.TrimSpace(scanner.Text())
31 | // 如果行中包含 @Select 注解,则将相关信息添加到 selectList 中
32 | for _, keyword := range keywords {
33 | if strings.Contains(line, keyword) {
34 | if lastFile != file.Name() {
35 | selectList = append(selectList, fmt.Sprintf("====================================================================\n"))
36 | selectList = append(selectList, fmt.Sprintf("file [%s]\n%d: %s", file.Name(), lineNumber, line))
37 | lastFile = file.Name()
38 | } else {
39 | selectList = append(selectList, fmt.Sprintf("====================================================================\n"))
40 | selectList = append(selectList, fmt.Sprintf("%d : %s", lineNumber, line))
41 | }
42 | }
43 |
44 | }
45 | lineNumber++
46 | }
47 |
48 | }
49 | return nil
50 | })
51 | check(err)
52 |
53 | // 如果存在 @Select 注解,则将相关信息写入到 sql.txt 文件中
54 | if len(selectList) > 0 {
55 | writeToFile("sql.txt", selectList)
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/PHP-Code/PHPSql/Sql.go:
--------------------------------------------------------------------------------
1 | package PHPSql
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | )
7 |
8 | // check 函数用于检查错误,如果错误不为 nil 则触发 panic
9 | func check(e error) {
10 | if e != nil {
11 | panic(e)
12 | }
13 | }
14 |
15 | // Sqlcheck 函数是我们的主函数,负责执行 SQL 检查的逻辑
16 | func Sqlcheck(dir string) {
17 | // 检查是否存在 @Select 注解
18 | findSqlByCode(dir)
19 |
20 | fmt.Println("sql分析完成")
21 | }
22 |
23 | // writeToFile 函数用于将信息写入文件
24 | func writeToFile(filename string, lines []string) {
25 | // 打开文件,如果文件不存在则创建,如果存在则追加写入
26 | outputFile, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
27 | check(err)
28 | defer outputFile.Close()
29 |
30 | // 将每一行信息写入文件
31 | for _, line := range lines {
32 | _, err = outputFile.WriteString(fmt.Sprintf("%s\n", line))
33 | check(err)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/PHP-Code/SSRF/SSRF.go:
--------------------------------------------------------------------------------
1 | package SSRF
2 |
3 | import (
4 | "CodeScan/FindFile"
5 | "fmt"
6 | )
7 |
8 | func PHP_SSRF(dir string) {
9 | FindFile.FindFileByPHP(dir, "SSRF.txt", []string{
10 | "curl_exec(",
11 | })
12 | fmt.Println("PHPSSRF分析完成")
13 | }
14 |
--------------------------------------------------------------------------------
/PHP-Code/Unserialize/ser.go:
--------------------------------------------------------------------------------
1 | package Unserialize
2 |
3 | import (
4 | "CodeScan/FindFile"
5 | "fmt"
6 | )
7 |
8 | func Unserialize(dir string) {
9 |
10 | FindFile.FindFileByPHP(dir, "Unserialize.txt", []string{
11 | "__destruct(",
12 | })
13 | fmt.Println("PHP反序列化分析完成")
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CodeScan
2 | 
3 | ## 工具概述
4 |
5 | 该工具目的为对大多数不完整的代码以及依赖快速进行Sink点匹配来帮助红队完成快速代码审计,开发该工具的初衷是以`Sink`到`Source`的思路来开发,为了将所有可疑的Sink点匹配出来并且凭借第六感进行快速漏洞挖掘,并且该工具开发可扩展性强,成本极低,目前工具支持的语言有PHP,Java(JSP)
6 |
7 | ## 编译
8 |
9 | ```bash
10 | ./build.sh
11 |
12 | # 会生成所有版本在releases下
13 | ```
14 |
15 | ## 功能
16 |
17 | 1. 框架识别
18 | 2. 涵盖大部分漏洞的Sink点的匹配(如图)
19 | 
20 | 3. 可自定义定制化修改黑白名单内容
21 | 4. 多模块化多语言化代码审计
22 | 5. 进行融于鉴权代码的快速匹配抓取
23 | 6. 根据Jar进行静态分析(默认分析)
24 |
25 | * mysqlconnect-->jdbc
26 | * Xstream --> xml/json
27 |
28 | ## 使用
29 |
30 | ```bash
31 | Usage of ./CodeScan_darwin_arm64:
32 | -L string
33 | 审计语言
34 | -d string
35 | 要扫描的目录
36 | -h string
37 | 使用帮助
38 | -lb string
39 | 行黑名单
40 | -m string
41 | 过滤的字符串
42 | -pb string
43 | 路径黑名单
44 | -r string
45 | RCE规则
46 | -u string
47 | 文件上传规则
48 |
49 |
50 | Example:
51 | CodeScan_windows_amd64.exe -L java -d ./net
52 | CodeScan_windows_amd64.exe -L php -d ./net
53 | CodeScan_windows_amd64.exe -d ./net -m "CheckSession.jsp"
54 | ```
55 |
56 | ## 高级用法+案例分析
57 |
58 | ### 高级用法
59 |
60 | `以下均以Java作为示例`
61 |
62 | #### 高扩展性
63 |
64 | 很简单的自定义,如果需要自定义一些匹配规则,首先可以在这里加入
65 |
66 | 
67 |
68 |
69 | 其次如果需要新增漏洞类型,只需要三步(这里以Sql为例)
70 |
71 | 1. 新建SQL目录
72 | 2. 定义一个方法叫 SqlCheck
73 | 3. 写一个sqlcheck.txt(生成的文件名) + 你自定义的规则
74 | 4. 最后在这里加入包名+方法名即可
75 |
76 | 
77 |
78 | ```go
79 | package SqlTest
80 |
81 | import (
82 | "CodeScan/FindFile"
83 | "fmt"
84 | )
85 |
86 | func SqlCheck(dir string) {
87 | FindFile.FindFileByJava(dir, "fastjson.txt", []string{".parseObject("})
88 | fmt.Println("SqlCheck分析完成")
89 |
90 | }
91 |
92 | ```
93 |
94 | #### 扫描位置
95 |
96 | 在打一些闭源代码的时候经常就一个Jar或者Class,反编译的时候会把依赖进行一起反编译,所以为了避免扫描一些依赖的误报,在工具中自带的黑名单中会过滤掉如下黑名单的包名,需要自定义的时候可自行修改,位置在`CommonVul/Rule/MatchPathRule.go`
97 |
98 | ```go
99 | var PathBlackJava = []string{
100 | "apache", "lombok", "microsoft", "solr",
101 | "amazonaws", "c3p0", "jodd", "afterturn", "hutool",
102 | "javassist", "alibaba", "aliyuncs", "javax", "jackson",
103 | "bytebuddy", "baomidou", "google", "netty", "redis", "mysql",
104 | "logback", "ognl", "oracle", "sun", "junit", "reactor", "github",
105 | "mchange", "taobao", "nimbusds", "opensymphony", "freemarker", "java", "apiguardian", "hibernate", "javassist", "jboss", "junit", "mybatis",
106 | "springframework", "slf4j",
107 | }
108 | ```
109 |
110 | 所以这也导致了一个问题,不能从顶层上直接扫描
111 |
112 | 
113 |
114 | `请把CodeScan放在Net同级目录下扫描(否则会忽略掉直接一个Java目录)`
115 |
116 | 请`-d`后面的参数尽量在`/src/main/java`之后,比如这里就需要把CodeScan放到`net`目录下开始扫描
117 |
118 | ```bash
119 | CodeScan_windows_amd64.exe -L java -d ./net
120 | ```
121 |
122 | #### 过滤字符串(只写了JSP + PHP)
123 |
124 | 比如现在有一个代码百分百为鉴权代码在JSP中
125 |
126 | ```java
127 | <%@ include file="../../common/js/CheckSession.jsp"%>
128 | ```
129 |
130 | 此时可以用一下功能来进行快速获取未鉴权代码
131 |
132 | ```bash
133 | CodeScan_windows_amd64.exe -d ./yuan -m "CheckSession.jsp"
134 | ```
135 |
136 | 此时会将不存在这个代码的文件都放到`NoAuthDir`目录中,然后可以再扫一遍就可以立刻定位到存在未鉴权并且存在Sink点的函数文件了
137 |
138 | ```bash
139 | CodeScan_windows_amd64.exe -L java -d ./NoAuthDir
140 | ```
141 |
142 | #### 静态分析依赖情况
143 |
144 | 只需要在CodeScan的目录下放入EvilJarList.txt即可匹配出来
145 |
146 | `EvilJarList.txt` 内容为存在可打漏洞的`Jar`,模版如下
147 |
148 | ```bash
149 | fastjson-1.2.47.jar
150 | resin-4.0.63.jar
151 | jackson-core-2.13.3.jar
152 | c3p0-0.9.5.2.jar
153 | commons-beanutils-1.9.4.jar
154 | commons-beanutils-1.9.3.jar
155 | commons-beanutils-1.9.2.jar
156 | commons-collections-3.2.1.jar
157 | mysql-connector-java-8.0.17.jar
158 | commons-collections4-4.0.jar
159 | shiro-core-1.10.1.jar
160 | aspectjweaver-1.9.5.jar
161 | rome-1.0.jar
162 | xstream-1.4.11.1.jar
163 | sqlite-jdbc-3.8.9.jar
164 | vaadin-server-7.7.14.jar
165 | hessian-4.0.63.jar
166 | ```
167 |
168 | #### 案例
169 | 案例请参考我的博客
170 | ```bash
171 | https://zjackky.github.io/post/develop-codescan-zwcz53.html
172 | ```
173 |
174 | ## TODO
175 |
176 | * [ ] 将结果从TXT转为Excel
177 | * [ ] Sink点继续完善
178 | * [ ] ASP
179 |
180 | ## 支持项目
181 |
182 | * 如果有师傅发现Bug或者有更好的建议请提issue感谢
183 | * 要是各位师傅通过本人的小工具挖到一些好洞记得回头点点Stars诶
184 |
185 | ## 免责申明
186 |
187 | * 如果您下载、安装、使用、修改本工具及相关代码,即表明您信任本工具
188 | * 在使用本工具时造成对您自己或他人任何形式的损失和伤害,我们不承担任何责任
189 | * 如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任
190 | * 请您务必审慎阅读、充分理解各条款内容,特别是免除或者限制责任的条款,并选择接受或不接受
191 | * 除非您已阅读并接受本协议所有条款,否则您无权下载、安装或使用本工具
192 | * 您的下载、安装、使用等行为即视为您已阅读并同意上述协议的约束
193 |
194 | ## 更新日志
195 |
196 | **2024/09/29**
197 |
198 | * 开源
199 |
200 | **2024/10/7**
201 |
202 | * 将扫描结果写入result目录中
203 |
204 | ## 鸣谢
205 |
206 | [xiaoqiuxx(github.com)](https://github.com/xiaoqiuxx)
207 |
--------------------------------------------------------------------------------
/Utils/JavaScanUtil.go:
--------------------------------------------------------------------------------
1 | package Utils
2 |
3 | import (
4 | "CodeScan/CommonVul/Rce"
5 | "CodeScan/CommonVul/Upload"
6 | "CodeScan/Java-Code/AMF"
7 | "CodeScan/Java-Code/Auth_Bypass"
8 | "CodeScan/Java-Code/El"
9 | "CodeScan/Java-Code/Fastjson"
10 | "CodeScan/Java-Code/Frame_Analysis"
11 | "CodeScan/Java-Code/JDBC"
12 | "CodeScan/Java-Code/JNDI"
13 | "CodeScan/Java-Code/JS"
14 | "CodeScan/Java-Code/JarStatic"
15 | "CodeScan/Java-Code/JavaSrciptShell"
16 | "CodeScan/Java-Code/Log4j"
17 | "CodeScan/Java-Code/ReadObject"
18 | "CodeScan/Java-Code/Reflect"
19 | "CodeScan/Java-Code/SSTI/FreeMarker"
20 | "CodeScan/Java-Code/Sql"
21 | "CodeScan/Java-Code/Zip"
22 | "github.com/cheggaaa/pb/v3"
23 | "os"
24 | "path/filepath"
25 | "strings"
26 | "sync"
27 | "time"
28 | )
29 |
30 | func Java_Codeing() {
31 | StartTime = time.Now()
32 | // 所有要执行的扫描函数
33 | scanFuncs := []func(string){
34 | Frame_Analysis.FrameAnalysiser,
35 | Auth_Bypass.Auth,
36 | Zip.Zipsilp,
37 | JNDI.Jndi,
38 | Sql.Sqlcheck,
39 | Rce.JavaRce,
40 | Upload.JavaUpload_check,
41 | ReadObject.Readobjectcheck,
42 | El.Elcheck,
43 | Fastjson.Parsecheck,
44 | Reflect.ReflectCheck,
45 | Log4j.Log4j,
46 | AMF.AmfCheck,
47 | FreeMarker.FreeSsti,
48 | JDBC.FindJDBC,
49 | JavaSrciptShell.FindJavaSrciptShell,
50 | JarStatic.Jarstaticer,
51 | JS.Eval,
52 | }
53 |
54 | var wg sync.WaitGroup
55 | wg.Add(len(scanFuncs)) // 根据方法数量动态调整 goroutine 数量
56 | progressBar = pb.New(len(scanFuncs)).SetRefreshRate(time.Millisecond * 100).Start()
57 | // 启动 goroutine 来执行扫描任务
58 | for _, scanFunc := range scanFuncs {
59 | go scanDirectory(scanFunc, *Dir, &wg)
60 | }
61 |
62 | wg.Wait()
63 | progressBar.Finish()
64 |
65 | // 处理web.xml
66 | Frame_Analysis.WebXmlScan(*Dir, []string{"*.htm", "*.do", "*.action", "exclude"})
67 |
68 | // 清理空文件
69 | root := "./" // 设置要检查的目录
70 | filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
71 | if err != nil {
72 | return err
73 | }
74 | if !info.IsDir() && strings.HasSuffix(info.Name(), ".txt") {
75 | if info.Size() == 0 {
76 | os.Remove(path)
77 | }
78 | }
79 | return nil
80 | })
81 | }
82 |
--------------------------------------------------------------------------------
/Utils/PHPScanUtil.go:
--------------------------------------------------------------------------------
1 | package Utils
2 |
3 | import (
4 | "CodeScan/CommonVul/Rce"
5 | "CodeScan/CommonVul/Upload"
6 | "CodeScan/PHP-Code/FileRead"
7 | "CodeScan/PHP-Code/Include"
8 | "CodeScan/PHP-Code/PHPSql"
9 | "CodeScan/PHP-Code/SSRF"
10 | "CodeScan/PHP-Code/Unserialize"
11 | "github.com/cheggaaa/pb/v3"
12 | "os"
13 | "path/filepath"
14 | "strings"
15 | "sync"
16 | "time"
17 | )
18 |
19 | func PHP_Codeing() {
20 | StartTime = time.Now()
21 |
22 | // 所有要执行的扫描函数
23 | scanFuncs := []func(string){
24 | Upload.PHPUpload_check,
25 | Rce.PHPRce,
26 | PHPSql.Sqlcheck,
27 | FileRead.Read,
28 | Unserialize.Unserialize,
29 | SSRF.PHP_SSRF,
30 | Include.Include,
31 | }
32 |
33 | var wg sync.WaitGroup
34 | wg.Add(len(scanFuncs)) // 根据方法数量动态调整 goroutine 数量
35 | progressBar = pb.New(len(scanFuncs)).SetRefreshRate(time.Millisecond * 100).Start()
36 | // 启动 goroutine 来执行扫描任务
37 | for _, scanFunc := range scanFuncs {
38 | go scanDirectory(scanFunc, *Dir, &wg)
39 | }
40 |
41 | wg.Wait()
42 | progressBar.Finish()
43 | // 清理空文件
44 | root := "./" // 设置要检查的目录
45 | filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
46 | if err != nil {
47 | return err
48 | }
49 | if !info.IsDir() && strings.HasSuffix(info.Name(), ".txt") {
50 | if info.Size() == 0 {
51 | os.Remove(path)
52 | }
53 | }
54 | return nil
55 | })
56 | }
57 |
--------------------------------------------------------------------------------
/Utils/common.go:
--------------------------------------------------------------------------------
1 | package Utils
2 |
3 | import (
4 | "github.com/cheggaaa/pb/v3"
5 | "strings"
6 | "sync"
7 | "time"
8 | )
9 |
10 | var (
11 | progressBar *pb.ProgressBar
12 | StartTime time.Time
13 | )
14 |
15 | // scanDirectory 函数用于启动一个 goroutine 来扫描指定目录
16 | func scanDirectory(scanFunc func(string), dir string, wg *sync.WaitGroup) {
17 | scanFunc(dir)
18 | progressBar.Increment()
19 | wg.Done()
20 | }
21 |
22 | func ClearDir(dir string) string {
23 |
24 | // 将 \ 转换为 /
25 | dir = strings.ReplaceAll(dir, `\\`, "/")
26 | dir = strings.ReplaceAll(dir, `\`, "/")
27 |
28 | return dir
29 | }
30 |
--------------------------------------------------------------------------------
/Utils/flag.go:
--------------------------------------------------------------------------------
1 | package Utils
2 |
3 | import (
4 | Rule2 "CodeScan/CommonVul/Rule"
5 | "CodeScan/Filter"
6 | "flag"
7 | "fmt"
8 | "github.com/fatih/color"
9 | "strings"
10 | )
11 |
12 | var (
13 | Dir *string
14 | language *string
15 | help *string
16 | )
17 |
18 | func Start() {
19 | // 开始审计
20 |
21 | parseFlag()
22 | *language = strings.ToLower(*language)
23 | if *language == "java" {
24 | Java_Codeing()
25 | }
26 |
27 | if *language == "php" {
28 | PHP_Codeing()
29 | }
30 |
31 | }
32 |
33 | func parseFlag() {
34 |
35 | // 高级命令行解析
36 | help = flag.String("h", "", "使用帮助")
37 | Dir = flag.String("d", "", "要扫描的目录")
38 | language = flag.String("L", "", "审计语言")
39 | pathBlackRule := flag.String("pb", "", "路径黑名单")
40 | lineBlackRule := flag.String("lb", "", "行黑名单")
41 | uploadRule := flag.String("u", "", "文件上传规则")
42 | rceRule := flag.String("r", "", "RCE规则")
43 | filterfile := flag.String("m", "", "过滤的字符串")
44 | //outdir := flag.String("o", "", "输出结果")
45 | flag.Parse()
46 |
47 | if *language == "" && *filterfile == "" {
48 | color.Red("请使用 -L 选项提供扫描语言")
49 | return
50 | }
51 |
52 | if *language != "" {
53 |
54 | if *Dir != "" {
55 | *Dir = ClearDir(*Dir)
56 | if *pathBlackRule != "" {
57 | // 读取路径黑名单
58 | Rule2.PathBlackJava = append(Rule2.PathBlackJava, *pathBlackRule)
59 | fmt.Println("路径黑名单:", Rule2.PathBlackJava)
60 | } // 所有要执行的扫描函数
61 |
62 | if *lineBlackRule != "" {
63 | Rule2.LineBlack = append(Rule2.LineBlack, *lineBlackRule)
64 | }
65 |
66 | if *uploadRule != "" {
67 | if *language == "java" {
68 | Rule2.JavaUploadRuleList = append(Rule2.JavaUploadRuleList, *uploadRule)
69 | } else if *language == "php" {
70 | Rule2.PHPUploadRuleList = append(Rule2.PHPUploadRuleList, *uploadRule)
71 | }
72 |
73 | }
74 |
75 | if *rceRule != "" {
76 | Rule2.JavaRceRuleList = append(Rule2.JavaRceRuleList, *rceRule)
77 | }
78 |
79 | }
80 |
81 | }
82 |
83 | if *filterfile != "" {
84 | if *Dir != "" {
85 | Filter.FilterFile(*filterfile, *Dir)
86 |
87 | } else {
88 | color.Red("请使用 -d 选项提供目录")
89 | return
90 | }
91 |
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Define the list of target operating systems and architectures
4 | os_archs=("darwin:amd64" "darwin:arm64" "linux:amd64" "windows:amd64")
5 |
6 | # Define the Go compiler flags
7 | LDFLAGS="-s -w"
8 |
9 | # Loop through each OS/architecture pair and build JodeScanner
10 | for pair in "${os_archs[@]}"; do
11 | os=$(echo "$pair" | cut -d ":" -f 1)
12 | arch=$(echo "$pair" | cut -d ":" -f 2)
13 | output="./releases/CodeScan_${os}_${arch}"
14 |
15 | # For Windows, add .exe extension to the output file
16 | if [[ "$os" == "windows" ]]; then
17 | output="$output.exe"
18 | fi
19 |
20 | # Build JodeScanner for the current OS/architecture pair
21 | echo "Building $output..."
22 | GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "$LDFLAGS" -o "$output" main.go
23 | echo "Build $output done"
24 | done
25 |
26 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module CodeScan
2 |
3 | go 1.22.1
4 |
5 | require (
6 | github.com/cheggaaa/pb/v3 v3.1.5
7 | github.com/fatih/color v1.16.0
8 | )
9 |
10 | require (
11 | github.com/VividCortex/ewma v1.2.0 // indirect
12 | github.com/mattn/go-colorable v0.1.13 // indirect
13 | github.com/mattn/go-isatty v0.0.20 // indirect
14 | github.com/mattn/go-runewidth v0.0.15 // indirect
15 | github.com/rivo/uniseg v0.2.0 // indirect
16 | golang.org/x/sys v0.14.0 // indirect
17 | )
18 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
2 | github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
3 | github.com/cheggaaa/pb/v3 v3.1.5 h1:QuuUzeM2WsAqG2gMqtzaWithDJv0i+i6UlnwSCI4QLk=
4 | github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6jM60XI=
5 | github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
6 | github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
7 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
8 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
9 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
10 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
11 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
12 | github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
13 | github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
14 | github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
15 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
16 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
17 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
18 | golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
19 | golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
20 |
--------------------------------------------------------------------------------
/jarFiles.txt:
--------------------------------------------------------------------------------
1 | HikariCP-2.7.8.jar
2 | aliyun-java-sdk-core-3.4.0.jar
3 | aliyun-java-sdk-ecs-4.2.0.jar
4 | aliyun-java-sdk-kms-2.7.0.jar
5 | aliyun-java-sdk-ram-3.0.0.jar
6 | aliyun-java-sdk-sts-3.0.0.jar
7 | aliyun-sdk-oss-3.10.1.jar
8 | byte-buddy-1.7.10.jar
9 | classmate-1.3.4.jar
10 | commons-codec-1.11.jar
11 | commons-pool2-2.5.0.jar
12 | fastjson-1.2.83.jar
13 | gson-2.8.2.jar
14 | guava-18.0.jar
15 | hibernate-validator-6.0.7.Final.jar
16 | httpclient-4.5.2.jar
17 | httpcore-4.4.9.jar
18 | jackson-annotations-2.9.0.jar
19 | jackson-core-2.9.4.jar
20 | jackson-databind-2.9.4.jar
21 | jackson-dataformat-yaml-2.9.4.jar
22 | jackson-datatype-jdk8-2.9.4.jar
23 | jackson-datatype-jsr310-2.9.4.jar
24 | jackson-module-parameter-names-2.9.4.jar
25 | java-semver-0.9.0.jar
26 | javassist-3.21.0-GA.jar
27 | javax.annotation-api-1.3.2.jar
28 | jboss-logging-3.3.2.Final.jar
29 | jdom-1.1.jar
30 | jedis-2.9.0.jar
31 | jettison-1.1.jar
32 | jsqlparser-1.3.jar
33 | jul-to-slf4j-1.7.25.jar
34 | jxl-2.6.12.jar
35 | log4j-1.2.14.jar
36 | log4j-api-2.10.0.jar
37 | log4j-to-slf4j-2.15.0.jar
38 | logback-classic-1.2.3.jar
39 | logback-core-1.2.3.jar
40 | lombok-1.18.12.jar
41 | mapstruct-1.1.0.Final.jar
42 | mybatis-3.4.6.jar
43 | mybatis-plus-3.0.7.1.jar
44 | mybatis-plus-annotation-3.0.7.1.jar
45 | mybatis-plus-boot-starter-3.0.7.1.jar
46 | mybatis-plus-core-3.0.7.1.jar
47 | mybatis-plus-extension-3.0.7.1.jar
48 | mybatis-spring-1.3.2.jar
49 | mysql-connector-java-8.0.11.jar
50 | pf4j-3.1.0.jar
51 | protobuf-java-2.6.0.jar
52 | reflections-0.9.11.jar
53 | slf4j-api-1.7.25.jar
54 | snakeyaml-1.19.jar
55 | spring-aop-5.0.4.RELEASE.jar
56 | spring-beans-5.0.4.RELEASE.jar
57 | spring-boot-2.0.0.RELEASE.jar
58 | spring-boot-autoconfigure-2.0.0.RELEASE.jar
59 | spring-boot-starter-2.0.0.RELEASE.jar
60 | spring-boot-starter-jdbc-2.0.0.RELEASE.jar
61 | spring-boot-starter-json-2.0.0.RELEASE.jar
62 | spring-boot-starter-logging-2.0.0.RELEASE.jar
63 | spring-boot-starter-redis-1.4.1.RELEASE.jar
64 | spring-boot-starter-tomcat-2.0.0.RELEASE.jar
65 | spring-boot-starter-web-2.0.0.RELEASE.jar
66 | spring-context-5.0.4.RELEASE.jar
67 | spring-context-support-5.0.4.RELEASE.jar
68 | spring-core-5.0.4.RELEASE.jar
69 | spring-data-commons-2.0.5.RELEASE.jar
70 | spring-data-keyvalue-2.0.5.RELEASE.jar
71 | spring-data-redis-2.0.5.RELEASE.jar
72 | spring-expression-5.0.4.RELEASE.jar
73 | spring-jcl-5.0.4.RELEASE.jar
74 | spring-jdbc-5.0.4.RELEASE.jar
75 | spring-oxm-5.0.4.RELEASE.jar
76 | spring-plugin-core-1.2.0.RELEASE.jar
77 | spring-plugin-metadata-1.2.0.RELEASE.jar
78 | spring-tx-5.0.4.RELEASE.jar
79 | spring-web-5.0.4.RELEASE.jar
80 | spring-webmvc-5.0.4.RELEASE.jar
81 | springboot-plugin-framework-2.2.1-RELEASE.jar
82 | springboot-plugin-framework-extension-mybatis-2.2.1-RELEASE.jar
83 | springfox-core-2.7.0.jar
84 | springfox-schema-2.7.0.jar
85 | springfox-spi-2.7.0.jar
86 | springfox-spring-web-2.7.0.jar
87 | springfox-swagger-common-2.7.0.jar
88 | springfox-swagger2-2.7.0.jar
89 | stax-api-1.0.1.jar
90 | swagger-annotations-1.5.13.jar
91 | swagger-bootstrap-ui-1.6.jar
92 | swagger-models-1.5.13.jar
93 | tomcat-embed-core-8.5.28.jar
94 | tomcat-embed-el-8.5.28.jar
95 | tomcat-embed-websocket-8.5.28.jar
96 | validation-api-2.0.1.Final.jar
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "CodeScan/Utils"
5 | "fmt"
6 | "github.com/fatih/color"
7 | "time"
8 | )
9 |
10 | func main() {
11 | fmt.Println(`
12 |
13 |
14 | ' ██████╗ ██████╗ ██████╗ ███████╗███████╗ ██████╗ █████╗ ███╗ ██╗
15 | ' ██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔════╝██╔════╝██╔══██╗████╗ ██║
16 | ' ██║ ██║ ██║██║ ██║█████╗ ███████╗██║ ███████║██╔██╗ ██║
17 | ' ██║ ██║ ██║██║ ██║██╔══╝ ╚════██║██║ ██╔══██║██║╚██╗██║
18 | ' ╚██████╗╚██████╔╝██████╔╝███████╗███/.████║╚██████╗██║ ██║██║ ╚████║
19 | ' ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═══╝
20 | ' -- by zjacky,xiaoqiuxx
21 |
22 | `)
23 | Utils.Start()
24 | elapsed := time.Since(Utils.StartTime) // 计
25 | color.Green("[+] 扫描完成! 花费时长:%s\n", elapsed) // 算经过的时间
26 | }
27 |
--------------------------------------------------------------------------------