2019-2020-2 《网络对抗技术》 Exp8 Web基础

实践目标

本实践目标是安装 LAMP 构建 Web 服务器,并进行一些简单的攻击实践。

回答实践问题

1.什么是表单?

  • 表单在网页中主要负责数据采集功能。一个表单有三个基本组成部分:
    • 表单标签:这里面包含了处理表单数据所用CGI程序的URL以及数据提交到服务器的方法。
    • 表单域:包含了文本框(text)、密码框(password)、隐藏域(hidden)、多行文本框(TEXTAREA)、复选框(checkbox)、单选框(radio)、下拉选择框(select)和文件上传框(file)等。
    • 表单按钮:包括提交(submit)按钮、复位(reset)按钮和一般(button)按钮;用于将数据传送到服务器上的CGI脚本或者取消输入,还可以用表单按钮来控制其他定义了处理脚本的处理工作。

2.浏览器可以解析运行什么语言?

  • 支持HTML、XML及Python、PHP、JavaScript等脚本语言。

3.WebServer支持哪些动态语言?

  • ASP(ActiveServerPages)
  • JSP(JavaServerPages)
  • PHP(HypertextPreprocessor)

实践过程

docker 启动 lamp 容器

由于 kali 虚拟机出现了些莫名奇妙的错误,暂时不想搞这个东西,本次实验通过 Ubuntu 20.04 的 docker 安装 HTTPd 容器来进行。

  • 拉取 tutum/lamp image。

  • 以此构建运行 lamp 容器。

    • 映射端口:11201 -> 8011202 -> 443
    • 以交互式容器运行:-i -t

    可以看到容器列表:

  • 以 Ubuntu IP + 端口 访问容器的 Web 服务。

Web前端:HTML

能正常安装、启停Apache。理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML。

  • 容器中 apache2 服务默认已启用,可直接以 Ubuntu IP + 端口 访问容器的 Web 服务。

    • 如果要启用 apache2 :

      sudo service apache2 start
      
  • 该容器默认 web 服务的文件夹为 /var/www/html

    • 进入该文件。

      cd /var/www/html
      
    • ls 可以看到 index.php ,说明容器支持 PHP 。

  • 重新编写 index.php 文件:

    • 以下代码中不包含 PHP 语句,仅包含 html 语句。
    <html>
    <head>
    <title>Login</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    
        <h2 align="center">Login</h2>
    	<center>
            <form action="login" method="post">
                <input placeholder="Username" name="Name" class="user" type="email">
                <br>
                </br>
                <input  placeholder="Password" name="Password" class="pass" type="password">
                <br>
                </br>
                <input type="submit" value="Login">
            </form>
    	</center>
    </body>
    </html>
    
  • 重新以 Ubuntu IP + 端口 访问容器的 Web 服务。

Web前端:JavaScipt

理解JavaScript的基本功能,理解DOM。编写JavaScript验证用户名、密码的规则。

  • 以之前代码为基础,添加 一段 JavaScript 代码,结果编写为 index_add_js.php

    <html>
    <head>
    <title>User_Login</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    
    <body>
    
        <h2 align="center">Login</h2>
    	<center>
            <form action="login.php" method="post" name="form_login">
                <input placeholder="Username" name="Username" class="user" type="text" onfocus="if (this.value=='Your username') this.value='';" />
                <br>
                </br>
                <input  placeholder="Password" name="Password" class="pass" type="password" onfocus="if (this.value=='Your password') this.value='';"/>
                <br>
                </br>
                <input type="submit" value="Login"  onClick="return validateLogin()"/>
            </form>
    	</center>
    
    <script language="javascript">  
        function validateLogin(){  
            var sUserName = document.form_login.Name.value ;  
            var sPassword = document.form_login.Password.value ;    
            if ((sUserName =="") || (sUserName=="Your username")){  
            alert("请输入用户名!");  
            return false ;  
            }  
    
            if ((sPassword =="") || (sPassword=="Your password")){  
            alert("请输入密码!");  
            return false ;  
            }  
        }   
    </script>  
    
    </body>
    </html>
    
  • 重新以 Ubuntu IP + 端口 + index_add_js.php 访问容器的 Web 服务。

  • 无用户名输入提示:

  • 无密码输入提示:

