RapiDAST provides a framework for continuous, proactive and fully automated dynamic scanning against web apps/API.

Overview

RapiDAST

RapiDAST provides a framework for continuous, proactive and fully automated dynamic scanning against web apps/API.

Its core engine is OWASP ZAP Proxy (https://owasp.org/www-project-zap/). Taking advantage of the ZAP container, this project provides value as follows:

  • Easy automation(via fully working in CLI with yaml configuration) of API scanning based on OAS definition
  • Create users' own custom rules via yaml files
  • XML, HTML, JSON report generation

Prerequisites

podman or docker is required.

For podman

$ pip3 install podman-compose
$ podman pull docker.io/owasp/zap2docker-stable

Quick Scan Example(using podman)

  1. Get a URL for the OAS3 definition file
  2. Get a URL for the target API
  3. Create config.yaml with the URLs and place it in config/
  4. zaproxy container must be running (either runenv.sh or runenv-debug.sh)
$ ./runenv.sh

Run in the project root directory,

$ test/scan-example-with-podman.sh 
   

   

When a scan is completed, its report will be generated in the results/

Example

$ test/scan-example-with-podman.sh testrun                
Deleting previously generated scripts                                              
Loading the script to ZAP                                                          
Templating script Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d2                    
Loading script Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d2 in ZAP from /tmp/Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d25k5s0yj7.js                                 
Enabling script Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d2 in ZAP               
Script Rule_Gen_05eec230-5ba0-4bf5-b1d0-43268b8542d2 successfully loaded and enabled                                                                                   
Creating session in: /zap/results/testrun/sessions/20211210-041924/session1          
Excluded URLs: ^(?:(?!http://192.168.109.202:9000).*).$                               
Include URL in context: http://192.168.109.202:9000/api/.*                            
Exclude URL from context:                                                          
Importing API: /zap/config/oas/openapi.json                                        
>> Target Url: http://192.168.109.202:9000                                            
Start Active scan. Scan ID equals 0                                                
Scan Policies: ['API-minimal-example']                                             
Active Scan progress: 0%                                                           
Active Scan completed                                                                                                                                                  
Waiting for Passive Scan to complete                                                                                                                                   
Passive Scan completed                                                             
XML report saved in: /zap/results/testrun/demo1-report-20211210-041924.xml

$ ls -al results/testrun
total 48
-rw-r--r--. 1 fedora fedora 9198 Dec 13 08:11 demo1-report-20211210-041924.xml
drwxr-xr-x. 7 fedora fedora  140 Dec 13 08:11 sessions

Usage

podman

Run as daemon

Run a container

$ podman-compose -f podman-compose.yml up 
$ podman unshare chown 1000 ./results (podman bind volumes as container root while the app runs as container zap user)

Launch a scan

$ podman exec zaproxy python /zap/scripts/apis_scan.py 
   

   

Stopping Environments

$ podman-compose -f podman-compose.yml down

Run with GUI (useful for debugging)

This is taking advantage of ZAP's webswing feature. See https://www.zaproxy.org/docs/docker/webswing/.

Run a container

$ podman-compose -f podman-compose-ui.yml up 
$ podman unshare chown 1000 ./results (podman bind volumes as container root while the app runs as container zap user)

After the step, it is necessary to navigate to the GUI via http://127.0.0.1:8081/zap to start an actual ZAP instance.

Create a custom rule

It is possible to create a custom rule yaml file and apply to the ZAP instance. Refer to a few examples of the yaml rule files in the scripts/gen-zap-script/rules directory.

Apply custom rules to the running ZAP instance before launching a scan.

Example: Load and enable custom rule
$ podman exec zaproxy python scripts/gen-zap-script/cli.py --from-yaml scripts/gen-zap-script/rules/software_version_revealed.yaml --api-key=
   
     --load-and-enable 

   
Example: Delete existing custom rules
$ podman exec zaproxy python scripts/gen-zap-script/cli.py --api-key=
   
     --delete

   

Launch a scan

$ podman exec zaproxy python /zap/scripts/apis_scan.py 
   

   

Stopping Environments

$ podman-compose -f podman-compose-ui.yml down

docker

Run as daemon

Run a container

$ docker-compose up zaproxy 

Launch a scan

$ docker-compose exec zaproxy python /zap/scripts/apis_scan.py 
   

   

Stopping Environments

$ docker-compose down

Run with GUI (useful for debugging)

This is taking advantage of ZAP's webswing feature. See https://www.zaproxy.org/docs/docker/webswing/.

Run a container

$ docker-compose up zaproxy_ui

After the step, it is necessary to navigate to the GUI via http://127.0.0.1:8081/zap to start an actual ZAP instance.

Launch a scan

$ docker-compose exec zaproxy_ui python /zap/scripts/apis_scan.py 
   

   

Stopping Environments

$ docker-compose down
Comments
  • Add operator option to be used for deploying to Kubernetes/OCP environments

    Add operator option to be used for deploying to Kubernetes/OCP environments

    Adds helm operator that provides a controller that handles

    • RapiDAST - main CRD that manages running RapiDAST as a job on the cluster
    • ~~RapiDASTCC - provides PVC that is used by RapiDAST for persistence, along with a pod using the PVC for simple copying of artifacts produced by the jobs~~

    This operator code has been refactored to account for API_KEY option now as an environment variable. In the RapiDAST CRD, the boolean option for apiKeyRequired can be set to true. As implemented, this will create a secret, and the api key will have to be updated there manually.

    Feedback welcome.

    • Edit - Moved beyond needing the RapiDASTCC API. PVC now created as needed when creating RapiDASTs.
    opened by jpweiser 7
  • Unable to run zaproxy on mac m1 using docker and podman both.

    Unable to run zaproxy on mac m1 using docker and podman both.

    Hi,

    I got a Mac M1 recently and I am trying to run the zaproxy tests against a config by placing the open api url and target url as expected in the config/config.yml and then following steps below but getting the below error.

    Any help would be appreciated, thanks.

    rapidast (master %) $ docker-compose up zaproxy
    [+] Running 1/0
     ⠿ Container zaproxy  Created                                                                                                                                                                                                                                              0.1s
    Attaching to zaproxy
    
    

    Trying to run the scan as per the README file:

    $ docker-compose exec zaproxy python /zap/scripts/apis_scan.py reports                                                                                                                                        1
    Traceback (most recent call last):
      File "/usr/local/lib/python3.8/dist-packages/urllib3/connection.py", line 174, in _new_conn
        conn = connection.create_connection(
      File "/usr/local/lib/python3.8/dist-packages/urllib3/util/connection.py", line 95, in create_connection
        raise err
      File "/usr/local/lib/python3.8/dist-packages/urllib3/util/connection.py", line 85, in create_connection
        sock.connect(sa)
    ConnectionRefusedError: [Errno 111] Connection refused
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/usr/local/lib/python3.8/dist-packages/urllib3/connectionpool.py", line 703, in urlopen
        httplib_response = self._make_request(
      File "/usr/local/lib/python3.8/dist-packages/urllib3/connectionpool.py", line 398, in _make_request
        conn.request(method, url, **httplib_request_kw)
      File "/usr/local/lib/python3.8/dist-packages/urllib3/connection.py", line 239, in request
        super(HTTPConnection, self).request(method, url, body=body, headers=headers)
      File "/usr/lib/python3.8/http/client.py", line 1256, in request
        self._send_request(method, url, body, headers, encode_chunked)
      File "/usr/lib/python3.8/http/client.py", line 1302, in _send_request
        self.endheaders(body, encode_chunked=encode_chunked)
      File "/usr/lib/python3.8/http/client.py", line 1251, in endheaders
        self._send_output(message_body, encode_chunked=encode_chunked)
      File "/usr/lib/python3.8/http/client.py", line 1011, in _send_output
        self.send(msg)
      File "/usr/lib/python3.8/http/client.py", line 951, in send
        self.connect()
      File "/usr/local/lib/python3.8/dist-packages/urllib3/connection.py", line 205, in connect
        conn = self._new_conn()
      File "/usr/local/lib/python3.8/dist-packages/urllib3/connection.py", line 186, in _new_conn
        raise NewConnectionError(
    urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x4002245400>: Failed to establish a new connection: [Errno 111] Connection refused
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/usr/local/lib/python3.8/dist-packages/requests/adapters.py", line 440, in send
        resp = conn.urlopen(
      File "/usr/local/lib/python3.8/dist-packages/urllib3/connectionpool.py", line 785, in urlopen
        retries = retries.increment(
      File "/usr/local/lib/python3.8/dist-packages/urllib3/util/retry.py", line 592, in increment
        raise MaxRetryError(_pool, url, error or ResponseError(cause))
    urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8090): Max retries exceeded with url: http://zap/JSON/core/action/newSession/?apikey=cnmeemn7jp7ijd8rl5u14q40v8&name=%2Fzap%2Fresults%2Freports%2Fsessions%2F20220419-170600%2Fsession1&overwrite=True (Caused by ProxyError('Cannot connect to proxy.', NewConnectionError('<urllib3.connection.HTTPConnection object at 0x4002245400>: Failed to establish a new connection: [Errno 111] Connection refused')))
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/zap/scripts/apis_scan.py", line 313, in <module>
        create_session(session_fullpath_name)
      File "/zap/scripts/apis_scan.py", line 17, in create_session
        zap.core.new_session(name=session_name, overwrite=True)
      File "/usr/local/lib/python3.8/dist-packages/zapv2/core.py", line 357, in new_session
        return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/newSession/', params)))
      File "/usr/local/lib/python3.8/dist-packages/zapv2/__init__.py", line 200, in _request
        data = self._request_api(url, get)
      File "/usr/local/lib/python3.8/dist-packages/zapv2/__init__.py", line 180, in _request_api
        response = self.session.get(url, params=query, proxies=self.__proxies, verify=False)
      File "/usr/local/lib/python3.8/dist-packages/requests/sessions.py", line 542, in get
        return self.request('GET', url, **kwargs)
      File "/usr/local/lib/python3.8/dist-packages/requests/sessions.py", line 529, in request
        resp = self.send(prep, **send_kwargs)
      File "/usr/local/lib/python3.8/dist-packages/requests/sessions.py", line 645, in send
        r = adapter.send(request, **kwargs)
      File "/usr/local/lib/python3.8/dist-packages/requests/adapters.py", line 513, in send
        raise ProxyError(e, request=request)
    requests.exceptions.ProxyError: HTTPConnectionPool(host='127.0.0.1', port=8090): Max retries exceeded with url: http://zap/JSON/core/action/newSession/?apikey=cnmeemn7jp7ijd8rl5u14q40v8&name=%2Fzap%2Fresults%2Freports%2Fsessions%2F20220419-170600%2Fsession1&overwrite=True (Caused by ProxyError('Cannot connect to proxy.', NewConnectionError('<urllib3.connection.HTTPConnection object at 0x4002245400>: Failed to establish a new connection: [Errno 111] Connection refused')))
    
    opened by anarang 6
  • URL Scanning Ability.

    URL Scanning Ability.

    Adding the ability to scan from URLs specified in a URL Scan config file that does not have an OAS definition. Note that the reason the importurls method has been added here is because the zap python API project currently does not support exim (the new ZAP addon for importing urls) and only makes use of the deprecated importurls addon. I've added support for exim imports instead in the new method.

    opened by rh-gtucker 4
  • Podman compose results user owned

    Podman compose results user owned

    Podman 3.1.0 and above support the "U" flag to change ownership of
    volumes.
    This makes the `unshare chown` unecessary when using podman >= 3.1
    IIUC, it does not affect older versions, which will simply ignore the
    unknown flag.
    
    opened by cedricbu 4
  • compose files clean up and API_KEY removal

    compose files clean up and API_KEY removal

    List of changes:

    • API_KEY was removed from config.yaml and moved to an env file
    • entrypoint.sh and entrypoint_ui.sh files created
    • config/requirements.txt was created
    • tty: true and stdin_open: true removed from compose files as they have no effect
    opened by lpardoRH 3
  • Actions

    Actions

    based on https://github.com/RedHatProductSecurity/rapidast/pull/14 so changes should be more easy to see once that PR is merged.

    Added rapidast-scan action as example

    opened by lpardoRH 2
  • Introducing a new podman wrapper

    Introducing a new podman wrapper

    The main reason for the wrapper is to avoid the need to run unshare, by formatting a defined user mapping, such that the zap user maps the host user. This way ZAP can write in the ./results share without needing to change ownership.

    source: https://github.com/containers/podman/blob/main/troubleshooting.md#39-podman-run-fails-with-error-unrecognized-namespace-mode-keep-iduid1000gid1000-passed In very recent podman version, this hack can be simplified.

    This change is backward compatible : nothing prevents the user to use any old methods for starting RapiDAST.

    Note: Unlike runenv.sh, this script does not attempt to stop the container in case it is already running. The reasoning is : if RapiDAST is currently undergoing a looooong scan, a user probably prefers the new command to fail, rather than cancelling the current scan. However, we could improve that.

    Other minor changes: In README.md:

    • removed the reference to [podman|docker] pull, as it refers to a different image, and afaik, will be done by the compose command
    • updated with the new command, removed references to unshare
    • few minor readability/consistency update

    In runenv.sh / runenv-ui.sh: echo "deprecated" message

    opened by cedricbu 1
  • Adding docker compose files and parameterized token authentication script

    Adding docker compose files and parameterized token authentication script

    • Adding a docker version for starting the zaproxy tool
    • Adding a parameterized http authentication script to be able to pass the parameters from the config where it wont be pushed to any repo accidentally

    For openshift console runs:

    HttpSenderScriptFilePath: 'scripts/add-token-cookie-param.js'
    HttpSenderScriptDescription: 'add a cookie to each HTTP request'
    HTTPParams: {"cookieName": 'openshift-session-token', "cookieVal": 'sha256~**'}
    
    opened by paigerube14 1
  • Applied pre-commit config to the existing changes

    Applied pre-commit config to the existing changes

    Some code was changed manually. So it needs some testing before merging. Please, review changes in python files carefully.

    During my work on the pre-commit fixes I found that some checks are not so convenient to use or they edit files which they shouldn't touch. Thus the pre-commit config was updated.

    The pydocstyle checks are still missing here:

    scripts/config.py:1 at module level:
            D100: Missing docstring in public module
    scripts/gen_zap_script/lib.py:1 at module level:
            D100: Missing docstring in public module
    scripts/gen_zap_script/lib.py:30 in private class `Script`:
            D205: 1 blank line required between summary line and description (found 0)
    scripts/gen_zap_script/lib.py:30 in private class `Script`:
            D212: Multi-line docstring summary should start at the first line
    scripts/gen_zap_script/lib.py:87 in public function `add_and_load_script`:
            D103: Missing docstring in public function
    scripts/gen_zap_script/lib.py:114 in public function `delete_all_loaded_scripts`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:1 at module level:
            D100: Missing docstring in public module
    scripts/apis_scan.py:18 in public function `create_session`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:38 in public function `enable_httpsender_script`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:61 in public function `create_context`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:158 in public function `enable_passive_scanner`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:164 in public function `import_urls`:
            D205: 1 blank line required between summary line and description (found 0)
    scripts/apis_scan.py:164 in public function `import_urls`:
            D212: Multi-line docstring summary should start at the first line
    scripts/apis_scan.py:171 in public function `get_apis`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:225 in public function `check_scan_id`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:232 in public function `start_active_scanner`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:295 in public function `start_spider`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:316 in public function `wait_for_passive_scanner`:
            D103: Missing docstring in public function
    scripts/apis_scan.py:326 in public function `generate_report`:
            D103: Missing docstring in public function
    scripts/gen_zap_script/lib_usage_example.py:1 at module level:
            D100: Missing docstring in public module
    scripts/gen_zap_script/lib_usage_example.py:6 in public function `js_passive_script_example`:
            D103: Missing docstring in public function
    scripts/gen_zap_script/lib_usage_example.py:22 in public function `js_active_script_example`:
            D103: Missing docstring in public function
    scripts/gen_zap_script/cli.py:1 at module level:
            D100: Missing docstring in public module
    scripts/gen_zap_script/cli.py:57 in public function `add_finding_group`:
            D103: Missing docstring in public function
    scripts/gen_zap_script/cli.py:101 in public function `ms_check`:
            D103: Missing docstring in public function
    scripts/gen_zap_script/cli.py:163 in public function `file_lines_or_default`:
            D103: Missing docstring in public function
    

    Looking for help with it.

    UPDATE: We decided to disable the docstring check and split from this task

    opened by feuillemorte 1
  • Remove

    Remove "unshare" mode on volume mount

    The results directory should not have the "U" unshare mode. The reason is that the ./test/scan-example-with-podman.sh script intends to create a child directory in results. "U" here removes ownership from the EUID too early, and it's not the right directory to unshare anyway. We want to unshare the child. This patch reverts the addition of "U" mode on the results mount.

    opened by sparticvs 1
  • Hardcoded API Key

    Hardcoded API Key

    FYI, I just noticed that there is a hardcoded API key on this line:

    https://github.com/RedHatProductSecurity/rapidast/blob/3e477d72cd5c1fb721a7775769def4d988926e6d/entrypoint.sh#L12

    /cc @jpweiser since it was your commit, you may care.

    opened by sparticvs 1
  • WIP: Added models and query object

    WIP: Added models and query object

    Added model and a query object. It can work with config data like this:

    Config:

    general:
      serviceName: 'demo1'
      resultDir: '/results/'
      # appDir: '/zap'
      localProxy: 
        http: "http://127.0.0.1:8090"
    

    The query:

    >>> config = Config(config_file=args.rapidast_config)
    >>> config.q.general.localProxy.http.value
    'http://127.0.0.1:8090'
    

    Also it supports another way to call it:

    >>> config.q["general"]["localProxy"]["http"].value
    'http://127.0.0.1:8090'
    

    (Please, see tests for additional examples)

    If there is no a key in the config, the chain won't fail with a python error, it will return None instead.

    >>> config.q.general.WRONG_KEY.localProxy.http.value
    None
    

    It will save us from ugly chains like:

    config.get("general", {}).get("localProxy", {}).get("http")
    

    and it will safe us from unexpected python errors if a key is not presented in the config file

    P.S. the PR is in progress, it needs additional work before final review

    opened by feuillemorte 4
Releases(v1.1.0)
  • v1.1.0(Jul 29, 2022)

    • RapiDAST can run as an operator on Kubernetes or OpenShift
    • added Containerfile for building an RapiDAST image
    • support URL based scanning
    • support scriptBased Authentication
    • added pre-commit config
    • added a Github Actions workflow example
    • issues have been fixed (see the commit logs for more information)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Dec 21, 2021)

    RapiDAST v1.0.0 includes:

    • OpenAPI based scanning using OWASP ZAP with sample configuration and script files
    • OAUTH2 offline token handling for Script-based Authentication
    • Custom scanning rule generation
    • Support both docker and podman
    • Scanning report generation
    Source code(tar.gz)
    Source code(zip)
Owner
Red Hat Product Security
Red Hat Product Security
Red Hat Product Security
Python Library For Ethical Hacker

Python Library For Ethical Hacker

11 Nov 03, 2022
Complet and easy to run Port Scanner with Python

Port_Scanner Complet and easy to run Port Scanner with Python Installation 1- git clone https://github.com/s120000/Port_Scanner 2- cd Port_Scanner 3-

1 May 19, 2022
Automatically fetch, measure, and merge subscription links on the network, use Github Action

Free Node Merge Introduction Modified from alanbobs999/TopFreeProxies It measures the speed of free nodes on the network and import the stable and hig

52 Jul 16, 2022
S2-061 的payload,以及对应简单的PoC/Exp

S2-061 脚本皆根据vulhub的struts2-059/061漏洞测试环境来写的,不具普遍性,还望大佬多多指教 struts2-061-poc.py(可执行简单系统命令) 用法:python struts2-061-poc.py http://ip:port command 例子:python

dreamer 46 Oct 20, 2022
This is the fuzzer I made to fuzz Preview on macOS and iOS like 8years back when I just started fuzzing things.

Fuzzing PDFs like its 1990s This is the fuzzer I made to fuzz Preview on macOS and iOS like 8years back when I just started fuzzing things. Some discl

Chaithu 14 Sep 30, 2022
Python HDFS client

Python HDFS client Because the world needs yet another way to talk to HDFS from Python. Usage This library provides a Python client for WebHDFS. NameN

Jing Wang 82 Dec 28, 2022
Agile Threat Modeling Toolkit

Threagile is an open-source toolkit for agile threat modeling:

Threagile 425 Jan 07, 2023
Universal Radio Hacker: Investigate Wireless Protocols Like A Boss

The Universal Radio Hacker (URH) is a complete suite for wireless protocol investigation with native support for many common Software Defined Radios.

Dr. Johannes Pohl 9k Jan 03, 2023
Web Scraping com Python - Raspando Vagas para Programadores

Web Scraping com Python - Raspando Vagas para Programadores Sobre o Projeto Web

Kayo Libarino 3 Dec 30, 2021
vulnerable APIs

vulnerable-apis vulnerable APIs inspired by https://github.com/mattvaldes/vulnerable-api Setup Docker If, Out of the box docker pull kmmanoj/vulnerabl

9 Jun 01, 2022
Advanced subdomain scanner, any domain hidden subdomains

little advanced subdomain scanner made in python, works very quick and has options to change the port u want it to connect for

Nano 5 Nov 23, 2021
Better-rtti-parser - IDA script to parse RTTI information in executable

RTTI parser Parses RTTI information from executable. Example HexRays decompiler view Before: After: Functions window Before: After: Structs window Ins

101 Jan 04, 2023
XSS scanner in python

DeadXSS XSS scanner in python How to Download: Step 1: git clone https://github.com/Deadeye0x/DeadXSS.git Step 2: cd DeadXSS Step 3: python3 DeadXSS.p

2 Jul 17, 2022
HashDB API hash lookup plugin for IDA Pro

HashDB IDA Plugin Malware string hash lookup plugin for IDA Pro. This plugin connects to the OALABS HashDB Lookup Service. Adding New Hash Algorithms

OALabs 237 Dec 21, 2022
CVE-2022-21907 Vulnerability PoC

CVE-2022-21907 Description POC for CVE-2022-21907: HTTP Protocol Stack Remote Code Execution Vulnerability. create by antx at 2022-01-17, just some sm

Michele 16 Dec 18, 2022
宝塔面板Windows版提权方法

宝塔面板Windows提权方法 本项目整理一些宝塔特性,可以在无漏洞的情况下利用这些特性来增加提权的机会。

298 Dec 14, 2022
It is a very simple XSS simulator based on flask, python.

It is a very simple XSS simulator based on flask, python. The purpose of making this is for teaching the concept of XSS.

Satin Wuker 3 May 10, 2022
A python script to turn Ubuntu Desktop in a one stop security platform. The InfoSec Fortress installs the packages,tools, and resources to make Ubuntu 20.04 capable of both offensive and defensive security work.

infosec-fortress A python script to turn Ubuntu Desktop into a strong DFIR/RE System with some teeth (Purple Team Ops)! This is intended to create a s

James 41 Dec 30, 2022
A Python r2pipe script to automatically create a Frida hook to intercept TLS traffic for Flutter based apps

boring-flutter A Python r2pipe script to automatically create a Frida hook to intercept TLS traffic for Flutter based apps. Currently only supporting

Hamza 64 Oct 18, 2022
Simples brute forcer de diretorios para web pentest.

🦑 dirbruter Simples brute forcer de diretorios para web pentest. ❕ Atenção Não ataque sites privados. Isto é illegal. 🖥️ Pré-requisitos Ultima versã

Dio brando 6 Jan 22, 2022