├── .gitignore ├── .vscode └── launch.json ├── README.md ├── final.txt ├── firecheck ├── gf.txt └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch", 9 | "type": "go", 10 | "request": "launch", 11 | "mode": "auto", 12 | "program": "${file}", 13 | "env": {}, 14 | "args": ["-u", "testdb-1ec09.firebaseio.com", "-w", "1"] 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # firecheck 2 | 3 | A tool written in go to check permissions (R W D) on firebase instances. 4 | 5 | ## Installing 6 | 7 | Requires [Go](https://golang.org/dl/) 8 | 9 | `go get -u github.com/bp0lr/firecheck` 10 | 11 | ## How To Use: 12 | 13 | Examples: 14 | - `firecheck -u "https://testdb-1ec08.firebaseio.com"` 15 | - `firecheck -u "https://testdb-1ec08.firebaseio.com" -H "foo: bar" -o result.txt -s` 16 | - `cat urls.txt | firecheck -o result.txt -s` 17 | 18 | Options: 19 | ``` 20 | -H, --header stringArray Add custom Headers to the request 21 | -o, --output string Output file to save the results to 22 | -p, --proxy string Add a HTTP proxy 23 | -r, --random-agent Set a random User Agent 24 | -s, --simple Display only the url without R W D 25 | -u, --url string The firebase url to test 26 | -m, --user string Add your username for write POC 27 | -v, --verbose Display extra info about what is going on 28 | -w, --workers int Workers amount (default 50) 29 | ``` 30 | 31 | ## Practical Use 32 | 33 | Try this tool in conbination with others for max results. 34 | 35 | one line example: 36 | - getJS (https://github.com/003random/getJS) 37 | - fget (https://github.com/bp0lr/fget) 38 | - gf (https://github.com/tomnomnom/gf) 39 | - js-beautify (npm js-beautify) 40 | - httpx (https://github.com/projectdiscovery/httpx) 41 | 42 | ```cat urls.txt | getJS --complete --resolve | fget -w 50 -r -f -o . && find results/ -iname '*.js' -exec bash -c "js-beautify --quiet -o {}.ok.js {} > /dev/null 2>&1" \; && find results/ -type f -name "*.js" \! -name "*.ok.js" -exec rm -f {} \; && for D in `find results/ -type d`; do for file in `find ${D} -type f`; do gf firebase_secrets ${file} | awk -F: '{print $3}' >> gf.txt; done; done && cat gf.txt | httpx -silent | firecheck -v -o firebase.txt``` 43 | -------------------------------------------------------------------------------- /final.txt: -------------------------------------------------------------------------------- 1 | https://readthestore-staging.appspot.com 2 | https://readthestore-staging.appspot.com 3 | https://cdpc-staging.appspot.com 4 | https://wholesalerp4p-staging.appspot.com 5 | https://rbpipe-staging.appspot.com 6 | https://valuecreator-staging.appspot.com 7 | https://wholesalerp4p-staging.appspot.com 8 | https://pcapp-staging.appspot.com 9 | https://rbpipe-staging.appspot.com 10 | https://valuecreator-staging.appspot.com 11 | https://pcapp-staging.appspot.com 12 | https://cdpc-staging.appspot.com 13 | https://coachinginfocus-staging.appspot.com 14 | https://wholesalerp4p-staging.firebaseapp.com 15 | https://wholesalerp4p-staging.firebaseapp.com 16 | https://pcapp-staging.firebaseapp.com 17 | https://pcapp-staging.firebaseapp.com 18 | https://coachinginfocus-staging.appspot.com 19 | https://valuecreator-staging.firebaseapp.com 20 | https://valuecreator-staging.firebaseapp.com 21 | https://rbpipe-staging.firebaseapp.com 22 | https://rbpipe-staging.firebaseapp.com 23 | https://cdpc-staging.firebaseapp.com 24 | https://cdpc-staging.firebaseapp.com 25 | https://coachinginfocus-staging.firebaseapp.com 26 | https://coachinginfocus-staging.firebaseapp.com 27 | https://readthestore-staging.firebaseapp.com 28 | https://readthestore-staging.firebaseapp.com 29 | https://valuecreator-staging.firebaseio.com 30 | https://valuecreator-staging.firebaseio.com 31 | https://rbpipe-staging.firebaseio.com 32 | https://rbpipe-staging.firebaseio.com 33 | https://pcapp-staging.firebaseio.com 34 | https://pcapp-staging.firebaseio.com 35 | https://cdpc-staging.firebaseio.com 36 | https://readthestore-staging.firebaseio.com 37 | https://pcapp-staging.firebaseio.com 38 | https://pcapp-staging.firebaseio.com 39 | https://cdpc-staging.firebaseio.com 40 | https://cdpc-staging.firebaseio.com 41 | https://coachinginfocus-staging.firebaseio.com 42 | https://readthestore-staging.firebaseio.com 43 | https://cdpc-staging.firebaseio.com 44 | https://readthestore-staging.firebaseio.com 45 | https://pcapp-staging.firebaseio.com 46 | https://readthestore-staging.firebaseio.com 47 | https://wholesalerp4p-staging.firebaseio.com 48 | https://wholesalerp4p-staging.firebaseio.com 49 | https://pcapp-staging.firebaseio.com 50 | https://wholesalerp4p-staging.firebaseio.com 51 | https://wholesalerp4p-staging.firebaseio.com 52 | https://coachinginfocus-staging.firebaseio.com 53 | -------------------------------------------------------------------------------- /firecheck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bp0lr/firecheck/7f449e0cb96b8f752c54fd6f819e93837328823a/firecheck -------------------------------------------------------------------------------- /gf.txt: -------------------------------------------------------------------------------- 1 | pcapp-staging.firebaseio.com 2 | pcapp-staging.firebaseio.com 3 | cdpc-staging.firebaseio.com 4 | readthestore-staging.firebaseio.com 5 | wholesalerp4p-staging.firebaseio.com 6 | pcapp-staging.firebaseapp.com 7 | pcapp-staging.firebaseio.com 8 | pcapp-staging.appspot.com 9 | rbpipe-staging.firebaseapp.com 10 | rbpipe-staging.firebaseio.com 11 | rbpipe-staging.appspot.com 12 | cdpc-staging.firebaseapp.com 13 | cdpc-staging.firebaseio.com 14 | cdpc-staging.appspot.com 15 | readthestore-staging.firebaseapp.com 16 | readthestore-staging.firebaseio.com 17 | readthestore-staging.appspot.com 18 | wholesalerp4p-staging.firebaseapp.com 19 | wholesalerp4p-staging.firebaseio.com 20 | wholesalerp4p-staging.appspot.com 21 | valuecreator-staging.firebaseapp.com 22 | valuecreator-staging.firebaseio.com 23 | valuecreator-staging.appspot.com 24 | coachinginfocus-staging.firebaseapp.com 25 | coachinginfocus-staging.firebaseio.com 26 | coachinginfocus-staging.appspot.com 27 | pcapp-staging.firebaseio.com 28 | pcapp-staging.firebaseio.com 29 | cdpc-staging.firebaseio.com 30 | readthestore-staging.firebaseio.com 31 | wholesalerp4p-staging.firebaseio.com 32 | pcapp-staging.firebaseapp.com 33 | pcapp-staging.firebaseio.com 34 | pcapp-staging.appspot.com 35 | rbpipe-staging.firebaseapp.com 36 | rbpipe-staging.firebaseio.com 37 | rbpipe-staging.appspot.com 38 | cdpc-staging.firebaseapp.com 39 | cdpc-staging.firebaseio.com 40 | cdpc-staging.appspot.com 41 | readthestore-staging.firebaseapp.com 42 | readthestore-staging.firebaseio.com 43 | readthestore-staging.appspot.com 44 | wholesalerp4p-staging.firebaseapp.com 45 | wholesalerp4p-staging.firebaseio.com 46 | wholesalerp4p-staging.appspot.com 47 | valuecreator-staging.firebaseapp.com 48 | valuecreator-staging.firebaseio.com 49 | valuecreator-staging.appspot.com 50 | coachinginfocus-staging.firebaseapp.com 51 | coachinginfocus-staging.firebaseio.com 52 | coachinginfocus-staging.appspot.com 53 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // 2 | // @bp0lr - 11/11/2020 3 | // 4 | 5 | package main 6 | 7 | import ( 8 | "os" 9 | "fmt" 10 | "net" 11 | "sync" 12 | "time" 13 | "bytes" 14 | "bufio" 15 | "strings" 16 | "net/url" 17 | "net/http" 18 | "math/rand" 19 | "crypto/tls" 20 | 21 | "encoding/json" 22 | 23 | flag "github.com/spf13/pflag" 24 | ) 25 | 26 | var ( 27 | workersArg int 28 | headerArg []string 29 | urlArg string 30 | userArg string 31 | proxyArg string 32 | outputFileArg string 33 | verboseArg bool 34 | useRandomAgentArg bool 35 | notFancyArg bool 36 | ) 37 | 38 | type bbTest struct { 39 | Txt string `json:"txt"` 40 | User string `json:"user"` 41 | } 42 | 43 | func main() { 44 | 45 | flag.StringArrayVarP(&headerArg, "header", "H", nil, "Add custom Headers to the request") 46 | flag.IntVarP(&workersArg, "workers", "w", 50, "Workers amount") 47 | flag.StringVarP(&urlArg, "url", "u", "", "The firebase url to test") 48 | flag.StringVarP(&userArg, "user", "m", "", "Add your username for write POC") 49 | flag.BoolVarP(&verboseArg, "verbose", "v", false, "Display extra info about what is going on") 50 | flag.StringVarP(&proxyArg, "proxy", "p", "", "Add a HTTP proxy") 51 | flag.BoolVarP(&useRandomAgentArg, "random-agent", "r", false, "Set a random User Agent") 52 | flag.StringVarP(&outputFileArg, "output", "o", "", "Output file to save the results to") 53 | flag.BoolVarP(¬FancyArg, "simple", "s", false, "Display only the url without R W D") 54 | 55 | flag.Parse() 56 | 57 | //concurrency 58 | workers := 50 59 | if workersArg > 0 && workersArg < 100 { 60 | workers = workersArg 61 | } 62 | 63 | client := newClient(proxyArg) 64 | 65 | jobs := make(chan string) 66 | var wg sync.WaitGroup 67 | 68 | var outputFile *os.File 69 | var err0 error 70 | if outputFileArg != "" { 71 | outputFile, err0 = os.OpenFile(outputFileArg, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644) 72 | if err0 != nil { 73 | fmt.Printf("cannot write %s: %s", outputFileArg, err0.Error()) 74 | return 75 | } 76 | 77 | defer outputFile.Close() 78 | } 79 | 80 | for i := 0; i < workers; i++ { 81 | wg.Add(1) 82 | go func() { 83 | for raw := range jobs { 84 | 85 | u, err := url.ParseRequestURI(raw) 86 | if err != nil { 87 | if verboseArg { 88 | fmt.Printf("[-] Invalid url: %s\n", raw) 89 | } 90 | continue 91 | } 92 | 93 | processRequest(u, client, outputFile) 94 | 95 | } 96 | wg.Done() 97 | }() 98 | } 99 | 100 | if len(urlArg) < 1 { 101 | sc := bufio.NewScanner(os.Stdin) 102 | for sc.Scan() { 103 | jobs <- sc.Text() 104 | } 105 | } else { 106 | jobs <- urlArg 107 | } 108 | 109 | close(jobs) 110 | wg.Wait() 111 | } 112 | 113 | func processRequest(u *url.URL, client *http.Client, outputFile *os.File) { 114 | 115 | if verboseArg { 116 | fmt.Printf("[+] Testing: %v\n", u.String()) 117 | } 118 | 119 | //check read 120 | ///////////////////////////////////////////////////////////////////////// 121 | read, resp, err :=check("R", u, client) 122 | write, _, _ :=check("W", u, client) 123 | delete, _, _ :=check("D", u, client) 124 | 125 | if(read || write || delete){ 126 | if(notFancyArg){ 127 | fmt.Printf("%v\n", u.String()) 128 | } else { 129 | str:= "[+] " + u.String() + " => " 130 | if(read){ 131 | str+= " R " 132 | } 133 | if(write){ 134 | str+= " W " 135 | } 136 | if(delete){ 137 | str+= " D " 138 | } 139 | 140 | if outputFileArg != "" { 141 | outputFile.WriteString(u.String() + "\n") 142 | } 143 | 144 | fmt.Println(str) 145 | } 146 | } else { 147 | if(err != nil && verboseArg){ 148 | fmt.Printf("[-] Error: %v [%v]\n", err, resp) 149 | } else { 150 | if(verboseArg){ 151 | fmt.Printf("[-] %v [%v]\n", u.String(), resp) 152 | } 153 | } 154 | } 155 | } 156 | 157 | func newClient(proxy string) *http.Client { 158 | tr := &http.Transport{ 159 | MaxIdleConns: 30, 160 | IdleConnTimeout: time.Second, 161 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 162 | DialContext: (&net.Dialer{ 163 | Timeout: time.Second * 10, 164 | }).DialContext, 165 | } 166 | 167 | if proxy != "" { 168 | if p, err := url.Parse(proxy); err == nil { 169 | tr.Proxy = http.ProxyURL(p) 170 | } 171 | } 172 | 173 | client := &http.Client{ 174 | Transport: tr, 175 | Timeout: time.Second * 5, 176 | } 177 | 178 | client.CheckRedirect = func(req *http.Request, via []*http.Request) error { 179 | return http.ErrUseLastResponse 180 | } 181 | 182 | return client 183 | } 184 | 185 | func getUserAgent() string { 186 | payload := []string{ 187 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", 188 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36", 189 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0", 190 | "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36", 191 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Safari/605.1.15", 192 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36", 193 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0", 194 | "Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4", 195 | "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko", 196 | "Mozilla/5.0 (iPad; CPU OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53", 197 | "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)", 198 | } 199 | 200 | rand.Seed(time.Now().UnixNano()) 201 | randomIndex := rand.Intn(len(payload)) 202 | 203 | pick := payload[randomIndex] 204 | 205 | return pick 206 | } 207 | 208 | //CheckRead desc 209 | func check(checkType string, u *url.URL, client *http.Client) (bool, int, error){ 210 | 211 | var url string 212 | var req *http.Request 213 | var err error 214 | 215 | // Read 216 | if(checkType == "R"){ 217 | url = u.Scheme + "://" + u.Host + "/.json" 218 | req, err = http.NewRequest("GET", url, nil) 219 | } 220 | 221 | // Write 222 | if(checkType == "W"){ 223 | url = u.Scheme + "://" + u.Host + "/BountyTest.json" 224 | 225 | bb := bbTest{Txt: "Bounty test" } 226 | if(len(userArg) > 0){ 227 | bb.User = userArg 228 | } else { 229 | bb.User = "firecheck" 230 | } 231 | 232 | j, _:=json.Marshal(bb) 233 | 234 | req, err = http.NewRequest("PUT", url, bytes.NewBuffer(j)) 235 | } 236 | 237 | // Delete 238 | if(checkType == "D"){ 239 | url = u.Scheme + "://" + u.Host + "/BountyTest.json" 240 | req, err = http.NewRequest("DELETE", url, nil) 241 | } 242 | 243 | if err != nil { 244 | if verboseArg { 245 | fmt.Printf("[-] Error: %v\n", err) 246 | } 247 | return false, 0, err 248 | } 249 | 250 | if useRandomAgentArg { 251 | req.Header.Set("User-Agent", getUserAgent()) 252 | } else { 253 | req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; firecheck/1.0)") 254 | } 255 | 256 | // add headers to the request 257 | for _, h := range headerArg { 258 | parts := strings.SplitN(h, ":", 2) 259 | 260 | if len(parts) != 2 { 261 | continue 262 | } 263 | req.Header.Set(parts[0], parts[1]) 264 | } 265 | 266 | // send the request 267 | resp, err := client.Do(req) 268 | 269 | if err != nil { 270 | if verboseArg { 271 | fmt.Printf("[-] Error: %v\n", err) 272 | } 273 | return false, 0, err 274 | } 275 | 276 | defer resp.Body.Close() 277 | 278 | if(resp.StatusCode == 200){ 279 | return true, 200, nil 280 | } 281 | 282 | return false, resp.StatusCode, nil 283 | } --------------------------------------------------------------------------------