()
| 269 | |
| 270 | |
| 271 | def main(): |
| 272 | global THREADS |
| 273 | |
| 274 | signal.signal(signal.SIGINT, __signal_handler) |
| 275 | |
| 276 | parser = argparse.ArgumentParser(description="Find interesting Amazon S3 Buckets by watching certificate transparency logs.", |
| 277 | usage="python bucket-stream.py", |
| 278 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) |
| 279 | parser.add_argument("--only-interesting", action="store_true", dest="only_interesting", default=False, |
| 280 | help="Only log 'interesting' buckets whose contents match anything within keywords.txt") |
| 281 | parser.add_argument("--skip-lets-encrypt", action="store_true", dest="skip_lets_encrypt", default=False, |
| 282 | help="Skip certs (and thus listed domains) issued by Let's Encrypt CA") |
| 283 | parser.add_argument("-t", "--threads", metavar="", type=int, dest="threads", default=20, |
| 284 | help="Number of threads to spawn. More threads = more power. Limited to 5 threads if unauthenticated.") |
| 285 | parser.add_argument("--ignore-rate-limiting", action="store_true", dest="ignore_rate_limiting", default=False, |
| 286 | help="If you ignore rate limits not all buckets will be checked") |
| 287 | parser.add_argument("-l", "--log", dest="log_to_file", default=False, action="store_true", |
| 288 | help="Log found buckets to a file buckets.log") |
| 289 | parser.add_argument("-s", "--source", dest="source", default=None, |
| 290 | help="Data source to check for bucket permutations. Uses certificate transparency logs if not specified.") |
| 291 | parser.add_argument("-p", "--permutations", dest="permutations", default="permutations/default.txt", |
| 292 | help="Path of file containing a list of permutations to try (see permutations/ dir).") |
| 293 | |
| 294 | parser.parse_args(namespace=ARGS) |
| 295 | logging.disable(logging.WARNING) |
| 296 | |
| 297 | if not CONFIG["aws_access_key"] or not CONFIG["aws_secret"]: |
| 298 | cprint("It is highly recommended to enter AWS keys in config.yaml otherwise you will be severely rate limited!"\ |
| 299 | "You might want to run with --ignore-rate-limiting", "red") |
| 300 | |
| 301 | if ARGS.threads > 5: |
| 302 | cprint("No AWS keys, reducing threads to 5 to help with rate limiting.", "red") |
| 303 | ARGS.threads = 5 |
| 304 | |
| 305 | THREADS = list() |
| 306 | |
| 307 | cprint("Starting bucket-stream with {0} threads. Loaded {1} permutations."\ |
| 308 | .format(ARGS.threads, len([x for x in get_permutations("")])), "green") |
| 309 | |
| 310 | q = BucketQueue(maxsize=QUEUE_SIZE) |
| 311 | THREADS.extend([BucketWorker(q) for _ in range(0, ARGS.threads)]) |
| 312 | THREADS.extend([UpdateThread(q)]) |
| 313 | |
| 314 | if ARGS.source is None: |
| 315 | THREADS.extend([CertStreamThread(q)]) |
| 316 | else: |
| 317 | for line in open(ARGS.source): |
| 318 | for permutation in get_permutations(line.strip()): |
| 319 | q.put(BUCKET_HOST % permutation) |
| 320 | |
| 321 | for t in THREADS: |
| 322 | t.daemon = True |
| 323 | t.start() |
| 324 | |
| 325 | while True: |
| 326 | try: |
| 327 | signal.pause() |
| 328 | except AttributeError: |
no test coverage detected