20192424王昭云 2021-2022-2 《网络与系统攻防技术》实验八实验报告修改版
实验八 Web安全
1.实验内容及要求
(1)Web前端HTML
能正常安装、启停Apache。理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML。
(2)Web前端javascipt
理解JavaScript的基本功能,理解DOM。
在(1)的基础上,编写JavaScript验证用户名、密码的规则。在用户点击登陆按钮后回显“欢迎+输入的用户名”
尝试注入攻击:利用回显用户名注入HTML及JavaScript。
(3)Web后端:MySQL基础:正常安装、启动MySQL,建库、创建用户、修改密码、建表
(4)Web后端:编写PHP网页,连接数据库,进行用户认证
(5)最简单的SQL注入,XSS攻击测试
(6)安装Webgoat或类似平台,并完成SQL注入、XSS、CSRF攻击。
3.学习中遇到的问题及解决
遇到php没有mysal的dll以及ext文件
遇到apache安装后本地网页不能被访问
以上问题解决方法我写在实验过程中了
唉,算了,为了实验评分,再写一遍
问题一解决办法
- 直接使用最原始的yum install php,php-mysql,php-fpm
问题2解决办法
2.实验过程
Web前端HTML
-
apache安装与部署
-
环境centos7.6系统,已经安装python3并且设置了python3和Python2分开的软连接
-
安装
-
安装apache
- yum install httpd* -y
-
启动apache
- systemctl start httpd.service
-
查看apache状态
- systemctl status httpd.service
-
-
简单部署
-
设置主目录,我设置的主目录为/www/website/目录下,并在里面放置一个html文件。
-
修改配置文件httpd.conf,配置文件应该是在计算机文件里,然后实在找不到可以用find / -name httpd.conf搜索一下,其中/的意思是在这个目录中找,包含子目录,-name参数意思是按照名字查找
-
上图中为什么找到两个httpd.conf文件呢?其实是因为我们的apache正在运行所以有一个是临时文件它的路径里包含了temp,为了防止运行中的文件不能修改,我们先用systemctl kill httpd.service把apache服务关了
-
打开后本着深入学习其工作原理的原则,我来为大家讲解一下这个配置文件中部分语句的作用,详情见https://blog.csdn.net/WuLex/article/details/106868978?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-0-106868978-blog-40426259.pc_relevant_antiscanv2&spm=1001.2101.3001.4242.1&utm_relevant_index=3
- 配置文件包括一下三部分
1)Global Environment—全局环境配置,决定Apache服务器的全局参数
2)Main server configuration—主服务配置,相当于是Apache中的默认Web站点,如果我们的服务器中只有一个站点,那么就只需在这里配置就可以了。
3)Virtual Hosts—虚拟主机,虚拟主机不能与Main Server主服务器共存,当启用了虚拟主机之后,Main Server就不能使用了 - ServerRoot为服务器及其配置文件所在目录,部署网站不用管它
- PidFile run/httpd.pid是设置统一的父进程号,方便快速识别与不同客户间的连接,不然他们的进程号是不固定的。
- Timeout 60为服务器的断开时间
- KeepAlive Off为是否保持持续连接
- MaxKeepAliveRequests 100为最大挂起数
- 配置文件包括一下三部分
-
修改文件
-
修改后出现如下问题
-
-
-
编写前端带有表单的网页
<html> <head> <title>表单</title> </head> <body> <form> 姓名:<input type="text" value="wzy20192424" name="userName"/><br> 密码:<input type="password" value="111" name="pwd"/><br> </form> <br> <form> <input type="radio" value="male" name="sex" checked/>男 <input type="radio" value="male" name="sex"/>女<br> </form> <br> <form> <input type="checkbox" value="playguita" name="specialty" checked/>弹吉他 <input type="checkbox" value="唱歌" name="singing" checked/>唱歌 <input type="checkbox" value="弹吉他" name="playing" checked/>弹吉他 <input type="checkbox" value="十项全能" name="all" checked/>十项全能 </form> <br> <form action="" enctype="multipart/form-data"> 帅照:<input type="file" name="fileName"/> </form> <br> 地区: <select name="cities" size="2" multiple> <option value="sichuan" selected/>四川 <option value="guangdong" />广东 <option value="guangxi" />广西 <option value="上海"/>上海 </select> <br> <br> 更多描述:<textarea name="更多描述:" cols="100" rows="10"></textarea> <br> <br> <form> <input type="submit" value="提交"/> <input type="reset" value="重置" /> <input type="button" value="关闭" /> </form> </body> </html>```
-
将该网页在su权限下部署到apache的服务器根目录
-
成功在局域网的其他主机上访问
-
get和post请求的区别
- 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务端响应200,请求成功。
- 对于POST方式的请求,浏览器会先发送http header给服务端,告诉服务端等一下会有数据过来,服务端响应100 continue,告诉浏览器我已经准备接收数据,浏览器再post发送一个data给服务端,服务端响应200,请求成功。
- 但是上面所说的post会比get多一个tcp包其实不太严谨。多发的那个expect 100 continue header报文,是由客户端对http的post和get的请求策略决定的,目的是为了避免浪费资源,如带宽,数据传输消耗的时间等等。所以客户端会在发送header的时候添加expect 100去探探路,如果失败了就不用继续发送data,从而减少了资源的浪费。所以是否在发送一个包取决了客户端的实现策略,和get/post并没什么关系。有的客户端比如fireFox就只发送一个包。
-
什么是DOM
-
DOM就是document object model的缩写,是js语言中用于操作页面及其元素的对象,比如操纵鼠标特性,点击位置检测等等。
-
通过js实现一个前端判断输入用户名,密码是否正确并回显的网页,代码如下:
<html> <head> <title>表单</title> </head> <body> <form> 姓名:<input type="text" value="wzy20192424" name="userName"/><br> 密码:<input type="password" name="pwd"/><br> </form> <br> <form> <input type="radio" value="male" name="sex" checked/>男 <input type="radio" value="male" name="sex"/>女<br> </form> <br> <form> <input type="checkbox" value="playguita" name="specialty" checked/>弹吉他 <input type="checkbox" value="唱歌" name="singing" checked/>唱歌 <input type="checkbox" value="弹吉他" name="playing" checked/>弹吉他 <input type="checkbox" value="十项全能" name="all" checked/>十项全能 </form> <br> <form action="" enctype="multipart/form-data"> 帅照:<input type="file" name="fileName"/> </form> <br> 地区: <select name="cities" size="2" multiple> <option value="sichuan" selected/>四川 <option value="guangdong" />广东 <option value="guangxi" />广西 <option value="上海"/>上海 </select> <br> <br> 更多描述:<textarea name="更多描述:" cols="100" rows="10"></textarea> <br> <br> <form method="post" onsubmit="login()"> <input type="submit" value="提交" id="submit"/> <input type="reset" value="重置" name="reset"/> <input type="button" value="关闭" name="exit"/> </form> <script> function login(){ let username=document.querySelectorAll('input')[0].value let password=document.querySelectorAll('input')[1].value if(username=='wzy20192424' && password=='111') { alert(username+"登录成功") } else { alert("密码或者用户名错误") } } </script> </body> </html>
-
代码失败原因是没有后端,不过可以在前端检测密码用户名是否正确,其中就使用了dom的方法
-
-
尝试注入攻击
-
前端使用如下代码
<html> <head> <title>表单</title> </head> <body> <form method="post" onsubmit="login()"> 姓名:<input type="text" value="wzy20192424" name="userName"/><br> 密码:<input type="password" name="pwd"/><br> <br> <input type="radio" value="male" name="sex" checked/>男 <input type="radio" value="male" name="sex"/>女<br> <br> <input type="checkbox" value="playguita" name="specialty" checked/>弹吉他 <input type="checkbox" value="唱歌" name="singing" checked/>唱歌 <input type="checkbox" value="弹吉他" name="playing" checked/>弹吉他 <input type="checkbox" value="十项全能" name="all" checked/>十项全能 <br> <form action="" enctype="multipart/form-data"> 帅照:<input type="file" name="fileName"/> <br> 地区: <select name="cities" size="2" multiple> <option value="sichuan" selected/>四川 <option value="guangdong" />广东 <option value="guangxi" />广西 <option value="上海"/>上海 </select> <br> <br> 更多描述:<textarea name="更多描述:" cols="100" rows="10"></textarea> <br> <br> <input type="submit" value="提交" id="submit"/> <input type="reset" value="重置" name="reset"/> <input type="button" value="关闭" name="exit"/> </form> <script> function login(){ let username=document.querySelectorAll('input')[0].value let password=document.querySelectorAll('input')[1].value if(username=='wzy20192424' || password=='111') { alert(username+"登录成功") document.write(username+"登录成功") } else { alert("密码或者用户名错误") } } </script> </body> </html>
-
输入
wzy20192424
进行注入攻击 -
可见alert不受html语言注入影响
-
不过dom.write受到了注入影响
-
Web后端
-
安装php
-
开始升级PHP更新源:
-
直接复制下面代码,依次执行既可。
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm yum remove php-common -y yum install -y php72w php72w-opcache php72w-xml php72w-mcrypt php72w-gd php72w-devel php72w-mysql php72w-intl php72w-mbstring
-
-
查看版本:
-
执行下面命令,查看版本号。
php -v
-
安装php fpm依次执行下面命令:
systemctl start php-fpm.service //启动php systemctl enable php-fpm.service//设置开机自启动 systemctl restart httpd //重新启动apache服务
-
-
测试
-
写个php文件
登录成功<br> <?php echo "你好" ?>
-
对应的html文件为
<html> <head> <title>表单</title> </head> <body> <form action="./welcome.php" method="post" onsubmit="login()"> 姓名:<input type="text" value="wzy20192424" name="userName"/><br> 密码:<input type="password" name="pwd"/><br> <br> <input type="radio" value="male" name="sex" checked/>男 <input type="radio" value="male" name="sex"/>女<br> <br> <input type="checkbox" value="playguita" name="specialty" checked/>弹吉他 <input type="checkbox" value="唱歌" name="singing" checked/>唱歌 <input type="checkbox" value="弹吉他" name="playing" checked/>弹吉他 <input type="checkbox" value="十项全能" name="all" checked/>十项全能 <br> <form action="" enctype="multipart/form-data"> 帅照:<input type="file" name="fileName"/> <br> 地区: <select name="cities" size="2" multiple> <option value="sichuan" selected/>四川 <option value="guangdong" />广东 <option value="guangxi" />广西 <option value="上海"/>上海 </select> <br> <br> 更多描述:<textarea name="更多描述:" cols="100" rows="10"></textarea> <br> <br> <input type="submit" value="提交" id="submit"/> <input type="reset" value="重置" name="reset"/> <input type="button" value="关闭" name="exit"/> </form> <script> function login(){ let username=document.querySelectorAll('input')[0].value let password=document.querySelectorAll('input')[1].value if(username=='wzy20192424' && password=='111') { alert(username+"登录成功") } else { alert("密码或者用户名错误") } } </script> </body> </html>
-
运行结果成功将数据从前端返回到了后端
-
-
-
前端通过输入注入html语言让php返回
-
安装mysql
-
由于centOS7中默认安装了MariaDB,需要先进行卸载
-
下载MySQL仓库并安装
-
wget https://repo.mysql.com//mysql80-community-release-el7-3.noarch.rpm
-
yum -y install mysql80-community-release-el7-3.noarch.rpm
-
安装过程中可能遇到如下报错无法安装,原因是Mysql的GPG升级了,需要重新获取
-
执行以下命令再安装即可
-
rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
-
默认安装MySQL8.0,如果需要安装MySQL5.7的话需要修改/etc/yum.repos.d/mysql-community.repo配置文件
-
将mysql80中enabled属性改为0,并添加图中红框内代码(安装MySQL8.0跳过该步骤)
-
安装MySQL数据库
- yum -y install mysql-community-server
-
开启mysql服务
- systemctl start mysqld.service
-
查看mysql默认密码并登陆
- cat /var/log/mysqld.log | grep password
- mysql -uroot -p
-
-
MySQL相关配置修改
-
修改初始密码(若想改为弱密码)
-
设置远程连接(前提:关闭防火墙或开放3306端口)
-
在实际工作中,经常会用到诸如DBeaver等的数据库管理工具进行远程连接mysql数据库,需要设置允许远程连接。
-
在mysql数据库的user表中查看host,默认只允许localhost访问
-
只需将localhost改为%允许任意地址访问即可
-
update user set host = '%' where user = 'root';
-
flush privileges; # 刷新权限 权限更新后刷新才会起作用
-
注:如果使用客户端连接提示了plugin caching_sha2_password错误,这是因为MySQL8.0的密码策略默认为caching_sha2_password(MySQL5.7无此问题)
-
update user set plugin = 'mysql_native_password' where user = 'root';
-
flush privileges; # 刷新权限 权限更新后刷新才会起作用
-
修改完成后可以正确建立远程连接
-
-
-
-
SQLyog安装
-
使用php连接mysql,代码如下
$servername = "192.168.189.161"; $username = "root"; $password = "Mydb2021+"; // 创建连接 $conn = new mysqli($servername, $username, $password); // 检测连接 if ($conn->connect_error) { echo "链接失败"; die("连接失败: " . $conn->connect_error); } echo "连接成功"; ?>``` - 该php后端执行报错,通过下载debug程序发现报错如下,原因是服务器主目录下没有mysqli类
- 在项目的部署时,由于开发环境和运行环境不同,会出现这个问题,即缺少 mysqli 扩展。
- 我们需要从头检查一下PHP配置。
- 1.看看php的ext目录中是否有php_mysqli.dll文件
- 如果有这个文件,就说明你的PHP安装没有问题,继续下面的步骤。
- 如果没有的话你需要重新装个php 。
- [![image.png](https://i.postimg.cc/FFCVXFXK/image.png)](https://postimg.cc/Lhf1zpXd)
- 我没有该文件,所以重新装吧,使用我前面教程的不用重装,我php不是用前面教程装的,前面教程不会出现这个问题
- 2.打开php.ini,找到
- ;extension=php_mysqli.dll
- (把前面的;去掉)
- 3.找到
- ;extension_dir="./ext"
- 把前面的分号";"去掉,改为(相对于php的安装路径的ext目录)
- extension_dir = "e:php\ext"
- e:php为php的存放目录(例如我的路径为F:\workplace\php7\ext)
- 重启Apache服务器。
- 亲测,到这里就可以解决了。
- 其实安装php没这么复杂,别被网上教程骗了,我后来三行命令解决问题
- 可能安装之前要删除以前安装的版本用yum remove php
- yum install php
- yum install php-fpm
- yum install php-mysql
-
php连接数据库代码如下
$servername = "192.168.189.161"; $username = "root"; $password = "Mydb2021+"; // 创建连接 $conn = new mysqli($servername, $username, $password); // 检测连接 if (!$conn) { die("Connection failed: " . mysqli_connect_error()); } echo "连接成功"; ?>``` - 连接成功 - [![image.png](https://i.postimg.cc/D0Ssws3w/image.png)](https://postimg.cc/p5ty0mdw)
-
远程建表
-
使用php对表进行数据插入
这里是sql <?php
$servername = "192.168.189.162";$passwd = "Mydb2021+"; $dbname="wzy20192424"; // 创建连接 $conn = new mysqli($servername, $username, $passwd ,$dbname); // 检测连接 if (!$conn) { die("Connection failed: " . mysqli_connect_error()); } echo "连接成功"; $sql = "INSERT INTO users(user,password) values('green','111');"; // $sql = "create table test(ID char(9) primary key);"; if ($conn->query($sql) === TRUE) { echo "新记录插入成功"; } else { echo "Error: " . $sql . "<br>" . $conn->error; } $conn->close(); ?>``` - 插入成功,浏览器视角 - [![image.png](https://i.postimg.cc/CdyZMQ4c/image.png)](https://postimg.cc/8fHktw9v) - 数据库视角 - [![image.png](https://i.postimg.cc/RC2GnCsD/image.png)](https://postimg.cc/9zty62jd)
-
使用php连接数据库做到对前端传回来的用户名和密码和数据库做比对,然后判断
$uname=$_POST["userName"]; $pwd=$_POST["pwd"]; echo $uname; $query_str="SELECT * FROM users where user='$uname' and password='$pwd';"; $mysqli = new mysqli("192.168.189.162", "root", "Mydb2021+", "wzy20192424"); /* check connection */ if ($mysqli->connect_errno) { printf("Connect failed: %s\n", $mysqli->connect_error); exit(); } echo "connection okk!"; /* Select queries return a resultset */ 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(); ?>``` - 成功视角 - [![image.png](https://i.postimg.cc/8zSHtKVd/image.png)](https://postimg.cc/4mWV31yn) - 失败视角 - [![image.png](https://i.postimg.cc/vm8vd4Tc/image.png)](https://postimg.cc/fVFdcTxN)
最简单的SQL注入
-
在用户名输入框输入' or 1=1#,密码任意输入,可登陆成功:
-
php页面返回登录成功
-
这样构造出的内部语句为:$query_str="SELECT * FROM users WHERE USER='wzy20192424' OR 1=1#' and password=',查出记录的条件从表中的user和password与所输入数据相同,变成了user和password与所输入数据相同或1=1,所以该语句一定能查出记录,数据库中执行结果如下:
XSS攻击测试
安装Webgoat或类似平台,并完成SQL注入、XSS、CSRF攻击。
-
-
参考博客[webgoat安装教程(windows)]
-
建议开VPN进https://github.com/WebGoat/WebGoat/releases,不然可能进不去。我用的免费VPN叫做如图
-
-
- 过程略,因为我是以前安装好的
-
运行webgoat
-
sql注入
-
XSS
-
CSRF