├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── README.zh-CN.md ├── artwork ├── dvwa_sentry_index.png └── sentry_detail.png ├── composer.json ├── dvwa ├── Dockerfile ├── README.md ├── README.zh-CN.md ├── config.inc.php ├── entrypoint.php └── prvd.ini ├── entrypoint.php ├── phpunit.xml ├── prvd.ini ├── src ├── Client.php ├── Config.php ├── Entry.php ├── Utils.php ├── filter │ ├── 001-base64_decode.php │ ├── 001-basename.php │ ├── 001-dirname.php │ ├── 001-explode.php │ ├── 001-gzuncompress.php │ ├── 001-hex2bin.php │ ├── 001-html_entity_decode.php │ ├── 001-htmlspecialchars_decode.php │ ├── 001-implode.php │ ├── 001-join.php │ ├── 001-json_decode.php │ ├── 001-ltrim.php │ ├── 001-pathinfo.php │ ├── 001-rawurldecode.php │ ├── 001-rawurlencode.php │ ├── 001-rtrim.php │ ├── 001-sprintf.php │ ├── 001-str_ireplace.php │ ├── 001-str_pad.php │ ├── 001-str_replace.php │ ├── 001-strstr.php │ ├── 001-strtolower.php │ ├── 001-strtoupper.php │ ├── 001-substr.php │ ├── 001-trim.php │ ├── 001-urldecode.php │ ├── 001-urlencode.php │ └── 001-vsprintf.php ├── opcode │ ├── 001-assign_concat.php │ ├── 001-concat.php │ ├── 001-do_fcall.php │ ├── 001-do_fcall_by_name.php │ ├── 001-do_icall.php │ ├── 001-do_ucall.php │ ├── 001-echo.php │ ├── 001-exit.php │ ├── 001-fast_concat.php │ ├── 001-include_or_eval.php │ ├── 001-init_dynamic_call.php │ ├── 001-init_method_call.php │ ├── 001-init_user_call.php │ └── 001-rope_end.php └── sink │ ├── file │ ├── 001-copy.php │ ├── 001-dir.php │ ├── 001-file.php │ ├── 001-file_get_contents.php │ ├── 001-file_put_contents.php │ ├── 001-fopen.php │ ├── 001-glob.php │ ├── 001-highlight_file.php │ ├── 001-link.php │ ├── 001-move_uploaded_file.php │ ├── 001-opendir.php │ ├── 001-readfile.php │ ├── 001-rename.php │ ├── 001-rmdir.php │ ├── 001-scandir.php │ ├── 001-show_source.php │ └── 001-unlink.php │ ├── rce │ ├── 001-exec.php │ ├── 001-passthru.php │ ├── 001-popen.php │ ├── 001-proc_open.php │ ├── 001-shell_exec.php │ ├── 001-system.php │ └── 001-unserialize.php │ ├── sqli │ ├── 001-mysqli.php │ ├── 001-mysqli_init.php │ ├── 001-mysqli_multi_query.php │ ├── 001-mysqli_prepare.php │ ├── 001-mysqli_query.php │ ├── 001-mysqli_real_query.php │ ├── 001-pdo.php │ ├── 001-pg_prepare.php │ ├── 001-pg_query.php │ ├── 001-pg_query_params.php │ ├── 001-pg_send_prepare.php │ ├── 001-pg_send_query.php │ ├── 001-pg_send_query_params.php │ └── 001-sqlite3.php │ ├── ssrf │ ├── 001-curl_exec.php │ ├── 001-fsockopen.php │ └── 001-get_headers.php │ └── xss │ ├── 001-print_r.php │ ├── 001-printf.php │ └── 001-vprintf.php ├── test.sh ├── tests ├── bootstrap.php ├── filter │ ├── 001-base64_decode.php │ ├── 001-basename.php │ ├── 001-dirname.php │ ├── 001-explode.php │ ├── 001-gzuncompress.php │ ├── 001-hex2bin.php │ ├── 001-html_entity_decode.php │ ├── 001-htmlspecialchars_decode.php │ ├── 001-implode.php │ ├── 001-join.php │ ├── 001-json_decode.php │ ├── 001-ltrim.php │ ├── 001-pathinfo.php │ ├── 001-rawurldecode.php │ ├── 001-rawurlencode.php │ ├── 001-rtrim.php │ ├── 001-sprintf.php │ ├── 001-str_ireplace.php │ ├── 001-str_pad.php │ ├── 001-str_replace.php │ ├── 001-strstr.php │ ├── 001-strtolower.php │ ├── 001-strtoupper.php │ ├── 001-substr.php │ ├── 001-trim.php │ ├── 001-urldecode.php │ ├── 001-urlencode.php │ └── 001-vsprintf.php ├── opcode │ ├── 001-assign_concat.php │ ├── 001-concat.php │ ├── 001-do_fcall.php │ ├── 001-do_fcall_by_name.php │ ├── 001-do_icall.php │ ├── 001-do_ucall.php │ ├── 001-echo.php │ ├── 001-exit.php │ ├── 001-fast_concat.php │ ├── 001-include_or_eval.php │ ├── 001-init_dynamic_call.php │ ├── 001-init_method_call.php │ ├── 001-init_user_call.php │ └── 001-rope_end.php └── sink │ ├── file │ ├── 001-copy.php │ ├── 001-dir.php │ ├── 001-file.php │ ├── 001-file_get_contents.php │ ├── 001-file_put_contents.php │ ├── 001-fopen.php │ ├── 001-glob.php │ ├── 001-highlight_file.php │ ├── 001-link.php │ ├── 001-move_uploaded_file.php │ ├── 001-opendir.php │ ├── 001-readfile.php │ ├── 001-rename.php │ ├── 001-rmdir.php │ ├── 001-scandir.php │ ├── 001-show_source.php │ └── 001-unlink.php │ ├── rce │ ├── 001-exec.php │ ├── 001-passthru.php │ ├── 001-popen.php │ ├── 001-proc_open.php │ ├── 001-shell_exec.php │ ├── 001-system.php │ └── 001-unserialize.php │ ├── sqli │ ├── 001-mysqli.php │ ├── 001-mysqli_init.php │ ├── 001-mysqli_multi_query.php │ ├── 001-mysqli_prepare.php │ ├── 001-mysqli_query.php │ ├── 001-mysqli_real_query.php │ ├── 001-pdo.php │ ├── 001-pg_prepare.php │ ├── 001-pg_query.php │ ├── 001-pg_query_params.php │ ├── 001-pg_send_prepare.php │ ├── 001-pg_send_query.php │ ├── 001-pg_send_query_params.php │ ├── 001-sqlite3.php │ └── config.php │ ├── ssrf │ ├── 001-curl_exec.php │ ├── 001-file_get_contents.php │ ├── 001-fsockopen.php │ └── 001-get_headers.php │ └── xss │ ├── 001-print_r.php │ ├── 001-printf.php │ └── 001-vprintf.php ├── tools ├── fuzzer.php └── fuzzer.py └── travis-php.ini /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | .idea/ 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | .DS_Store 7 | site/ 8 | vendor/ 9 | modules/ 10 | tools/ 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.0 5 | - 7.1 6 | - 7.2 7 | - 7.3 8 | - nightly 9 | 10 | matrix: 11 | allow_failures: 12 | - php: nightly 13 | 14 | services: 15 | - mysql 16 | - postgresql 17 | - docker 18 | 19 | before_script: 20 | - git clone https://github.com/fate0/xmark.git 21 | - cd xmark && phpize && ./configure && make && cd .. 22 | - mv ./xmark/modules ./modules 23 | - composer install 24 | 25 | script: 26 | - php -n -c travis-php.ini ./vendor/bin/phpunit -c phpunit.xml 27 | 28 | after_success: 29 | - docker build -t prvd-dvwa:latest ./dvwa 30 | - docker tag prvd-dvwa:latest fate0/prvd-dvwa:latest 31 | - docker build -t prvd:latest ./ 32 | - docker tag prvd:latest fate0/prvd:latest 33 | - docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD" 34 | - docker push fate0/prvd-dvwa:latest 35 | - docker push fate0/prvd:latest 36 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.2-apache 2 | MAINTAINER fate0 3 | 4 | 5 | # 注释为中国区域使用的源 6 | # RUN echo 'deb http://mirrors.aliyun.com/debian/ stretch main non-free contrib' > /etc/apt/sources.list 7 | 8 | RUN apt-get clean && \ 9 | rm -rf /var/lib/apt/lists/* && \ 10 | apt-get update && \ 11 | DEBIAN_FRONTEND=noninteractive apt-get install -y \ 12 | unzip \ 13 | libfreetype6-dev \ 14 | libjpeg62-turbo-dev \ 15 | libpng-dev \ 16 | && \ 17 | curl -sOSL https://github.com/fate0/xmark/archive/master.zip && unzip -q master.zip && rm master.zip && \ 18 | curl -sOSL https://github.com/fate0/prvd/archive/master.zip && unzip -q master.zip && rm master.zip && \ 19 | mkdir -p /data && \ 20 | mv xmark-master /data/xmark && \ 21 | mv prvd-master /data/prvd && \ 22 | curl --silent --show-error https://getcomposer.org/installer | php && \ 23 | # COMPOSER_ALLOW_SUPERUSER=1 php composer.phar config repo.packagist composer https://packagist.phpcomposer.com -d /data/prvd/ && \ 24 | COMPOSER_ALLOW_SUPERUSER=1 php composer.phar install -d /data/prvd/ --no-dev && \ 25 | rm composer.phar \ 26 | && \ 27 | mv $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini && \ 28 | docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && \ 29 | docker-php-ext-install iconv gd mysqli pdo pdo_mysql && \ 30 | docker-php-ext-configure /data/xmark --enable-xmark && \ 31 | docker-php-ext-install /data/xmark && \ 32 | rm -rf /data/xmark \ 33 | && \ 34 | apt-get clean && \ 35 | rm -rf /var/lib/apt/lists/* 36 | 37 | 38 | COPY prvd.ini $PHP_INI_DIR/conf.d/prvd.ini 39 | 40 | 41 | EXPOSE 80 42 | 43 | 44 | COPY entrypoint.php / 45 | ENTRYPOINT ["php", "-n", "/entrypoint.php"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # prvd 2 | 3 | [![Build Status](https://travis-ci.org/fate0/prvd.svg?branch=master)](https://travis-ci.org/fate0/prvd) 4 | ![GitHub](https://img.shields.io/github/license/fate0/prvd.svg) 5 | 6 | [中文文档](https://github.com/fate0/prvd/blob/master/README.zh-CN.md) 7 | 8 | 9 | ### Table of Contents 10 | 11 | * [Introduction](#introduction) 12 | * [Installation](#installation) 13 | * [Configuration](#configuration) 14 | * [DVWA](#dvwa) 15 | * [How it work](#how-it-work) 16 | * [Ref](#ref) 17 | 18 | 19 | ### Introduction 20 | 21 | PHP Runtime Vulnerability Detection 22 | 23 | ![sentry_detail](https://raw.githubusercontent.com/fate0/prvd/master/artwork/sentry_detail.png) 24 | 25 | 26 | ### Installation 27 | 28 | 1. git clone to a non-web directory, assuming the directory is `/data/prvd` 29 | 30 | ``` sh 31 | git clone https://github.com/fate0/prvd.git /data/prvd 32 | ``` 33 | 34 | 2. composer 35 | 36 | ``` sh 37 | composer install 38 | ``` 39 | 40 | 3. install xmark extension 41 | 42 | * [install xmark](https://github.com/fate0/xmark) 43 | 44 | 4. edit php.ini 45 | 46 | * set `auto_prepend_file` to `/data/prvd/src/Entry.php` 47 | * set `extension` to `xmark.so` 48 | * for the rest of the configuration, please copy the contents of prvd.ini in this project 49 | 50 | 51 | ### Configuration 52 | 53 | edit `/data/prvd/src/Config.php` 54 | 55 | ``` php 56 | define("PRVD_FUZZER_DSN", ""); 57 | define("PRVD_SENTRY_DSN", ""); 58 | define("PRVD_TAINT_ENABLE", true); 59 | define("PRVD_TANZI", "xtanzi"); 60 | define("PRVD_LOG_FILE", "/data/prvd/prvd.log"); 61 | ``` 62 | 63 | Sign up for an account at [https://sentry.io](https://sentry.io) or install sentry server by yourself 64 | 65 | 66 | ### DVWA 67 | 68 | You can use the docker to experience prvd 69 | 70 | ```sh 71 | docker pull fate0/prvd-dvwa 72 | docker run -d -e "PRVD_SENTRY_DSN={YOUR_SENTRY_DSN}" -p 80:80 fate0/prvd-dvwa 73 | ``` 74 | 75 | The environment variables that can be set are 76 | 77 | * `PRVD_FUZZER_DSN` 78 | * `PRVD_SENTRY_DSN` 79 | * `PRVD_TAINT_ENABLE` 80 | * `PRVD_TANZI` 81 | 82 | 83 | More about `prvd-dvwa` can be seen [here](https://github.com/fate0/prvd/blob/master/dvwa/README.md) 84 | 85 | 86 | ### How it work 87 | 88 | * [PHP Runtime Vulnerability Detection](http://blog.fatezero.org/2018/11/11/prvd/) 89 | 90 | 91 | ### Ref 92 | 93 | * [xmark](https://github.com/fate0/xmark) 94 | -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- 1 | # prvd 2 | 3 | [![Build Status](https://travis-ci.org/fate0/prvd.svg?branch=master)](https://travis-ci.org/fate0/prvd) 4 | ![GitHub](https://img.shields.io/github/license/fate0/prvd.svg) 5 | 6 | 7 | ### 介绍 8 | 9 | PHP 动态漏洞检测 10 | 11 | ![sentry_detail](https://raw.githubusercontent.com/fate0/prvd/master/artwork/sentry_detail.png) 12 | 13 | 14 | ### 安装 15 | 16 | 1. git clone 到一个非 web 目录下,假设目录为 `/data/prvd` 17 | 18 | ``` sh 19 | git clone https://github.com/fate0/prvd.git /data/prvd 20 | ``` 21 | 22 | 2. 安装依赖 23 | 24 | ``` sh 25 | composer install 26 | ``` 27 | 28 | 3. 下载编译 xmark 29 | 30 | * [install xmark](https://github.com/fate0/xmark) 31 | 32 | 4. 更改 php.ini 配置文件 33 | 34 | * `auto_prepend_file` 配置成 `/data/prvd/src/Entry.php` 35 | * `extension` 配置成 `xmark.so` 路径 36 | * 其余的配置请直接 copy 本项目中 prvd.ini 的内容 37 | 38 | ### 配置 39 | 40 | 使用编辑器打开 `/data/prvd/src/Config.php` 41 | 42 | ``` php 43 | define("PRVD_FUZZER_DSN", ""); // fuzzer dsn 地址 44 | define("PRVD_SENTRY_DSN", ""); // sentry dsn 地址 45 | define("PRVD_TAINT_ENABLE", true); // 是否启用 taint 模式 46 | define("PRVD_TANZI", "xtanzi"); // payload 关键字 47 | define("PRVD_LOG_FILE", "/data/prvd/prvd.log"); // log 文件 48 | ``` 49 | 50 | 前往 [https://sentry.io](https://sentry.io) 注册一个账号,或者自建一套 sentry 服务 51 | 52 | ### dvwa 53 | 54 | 可以使用 docker 体验一下 prvd 55 | 56 | ```sh 57 | docker pull fate0/prvd-dvwa 58 | docker run -d -e "PRVD_SENTRY_DSN={YOUR_SENTRY_DSN}" -p 80:80 fate0/prvd-dvwa 59 | ``` 60 | 61 | 可设置的环境变量有 62 | 63 | * `PRVD_FUZZER_DSN` 64 | * `PRVD_SENTRY_DSN` 65 | * `PRVD_TAINT_ENABLE` 66 | * `PRVD_TANZI` 67 | 68 | 69 | 更多关于 `prvd-dvwa` 可以看[这里](https://github.com/fate0/prvd/blob/master/dvwa/README.zh-CN.md) 70 | 71 | ### 原理 72 | 73 | * [PHP 运行时漏洞检测](http://blog.fatezero.org/2018/11/11/prvd/) 74 | 75 | ### 引用 76 | 77 | * [xmark](https://github.com/fate0/xmark) 78 | -------------------------------------------------------------------------------- /artwork/dvwa_sentry_index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fate0/prvd/6ae3c0507f569f355b44acab1a87c6e8fbac1f64/artwork/dvwa_sentry_index.png -------------------------------------------------------------------------------- /artwork/sentry_detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fate0/prvd/6ae3c0507f569f355b44acab1a87c6e8fbac1f64/artwork/sentry_detail.png -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fate0/prvd", 3 | "type": "project", 4 | "description": "PHP Runtime Vulnerability Detection", 5 | "license": "BSD-3-Clause", 6 | 7 | "authors": [ 8 | { 9 | "name": "fate0", 10 | "email": "fate0@fatezero.org", 11 | "homepage": "http://www.fatezero.org" 12 | } 13 | ], 14 | 15 | "require-dev": { 16 | "phpunit/phpunit": "<=7.2" 17 | }, 18 | 19 | "require": { 20 | "php": "^7.0", 21 | "sentry/sentry": "1.10" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /dvwa/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.2-apache 2 | MAINTAINER fate0 3 | 4 | 5 | # 注释为中国区域使用的源 6 | # RUN echo 'deb http://mirrors.aliyun.com/debian/ stretch main non-free contrib' > /etc/apt/sources.list 7 | 8 | RUN apt-get clean && \ 9 | rm -rf /var/lib/apt/lists/* && \ 10 | apt-get update && \ 11 | DEBIAN_FRONTEND=noninteractive apt-get install -y \ 12 | debconf-utils && \ 13 | echo mariadb-server mysql-server/root_password password vulnerables | debconf-set-selections && \ 14 | echo mariadb-server mysql-server/root_password_again password vulnerables | debconf-set-selections && \ 15 | DEBIAN_FRONTEND=noninteractive apt-get install -y \ 16 | mariadb-server \ 17 | unzip \ 18 | libfreetype6-dev \ 19 | libjpeg62-turbo-dev \ 20 | libpng-dev \ 21 | && \ 22 | curl -sOSL https://github.com/fate0/xmark/archive/master.zip && unzip -q master.zip && rm master.zip && \ 23 | curl -sOSL https://github.com/fate0/prvd/archive/master.zip && unzip -q master.zip && rm master.zip && \ 24 | curl -sOSL https://github.com/ethicalhack3r/DVWA/archive/master.zip && unzip -q master.zip && rm master.zip && \ 25 | mkdir -p /data && \ 26 | mv xmark-master /data/xmark && \ 27 | mv prvd-master /data/prvd && \ 28 | mv DVWA-master/* /var/www/html/ && \ 29 | chmod -R 777 /var/www/html/ && \ 30 | # 取消 dvwa checkToken 31 | sed -i '/function checkToken/a return;' /var/www/html/dvwa/includes/dvwaPage.inc.php && \ 32 | cp /data/prvd/tools/fuzzer.php /var/www/html/ && \ 33 | curl --silent --show-error https://getcomposer.org/installer | php && \ 34 | # COMPOSER_ALLOW_SUPERUSER=1 php composer.phar config repo.packagist composer https://packagist.phpcomposer.com -d /data/prvd/ && \ 35 | COMPOSER_ALLOW_SUPERUSER=1 php composer.phar install -d /data/prvd/ --no-dev && \ 36 | rm composer.phar \ 37 | && \ 38 | mv $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini && \ 39 | docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && \ 40 | docker-php-ext-install gd iconv mysqli pdo pdo_mysql && \ 41 | docker-php-ext-configure /data/xmark --enable-xmark && \ 42 | docker-php-ext-install /data/xmark && \ 43 | rm -rf /data/xmark \ 44 | && \ 45 | apt-get clean && \ 46 | rm -rf /var/lib/apt/lists/* 47 | 48 | 49 | COPY prvd.ini $PHP_INI_DIR/conf.d/prvd.ini 50 | COPY config.inc.php /var/www/html/config/ 51 | 52 | 53 | RUN service mysql start && \ 54 | sleep 3 && \ 55 | mysql -uroot -pvulnerables -e "CREATE USER dvwa@localhost IDENTIFIED BY 'p@ssw0rd';CREATE DATABASE dvwa;GRANT ALL privileges ON dvwa.* TO 'dvwa'@localhost;" 56 | 57 | 58 | EXPOSE 80 59 | 60 | 61 | COPY entrypoint.php / 62 | ENTRYPOINT ["php", "-n", "/entrypoint.php"] -------------------------------------------------------------------------------- /dvwa/README.md: -------------------------------------------------------------------------------- 1 | # prvd-dvwa 2 | 3 | ## Introduction 4 | 5 | prvd-dvwa is a dvwa environment with prvd installed, which is used to simply experience prvd. 6 | 7 | ![dvwa_sentry_index](https://raw.githubusercontent.com/fate0/prvd/master/artwork/dvwa_sentry_index.png) 8 | 9 | 10 | ## Installation 11 | 12 | ```sh 13 | docker pull fate0/prvd-dvwa 14 | docker run -d -e "PRVD_SENTRY_DSN={YOUR_SENTRY_DSN}" -p 80:80 fate0/prvd-dvwa 15 | ``` 16 | 17 | The environment variables that can be set are 18 | 19 | * `PRVD_FUZZER_DSN` 20 | * `PRVD_SENTRY_DSN` 21 | * `PRVD_TAINT_ENABLE` 22 | * `PRVD_TANZI` 23 | 24 | ## 漏洞 25 | 26 | In the prvd-dvwa environment, prvd is able to detect the following types of vulnerabilities: 27 | 28 | * Command Injection 29 | * File Inclusion 30 | * File Upload 31 | * SQL Injection 32 | * SQL Injection (Blind) 33 | * Partial XSS 34 | 35 | 36 | There are also false positives in taint mode, such as in the case of `File Inclusion` (impossible level): 37 | 38 | ```php 39 | 40 | 55 | ``` 56 | 57 | There is no filter function to clear the flag on the `$file` variable. 58 | So there was a false positive. 59 | 60 | There is also a false negative in the taint mode, such as in the case of the `SQL Injection` (medium level): 61 | 62 | ```php 63 | ' . mysqli_error($GLOBALS["___mysqli_ston"]) . '' ); 75 | 76 | // ... 77 | } 78 | ``` 79 | 80 | `mysqli_real_escape_string` will remove the flag of the variable, which is normal. 81 | However, the SQL statement does not use quotes to surround `$id`, so this is a false negative. 82 | 83 | Similarly, the payload mode will also have a false negative, which will not be described. 84 | 85 | Other types of vulnerabilities, such as vulnerabilities on the client side and logical types of 86 | vulnerabilities on the server side, are not detectable by prvd. -------------------------------------------------------------------------------- /dvwa/README.zh-CN.md: -------------------------------------------------------------------------------- 1 | # prvd-dvwa 2 | 3 | ## 介绍 4 | 5 | prvd-dvwa 是一个安装了 prvd 的 dvwa 环境,用于简单地体验 prvd 的能力。 6 | 7 | ![dvwa_sentry_index](https://raw.githubusercontent.com/fate0/prvd/master/artwork/dvwa_sentry_index.png) 8 | 9 | 10 | ## 安装 11 | 12 | ```sh 13 | docker pull fate0/prvd-dvwa 14 | docker run -d -e "PRVD_SENTRY_DSN={YOUR_SENTRY_DSN}" -p 80:80 fate0/prvd-dvwa 15 | ``` 16 | 17 | 可设置的环境变量有 18 | 19 | * `PRVD_FUZZER_DSN` 20 | * `PRVD_SENTRY_DSN` 21 | * `PRVD_TAINT_ENABLE` 22 | * `PRVD_TANZI` 23 | 24 | ## 漏洞 25 | 26 | prvd-dvwa 环境中,prvd 能够检测下面几种类型漏洞: 27 | 28 | * Command Injection 29 | * File Inclusion 30 | * File Upload 31 | * SQL Injection 32 | * SQL Injection (Blind) 33 | * 部分 XSS 34 | 35 | 其中 taint 模式下也会有误报的情况,例如在 File Inclusion 关卡 impossible 难度的情况下: 36 | ```php 37 | 38 | 53 | ``` 54 | 55 | 虽然已经指定了具体文件名,但是并没有什么 filter 函数将 `$file` 变量上的 flag 给清除了, 56 | 所以就产生了一个误报。 57 | 58 | taint 模式也会有漏报的情况,例如在 SQL Injection 关卡 medium 难度的情况下: 59 | 60 | ```php 61 | ' . mysqli_error($GLOBALS["___mysqli_ston"]) . '' ); 73 | 74 | // ... 75 | } 76 | ``` 77 | 78 | `mysqli_real_escape_string` 会将变量的 flag 给去除掉,这是很正常的情况, 79 | 但是 SQL 语句中并没有使用引号对 `$id` 包围,所以就产生了一个漏报。 80 | 81 | 同样 payload 模式也会有漏报的情况,具体不再描述。 82 | 83 | 其他类型的漏洞,例如在客户端上的漏洞、服务器端上逻辑类型的漏洞,prvd 均没办法检测。 84 | -------------------------------------------------------------------------------- /dvwa/config.inc.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dvwa/entrypoint.php: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | tests 13 | 14 | 15 | 16 | 17 | 18 | src 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /prvd.ini: -------------------------------------------------------------------------------- 1 | magic_quotes_gpc = Off 2 | allow_url_fopen = On 3 | allow_url_include = On 4 | 5 | auto_prepend_file = "/data/prvd/src/Entry.php" 6 | 7 | [xmark] 8 | xmark.enable = 1 9 | xmark.rename_enable = 0 10 | xmark.rename_classes = " 11 | SQLite3:prvd_SQLite3, 12 | mysqli:prvd_mysqli, 13 | PDO:prvd_PDO, 14 | " 15 | xmark.rename_functions = " 16 | base64_decode:prvd_base64_decode, 17 | basename:prvd_basename, 18 | dirname:prvd_dirname, 19 | explode:prvd_explode, 20 | gzuncompress:prvd_gzuncompress, 21 | hex2bin:prvd_hex2bin, 22 | html_entity_decode:prvd_html_entity_decode, 23 | htmlspecialchars_decode:prvd_htmlspecialchars_decode, 24 | implode:prvd_implode, 25 | join:prvd_join, 26 | json_decode:prvd_json_decode, 27 | ltrim:prvd_ltrim, 28 | pathinfo:prvd_pathinfo, 29 | rawurldecode:prvd_rawurldecode, 30 | rawurlencode:prvd_rawurlencode, 31 | rtrim:prvd_rtrim, 32 | sprintf:prvd_sprintf, 33 | str_ireplace:prvd_str_ireplace, 34 | str_pad:prvd_str_pad, 35 | str_replace:prvd_str_replace, 36 | strstr:prvd_strstr, 37 | strtolower:prvd_strtolower, 38 | strtoupper:prvd_strtoupper, 39 | substr:prvd_substr, 40 | trim:prvd_trim, 41 | urldecode:prvd_urldecode, 42 | urlencode:prvd_urlencode, 43 | vsprintf:prvd_vsprintf, 44 | exec:prvd_exec, 45 | passthru:prvd_passthru, 46 | popen:prvd_popen, 47 | proc_open:prvd_proc_open, 48 | shell_exec:prvd_shell_exec, 49 | system:prvd_system, 50 | unserialize:prvd_unserialize, 51 | copy:prvd_copy, 52 | dir:prvd_dir, 53 | file:prvd_file, 54 | file_get_contents:prvd_file_get_contents, 55 | file_put_contents:prvd_file_put_contents, 56 | fopen:prvd_fopen, 57 | glob:prvd_glob, 58 | highlight_file:prvd_highlight_file, 59 | link:prvd_link, 60 | move_uploaded_file:prvd_move_uploaded_file, 61 | opendir:prvd_opendir, 62 | readfile:prvd_readfile, 63 | rename:prvd_rename, 64 | rmdir:prvd_rmdir, 65 | scandir:prvd_scandir, 66 | show_source:prvd_show_source, 67 | unlink:prvd_unlink, 68 | mysqli_init:prvd_mysqli_init, 69 | mysqli_multi_query:prvd_mysqli_multi_query, 70 | mysqli_query:prvd_mysqli_query, 71 | mysqli_prepare:prvd_mysqli_prepare, 72 | mysqli_real_query:prvd_mysqli_real_query, 73 | pg_prepare:prvd_pg_prepare, 74 | pg_query:prvd_pg_query, 75 | pg_query_params:prvd_pg_query_params, 76 | pg_send_prepare:prvd_pg_send_prepare, 77 | pg_send_query:prvd_pg_send_query, 78 | pg_send_query_params:prvd_pg_send_query_params, 79 | curl_exec:prvd_curl_exec, 80 | fsockopen:prvd_fsockopen, 81 | get_headers:prvd_get_headers, 82 | print_r:prvd_print_r, 83 | printf:prvd_printf, 84 | vprintf:prvd_vprintf 85 | " -------------------------------------------------------------------------------- /src/Client.php: -------------------------------------------------------------------------------- 1 | captureMessage($message, array(), $level, $stack); 16 | } 17 | } 18 | 19 | class PRVD_Fuzzer_Client extends Raven_Client 20 | { 21 | public function __construct($options_or_dsn = null, $options = array()) 22 | { 23 | if (is_array($options_or_dsn)) { 24 | $options = array_merge($options_or_dsn, $options); 25 | } 26 | 27 | if (!is_array($options_or_dsn) && !empty($options_or_dsn)) { 28 | $dsn = $options_or_dsn; 29 | } elseif (!empty($_SERVER['SENTRY_DSN'])) { 30 | $dsn = @$_SERVER['SENTRY_DSN']; 31 | } elseif (!empty($options['dsn'])) { 32 | $dsn = $options['dsn']; 33 | } else { 34 | $dsn = null; 35 | } 36 | 37 | if (!empty($dsn)) { 38 | $options = array_merge($options, $this->parseDSN($dsn)); 39 | } 40 | 41 | $options['trace'] = false; 42 | $options['processors'] = array(); 43 | $options['auto_log_stacks'] = false; 44 | 45 | unset($options['dsn']); 46 | unset($_SERVER['SENTRY_DSN']); 47 | 48 | parent::__construct($options); 49 | } 50 | 51 | public static function parseDSN($dsn) 52 | { 53 | switch (strtolower($dsn)) { 54 | case '': 55 | case 'false': 56 | case '(false)': 57 | case 'empty': 58 | case '(empty)': 59 | case 'null': 60 | case '(null)': 61 | return array(); 62 | } 63 | 64 | $url = parse_url($dsn); 65 | $scheme = (isset($url['scheme']) ? $url['scheme'] : ''); 66 | if (!in_array($scheme, array('http', 'https'))) { 67 | throw new InvalidArgumentException( 68 | 'Unsupported Sentry DSN scheme: ' . 69 | (!empty($scheme) ? $scheme : '') 70 | ); 71 | } 72 | 73 | $netloc = (isset($url['host']) ? $url['host'] : null); 74 | $netloc .= (isset($url['port']) ? ':' . $url['port'] : null); 75 | $path = (isset($url['path']) ? $url['path'] : ''); 76 | $username = (isset($url['user']) ? $url['user'] : null); 77 | $password = (isset($url['pass']) ? $url['pass'] : null); 78 | 79 | if (empty($netloc) || empty($username)) { 80 | throw new InvalidArgumentException('Invalid Sentry DSN: ' . $dsn); 81 | } 82 | 83 | return array( 84 | 'server' => sprintf('%s://%s%s', $scheme, $netloc, $path), 85 | 'project' => 0, 86 | 'public_key' => $username, 87 | 'secret_key' => $password, 88 | ); 89 | } 90 | 91 | public function captureRequest() 92 | { 93 | if (!static::is_http_request()) return; 94 | 95 | $data = $this->get_http_data(); 96 | $data['platform'] = 'php'; 97 | if (!empty($_GET)) { 98 | $data['request']['query'] = $_GET; 99 | } 100 | if (!empty($_FILES)) { 101 | $data['request']['files'] = $_FILES; 102 | } 103 | 104 | $this->process($data); 105 | $this->send($data); 106 | } 107 | 108 | public function capture($data, $stack = null, $vars = null) 109 | { 110 | // do nothing 111 | } 112 | 113 | public function install(...$args) 114 | { 115 | // do nothing 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Config.php: -------------------------------------------------------------------------------- 1 | &$value) { 53 | if (stripos($key, 'HTTP_') === 0) { 54 | prvd_xmark($value); 55 | } 56 | } 57 | 58 | 59 | // 1. 加载 sink 60 | prvd_load_file(PRVD_ABSPATH."sink/*/*.php"); 61 | 62 | // 2. 加载 filter 63 | prvd_load_file(PRVD_ABSPATH."filter/*.php"); 64 | 65 | // 3. 加载 opcode 66 | prvd_load_opcode(PRVD_ABSPATH."opcode/*.php"); 67 | 68 | 69 | // delay require 70 | require(PRVD_ABSPATH."../vendor/autoload.php"); 71 | require(PRVD_ABSPATH."Client.php"); 72 | 73 | 74 | if (!PRVD_IS_SENTRY_REQUEST) { 75 | $prvd_sentry_client = new PRVD_Sentry_Client(PRVD_SENTRY_DSN); 76 | } 77 | 78 | 79 | function prvd_shutdown_capture_request() { 80 | // 如果 header 信息不是来源于 fuzzer,那就发送相关信息给 fuzzer 81 | if (PRVD_FUZZER_DSN && !PRVD_IS_FUZZER_REQUEST && !PRVD_IS_SENTRY_REQUEST) { 82 | $prvd_fuzzer_client = new PRVD_Fuzzer_Client(PRVD_FUZZER_DSN); 83 | $prvd_fuzzer_client->captureRequest(); 84 | } 85 | } 86 | 87 | register_shutdown_function('prvd_shutdown_capture_request'); 88 | 89 | -------------------------------------------------------------------------------- /src/Utils.php: -------------------------------------------------------------------------------- 1 | &$value) { 30 | if (prvd_xcheck($value, $recursive)) return true; 31 | } 32 | } 33 | 34 | return false; 35 | } 36 | 37 | 38 | /** 39 | * 给变量打上标记 40 | * @param $var 41 | * @param bool $recursive 42 | */ 43 | function prvd_xmark(&$var, $recursive=true) { 44 | if (!PRVD_TAINT_ENABLE) return; 45 | 46 | if (is_string($var)) { 47 | xmark($var); 48 | } elseif (is_array($var) && $recursive) { 49 | foreach ($var as $key => &$value) { 50 | prvd_xmark($value, $recursive); 51 | } 52 | } 53 | } 54 | 55 | 56 | /** 57 | * 检测 callback 相关变量 58 | * @param $call 59 | * @param $params 60 | * @param $message 61 | */ 62 | function prvd_check_callback($call, $params, $message) { 63 | global $prvd_sentry_client; 64 | if (!$prvd_sentry_client) return; 65 | 66 | if (empty($params)) return; 67 | 68 | $calls = array( 69 | "array_diff_uassoc" => -1, 70 | "array_diff_ukey" => -1, 71 | "array_filter" => 1, 72 | "array_intersect_uassoc" => -1, 73 | "array_intersect_ukey" => -1, 74 | "array_map" => 0, 75 | "array_reduce" => 1, 76 | "array_udiff" => -1, 77 | "array_udiff_assoc" => -1, 78 | "array_udiff_uassoc" => -1, 79 | "array_uintersect" => -1, 80 | "array_uintersect_assoc" => -1, 81 | "array_uintersect_uassoc" => -1, 82 | "array_walk" => 1, 83 | "array_walk_recursive" => 1, 84 | "iterator_apply" => 1, 85 | "ob_start" => 0, 86 | "preg_replace_callback" => 1, 87 | "register_shutdown_function" => 0, 88 | "register_tick_function" => 0, 89 | "set_error_handler" => 0, 90 | "set_exception_handler" => 0, 91 | "spl_autoload_register" => 0, 92 | "uasort" => 1, 93 | "uksort" => 1, 94 | "usort" => 1, 95 | ); 96 | 97 | $reported = false; 98 | 99 | if (!is_string($call) && !is_array($call)) return; 100 | if (is_array($call)) $call = $call[0].'::'.$call[1]; 101 | if (!isset($calls[$call])) return; 102 | 103 | $callback_index = $calls[$call]; 104 | 105 | if ($callback_index >= 0 && isset($params[$callback_index])) 106 | $callback = $params[$callback_index]; 107 | elseif ($callback_index < 0 && isset($params[count($params)+$callback_index])) 108 | $callback = $params[count($params)+$callback_index]; 109 | else 110 | return; 111 | 112 | if (is_string($callback)) { 113 | if (stripos($callback, PRVD_TANZI) !== false) { 114 | $prvd_sentry_client->captureVuln($message); 115 | $reported = true; 116 | } 117 | } elseif (is_array($callback)) { 118 | if (is_string($callback[0]) && stripos($callback[0], PRVD_TANZI) !== false) { 119 | $prvd_sentry_client->captureVuln($message); 120 | $reported = true; 121 | } 122 | if (is_string($callback[1]) && stripos($callback[1], PRVD_TANZI) !== false) { 123 | $prvd_sentry_client->captureVuln($message); 124 | $reported = true; 125 | } 126 | } 127 | 128 | if (PRVD_TAINT_ENABLE && !$reported && prvd_xcheck($callback)) { 129 | $prvd_sentry_client->captureVuln($message, "debug"); 130 | } 131 | } 132 | 133 | 134 | /** 135 | * 检测动态调用函数名是否可控 136 | * @param $funcname 137 | * @param $message 138 | */ 139 | function prvd_check_dynamic_call(&$funcname, $message) { 140 | global $prvd_sentry_client; 141 | if (!$prvd_sentry_client) return; 142 | 143 | $reported = false; 144 | 145 | if (is_string($funcname)) { 146 | if (stripos($funcname, PRVD_TANZI) !== false) { 147 | $prvd_sentry_client->captureVuln($message); 148 | $reported = true; 149 | } 150 | } else if (is_array($funcname)) { 151 | if (is_string($funcname[0]) && (stripos($funcname[0], PRVD_TANZI) !== false)) { 152 | $prvd_sentry_client->captureVuln($message); 153 | $reported = true; 154 | } 155 | 156 | if (is_string($funcname[1]) && (stripos($funcname[1], PRVD_TANZI) !== false)) { 157 | $prvd_sentry_client->captureVuln($message); 158 | $reported = true; 159 | } 160 | } 161 | 162 | if (PRVD_TAINT_ENABLE && !$reported && prvd_xcheck($funcname)) { 163 | $prvd_sentry_client->captureVuln($message, "debug"); 164 | } 165 | } 166 | 167 | 168 | /** 169 | * 检测 path 相关变量 170 | * @param $path 171 | * @param $message 172 | */ 173 | function prvd_check_path(&$path, $message) { 174 | global $prvd_sentry_client; 175 | if (!$prvd_sentry_client) return; 176 | 177 | $reported = false; 178 | 179 | if (stripos($path, "../". PRVD_TANZI) !== false || stripos($path, "..\\". PRVD_TANZI) !== false) { 180 | $prvd_sentry_client->captureVuln($message); 181 | $reported = true; 182 | } 183 | 184 | if (PRVD_TAINT_ENABLE && !$reported && prvd_xcheck($path)) { 185 | $prvd_sentry_client->captureVuln($message, "debug"); 186 | } 187 | } 188 | 189 | 190 | /** 191 | * 检测是否存在 SQL 注入 192 | * @param $query 193 | * @param $message 194 | * @param $error 195 | */ 196 | function prvd_check_sqli(&$query, $message) { 197 | global $prvd_sentry_client; 198 | if (!$prvd_sentry_client) return; 199 | 200 | if (prvd_detect_sql_injection($query)) { 201 | $prvd_sentry_client->captureVuln($message); 202 | } else if (PRVD_TAINT_ENABLE && prvd_xcheck($query)) { 203 | $prvd_sentry_client->captureVuln($message, "debug"); 204 | } 205 | } 206 | 207 | 208 | /** 209 | * 检测是否存在命令注入 210 | * @param $command 211 | * @param $message 212 | */ 213 | function prvd_check_rce(&$command, $message) { 214 | global $prvd_sentry_client; 215 | if (!$prvd_sentry_client) return; 216 | 217 | if (prvd_detect_cmd_injection($command)) { 218 | $prvd_sentry_client->captureVuln($message); 219 | } else if (PRVD_TAINT_ENABLE && prvd_xcheck($command)) { 220 | $prvd_sentry_client->captureVuln($message, "debug"); 221 | } 222 | } 223 | 224 | 225 | /** 226 | * 检测是否存在 XSS 227 | * @param $str 228 | * @param $message 229 | */ 230 | function prvd_check_xss(&$str, $message) { 231 | global $prvd_sentry_client; 232 | if (!$prvd_sentry_client) return; 233 | 234 | if (PRVD_TAINT_ENABLE && prvd_xcheck($str)) { 235 | $prvd_sentry_client->captureVuln($message, "debug"); 236 | } 237 | } 238 | 239 | 240 | /** 241 | * 检测是否存在反序列化 242 | * @param $str 243 | * @param $message 244 | */ 245 | function prvd_check_unserialize(&$str, $message) { 246 | global $prvd_sentry_client; 247 | if (!$prvd_sentry_client) return; 248 | 249 | if (prvd_detect_unserialize($str)) { 250 | $prvd_sentry_client->captureVuln($message); 251 | }else if (PRVD_TAINT_ENABLE && prvd_xcheck($str)) { 252 | $prvd_sentry_client->captureVuln($message, "debug"); 253 | } 254 | } 255 | 256 | 257 | /** 258 | * 检测是否存在 SSRF 259 | * @param $url 260 | * @param $message 261 | */ 262 | function prvd_check_ssrf(&$url, $message) { 263 | global $prvd_sentry_client; 264 | if (!$prvd_sentry_client) return; 265 | 266 | $host = parse_url($url, PHP_URL_HOST); 267 | if (!$host) $host = $url; 268 | 269 | if (stripos($host, PRVD_TANZI) !== false) { 270 | $prvd_sentry_client->captureVuln($message); 271 | } else if (PRVD_TAINT_ENABLE && prvd_xcheck($url)) { 272 | $prvd_sentry_client->captureVuln($message, "debug"); 273 | } 274 | } 275 | 276 | 277 | function prvd_log($content) { 278 | $file_put_contents = prvd_get_function('file_put_contents'); 279 | $file_put_contents(PRVD_LOG_FILE, $content."\n", FILE_APPEND); 280 | } 281 | 282 | 283 | /** 284 | * 加载文件 285 | * @param $pattern 286 | */ 287 | function prvd_load_file($pattern) { 288 | $glob = prvd_get_function("glob"); 289 | $ksort = prvd_get_function("ksort"); 290 | $basename = prvd_get_function("basename"); 291 | 292 | $file_list = $glob($pattern); 293 | 294 | $result_list = array(); 295 | foreach ($file_list as $absfilename) { 296 | if (in_array($basename($absfilename), $result_list)) { 297 | prvd_log("error: function ".$basename($absfilename)." already exists in ".$file_list[$basename($absfilename)]); 298 | continue; 299 | } 300 | 301 | $result_list[$basename($absfilename)] = $absfilename; 302 | } 303 | 304 | $ksort($result_list); 305 | foreach ($result_list as $filename => $absfilename) { 306 | $funcname = preg_replace("/\d{3}\-/", "", $filename); 307 | $funcname = preg_replace("/.php$/", "", $funcname); 308 | 309 | if (!function_exists(PRVD_RENAME_PREFIX.$funcname) && !class_exists(PRVD_RENAME_PREFIX.$funcname)) { 310 | prvd_log("error: function/class ".PRVD_RENAME_PREFIX.$funcname." not exists"); 311 | continue; 312 | } 313 | 314 | if (function_exists($funcname) || class_exists($funcname)) { 315 | prvd_log("error: function/class ".$funcname." already exists"); 316 | continue; 317 | } 318 | 319 | require($absfilename); 320 | } 321 | } 322 | 323 | 324 | /** 325 | * 加载 opcode 相关文件 326 | * @param $pattern 327 | */ 328 | function prvd_load_opcode($pattern) { 329 | $glob = prvd_get_function("glob"); 330 | $ksort = prvd_get_function("ksort"); 331 | $basename = prvd_get_function("basename"); 332 | 333 | $file_list = $glob($pattern); 334 | 335 | $result_list = array(); 336 | foreach ($file_list as $absfilename) { 337 | $result_list[$basename($absfilename)] = $absfilename; 338 | } 339 | 340 | $ksort($result_list); 341 | foreach ($result_list as $filename => $absfilename) { 342 | require($absfilename); 343 | } 344 | } 345 | 346 | 347 | $prvd_translate_lang = array( 348 | "Remote Code Execute" => "远程代码执行", 349 | "Remote Command Execute" => "远程命令执行", 350 | "Sql Injection" => "SQL 注入", 351 | "Cross Site Scripting" => "跨站脚本攻击", 352 | "File Inclusion" => "文件包含", 353 | "Arbitrary File Access" => "任意文件读取", 354 | "Arbitrary File Upload" => "任意文件上传", 355 | "Arbitrary File Write" => "任意文件写入", 356 | "Arbitrary File Delete" => "任意文件删除", 357 | "Directory Traversal" => "目录遍历", 358 | "Server Side Request Forgery" => "服务器端请求伪造", 359 | ); 360 | 361 | 362 | /** 363 | * @param $str 364 | * @return string 365 | */ 366 | function prvd_translate($str) { 367 | global $prvd_translate_lang; 368 | if (isset($prvd_translate_lang[$str])) { 369 | return $prvd_translate_lang[$str]; 370 | } else { 371 | return $str; 372 | } 373 | } 374 | 375 | 376 | const PRVD_KEYWORD_ALLOW_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789$_'; 377 | const PRVD_WHITESPACE = " \t\n\r\v\f"; 378 | /** 379 | * 检测 SQL 语句是否异常 380 | * @param $sql_string 381 | * @return bool 382 | */ 383 | function prvd_detect_sql_injection($sql_string) { 384 | $strlen = prvd_get_function('strlen'); 385 | $stripos = prvd_get_function('stripos'); 386 | $substr = prvd_get_function('substr'); 387 | $in_array = prvd_get_function('in_array'); 388 | 389 | $cur_pos = 0; 390 | $sql_string_len = $strlen($sql_string); 391 | 392 | 393 | while ($cur_pos < $sql_string_len) { 394 | while ($stripos(PRVD_WHITESPACE, $substr($sql_string, $cur_pos, 1)) !== FALSE) $cur_pos ++; 395 | 396 | if ($stripos('\'"`', $substr($sql_string, $cur_pos, 1)) !== FALSE) { 397 | // handle literal 398 | $quote = $substr($sql_string, $cur_pos, 1); 399 | $cur_pos ++; 400 | while ($cur_pos < $sql_string_len) { 401 | if ($quote === $substr($sql_string, $cur_pos, 1)) 402 | break; 403 | elseif ($in_array($substr($sql_string, $cur_pos, 2), array('\\\\', '\\\'', '\\"'))) 404 | $cur_pos += 1; 405 | 406 | $cur_pos ++; 407 | } 408 | 409 | // broken sql statement 410 | if ($cur_pos == $sql_string_len) return TRUE; 411 | 412 | $cur_pos ++; 413 | 414 | } elseif ('/*' === $substr($sql_string, $cur_pos, 2)) { 415 | // handle comment 416 | $cur_pos += 2; 417 | $comment_start = $cur_pos; 418 | while ($cur_pos < $sql_string_len) { 419 | if ('*/' === $substr($sql_string, $cur_pos, 2)) break; 420 | $cur_pos ++; 421 | } 422 | if ($stripos($substr($sql_string, $comment_start, $cur_pos-$comment_start), PRVD_TANZI) !== FALSE) 423 | return TRUE; 424 | $cur_pos += 2; 425 | 426 | } elseif ('--' === $substr($sql_string, $cur_pos, 2)) { 427 | // handle inline comment 428 | $cur_pos = $sql_string_len; 429 | 430 | } elseif ($stripos(PRVD_KEYWORD_ALLOW_CHARS, $substr($sql_string, $cur_pos, 1)) === FALSE) { 431 | // handle op 432 | $cur_pos ++; 433 | 434 | } else { 435 | // handle keyword 436 | $keyword_start = $cur_pos; 437 | while ($cur_pos < $sql_string_len) { 438 | if ($stripos(PRVD_KEYWORD_ALLOW_CHARS, $substr($sql_string, $cur_pos, 1)) === FALSE) break; 439 | $cur_pos ++; 440 | } 441 | if ($stripos($substr($sql_string, $keyword_start, $cur_pos-$keyword_start), PRVD_TANZI) !== FALSE) 442 | return TRUE; 443 | } 444 | } 445 | 446 | return FALSE; 447 | } 448 | 449 | 450 | /** 451 | * 检测 CMD 语句是否异常 452 | * @param $cmd_string 453 | * @return bool 454 | */ 455 | function prvd_detect_cmd_injection($cmd_string) { 456 | // TODO: 目前只考虑了逃脱引号的情况,在双引号内的情况暂未支持 457 | $strlen = prvd_get_function('strlen'); 458 | $stripos = prvd_get_function('stripos'); 459 | $substr = prvd_get_function('substr'); 460 | $in_array = prvd_get_function('in_array'); 461 | 462 | $cur_pos = 0; 463 | $cmd_string_len = $strlen($cmd_string); 464 | 465 | while ($cur_pos < $cmd_string_len) { 466 | while ($stripos(PRVD_WHITESPACE, $substr($cmd_string, $cur_pos, 1)) !== FALSE) $cur_pos++; 467 | 468 | 469 | if ($stripos('\'"', $substr($cmd_string, $cur_pos, 1)) !== FALSE) { 470 | // handle literal 471 | $quote = $substr($cmd_string, $cur_pos, 1); 472 | $cur_pos ++; 473 | while ($cur_pos < $cmd_string_len) { 474 | if ($quote === $substr($cmd_string, $cur_pos, 1)) 475 | break; 476 | elseif ($in_array($substr($cmd_string, $cur_pos, 2), array('\\\\', '\\\'', '\\"'))) 477 | $cur_pos += 1; 478 | 479 | $cur_pos ++; 480 | } 481 | 482 | // broken cmd statement 483 | if ($cur_pos == $cmd_string_len) return TRUE; 484 | 485 | $cur_pos ++; 486 | } elseif ($stripos(PRVD_KEYWORD_ALLOW_CHARS, $substr($cmd_string, $cur_pos, 1)) === FALSE) { 487 | // handle op 488 | $cur_pos ++; 489 | 490 | } else { 491 | // handle keyword 492 | $keyword_start = $cur_pos; 493 | while ($cur_pos < $cmd_string_len) { 494 | if ($stripos(PRVD_KEYWORD_ALLOW_CHARS, $substr($cmd_string, $cur_pos, 1)) === FALSE) break; 495 | $cur_pos ++; 496 | } 497 | if ($stripos($substr($cmd_string, $keyword_start, $cur_pos-$keyword_start), PRVD_TANZI) !== FALSE) 498 | return TRUE; 499 | } 500 | } 501 | 502 | return FALSE; 503 | } 504 | 505 | 506 | function prvd_detect_unserialize($serialize_string) { 507 | // TODO: 508 | 509 | return FALSE; 510 | } -------------------------------------------------------------------------------- /src/filter/001-base64_decode.php: -------------------------------------------------------------------------------- 1 | captureVuln(prvd_translate("Remote Code Execute")); 13 | $reported = true; 14 | } elseif (stripos($param, "../". PRVD_TANZI) !== false || stripos($param, "..\\". PRVD_TANZI) !== false) { 15 | $prvd_sentry_client->captureVuln(prvd_translate("Remote Code Execute")); 16 | $reported = true; 17 | } 18 | } 19 | 20 | if (PRVD_TAINT_ENABLE && !$reported && prvd_xcheck($param)) { 21 | $prvd_sentry_client->captureVuln(prvd_translate("Remote Code Execute"), "debug"); 22 | } 23 | } 24 | 25 | xregister_opcode_callback(XMARK_INCLUDE_OR_EVAL, "prvd_include_or_eval_handler"); 26 | -------------------------------------------------------------------------------- /src/opcode/001-init_dynamic_call.php: -------------------------------------------------------------------------------- 1 | ./../'. PRVD_TANZI; 8 | 9 | 10 | class Dummy_Sentry_Client { 11 | public $captured = false; 12 | 13 | public function captureVuln(...$args) { 14 | $this->captured = true; 15 | } 16 | } -------------------------------------------------------------------------------- /tests/filter/001-base64_decode.php: -------------------------------------------------------------------------------- 1 | assertEquals(true, $is_mark); 15 | 16 | $result = base64_decode($str); 17 | 18 | $is_mark = prvd_xcheck($result); 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 20 | } 21 | } -------------------------------------------------------------------------------- /tests/filter/001-basename.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | 17 | $result = "2) ".basename($str).PHP_EOL; 18 | $is_mark = prvd_xcheck($result); 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 20 | 21 | $result = "3) ".basename($str).PHP_EOL; 22 | $is_mark = prvd_xcheck($result); 23 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 24 | 25 | $result = "4) ".basename("/etc/").PHP_EOL; 26 | $is_mark = prvd_xcheck($result); 27 | $this->assertEquals(false, $is_mark); 28 | 29 | $result = "5) ".basename(".").PHP_EOL; 30 | $is_mark = prvd_xcheck($result); 31 | $this->assertEquals(false, $is_mark); 32 | 33 | $result = "6) ".basename("/"); 34 | $is_mark = prvd_xcheck($result); 35 | $this->assertEquals(false, $is_mark); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /tests/filter/001-dirname.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | 17 | $result = dirname("/etc/") . PHP_EOL; 18 | $is_mark = prvd_xcheck($result); 19 | $this->assertEquals(false, $is_mark); 20 | 21 | $result = dirname(".") . PHP_EOL; 22 | $is_mark = prvd_xcheck($result); 23 | $this->assertEquals(false, $is_mark); 24 | 25 | $result = dirname("C:\\") . PHP_EOL; 26 | $is_mark = prvd_xcheck($result); 27 | $this->assertEquals(false, $is_mark); 28 | 29 | $result = dirname($str, 2); 30 | $is_mark = prvd_xcheck($result); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /tests/filter/001-explode.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | 17 | $is_mark = prvd_xcheck($pieces[1]); 18 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 19 | 20 | $data = "foo:*:1023:1000::/home/foo:/bin/sh"; 21 | prvd_xmark($data); 22 | list($user, $pass, $uid, $gid, $gecos, $home, $shell) = explode(":", $data); 23 | 24 | $is_mark = prvd_xcheck($user); 25 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 26 | 27 | $is_mark = prvd_xcheck($pass); 28 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 29 | } 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/filter/001-gzuncompress.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/filter/001-hex2bin.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/filter/001-html_entity_decode.php: -------------------------------------------------------------------------------- 1 | dog now"; 11 | $id = "test"; 12 | prvd_xmark($id); 13 | 14 | $a = htmlentities($orig); 15 | $b = $a.$id; 16 | $c = html_entity_decode($b); 17 | 18 | $is_mark = prvd_xcheck($a); 19 | $this->assertEquals(false, $is_mark); 20 | 21 | $is_mark = prvd_xcheck($b); 22 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 23 | 24 | $is_mark = prvd_xcheck($c); 25 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 26 | 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /tests/filter/001-htmlspecialchars_decode.php: -------------------------------------------------------------------------------- 1 | this -> "

