testAnonymousAccess 测试FTP匿名访问
(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State)
| 171 | |
| 172 | // testAnonymousAccess 测试FTP匿名访问 |
| 173 | func (p *FTPPlugin) testAnonymousAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { |
| 174 | target := info.Target() |
| 175 | |
| 176 | anonymousCreds := []Credential{ |
| 177 | {Username: "anonymous", Password: "anonymous"}, |
| 178 | {Username: "anonymous", Password: ""}, |
| 179 | {Username: "ftp", Password: "ftp"}, |
| 180 | } |
| 181 | |
| 182 | for _, cred := range anonymousCreds { |
| 183 | select { |
| 184 | case <-ctx.Done(): |
| 185 | return nil |
| 186 | default: |
| 187 | } |
| 188 | |
| 189 | result := p.doFTPAuth(ctx, info, cred, config, state) |
| 190 | if result.Success && result.Conn != nil { |
| 191 | // 获取文件列表 |
| 192 | ftpConn, ok := result.Conn.(*ftpConnWrapper) |
| 193 | if !ok { |
| 194 | _ = result.Conn.Close() |
| 195 | return nil |
| 196 | } |
| 197 | fileList := p.listFTPFiles(ftpConn.ServerConn) |
| 198 | _ = result.Conn.Close() |
| 199 | |
| 200 | var output strings.Builder |
| 201 | output.WriteString(fmt.Sprintf("FTP %s 匿名访问 - %s:%s", target, cred.Username, cred.Password)) |
| 202 | if len(fileList) > 0 { |
| 203 | for _, file := range fileList { |
| 204 | output.WriteString(fmt.Sprintf("\n [->] %s", file)) |
| 205 | } |
| 206 | } |
| 207 | common.LogVuln(output.String()) |
| 208 | |
| 209 | return &ScanResult{ |
| 210 | Type: plugins.ResultTypeCredential, |
| 211 | Success: true, |
| 212 | Service: "ftp", |
| 213 | Username: cred.Username, |
| 214 | Password: cred.Password, |
| 215 | Banner: "FTP匿名访问", |
| 216 | } |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | return nil |
| 221 | } |
| 222 | |
| 223 | // getFileListAfterAuth 认证成功后获取文件列表 |
| 224 | func (p *FTPPlugin) getFileListAfterAuth(info *common.HostInfo, username, password string, config *common.Config, state *common.State) []string { |