Web后端:MySQL基础

  • 容器中 mysql 服务默认已启用。

    • 如果要启用 mysql :

      sudo /etc/init.d/mysql start
      

用户信息操作

  • 使用 root 权限进入 mysql 控制台:

    mysql -u root -p
    
    • 该容器 mysql 默认密码为 空。

    • 或者:

      update user set password=PASSWORD("yogile") where user='root';
      

      更新权限:

      flush privileges;
      
  • 更新数据库 root 密码。

    set password for 'root'@'localhost' =password('数据库root用户密码');
    

    • 这时,退出并使用空密码尝试登录 mysql 控制台。

  • 查看当前用户信息。

    select user, password, host from user;
    
  • 添加数据库新用户。

    grant select,insert,update,delete on 数据库名.* to 用户名@登录主机 identified by "密码";
    
    • 示例:

      grant select,insert,update,delete on yogile_exp8.login to yogile@localhost identified by "yogile";
      

      以 localhost IP 创建名为 yogile 、密码为 yogile 的数据库账号,并将 yogile_exp8 数据库下的 login 数据表的查找、插入、更新、删除 权限授予该账号。

    • 以新用户身份登录。

数据库操作

  • 查看数据库基本信息。

    show databases;
    

  • 创建数据库 yogile_exp8

    create database yogile_exp8;
    

  • 选定操作名为 yogile_exp8 的数据库。

    use yogile_exp8;
    
  • 建立数据库表 login ,并设置字段基本信息。

    create table login (username VARCHAR(20), password VARCHAR(20));
    

    该图包含上面两点。

  • 插入数据。

    insert into login values('yogile', '123123123');
    
  • 查询表中的数据.

    select * from login;
    
  • 指定字段信息,查询表中的数据。

    select * from login where username = 'yogile';
    
  • 指定字段信息,查询表中的某一字段的数据。

    select username from login where username = 'yogile';
    

    该图包含上面四点。

Web后端:PHP 与 MySQL

编写PHP网页,连接数据库,进行用户认证。

  • 编写 PHP 文件 index_php_mysql.php 测试 PHP 以及数据库连接。

    <?php 
    	$servername = "localhost";
        $mysqli_account = "yogile";
        $mysqli_pwd = "yogile";
        $mysqli_list = "yogile_exp8";
    
    // 创建连接
        $link = mysqli_connect($servername, $mysqli_account, $mysqli_pwd, $mysqli_list);
    ?>
    <html>
    <head>
    	<title>Hello world!</title>
    	<style>
    	body {
    		background-color: white;
    		text-align: center;
    		padding: 50px;
    		font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
    	}
    
    	#logo {
    		margin-bottom: 40px;
    	}
    	</style>
    </head>
    <body>
    	<h1><?php echo "Hello world!"; ?></h1>
    	<?php if(!$link) { ?>
    		<h2>Can't connect to local MySQL Server!</h2>
    	<?php } else { ?>
    		<h2>Successful connect to local MySQL Server!</h2>
    	<?php } ?>
    </body>
    </html>
    
    • 如果 PHP 编译无误、数据库连接成功。

  • 各项无误后,编写 login.php 文件,简单验证数据库登录。

    • 注意:这里 $_POST 获取参数值的参数名必须是 HTML <form> 语句中的 <input>name 一致。
    <?php
    $uname=$_POST["Username"];
    $pwd=$_POST["Password"];
    echo $uname;
    $query_str="SELECT * FROM login where username='$uname' and password='$pwd';";
    
    $servername = "localhost";
    $mysqli_account = "yogile";
    $mysqli_pwd = "yogile";
    $mysqli_list = "yogile_exp8";
    $mysqli = new mysqli($servername, $mysqli_account, $mysqli_pwd, $mysqli_list);
    
    $query_str1="use yogile_exp8;";
    
    /* check connection */
    if ($mysqli->connect_errno) {
        printf("Connect failed: %s\n", $mysqli->connect_error);
        exit();
    }
    echo "connection ok!";
    /* Select queries return a resultset */
    if ($result = $mysqli->query($query_str1))
    echo"<br>Success into database!";
    echo $uname;
    if ($result = $mysqli->query($query_str)) {
        if ($result->num_rows > 0 ){
                echo "<br> {$uname}:Welcome!!! <br> ";
        } 
        else {
            echo "<br> login failed!!!! <br> " ; }
        /* free result set */
        $result->close();
    }
    $mysqli->close();
    ?>
    
  • login.php 文件编写完成后,重新访问 index_add_js.php 网页。

    • 输入错误密码。

    • 输入正确密码。