\n"; 11 | prvd_xmark($str); 12 | 13 | $result = htmlspecialchars_decode($str); 14 | $is_mark = prvd_xcheck($result); 15 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | 17 | $result = htmlspecialchars_decode($str, ENT_NOQUOTES); 18 | $is_mark = prvd_xcheck($result); 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/filter/001-implode.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 17 | } 18 | } 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/filter/001-join.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 17 | } 18 | } 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/filter/001-json_decode.php: -------------------------------------------------------------------------------- 1 | assertEquals(false, $is_mark); 20 | 21 | $result = json_decode($json, true); 22 | $is_mark = prvd_xcheck($result); 23 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 24 | } 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/filter/001-ltrim.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 22 | 23 | $result = ltrim($hello, "Hdle"); 24 | $is_mark = prvd_xcheck($result); 25 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 26 | 27 | $result = ltrim($binary, "\x00..\x1F"); 28 | $is_mark = prvd_xcheck($result); 29 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 30 | } 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/filter/001-pathinfo.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 17 | 18 | $result = $path_parts['basename']; 19 | $is_mark = prvd_xcheck($result); 20 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 21 | 22 | $result = $path_parts['extension']; 23 | $is_mark = prvd_xcheck($result); 24 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 25 | 26 | $result = $path_parts['filename']; 27 | $is_mark = prvd_xcheck($result); 28 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/filter/001-rawurldecode.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | } 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/filter/001-rawurlencode.php: -------------------------------------------------------------------------------- 1 | '; 11 | prvd_xmark($str); 12 | $result = 'assertEquals(PRVD_TAINT_ENABLE, $is_mark); 22 | 23 | $result = rtrim($hello, "Hdle"); 24 | $is_mark = prvd_xcheck($result); 25 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 26 | 27 | $result = rtrim($binary, "\x00..\x1F"); 28 | $is_mark = prvd_xcheck($result); 29 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/filter/001-sprintf.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/filter/001-str_ireplace.php: -------------------------------------------------------------------------------- 1 | "); 14 | 15 | $is_mark = prvd_xcheck($result); 16 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 17 | } 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/filter/001-str_pad.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | 17 | $result = str_pad($input, 10, "-=", STR_PAD_LEFT); // produces "-=-=-Alien" 18 | $is_mark = prvd_xcheck($result); 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 20 | 21 | $result = str_pad($input, 10, "_", STR_PAD_BOTH); // produces "__Alien___" 22 | $is_mark = prvd_xcheck($result); 23 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 24 | 25 | $result = str_pad($input, 6, "___"); // produces "Alien_" 26 | $is_mark = prvd_xcheck($result); 27 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 28 | 29 | $result = str_pad($input, 3, "*"); 30 | $is_mark = prvd_xcheck($result); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /tests/filter/001-str_replace.php: -------------------------------------------------------------------------------- 1 | 11 | $str = ""; 12 | prvd_xmark($str); 13 | $result = str_replace("%body%", "black", $str); 14 | $is_mark = prvd_xcheck($result); 15 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | 17 | // Provides: Hll Wrld f PHP 18 | $str = "Hello World of PHP"; 19 | prvd_xmark($str); 20 | $vowels = array("a", "e", "i", "o", "u", "A", "E", "I", "O", "U"); 21 | $result = str_replace($vowels, "", $str); 22 | $is_mark = prvd_xcheck($result); 23 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 24 | 25 | // Provides: You should eat pizza, beer, and ice cream every day 26 | $phrase = "You should eat fruits, vegetables, and fiber every day."; 27 | prvd_xmark($phrase); 28 | $healthy = array("fruits", "vegetables", "fiber"); 29 | $yummy = array("pizza", "beer", "ice cream"); 30 | 31 | $result = str_replace($healthy, $yummy, $phrase); 32 | $is_mark = prvd_xcheck($result); 33 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 34 | 35 | // Provides: 2 36 | $str = "good golly miss molly!"; 37 | prvd_xmark($str); 38 | $result = str_replace("ll", "", $str, $count); 39 | $is_mark = prvd_xcheck($result); 40 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 41 | $this->assertEquals(2, $count); 42 | } 43 | } 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /tests/filter/001-strstr.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 15 | 16 | $result = strstr($email, '@', true); // As of PHP 5.3.0 17 | $is_mark = prvd_xcheck($result); 18 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /tests/filter/001-strtolower.php: -------------------------------------------------------------------------------- 1 | assertEquals($is_mark, PRVD_TAINT_ENABLE); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /tests/filter/001-strtoupper.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /tests/filter/001-substr.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | 17 | $result = substr($str, -2); // returns "ef" 18 | $is_mark = prvd_xcheck($result); 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 20 | 21 | $result = substr($str, -3, 1); // returns "d" 22 | $is_mark = prvd_xcheck($result); 23 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/filter/001-trim.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 22 | 23 | $result = trim($hello, "Hdle"); 24 | $is_mark = prvd_xcheck($result); 25 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 26 | 27 | $result = trim($binary, "\x00..\x1F"); 28 | $is_mark = prvd_xcheck($result); 29 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/filter/001-urldecode.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 20 | 21 | $result = urldecode($param[1]); 22 | $is_mark = prvd_xcheck($result); 23 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 24 | } 25 | } 26 | } 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /tests/filter/001-urlencode.php: -------------------------------------------------------------------------------- 1 | '; 13 | 14 | $is_mark = prvd_xcheck($result); 15 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | } 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/filter/001-vsprintf.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/opcode/001-assign_concat.php: -------------------------------------------------------------------------------- 1 | assertEquals(false, $is_mark); 13 | 14 | $append = "hello"; 15 | prvd_xmark($append); 16 | 17 | $result .= $append; 18 | $is_mark = prvd_xcheck($result); 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 20 | } 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/opcode/001-concat.php: -------------------------------------------------------------------------------- 1 | assertEquals(false, $is_mark); 13 | 14 | $append = "hello"; 15 | prvd_xmark($append); 16 | 17 | $result = "xxx".$append; 18 | $is_mark = prvd_xcheck($result); 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $is_mark); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/opcode/001-do_fcall.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/opcode/001-do_fcall_by_name.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 24 | } 25 | 26 | public function testWithPayload() 27 | { 28 | global $prvd_sentry_client; 29 | $prvd_sentry_client = new Dummy_Sentry_Client(); 30 | 31 | $function = "do_fcall_by_name_".PRVD_TANZI; 32 | 33 | $function(); 34 | $this->assertEquals(true, $prvd_sentry_client->captured); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/opcode/001-do_icall.php: -------------------------------------------------------------------------------- 1 | assertEquals(true, true); 12 | } 13 | } 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/opcode/001-do_ucall.php: -------------------------------------------------------------------------------- 1 | assertEquals(true, true); 12 | } 13 | } 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/opcode/001-echo.php: -------------------------------------------------------------------------------- 1 | expectOutputString($url); 16 | echo $url; 17 | 18 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /tests/opcode/001-exit.php: -------------------------------------------------------------------------------- 1 | assertEquals(true, prvd_xcheck($a)); 13 | 14 | $z = "$a hello"; 15 | $this->assertEquals(PRVD_TAINT_ENABLE, prvd_xcheck($z)); 16 | } 17 | } 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/opcode/001-include_or_eval.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | public function testEvalWithTaint() 21 | { 22 | global $prvd_sentry_client; 23 | $prvd_sentry_client = new Dummy_Sentry_Client(); 24 | 25 | $code = "\$d = 'test';"; 26 | prvd_xmark($code); 27 | 28 | eval($code); 29 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 30 | } 31 | 32 | public function testIncludeWithPayload() 33 | { 34 | global $prvd_sentry_client; 35 | $prvd_sentry_client = new Dummy_Sentry_Client(); 36 | 37 | $path = TEST_PAYLOAD; 38 | 39 | @include $path; 40 | $this->assertEquals(true, $prvd_sentry_client->captured); 41 | } 42 | 43 | public function testEvalWithPayload() 44 | { 45 | global $prvd_sentry_client; 46 | $prvd_sentry_client = new Dummy_Sentry_Client(); 47 | 48 | eval("\$xtanzi=1;"); 49 | $this->assertEquals(true, $prvd_sentry_client->captured); 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /tests/opcode/001-init_dynamic_call.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 22 | } 23 | 24 | public function testWithPayload() 25 | { 26 | global $prvd_sentry_client; 27 | $prvd_sentry_client = new Dummy_Sentry_Client(); 28 | 29 | $function = "init_dynamic_call_".PRVD_TANZI; 30 | 31 | $function(); 32 | $this->assertEquals(true, $prvd_sentry_client->captured); 33 | } 34 | } 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /tests/opcode/001-init_method_call.php: -------------------------------------------------------------------------------- 1 | $method(); 25 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 26 | } 27 | 28 | public function testWithPayload() 29 | { 30 | global $prvd_sentry_client; 31 | $prvd_sentry_client = new Dummy_Sentry_Client(); 32 | 33 | $c = new init_method_call_example(); 34 | $method = TEST_PAYLOAD; 35 | 36 | $c->$method(); 37 | $this->assertEquals(true, $prvd_sentry_client->captured); 38 | } 39 | } 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /tests/opcode/001-init_user_call.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | public function testWithPayload() 21 | { 22 | global $prvd_sentry_client; 23 | $prvd_sentry_client = new Dummy_Sentry_Client(); 24 | 25 | $method = TEST_PAYLOAD; 26 | 27 | @call_user_func(array("my_class", $method), "test"); 28 | $this->assertEquals(true, $prvd_sentry_client->captured); 29 | } 30 | } 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/opcode/001-rope_end.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $is_mark); 16 | } 17 | } 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/sink/file/001-copy.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 19 | } 20 | 21 | 22 | public function testWithPayload() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $file = TEST_PAYLOAD; 28 | $new_file = 'example.txt.bak'; 29 | 30 | @copy($file, $new_file); 31 | $this->assertEquals(true, $prvd_sentry_client->captured); 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /tests/sink/file/001-dir.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $dir = TEST_PAYLOAD; 27 | 28 | @dir($dir); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/sink/file/001-file.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-file_get_contents.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @file_get_contents($file); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/sink/file/001-file_put_contents.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @file_put_contents($file, 'test'); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/sink/file/001-fopen.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @fopen($file); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-glob.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @glob($file); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-highlight_file.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @highlight_file($file, true); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-link.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @link($file, 'newfile.txt'); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-move_uploaded_file.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @move_uploaded_file("test.txt", $file); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-opendir.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @opendir($file); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-readfile.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @readfile($file); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-rename.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @rename($file, "newname.txt"); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-rmdir.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @rmdir($file); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-scandir.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @scandir($file); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-show_source.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @show_source($file, true); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/file/001-unlink.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $file = TEST_PAYLOAD; 27 | 28 | @unlink($file); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/rce/001-exec.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $str = TEST_PAYLOAD; 27 | 28 | @exec("id {$str}"); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/rce/001-passthru.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $str = TEST_PAYLOAD; 27 | 28 | @passthru("id {$str}", $return_var); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/sink/rce/001-popen.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $str = TEST_PAYLOAD; 27 | 28 | @popen("id {$str}", "r"); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/rce/001-proc_open.php: -------------------------------------------------------------------------------- 1 | assertEquals(true, isset($pipes[1])); 25 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 26 | } 27 | 28 | 29 | public function testWithPayload() 30 | { 31 | global $prvd_sentry_client; 32 | $prvd_sentry_client = new Dummy_Sentry_Client(); 33 | 34 | $str = TEST_PAYLOAD; 35 | 36 | $proc = proc_open("id {$str}", 37 | array( 38 | array("pipe","r"), 39 | array("pipe","w"), 40 | array("pipe","w") 41 | ), 42 | $pipes); 43 | 44 | $this->assertEquals(true, isset($pipes[1])); 45 | $this->assertEquals(true, $prvd_sentry_client->captured); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tests/sink/rce/001-shell_exec.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | public function testBackquoteWithTaint() 21 | { 22 | global $prvd_sentry_client; 23 | $prvd_sentry_client = new Dummy_Sentry_Client(); 24 | 25 | $str = 'fate0'; 26 | prvd_xmark($str); 27 | 28 | @`id {$str}`; 29 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 30 | } 31 | 32 | public function testWithPayload() 33 | { 34 | global $prvd_sentry_client; 35 | $prvd_sentry_client = new Dummy_Sentry_Client(); 36 | 37 | $str = TEST_PAYLOAD; 38 | 39 | @shell_exec("id {$str}"); 40 | $this->assertEquals(true, $prvd_sentry_client->captured); 41 | } 42 | 43 | public function testBackquoteWithPayload() 44 | { 45 | global $prvd_sentry_client; 46 | $prvd_sentry_client = new Dummy_Sentry_Client(); 47 | 48 | $str = TEST_PAYLOAD; 49 | 50 | @`id {$str}`; 51 | $this->assertEquals(true, $prvd_sentry_client->captured); 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /tests/sink/rce/001-system.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $str = TEST_PAYLOAD; 27 | 28 | @system("id {$str}"); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/rce/001-unserialize.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 17 | } 18 | 19 | 20 | public function testWithPayload() 21 | { 22 | $this->assertEquals(true, true); 23 | /* 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $str = TEST_PAYLOAD; 28 | @unserialize($str); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | 31 | $prvd_sentry_client->captured = false; 32 | 33 | $str = serialize($str); 34 | var_dump($str); 35 | @unserialize($str); 36 | $this->assertEquals(false, $prvd_sentry_client->captured); 37 | */ 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-mysqli.php: -------------------------------------------------------------------------------- 1 | mysqli = new mysqli(MYSQL_DB_HOST, MYSQL_DB_USERNAME, MYSQL_DB_PASSWORD, MYSQL_DB_NAME); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | $this->mysqli->close(); 20 | } 21 | 22 | public function testQueryWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @$this->mysqli->query("SELECT user FROM user LIMIT ".$id); 31 | $this->assertEquals($prvd_sentry_client->captured, PRVD_TAINT_ENABLE); 32 | } 33 | 34 | public function testPrepareWithTaint() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = "1"; 40 | prvd_xmark($id); 41 | 42 | @$this->mysqli->prepare("SELECT user FROM user LIMIT ".$id); 43 | $this->assertEquals($prvd_sentry_client->captured, PRVD_TAINT_ENABLE); 44 | } 45 | 46 | public function testRealQueryWithTaint() 47 | { 48 | global $prvd_sentry_client; 49 | $prvd_sentry_client = new Dummy_Sentry_Client(); 50 | 51 | $id = "1"; 52 | prvd_xmark($id); 53 | 54 | @$this->mysqli->real_query("SELECT user FROM user LIMIT ".$id); 55 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 56 | } 57 | 58 | public function testMultiQueryWithTaint() 59 | { 60 | global $prvd_sentry_client; 61 | $prvd_sentry_client = new Dummy_Sentry_Client(); 62 | 63 | $id = "1"; 64 | prvd_xmark($id); 65 | 66 | @$this->mysqli->multi_query("SELECT user FROM user LIMIT ".$id); 67 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 68 | } 69 | 70 | 71 | public function testQueryWithPayload() 72 | { 73 | global $prvd_sentry_client; 74 | $prvd_sentry_client = new Dummy_Sentry_Client(); 75 | 76 | $id = TEST_PAYLOAD; 77 | 78 | @$this->mysqli->query("SELECT user FROM user LIMIT ".$id); 79 | $this->assertEquals(true, $prvd_sentry_client->captured); 80 | } 81 | 82 | public function testPrepareWithPayload() 83 | { 84 | global $prvd_sentry_client; 85 | $prvd_sentry_client = new Dummy_Sentry_Client(); 86 | 87 | $id = TEST_PAYLOAD; 88 | 89 | @$this->mysqli->prepare("SELECT user FROM user LIMIT ".$id); 90 | $this->assertEquals(true, $prvd_sentry_client->captured); 91 | } 92 | 93 | public function testRealQueryWithPayload() 94 | { 95 | global $prvd_sentry_client; 96 | $prvd_sentry_client = new Dummy_Sentry_Client(); 97 | 98 | $id = TEST_PAYLOAD; 99 | 100 | @$this->mysqli->real_query("SELECT user FROM user LIMIT ".$id); 101 | $this->assertEquals(true, $prvd_sentry_client->captured); 102 | } 103 | 104 | public function testMultiQueryWithPayload() 105 | { 106 | global $prvd_sentry_client; 107 | $prvd_sentry_client = new Dummy_Sentry_Client(); 108 | 109 | $id = TEST_PAYLOAD; 110 | 111 | @$this->mysqli->multi_query("SELECT user FROM user LIMIT ".$id); 112 | $this->assertEquals(true, $prvd_sentry_client->captured); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-mysqli_init.php: -------------------------------------------------------------------------------- 1 | assertEquals(true, $conn instanceof mysqli); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-mysqli_multi_query.php: -------------------------------------------------------------------------------- 1 | link = mysqli_connect(MYSQL_DB_HOST, MYSQL_DB_USERNAME, MYSQL_DB_PASSWORD, MYSQL_DB_NAME); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | mysqli_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @mysqli_multi_query($this->link, "SELECT user FROM user LIMIT ".$id); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | @mysqli_multi_query($this->link, "SELECT user FROM user LIMIT ".$id); 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-mysqli_prepare.php: -------------------------------------------------------------------------------- 1 | link = mysqli_connect(MYSQL_DB_HOST, MYSQL_DB_USERNAME, MYSQL_DB_PASSWORD, MYSQL_DB_NAME); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | mysqli_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @mysqli_prepare($this->link, "SELECT user FROM user LIMIT ".$id); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | @mysqli_prepare($this->link, "SELECT user FROM user LIMIT ".$id); 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-mysqli_query.php: -------------------------------------------------------------------------------- 1 | link = mysqli_connect(MYSQL_DB_HOST, MYSQL_DB_USERNAME, MYSQL_DB_PASSWORD, MYSQL_DB_NAME); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | mysqli_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @mysqli_query($this->link, "SELECT user FROM user LIMIT ".$id); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | @mysqli_query($this->link, "SELECT user FROM user LIMIT ".$id); 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-mysqli_real_query.php: -------------------------------------------------------------------------------- 1 | link = mysqli_connect(MYSQL_DB_HOST, MYSQL_DB_USERNAME, MYSQL_DB_PASSWORD, MYSQL_DB_NAME); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | mysqli_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @mysqli_real_query($this->link, "SELECT user FROM user LIMIT ".$id); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | @mysqli_real_query($this->link, "SELECT user FROM user LIMIT ".$id); 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-pdo.php: -------------------------------------------------------------------------------- 1 | pgsql = new PDO("pgsql:dbname=".PG_DB_NAME.";host=".PG_DB_HOST, PG_DB_USERNAME, PG_DB_PASSWORD); 17 | $this->mysql = new PDO("mysql:dbname=".MYSQL_DB_NAME.';host='.MYSQL_DB_HOST, MYSQL_DB_USERNAME, MYSQL_DB_PASSWORD); 18 | $this->sqlite = new PDO("sqlite:".SQLITE_DB); 19 | } 20 | 21 | public function testQueryWithTaint() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $id = "1"; 27 | prvd_xmark($id); 28 | 29 | $prvd_sentry_client->captured = false; 30 | $this->pgsql->query("SELECT user FROM pg_user LIMIT ".$id); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | 33 | $prvd_sentry_client->captured = false; 34 | $this->mysql->query("SELECT user from user LIMIT ".$id); 35 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 36 | 37 | $prvd_sentry_client->captured = false; 38 | $this->sqlite->query("SELECT name from sqlite_master LIMIT ".$id); 39 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 40 | } 41 | 42 | public function testPrepareWithTaint() 43 | { 44 | global $prvd_sentry_client; 45 | $prvd_sentry_client = new Dummy_Sentry_Client(); 46 | 47 | $id = "1"; 48 | prvd_xmark($id); 49 | 50 | $prvd_sentry_client->captured = false; 51 | $this->pgsql->prepare("SELECT user FROM pg_user LIMIT ".$id); 52 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 53 | 54 | $prvd_sentry_client->captured = false; 55 | $this->mysql->prepare("SELECT user from user LIMIT ".$id); 56 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 57 | 58 | $prvd_sentry_client->captured = false; 59 | $this->sqlite->prepare("SELECT name from sqlite_master LIMIT ".$id); 60 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 61 | } 62 | 63 | public function testExecWithTaint() 64 | { 65 | global $prvd_sentry_client; 66 | $prvd_sentry_client = new Dummy_Sentry_Client(); 67 | 68 | $id = "1"; 69 | prvd_xmark($id); 70 | 71 | $prvd_sentry_client->captured = false; 72 | $this->pgsql->exec("SELECT user FROM pg_user LIMIT ".$id); 73 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 74 | 75 | $prvd_sentry_client->captured = false; 76 | $this->mysql->exec("SELECT user FROM user LIMIT ".$id); 77 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 78 | 79 | $prvd_sentry_client->captured = false; 80 | $this->sqlite->exec("SELECT name FROM sqlite_master LIMIT ".$id); 81 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 82 | } 83 | 84 | public function testQueryWithPayload() 85 | { 86 | global $prvd_sentry_client; 87 | $prvd_sentry_client = new Dummy_Sentry_Client(); 88 | 89 | $id = TEST_PAYLOAD; 90 | 91 | $prvd_sentry_client->captured = false; 92 | @$this->pgsql->query("SELECT user FROM pg_user LIMIT ".$id); 93 | $this->assertEquals(true, $prvd_sentry_client->captured); 94 | 95 | $prvd_sentry_client->captured = false; 96 | @$this->mysql->query("SELECT user from user LIMIT ".$id); 97 | $this->assertEquals(true, $prvd_sentry_client->captured); 98 | 99 | $prvd_sentry_client->captured = false; 100 | @$this->sqlite->query("SELECT name from sqlite_master LIMIT ".$id); 101 | $this->assertEquals(true, $prvd_sentry_client->captured); 102 | } 103 | 104 | public function testPrepareWithPayload() 105 | { 106 | global $prvd_sentry_client; 107 | $prvd_sentry_client = new Dummy_Sentry_Client(); 108 | 109 | $id = TEST_PAYLOAD; 110 | 111 | $prvd_sentry_client->captured = false; 112 | @$this->pgsql->prepare("SELECT user FROM pg_user LIMIT ".$id); 113 | $this->assertEquals(true, $prvd_sentry_client->captured); 114 | 115 | $prvd_sentry_client->captured = false; 116 | @$this->mysql->prepare("SELECT user from user LIMIT ".$id); 117 | $this->assertEquals(true, $prvd_sentry_client->captured); 118 | 119 | $prvd_sentry_client->captured = false; 120 | @$this->sqlite->prepare("SELECT name from sqlite_master LIMIT ".$id); 121 | $this->assertEquals(true, $prvd_sentry_client->captured); 122 | } 123 | 124 | public function testExecWithPayload() 125 | { 126 | global $prvd_sentry_client; 127 | $prvd_sentry_client = new Dummy_Sentry_Client(); 128 | 129 | $id = TEST_PAYLOAD; 130 | 131 | $prvd_sentry_client->captured = false; 132 | @$this->pgsql->exec("SELECT user FROM pg_user LIMIT ".$id); 133 | $this->assertEquals(true, $prvd_sentry_client->captured); 134 | 135 | $prvd_sentry_client->captured = false; 136 | @$this->mysql->exec("SELECT user FROM user LIMIT ".$id); 137 | $this->assertEquals(true, $prvd_sentry_client->captured); 138 | 139 | $prvd_sentry_client->captured = false; 140 | @$this->sqlite->exec("SELECT name FROM sqlite_master LIMIT ".$id); 141 | $this->assertEquals(true, $prvd_sentry_client->captured); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-pg_prepare.php: -------------------------------------------------------------------------------- 1 | link = pg_connect("host=".PG_DB_HOST." port=".PG_DB_PORT." dbname=".PG_DB_NAME." user=".PG_DB_USERNAME." password=".PG_DB_PASSWORD); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | pg_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @pg_prepare($this->link, "my_query", 'SELECT user FROM pg_user LIMIT '.$id); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | @pg_prepare($this->link, "my_query", 'SELECT user FROM pg_user LIMIT '.$id); 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-pg_query.php: -------------------------------------------------------------------------------- 1 | link = pg_connect("host=".PG_DB_HOST." port=".PG_DB_PORT." dbname=".PG_DB_NAME." user=".PG_DB_USERNAME." password=".PG_DB_PASSWORD); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | pg_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @pg_query($this->link, 'SELECT user FROM pg_user LIMIT '.$id); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | @pg_query($this->link, 'SELECT user FROM pg_user LIMIT '.$id); 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-pg_query_params.php: -------------------------------------------------------------------------------- 1 | link = pg_connect("host=".PG_DB_HOST." port=".PG_DB_PORT." dbname=".PG_DB_NAME." user=".PG_DB_USERNAME." password=".PG_DB_PASSWORD); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | pg_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @pg_query_params($this->link, "SELECT user FROM pg_user LIMIT ".$id, array()); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | @pg_query_params($this->link, "SELECT user FROM pg_user LIMIT ".$id, array()); 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-pg_send_prepare.php: -------------------------------------------------------------------------------- 1 | link = pg_connect("host=".PG_DB_HOST." port=".PG_DB_PORT." dbname=".PG_DB_NAME." user=".PG_DB_USERNAME." password=".PG_DB_PASSWORD); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | pg_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @pg_send_prepare($this->link, "test_pg_send_prepare", "SELECT user FROM pg_user LIMIT ".$id); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | @pg_send_prepare($this->link, "test_pg_send_prepare", "SELECT user FROM pg_user LIMIT ".$id); 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-pg_send_query.php: -------------------------------------------------------------------------------- 1 | link = pg_connect("host=".PG_DB_HOST." port=".PG_DB_PORT." dbname=".PG_DB_NAME." user=".PG_DB_USERNAME." password=".PG_DB_PASSWORD); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | pg_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @pg_send_query($this->link, "SELECT user FROM pg_user LIMIT ".$id); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | $prvd_sentry_client->captured = false; 42 | @pg_send_query($this->link, "SELECT user FROM pg_user LIMIT ".$id); 43 | $this->assertEquals(true, $prvd_sentry_client->captured); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-pg_send_query_params.php: -------------------------------------------------------------------------------- 1 | link = pg_connect("host=".PG_DB_HOST." port=".PG_DB_PORT." dbname=".PG_DB_NAME." user=".PG_DB_USERNAME." password=".PG_DB_PASSWORD); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | pg_close($this->link); 20 | } 21 | 22 | public function testWithTaint() 23 | { 24 | global $prvd_sentry_client; 25 | $prvd_sentry_client = new Dummy_Sentry_Client(); 26 | 27 | $id = "1"; 28 | prvd_xmark($id); 29 | 30 | @pg_send_query_params($this->link, "SELECT user FROM pg_user LIMIT ".$id, array()); 31 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 32 | } 33 | 34 | public function testWithPayload() 35 | { 36 | global $prvd_sentry_client; 37 | $prvd_sentry_client = new Dummy_Sentry_Client(); 38 | 39 | $id = TEST_PAYLOAD; 40 | 41 | @pg_send_query_params($this->link, "SELECT user FROM pg_user LIMIT ".$id, array()); 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/sink/sqli/001-sqlite3.php: -------------------------------------------------------------------------------- 1 | db = new SQLite3(SQLITE_DB); 15 | @$this->db->exec('CREATE TABLE IF NOT EXISTS bar (bar STRING)'); 16 | } 17 | 18 | public function tearDown() 19 | { 20 | $this->db->close(); 21 | } 22 | 23 | public function testExecWithTaint() 24 | { 25 | global $prvd_sentry_client; 26 | $prvd_sentry_client = new Dummy_Sentry_Client(); 27 | 28 | $id = "1"; 29 | prvd_xmark($id); 30 | 31 | @$this->db->exec("SELECT name FROM sqlite_master LIMIT ".$id); 32 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 33 | } 34 | 35 | public function testQueryWithTaint() 36 | { 37 | global $prvd_sentry_client; 38 | $prvd_sentry_client = new Dummy_Sentry_Client(); 39 | 40 | $id = "1"; 41 | prvd_xmark($id); 42 | 43 | @$this->db->query("SELECT name FROM sqlite_master LIMIT ".$id); 44 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 45 | } 46 | 47 | public function testPrepareWithTaint() 48 | { 49 | global $prvd_sentry_client; 50 | $prvd_sentry_client = new Dummy_Sentry_Client(); 51 | 52 | $id = "1"; 53 | prvd_xmark($id); 54 | 55 | @$this->db->prepare("SELECT name FROM sqlite_master LIMIT ".$id); 56 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 57 | } 58 | 59 | public function testQuerySingleWithTaint() 60 | { 61 | global $prvd_sentry_client; 62 | $prvd_sentry_client = new Dummy_Sentry_Client(); 63 | 64 | $id = "1"; 65 | prvd_xmark($id); 66 | 67 | @$this->db->querySingle("SELECT name FROM sqlite_master LIMIT ".$id, true); 68 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 69 | } 70 | 71 | public function testExecWithPayload() 72 | { 73 | global $prvd_sentry_client; 74 | $prvd_sentry_client = new Dummy_Sentry_Client(); 75 | 76 | $id = TEST_PAYLOAD; 77 | 78 | @$this->db->exec("SELECT name FROM sqlite_master LIMIT ".$id); 79 | $this->assertEquals(true, $prvd_sentry_client->captured); 80 | } 81 | 82 | public function testQueryWithPayload() 83 | { 84 | global $prvd_sentry_client; 85 | $prvd_sentry_client = new Dummy_Sentry_Client(); 86 | 87 | $id = TEST_PAYLOAD; 88 | 89 | @$this->db->query("SELECT name FROM sqlite_master LIMIT ".$id); 90 | $this->assertEquals(true, $prvd_sentry_client->captured); 91 | } 92 | 93 | public function testPrepareWithPayload() 94 | { 95 | global $prvd_sentry_client; 96 | $prvd_sentry_client = new Dummy_Sentry_Client(); 97 | 98 | $id = TEST_PAYLOAD; 99 | 100 | @$this->db->prepare("SELECT name FROM sqlite_master LIMIT ".$id); 101 | $this->assertEquals(true, $prvd_sentry_client->captured); 102 | } 103 | 104 | public function testQuerySingleWithPayload() 105 | { 106 | global $prvd_sentry_client; 107 | $prvd_sentry_client = new Dummy_Sentry_Client(); 108 | 109 | $id = TEST_PAYLOAD; 110 | 111 | @$this->db->querySingle("SELECT name FROM sqlite_master LIMIT ".$id); 112 | $this->assertEquals(true, $prvd_sentry_client->captured); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /tests/sink/sqli/config.php: -------------------------------------------------------------------------------- 1 | assertEquals(false, $prvd_sentry_client->captured); 25 | } 26 | 27 | 28 | public function testWithPayload() 29 | { 30 | global $prvd_sentry_client; 31 | $prvd_sentry_client = new Dummy_Sentry_Client(); 32 | 33 | $url = TEST_PAYLOAD; 34 | 35 | $ch = curl_init(); 36 | curl_setopt($ch, CURLOPT_URL, $url); 37 | curl_setopt($ch, CURLOPT_HEADER, 0); 38 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 39 | curl_exec($ch); 40 | curl_close($ch); 41 | 42 | $this->assertEquals(true, $prvd_sentry_client->captured); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/sink/ssrf/001-file_get_contents.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $url = TEST_PAYLOAD; 27 | 28 | @file_get_contents($url); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /tests/sink/ssrf/001-fsockopen.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $host = TEST_PAYLOAD; 27 | 28 | @fsockopen($host, 80, $errno, $errstr, 30); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/sink/ssrf/001-get_headers.php: -------------------------------------------------------------------------------- 1 | assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 18 | } 19 | 20 | 21 | public function testWithPayload() 22 | { 23 | global $prvd_sentry_client; 24 | $prvd_sentry_client = new Dummy_Sentry_Client(); 25 | 26 | $url = TEST_PAYLOAD; 27 | 28 | @get_headers($url); 29 | $this->assertEquals(true, $prvd_sentry_client->captured); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/sink/xss/001-print_r.php: -------------------------------------------------------------------------------- 1 | expectOutputString($url); 17 | print_r($url); 18 | 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/sink/xss/001-printf.php: -------------------------------------------------------------------------------- 1 | expectOutputString("hello ".$url); 17 | printf("hello %s", $url); 18 | 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/sink/xss/001-vprintf.php: -------------------------------------------------------------------------------- 1 | expectOutputString("hello ".$url); 17 | vprintf("hello %s", array($url)); 18 | 19 | $this->assertEquals(PRVD_TAINT_ENABLE, $prvd_sentry_client->captured); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/fuzzer.php: -------------------------------------------------------------------------------- 1 | options = $options; 27 | $this->multi_handle = curl_multi_init(); 28 | $this->requests = array(); 29 | $this->join_timeout = $join_timeout; 30 | } 31 | 32 | public function __destruct() 33 | { 34 | $this->join(); 35 | } 36 | 37 | public function enqueue($url, $method = 'GET', $headers = array(), $data = null) 38 | { 39 | if (DEBUG) { 40 | echo json_encode(array( 41 | "method" => $method, 42 | "url" => $url, 43 | "headers" => $headers, 44 | "body" => $data, 45 | ), JSON_PRETTY_PRINT); 46 | return; 47 | } 48 | 49 | $ch = curl_init(); 50 | 51 | $new_headers = array(); 52 | foreach ($headers as $key => $value) { 53 | array_push($new_headers, $key .': '. $value); 54 | } 55 | // XXX(dcramer): Prevent 100-continue response form server (Fixes GH-216) 56 | $new_headers[] = 'Expect:'; 57 | 58 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); 59 | curl_setopt($ch, CURLOPT_HTTPHEADER, $new_headers); 60 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 61 | curl_setopt($ch, CURLOPT_URL, $url); 62 | 63 | curl_setopt_array($ch, $this->options); 64 | 65 | if (isset($data)) { 66 | curl_setopt($ch, CURLOPT_POST, true); 67 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 68 | } 69 | 70 | curl_multi_add_handle($this->multi_handle, $ch); 71 | 72 | $fd = (int)$ch; 73 | $this->requests[$fd] = 1; 74 | 75 | $this->select(); 76 | 77 | return $fd; 78 | } 79 | 80 | public function join($timeout = null) 81 | { 82 | if (!isset($timeout)) { 83 | $timeout = $this->join_timeout; 84 | } 85 | $start = time(); 86 | do { 87 | $this->select(); 88 | if (count($this->requests) === 0) { 89 | break; 90 | } 91 | usleep(10000); 92 | } while ($timeout !== 0 && time() - $start < $timeout); 93 | } 94 | 95 | protected function select() 96 | { 97 | $active = false; 98 | 99 | do { 100 | $mrc = curl_multi_exec($this->multi_handle, $active); 101 | } while ($mrc == CURLM_CALL_MULTI_PERFORM); 102 | 103 | while ($active && $mrc == CURLM_OK) { 104 | if (curl_multi_select($this->multi_handle) !== -1) { 105 | do { 106 | $mrc = curl_multi_exec($this->multi_handle, $active); 107 | } while ($mrc == CURLM_CALL_MULTI_PERFORM); 108 | } else { 109 | return; 110 | } 111 | } 112 | 113 | while ($info = curl_multi_info_read($this->multi_handle)) { 114 | $ch = $info['handle']; 115 | $fd = (int)$ch; 116 | 117 | curl_multi_remove_handle($this->multi_handle, $ch); 118 | 119 | if (!isset($this->requests[$fd])) { 120 | return; 121 | } 122 | 123 | unset($this->requests[$fd]); 124 | } 125 | } 126 | } 127 | 128 | 129 | function unparse_url($parsed_url) { 130 | $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; 131 | $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; 132 | $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; 133 | $user = isset($parsed_url['user']) ? $parsed_url['user'] : ''; 134 | $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : ''; 135 | $pass = ($user || $pass) ? "$pass@" : ''; 136 | $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; 137 | $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : ''; 138 | $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : ''; 139 | return "$scheme$user$pass$host$port$path$query$fragment"; 140 | } 141 | 142 | 143 | function build_data_files($boundary, $fields, $files) { 144 | $data = ''; 145 | $eol = "\r\n"; 146 | 147 | $delimiter = '-------------' . $boundary; 148 | 149 | foreach ($fields as $name => $content) { 150 | $data .= "--" . $delimiter . $eol 151 | . 'Content-Disposition: form-data; name="' . $name . "\"".$eol.$eol 152 | . $content . $eol; 153 | } 154 | 155 | foreach ($files as $name => $content) { 156 | $data .= "--" . $delimiter . $eol 157 | . 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $content[0] . '"' . $eol 158 | . 'Content-Transfer-Encoding: binary'.$eol 159 | ; 160 | 161 | $data .= $eol; 162 | $data .= $content[1] . $eol; 163 | } 164 | $data .= "--" . $delimiter . "--".$eol; 165 | 166 | return $data; 167 | } 168 | 169 | 170 | function parse_qs($query_string) { 171 | $result = array(); 172 | foreach (explode('&', $query_string) as $param) { 173 | $i = explode('=', $param); 174 | $result[$i[0]] = $i[1]; 175 | } 176 | 177 | return $result; 178 | } 179 | 180 | 181 | class Fuzzer { 182 | static public $payloads = array('\'"<'. PRVD_TANZI.'>./../'. PRVD_TANZI); 183 | public $request; 184 | private $curl_handler = null; 185 | 186 | function __construct($request) 187 | { 188 | $options = array( 189 | CURLOPT_VERBOSE => true, 190 | CURLOPT_CONNECTTIMEOUT => 2, 191 | CURLOPT_TIMEOUT => 2, 192 | ); 193 | 194 | $this->curl_handler = new CurlHandler($options); 195 | $this->request = $request; 196 | } 197 | 198 | public function start() 199 | { 200 | var_dump($this->request); 201 | if (isset($this->request['query'])) $this->fuzz_query(); 202 | if (isset($this->request['data'])) $this->fuzz_body(); 203 | if (isset($this->request['files'])) $this->fuzz_files(); 204 | if (isset($this->request['cookies'])) $this->fuzz_cookies(); 205 | if (isset($this->request['headers'])) $this->fuzz_headers(); 206 | 207 | $this->curl_handler->join(); 208 | } 209 | 210 | private function fuzz_query() 211 | { 212 | $query = $this->request['query']; 213 | $fuzz_queries = Fuzzer::fuzz_value($query); 214 | 215 | foreach ($fuzz_queries as $fuzz_query) { 216 | $fuzz_request = $this->request; 217 | $fuzz_request['query'] = $fuzz_query; 218 | $this->make_request($fuzz_request, 'query'); 219 | } 220 | } 221 | 222 | private function fuzz_body() 223 | { 224 | $body = $this->request['data']; 225 | $fuzz_queries = Fuzzer::fuzz_value($body); 226 | 227 | foreach ($fuzz_queries as $fuzz_query) { 228 | $fuzz_request = $this->request; 229 | $fuzz_request['data'] = $fuzz_query; 230 | $this->make_request($fuzz_request, 'body'); 231 | } 232 | } 233 | 234 | private function fuzz_cookies() 235 | { 236 | $cookie = $this->request['cookies']; 237 | $fuzz_queries = Fuzzer::fuzz_value($cookie); 238 | 239 | foreach ($fuzz_queries as $fuzz_query) { 240 | $fuzz_request = $this->request; 241 | $fuzz_request['cookies'] = $fuzz_query; 242 | $this->make_request($fuzz_request, 'cookies'); 243 | } 244 | } 245 | 246 | private function fuzz_files() 247 | { 248 | $files = $this->request['files']; 249 | foreach ($files as $key => $file) { 250 | $fuzz_files = Fuzzer::add_value($file['name']); 251 | foreach ($fuzz_files as $fuzz_file) { 252 | $fuzz_request = $this->request; 253 | $fuzz_request['files'][$key]['name'] = $fuzz_file; 254 | $this->make_request($fuzz_request, 'body'); 255 | } 256 | 257 | $fuzz_files = Fuzzer::add_value(''); 258 | foreach ($fuzz_files as $fuzz_file) { 259 | $fuzz_request = $this->request; 260 | $fuzz_request['files'][$key]['data'] = $fuzz_file; 261 | $this->make_request($fuzz_request, 'body'); 262 | } 263 | } 264 | } 265 | 266 | private function fuzz_headers() 267 | { 268 | $headers = $this->request['headers']; 269 | $fuzz_headers = Fuzzer::fuzz_value($headers); 270 | 271 | foreach ($fuzz_headers as $fuzz_header) { 272 | $fuzz_request = $this->request; 273 | $fuzz_request['headers'] = $fuzz_header; 274 | $this->make_request($fuzz_request, "headers"); 275 | } 276 | } 277 | 278 | static function add_value($value) 279 | { 280 | $result = array(); 281 | foreach (Fuzzer::$payloads as $payload) { 282 | array_push($result, $value.$payload); 283 | } 284 | 285 | return $result; 286 | } 287 | 288 | static function fuzz_value($data) 289 | { 290 | $reqs = array(); 291 | 292 | $_fuzz_value = function (&$value) use (&$data, &$reqs, &$_fuzz_value) { 293 | if (is_array($value)) { 294 | foreach ($value as $each_key => &$each_value) { 295 | $new_values = $_fuzz_value($each_value); 296 | 297 | if (!$new_values) continue; 298 | 299 | foreach ($new_values as $new_value) { 300 | $old_value = $each_value; 301 | $value[$each_key] = $new_value; 302 | array_push($reqs, unserialize(serialize($data))); 303 | $value[$each_key] = $old_value; 304 | } 305 | } 306 | } elseif (is_string($value)) { 307 | $r = Fuzzer::add_value($value); 308 | return $r; 309 | } 310 | }; 311 | 312 | $_fuzz_value($data); 313 | return $reqs; 314 | } 315 | 316 | private function make_request($req, $fuzz_origin=null) 317 | { 318 | $method = strtoupper($req['method']); 319 | $headers = $req['headers']; 320 | $content_type = $headers["Content-Type"]; 321 | $body = null; 322 | $files = array(); 323 | 324 | if ($fuzz_origin === "query" && $req['query']) { 325 | $parsed_url = parse_url($req['url']); 326 | $parsed_url['query'] = http_build_query($req['query']); 327 | $url = unparse_url($parsed_url); 328 | } else { 329 | $url = $req['url']; 330 | } 331 | 332 | if ($fuzz_origin === "body" && $req['data']) { 333 | if (stripos($content_type, 'application/x-www-form-urlencoded') !== false) { 334 | $body = http_build_query($req['data']); 335 | } elseif (stripos($content_type, 'application/json')) { 336 | $body = json_encode($req['data']); 337 | } 338 | } else { 339 | $body = $req['data']; 340 | } 341 | 342 | if (stripos($content_type, 'multipart/form-data') !== false) { 343 | $body = parse_qs(http_build_query($req['data'])); 344 | 345 | if (isset($req['files']) && $req['files']) { 346 | foreach ($req['files'] as $key => $data) { 347 | if (isset($req['files'][$key]['data'])) 348 | $files[$key] = array($req['files'][$key]['name'], $req['files'][$key]['data']); 349 | else 350 | $files[$key] = array($req['files'][$key]['name'], '!PNG Hello'); 351 | } 352 | } 353 | 354 | $boundary = uniqid(); 355 | $delimiter = '-------------' . $boundary; 356 | 357 | $body = build_data_files($boundary, $body, $files); 358 | $headers['Content-Type'] = 'multipart/form-data; boundary='.$delimiter; 359 | } 360 | 361 | if ($fuzz_origin === 'cookies' && $req['cookies']) { 362 | $cookie_string = http_build_query($req['cookies']); 363 | $cookie_string = str_replace('&', ';', $cookie_string); 364 | $headers['Cookie'] = $cookie_string; 365 | } 366 | 367 | $headers['prvd-fuzzer'] = 'halo_from_fate0'; 368 | if (isset($headers['Content-Length'])) { 369 | unset($headers['Content-Length']); 370 | } 371 | 372 | $this->curl_handler->enqueue($url, $method, $headers, $body); 373 | } 374 | } 375 | 376 | 377 | if (!isset($_SERVER['HTTP_X_SENTRY_AUTH'])) { 378 | echo "forbidden"; 379 | return; 380 | }; 381 | 382 | 383 | $sentry_info = array(); 384 | $auth = $_SERVER['HTTP_X_SENTRY_AUTH']; 385 | foreach(explode(",", $auth) as $i) { 386 | list($key, $value) = explode("=", $i); 387 | $sentry_info[trim($key)] = trim($value); 388 | } 389 | 390 | 391 | if ($sentry_info['sentry_key'] != PRVD_FUZZER_USRENAME || $sentry_info['sentry_secret'] != PRVD_FUZZER_PASSWORD) { 392 | echo "access deny"; 393 | return; 394 | } 395 | 396 | 397 | $data = file_get_contents('php://input'); 398 | if (!$data) { 399 | echo "require data"; 400 | return; 401 | } 402 | 403 | 404 | if (function_exists('gzcompress')) 405 | $data = gzuncompress(base64_decode($data)); 406 | $data = json_decode($data, true); 407 | 408 | 409 | $fuzzer = new Fuzzer($data['request']); 410 | $fuzzer->start(); 411 | -------------------------------------------------------------------------------- /tools/fuzzer.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import unicode_literals 5 | 6 | import gevent.monkey 7 | gevent.monkey.patch_all() 8 | 9 | import sys 10 | import json 11 | import zlib 12 | import copy 13 | import base64 14 | import logging 15 | import requests 16 | import gevent.queue 17 | from flask import Flask, request 18 | from gevent.pywsgi import WSGIServer 19 | 20 | 21 | PY2 = sys.version_info[0] == 2 22 | if not PY2: 23 | unicode = str 24 | from urllib.parse import quote, urlsplit, urlunsplit, parse_qsl 25 | else: 26 | from urlparse import urlsplit, urlunsplit, parse_qsl 27 | from urllib import quote 28 | 29 | logger = logging.getLogger(__name__) 30 | logging.basicConfig(level=logging.INFO) 31 | app = Flask(__name__) 32 | task_queue = gevent.queue.Queue() 33 | 34 | 35 | def handle_task_queue(): 36 | while True: 37 | task = task_queue.get() 38 | 39 | method = task['method'] 40 | url = task['url'] 41 | headers = task['headers'] 42 | body = task['body'] 43 | files = task['files'] 44 | 45 | header_string = '\n'.join([key + ':' + value for key, value in headers.items()]) 46 | logger.debug("sending request\n{} {}\n{}\n\n{}\n{}\n".format(method, url, header_string, body, files)) 47 | try: 48 | requests.request(method=method, url=url, headers=headers, data=body, files=files, 49 | allow_redirects=False, timeout=5) 50 | except: 51 | pass 52 | 53 | 54 | class Fuzzer(object): 55 | payloads = ['\'\">./../xtanzi'] 56 | 57 | def __init__(self, _request): 58 | self.request = _request 59 | 60 | def start(self): 61 | logger.debug('origin request: \n{}'.format(json.dumps(self.request, indent=4))) 62 | 63 | if 'query' in self.request and self.request['query']: 64 | self.fuzz_query() 65 | 66 | if 'data' in self.request and self.request['data']: 67 | self.fuzz_body() 68 | 69 | if 'files' in self.request and self.request['files']: 70 | self.fuzz_files() 71 | 72 | if 'cookies' in self.request and self.request['cookies']: 73 | self.fuzz_cookies() 74 | 75 | if 'headers' in self.request and self.request['headers']: 76 | self.fuzz_headers() 77 | 78 | def fuzz_query(self): 79 | query = copy.deepcopy(self.request['query']) 80 | fuzz_queries = self.fuzz_value(query) 81 | 82 | for each_fuzz_query in fuzz_queries: 83 | fuzz_request = copy.deepcopy(self.request) 84 | fuzz_request['query'] = each_fuzz_query 85 | self.make_request(fuzz_request, 'query') 86 | 87 | def fuzz_body(self): 88 | body = copy.deepcopy(self.request['data']) 89 | fuzz_queries = self.fuzz_value(body) 90 | 91 | for each_fuzz_query in fuzz_queries: 92 | fuzz_request = copy.deepcopy(self.request) 93 | fuzz_request['data'] = each_fuzz_query 94 | self.make_request(fuzz_request, 'body') 95 | 96 | def fuzz_cookies(self): 97 | cookie = copy.deepcopy(self.request['cookies']) 98 | fuzz_queries = self.fuzz_value(cookie) 99 | 100 | for each_fuzz_query in fuzz_queries: 101 | fuzz_request = copy.deepcopy(self.request) 102 | fuzz_request['cookies'] = each_fuzz_query 103 | self.make_request(fuzz_request, 'cookies') 104 | 105 | def fuzz_files(self): 106 | # 暂时不支持 array 107 | files = copy.deepcopy(self.request['files']) 108 | for key in files: 109 | file_info = files[key] 110 | # fuzz 文件名 111 | for each_fuzz_data in self.add_value(file_info['name']): 112 | fuzz_request = copy.deepcopy(self.request) 113 | fuzz_request['files'][key]['name'] = each_fuzz_data 114 | self.make_request(fuzz_request, 'body') 115 | 116 | # fuzz 文件内容 117 | for each_fuzz_data in self.add_value(''): 118 | fuzz_request = copy.deepcopy(self.request) 119 | fuzz_request['files'][key]['data'] = each_fuzz_data 120 | self.make_request(fuzz_request, 'body') 121 | 122 | def fuzz_headers(self): 123 | headers = copy.deepcopy(self.request['headers']) 124 | fuzz_headers = self.fuzz_value(headers) 125 | 126 | for each_fuzz_header in fuzz_headers: 127 | fuzz_request = copy.deepcopy(self.request) 128 | fuzz_request['headers'] = each_fuzz_header 129 | self.make_request(fuzz_request, 'headers') 130 | 131 | @staticmethod 132 | def make_request(req, fuzz_origin=None): 133 | method = req['method'] 134 | headers = req['headers'] 135 | content_type = headers.get('Content-Type', '').lower() 136 | body = None 137 | files = {} 138 | 139 | if fuzz_origin == 'query' and 'query' in req and req['query']: 140 | urlspliter = urlsplit(req['url']) 141 | query_string = Fuzzer.json_to_php_array_string(req['query']) 142 | url = urlunsplit((urlspliter.scheme, urlspliter.netloc, 143 | urlspliter.path, query_string, urlspliter.fragment)) 144 | else: 145 | url = req['url'] 146 | 147 | if fuzz_origin == 'body' and 'data' in req and req['data']: 148 | if 'application/x-www-form-urlencoded' in content_type: 149 | body = Fuzzer.json_to_php_array_string(req['data']) 150 | elif 'application/json' in content_type: 151 | body = json.dumps(req['data']) 152 | elif 'multipart/form-data' in content_type: 153 | body = {} 154 | for key, value in parse_qsl(Fuzzer.json_to_php_array_string(req['data'])): 155 | body[key] = (None, value) 156 | 157 | req['headers'].pop('Content-Type') 158 | else: 159 | body = req.get('data') 160 | 161 | # 'multipart/form-data' 情况下,PHP 不支持获取原始 POST 数据,需要将 file 信息也设置好 162 | if 'multipart/form-data' in content_type: 163 | if 'files' in req and req['files']: 164 | for key in req['files']: 165 | files[key] = (req['files'][key]['name'], req['files'][key].get('data', '!PNG Hello')) 166 | 167 | if fuzz_origin == 'cookies' and 'cookies' in req and req['cookies']: 168 | cookie_string = Fuzzer.json_to_php_array_string(req['cookies']) 169 | cookie_string = cookie_string.replace('&', ';') 170 | headers['Cookie'] = cookie_string 171 | 172 | headers['prvd-fuzzer'] = 'halo_from_fate0' 173 | if 'Content-Length' in headers: 174 | headers.pop('Content-Length') 175 | 176 | task_queue.put({ 177 | 'method': method, 178 | 'url': url, 179 | 'headers': headers, 180 | 'body': body, 181 | 'files': files 182 | }) 183 | 184 | @staticmethod 185 | def add_value(value): 186 | result = [] 187 | for i in Fuzzer.payloads: 188 | value = value or '' 189 | result.append(value + i) 190 | 191 | return result 192 | 193 | @staticmethod 194 | def fuzz_value(data): 195 | """ 196 | >>> Fuzzer.fuzz_value({'a': {"d": {"c": "x"}}}) 197 | [{'a': {'d': 'x\\'">./../xtanzi'}}] 198 | """ 199 | reqs = [] 200 | 201 | def _fuzz_value(value): 202 | if isinstance(value, (dict, list)): 203 | items = value.items() if isinstance(value, dict) else enumerate(value) 204 | for each_key, each_value in items: 205 | new_values = _fuzz_value(each_value) 206 | 207 | if not new_values: 208 | continue 209 | 210 | for each_new_value in new_values: 211 | value[each_key] = each_new_value 212 | reqs.append(copy.deepcopy(data)) 213 | value[each_key] = each_value # 还原 214 | 215 | elif isinstance(value, unicode): 216 | return Fuzzer.add_value(value) 217 | 218 | _fuzz_value(data) 219 | return reqs 220 | 221 | @staticmethod 222 | def json_to_php_array_string(data): 223 | """ 224 | >>> Fuzzer.json_to_php_array_string({"key1": "value1", 'key2': 'value2'}) 225 | 'key1=value1&key2=value2' 226 | >>> Fuzzer.json_to_php_array_string({"key1": {"key11": "value11"}, "key2": "value2"}) 227 | 'key1[key11]=value11&key2=value2' 228 | >>> Fuzzer.json_to_php_array_string({"key1": ["value1", "value12", "value13"]}) 229 | 'key1[]=value1&key1[]=value12&key1[]=value13' 230 | >>> Fuzzer.json_to_php_array_string({"key1": {"key11": ['value11', 'value12']}}) 231 | 'key1[key11][]=value11&key1[key11][]=value12' 232 | """ 233 | 234 | def to_string(value): 235 | if isinstance(value, dict): 236 | d = [] 237 | for each_key, each_value in value.items(): 238 | result = to_string(each_value) 239 | 240 | if isinstance(result, list): 241 | for i in result: 242 | d.append('[%s]%s' % (each_key, i)) 243 | else: 244 | d.append('[%s]%s' % (each_key, result)) 245 | 246 | return d 247 | 248 | elif isinstance(value, list): 249 | d = [] 250 | for each_value in value: 251 | result = to_string(each_value) 252 | 253 | if isinstance(result, list): 254 | for i in result: 255 | d.append('[]%s' % i) 256 | else: 257 | d.append('[]%s' % result) 258 | 259 | return d 260 | 261 | elif isinstance(value, unicode): 262 | return '=' + quote(value) 263 | 264 | d = [] 265 | for i in data: 266 | result = to_string(data[i]) 267 | if isinstance(result, list): 268 | for j in result: 269 | d.append(i + j) 270 | else: 271 | d.append(i + result) 272 | 273 | return '&'.join(sorted(d)) 274 | 275 | @staticmethod 276 | def fuzz(_request): 277 | f = Fuzzer(_request) 278 | f.start() 279 | 280 | 281 | @app.route('/fuzz', methods=['POST']) 282 | def index(): 283 | if 'X-Sentry-Auth' not in request.headers: 284 | return "forbidden" 285 | 286 | h = request.headers['X-Sentry-Auth'] 287 | sentry_info = {} 288 | for i in h.split(','): 289 | key, value = i.split('=') 290 | sentry_info[key.strip()] = value.strip() 291 | 292 | if sentry_info['sentry_key'] != 'admin' or sentry_info['sentry_secret'] != 'password': 293 | return "access deny" 294 | 295 | if not request.data: 296 | return "require data" 297 | 298 | data = base64.b64decode(request.data) 299 | try: 300 | data = zlib.decompress(data) 301 | except: 302 | pass 303 | 304 | data = data.decode('utf-8', errors='ignore') 305 | data = json.loads(data) 306 | 307 | Fuzzer.fuzz(data['request']) 308 | return 'hello' 309 | 310 | 311 | if __name__ == '__main__': 312 | gevent.spawn(handle_task_queue) 313 | http_server = WSGIServer(('0.0.0.0', 9090), app) 314 | http_server.serve_forever() 315 | -------------------------------------------------------------------------------- /travis-php.ini: -------------------------------------------------------------------------------- 1 | auto_prepend_file = "src/Entry.php" 2 | extension = "modules/xmark.so" 3 | 4 | [xmark] 5 | xmark.enable = 1 6 | xmark.rename_enable = 0 7 | xmark.rename_classes = " 8 | SQLite3:prvd_SQLite3, 9 | mysqli:prvd_mysqli, 10 | PDO:prvd_PDO, 11 | " 12 | xmark.rename_functions = " 13 | base64_decode:prvd_base64_decode, 14 | basename:prvd_basename, 15 | dirname:prvd_dirname, 16 | explode:prvd_explode, 17 | gzuncompress:prvd_gzuncompress, 18 | hex2bin:prvd_hex2bin, 19 | html_entity_decode:prvd_html_entity_decode, 20 | htmlspecialchars_decode:prvd_htmlspecialchars_decode, 21 | implode:prvd_implode, 22 | join:prvd_join, 23 | json_decode:prvd_json_decode, 24 | ltrim:prvd_ltrim, 25 | pathinfo:prvd_pathinfo, 26 | rawurldecode:prvd_rawurldecode, 27 | rawurlencode:prvd_rawurlencode, 28 | rtrim:prvd_rtrim, 29 | sprintf:prvd_sprintf, 30 | str_ireplace:prvd_str_ireplace, 31 | str_pad:prvd_str_pad, 32 | str_replace:prvd_str_replace, 33 | strstr:prvd_strstr, 34 | strtolower:prvd_strtolower, 35 | strtoupper:prvd_strtoupper, 36 | substr:prvd_substr, 37 | trim:prvd_trim, 38 | urldecode:prvd_urldecode, 39 | urlencode:prvd_urlencode, 40 | vsprintf:prvd_vsprintf, 41 | 42 | exec:prvd_exec, 43 | passthru:prvd_passthru, 44 | popen:prvd_popen, 45 | proc_open:prvd_proc_open, 46 | shell_exec:prvd_shell_exec, 47 | system:prvd_system, 48 | unserialize:prvd_unserialize, 49 | 50 | copy:prvd_copy, 51 | dir:prvd_dir, 52 | file:prvd_file, 53 | file_get_contents:prvd_file_get_contents, 54 | file_put_contents:prvd_file_put_contents, 55 | fopen:prvd_fopen, 56 | glob:prvd_glob, 57 | highlight_file:prvd_highlight_file, 58 | link:prvd_link, 59 | move_uploaded_file:prvd_move_uploaded_file, 60 | opendir:prvd_opendir, 61 | readfile:prvd_readfile, 62 | rename:prvd_rename, 63 | rmdir:prvd_rmdir, 64 | scandir:prvd_scandir, 65 | show_source:prvd_show_source, 66 | unlink:prvd_unlink, 67 | 68 | mysqli_init:prvd_mysqli_init, 69 | mysqli_multi_query:prvd_mysqli_multi_query, 70 | mysqli_query:prvd_mysqli_query, 71 | mysqli_prepare:prvd_mysqli_prepare, 72 | mysqli_real_query:prvd_mysqli_real_query, 73 | pg_prepare:prvd_pg_prepare, 74 | pg_query:prvd_pg_query, 75 | pg_query_params:prvd_pg_query_params, 76 | pg_send_prepare:prvd_pg_send_prepare, 77 | pg_send_query:prvd_pg_send_query, 78 | pg_send_query_params:prvd_pg_send_query_params, 79 | 80 | curl_exec:prvd_curl_exec, 81 | fsockopen:prvd_fsockopen, 82 | get_headers:prvd_get_headers, 83 | 84 | print_r:prvd_print_r, 85 | printf:prvd_printf, 86 | vprintf:prvd_vprintf 87 | " 88 | --------------------------------------------------------------------------------