最简单的SQL注入、XSS攻击测试

SQL注入

  • 就之前使用的代码,无论是在用户名,还是在密码的 <input> 中,输入 ' or 1=1# 都能判断登录成功。

  • 说明:

    select * from users where username='' or 1=1#' and password=''
    或
    select * from users where username='' and password='' or 1=1#'
    # 号后面的内容成为注释,or 1=1 使该SQL语句返回成功值。
    
  • 解决办法:使用正则表达式。

    • 下面是我编写的使用正则表达式的 JavaScript 表单检查函数。
    /**
     * 提交表单前检查表单内容
     * @param fromLogin
     * @returns {boolean}
     */
    function checkFrom(fromLogin) {
    	fromData[0] = fromLogin.name.value;
    	fromData[1] = fromLogin.password.value;
    	fromData[2] = fromLogin.verif.value;
    
    	// 检查 空字符串
    	for (let i = 0; i < 6; i++) {
    		if (fromData[i] === "") {
    			alert(fromList[i] + "不可为空");
    			// flag_result = false;
    			return false;
    		}
    	}
    
    	// 检查 name
    	if (/^[a-zA-Z][a-zA-Z0-9_-]{3,16}$/.test(fromData[0]) !== true) {
    		fromData[0] = "";
    		alert("用户名不满足条件:可包含字母开头、数字、下划线、减号的4到16位字符");
    		return false;
    	}
    	// 检查 password
    	let regExp_password = /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\W_!@#$%^&*`~()-+=]+$)(?![0-9\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9!@#$%^&*`~()]{8,20}$/;
    	if (regExp_password.test(fromData[1]) !== true) {
    		fromData[2] = "";
    		alert("密码格式错误,密码长度为8-20位,至少含有以下四种字符的其中三种:\n大写字母、小写字母、数字、特殊字符(!@#$%^&*`~())");
    		return false;
    	}
    	// 检查 verif
    	if (/^[a-zA-Z0-9_-]{4}$/.test(fromData[2]) !== true) {
    		fromData[2] = "";
    		alert("验证码错误,请重新获取");
    		return false;
    	}
    	if (fromData[2] !== verif_str) {
    		fromData[2] = "";
    		verif_str = "";
    		alert("验证码错误,请重新获取");
    		return false;
    	}
    
    	return true;
    }
    
    • 尝试SQL注入:

XSS攻击

  • 将一张图片放在/var/www/html目录下,在用户名输入框输入 <img src="xxxx.jpg" /> ,密码随意,读取图片。

  • 说明:

    XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。

  • 解决办法:使用正则表达式。

    • 我编写的使用正则表达式的表单检查函数在上一点。
  • 尝试XSS攻击。

实现总结与体会

  • 本次实验是安装 LAMP 组件构建 Web 服务器,并进行一些简单的攻击实践。
  • 上学期上过相关 JavaWeb 的相关课程,我自己也学习过 PHP 、Python 等语言,了解到想要做好网站的安全功能以及安全维护是非常困难的。
  • 所以对于不从事网络安全行业的所谓 “个人” 来说,使用现成已有的、商业化的 Web 服务,比如个人云盘 ownCloud、个人博客 WordPress 等等,都提供了基本可用的安全功能。
posted @ 2020-05-21 10:52  Yogile  阅读(228)  评论(0编辑  收藏  举报