PHP与MYSQL动态网站开发笔记-3.网站攻击与防御演示及源码
2021/7/18 19:35:43
本文主要是介绍PHP与MYSQL动态网站开发笔记-3.网站攻击与防御演示及源码,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一 基础功能
如图所示,为页面的根界面,未登录时自动进入此页面
1.注册
点击注册,会进入注册页面,如下图所示. 注册成功之后会自动跳转到登录界面
- 用户名不能少于3位
- 密码不能少于5位
- 密码用MD5哈希后存放到数据库中
- 邮箱可以不填
- 注册的数据库中数据如图所示:
2.登录和验证
注册成功之后,点击登录按钮,可以进入登录界面,如图所示
- 每次登录都需要输入验证码
- 验证码存在session中,每次刷新都会更换
- 当密码或者验证码错误时都无法登录
- 登录使用预编译防止SQL注入
- 登录功能中的验证码功能如下:
- 验证码的内容是随机变化的,无论是字符的位置,还是内容
- 验证码中添加了200个干扰点,防止机器识别
- 验证码中添加了3个干扰线
登录成功之后,进入如图所示的主界面
右上角有文件上传,SQL注入,反射型XSS,存储型XSS,CSRF,LOGOUT选项,不同选项具有不同功能
3.文件上传功能
点击Fileload
选项,进入文件上传功能.如图所示
- 文件上传只能上传图片类型,除此之外不允许上传
- 文件大小不能超过2M
- 文件上传成功后会使用
md5(uniqid(microtime(true),true))
重命名,来确保文件名不会重复 - 文件上传到根目录
uploads
文件夹,若该文件夹不存在会先创建此文件夹,再移动到此文件夹内 - 只允许通过HTTP POST类型上传过来的文件
- 上传文件的存储目录如图所示,由文件可看到文件均已重命名
4.数据查询功能
点击SQL INJECTION选项,可以进入数据查询页面,如图所示
- 输入id,查询用户名
- 如果id不存在,则不输出值
5.评论功能
点击XSS REFLECT或者XSS SRORE 选项可以进入评论页面,如图所示
- 输入评论会输出在下方
6.更改密码功能
点击CSRF选项,进入如图所示界面,该界面可以更改密码
7.登出功能
当点击LOGOUT
选项,会清空网站的所有session
- 当用户成功登陆后,创建session用来存储登录成功的信息
- 登出后再访问上述功能页面,本地的session自然与服务端不相等,会弹窗警告未登录,然后跳转登录界面,如下图所示
- 登出功能的代码如下所示:
- 登出就删除所有session
//1.开启 Session session_start(); //2.判断是否未登录就访问此页面 if($_SESSION['loginsucess']!='wzx'){ echo"<script type='text/javascript'>alert('please log in ');location='login.html';</script>";} //3.销毁所有 Session,并跳转会最初的根页面 session_unset(); echo"<script>location='index.html';</script>"
二 攻击与防御
在自己编写还未采用安全措施的网站上进行攻击
2.1 跨站点请求伪造攻击
CSRF攻击
- 假设被攻击者已经登录了系统,如图所示,该界面没有任何防护措施,功能是更改密码
-
攻击者构造请求连接
http://www.test.com/unsafeweb/csrf.php?newpass=qwert&confirmpass=qwert
然后通过一些手段欺骗用户点击
-
假设用户在登录状态时点击了此连接,就会导致攻击成功,用户的密码已经被更改,攻击如图所示
防御演示
- 如图所示为防御CSRF的网页,该网页具有如下特征
- 输入验证码才能更改密码
- 验证码是随机变化的,防止攻击者伪造
- 表单提交的时候,会提交本表单的Token值,如果与服务器的不一致,则更改失败
- 攻击者即使构造了伪造请求,但是由于token是基于微秒生成的,所以难以攻击成功
- Token值使用
burpsuite
进行抓包可以得到,如下图所示
- 即使抓到了Token值,但是它是使用
$_SESSION['token'] = md5(microtime());
来变化的 - 每微秒Token都会变化,每次刷新验证码都会变化
- 攻击者很难伪造出相同Token和验证码,确保不会发生CSRF攻击
- 该页面的部分代码如下所示:
//1.将提交过来的token与服务端的比较 if(isset($_REQUEST['token'])){ if($_REQUEST['token']!=$_SESSION['token']){; echo"<script type='text/javascript'>alert('Token error');location='csrf.php';</script>";}} //2.判断验证码是否正确 if(isset($_REQUEST['authcode1'])){ if(strtolower($_REQUEST['authcode1'])!=$_SESSION['authcode1']){ echo"<script type='text/javascript'> alert('verification code error');location='csrf.php';</script>";}} //3.判断两次输入的密码是否相同 if($newpass==$confirmpass){ if(($newpass!='')&&($confirmpass!='')){ $md_pass=md5($newpass);//使用MD5 //4.将md5后的新密码放入数据库 $sql="update user set password='$md_pass' where id=5"; $result=mysqli_query($link,$sql); if($result){ echo "<script>alert('Alert sucess');window.location.href='csrf.php'</script>";}}}
防御策略
-
验证请求的
Referer
值- 如果
Referer
是以自己的网站开头的域名,则说明该请求来自网站自己,是合法的 - 如果
Referer
是其他网站域名或空白,就有可能是CSRF攻击,服务器应拒绝该请求 - 但是此方法存在被绕过的可能
- 如果
-
在请求中放入攻击者不能伪造的信息
- 可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器验证此token
- 若请求中没有token或token的内容不正确,则认为请求可能是CSRF攻击从而拒绝该请求
2.2 SQL注入攻击
SQL注入(字符型)
- 如图所示页面,存在字符型注入漏洞
2.在用户名输入框中构造1' or 1=1#
,密码随便输入,验证码输入正确,如图所示
- ,点击
Login
,会显示登录成功,即注入成功,如图所示
SQL注入(数字型)
-
如下图所示页面,输入id,用来查询是否存在该用户,如果存在就返回用户名,不存在就返回空,该页面存在数字型注入漏洞
-
在页面中输入
4 and 1=1#
返回用户名 -
输入
4 and 1=2#
不返回结果.由此得出该页面存在数字型注入漏洞 -
输入
4 order by 4#
返回值,如下图所示;输入4 order by 5#
不返回结果,由此得出字段名由4个 -
输入
-1 union select 1,2,3,4#
,只输出2,表明第二个字段明会输出结果 -
输入
-1 union select 1,(select database()),3,4#
,返回了数据库的名字 -
输入
-1 union select 1,(select table_name from information_schema.tables where table_schema='member' limit 1,1),3,4#
查询到表名一个表名为user -
输入
-1 union select 1,(select column_name from information_schema.columns where table_schema='member' and table_name='user' limit 2,1),3,4#
得到一个字段名为password
,同理可以获得字段名id,username,email
-
输入
-1 union select 1,(select password from member.user where id=4),3,4#
得到id为4的用户的密码为b0baee9d279d34fa1dfd71aadb908c3f
,密码使用了MD5,可以使用彩虹表破解,破解后为11111
防御演示
- 在查询语句中使用预编译,可以有效防止SQL注入
- 如下图所示,使用同样的注入语句
- 点击登录按钮后,后弹出错误,注入失败
- 在数字型注入页面同样使用预编译,输入注入相同的内容:
-1 union select 1,(select password from member.user where id=4),3,4#
,但是这次没有返回值
5.使用id来查询的预编译代码如下所示:
//根据输入的id来查询用户名(使用预编译) $id=$_POST['id']; if($id!=''){ $sql="select * from user where id =?"; $stmt = $link->prepare($sql); $stmt->bind_param("i",$id); $stmt->execute(); $result=$stmt->get_result(); if($result){ $rows = mysqli_fetch_array($result); echo "<p style='margin: auto;width:320px;color: #bce8f1'>'username:'$rows[1]<br/></p>"; } }
防御策略
-
过滤危险字符
- 采用正则表达式匹配union,sleep,load_file等关键字,如果匹配到就退出程序
-
使用预编译语句,绑定变量
-
使用存储过程
- 先将SQL语句定义在数据库中
- 尽量避免在存储过程中使用动态SQL语句
- 若无法避免,应使用严格的输入过滤或编码函数来处理用户输入数据
-
检查数据类型
- 检查输入数据的数据类型,很大程度上可以对抗SQL注入
2.3 跨站脚本攻击
反射型XSS
1.在下面界面输入<script>alert("xss")</script>
- 点击comment,会弹窗显示xss
存储型XSS
1.在下面界面输入<script>alert("xss")</script>
2.点击comment,会显示xss,当再刷新页面,还会显示该弹窗
防御演示
- 以存储型XSS为例
- 输入评论后,后端会进行检查,将<,> , ' , " , & ,#等进行Html编码,让它以Html编码的形式存入数据库中
- 当输出到页面的时候,html会自动进行解释,然后还原成为原来的字符
- 不过输出的内容为字符串,不会再触发XSS攻击
- 特殊字符经过HTML编码后存到数据库,如下所示:
- 特殊字符转换代码如下所示:
//1.对传入的字符串str进行Html encode转换 $str_com=''; if ($comment !=null && $comment.trim()!=""){ for ($i = 0, $len=strlen($comment); $i < $len; $i++) { $arr1 = str_split($comment); switch($arr1[$i]) { case '&': $str_com.="&"; break; case '<': $str_com.="<"; break; case '>': $str_com.=">"; break; case '"': $str_com.="""; break; case ' ': $str_com.=" "; break; case '%': $str_com.=""; break; default: $str_com.= $arr1[$i]; } } }
XSS的防御策略
- 输入检查
- 在服务端检查用户输入的数据是否包含一些特殊的字符,如
<
,>
,'
,"
,等
- 在服务端检查用户输入的数据是否包含一些特殊的字符,如
- 输出检查
- 除了富文本的输出外,在变量输出到HTML页面时,可以使用编码或转义的方式来防御XSS
- 使用安全的编码函数
- 使用
HTMLEncode
等编码方式
- 使用
2.4 文件上传漏洞
文件上传绕过
-
如下图所示,为文件上传,该页面只允许上传图片类型
-
但是它的源码中只使用了
$_FILE['myFile']['type']
来判断类型
$type=$_FILES['myFile']['type']; $allowExt=array('jpeg','jpg','png','gif'); if(!in_array($type,$allowExt)){ echo"<script>alert('非法文件类型');window.location.href='do_upload.html'</script>"; }
-
$_FILE['myFile']['type']
是根据客户端发送过来的数据中Content-Type来判断类型,因此可以绕过 -
如下图上传图片类型的文件,而是扩展名为txt的文本文件
-
上传时使用
burpsuite
抓包,可以看到Content-Type的类型为text -
将text类型改为
image/png
-
然后将数据发送,显示上传成功
-
在上传目录uploads内可以发现此txt文件,文件经过了重命名
防御演示
-
如下图上传一个pptx类型的文件
-
使用
burpsuite
抓包,并修改Content-Type数据 -
但是上传失败
-
文件上传检测部分代码如下所示:
$_FILES['myFile']['type']
判断文件类型,只允许图片类型- 设置文件最大不能超过2M
- 移动文件到根目录下的uploads下,没有就先创建再移动
$ext
变量用来判断文件扩展名是否为$allowExt
白名单中的类型,防止$_FILES['myFile']['type']
被绕过is_uploaded_file($tmp_name)
用来只允许post传过来的文件getimagesize($tmp_name)
用来防止其他类型的文件更改后缀名,伪造成图片类型来上传$uniName=md5(uniqid(microtime(true),true)).'.'.$ext
用来重命名,并确保文件名不会重复- 重命名同时可以防止
.php.png
等这种多重扩展名的文件
//1.将文件属性赋值给变量 $filename=$_FILES['myFile']['name']; $type=$_FILES['myFile']['type']; $tmp_name=$_FILES['myFile']['tmp_name']; $size=$_FILES['myFile']['size']; $error=$_FILES['myFile']['error']; $allowExt=array('jpeg','jpg','png','gif');//允许上传类型白名单 //2.规定文件最大大小 $maxSize=2097152;//(2M) if($error==0){ if($size>$maxSize){ echo"<script>alert('上传文件过大');window.location.href='do_upload.html'</script>"; } //3.检查扩展名,如果扩展名不在规定的白名单内就禁止上传 $ext=pathinfo($filename,PATHINFO_EXTENSION); if(!in_array($ext,$allowExt)){ echo"<script>alert('非法文件类型');window.location.href='do_upload.html'</script>"; } //4.检查是否通过http post过来 if(!is_uploaded_file($tmp_name)){ echo"<script>alert('文件不是通过HTTP POST方式上传过来的'); window.location.href='do_upload.html'</script>"; } //5.检测是否是真的图片类型,不能是.txt改成.jpg等类似此种情况 //getimagesize可以检测是否为图片,如果不是返回false $flag=true; if($flag){ if(!getimagesize($tmp_name)){ echo"<script>alert('不是真正的图片类型');window.location.href='do_upload.html'</script>"; } } //6.检查是否存在uploads目录,没有文件就创建一个 $path='uploads'; if(!file_exists($path)){ mkdir($path,0777,true); chmod($path,0777); } //7.重命名文件,并确保文件名唯一 $uniName=md5(uniqid(microtime(true),true)).'.'.$ext;// $destination=$path.'/'.$uniName; //@ 错误抑制符 //8.移动文件到指定的目录 if(@move_uploaded_file($tmp_name,$destination)){ echo"<script>alert('上传成功');window.location.href='do_upload.html'</script>"; }else{ echo"<script>alert('上传失败');window.location.href='do_upload.html'</script>"; } }
防御策略
- 文件上传目录设置为不可执行
- 只要web容器无法解析该目录下的文件,即使上传了脚本文件,服务器也不会受到影响
- 判断文件类型
- 判断类型时,结合使用MIME Type,后缀检查等方式
- 文件检查时使用白名单的方式
- 对于图片的处理可以使用压缩函数或者resize函数,用来破坏图片中可能存在的HTML代码
- 使用随机数改写文件名和文件路径
- 文件上传如果要执行代码,需要用户能访问到这个文件
- 使用随机数更改文件路径和文件名,极大增加了攻击成本
- 此外文件重命名可以使
.shell.php.rar
,crossdomain
这种文件所实施的攻击无法成功
- 单独设置文件服务器域名
- 由于浏览器的同源策略,一系列客户端攻击将失效
- 比如上传
crossdomain.xml
,上传包含JavaScript
的XSS
利用等问题将得到解决
三 实验心得与体会
通过这次课程,我可以更灵活的使用的php
语言来编程了,此外对前端的HTML
,CSS
,Javascript
也有了一个大致的了解.
以前我对针对web攻击的防御策略只是停留在理论阶段,只是知道如何防御,不知道怎么写出代码,这个课程让我学会了实践上的防御攻击,让我对这些web攻击有了更加深刻的认识,也更加明晰了攻击原理,以及各种函数的漏洞利用you
此外,这门课程还让我又一次详细的复习了WEB安全,让我把忘在角落里的碎片知识重新捡了起来,收获颇丰.
四 网站源码
网站源码
解压密码为:Alucardlink
这篇关于PHP与MYSQL动态网站开发笔记-3.网站攻击与防御演示及源码的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23怎么实现安卓+php 热更新方案?-icode9专业技术文章分享
- 2024-11-22PHP 中怎么实现判断多个值是否为空、null 或者为 false?-icode9专业技术文章分享
- 2024-11-11开源 PHP 商城项目 CRMEB 二次开发和部署教程
- 2024-11-09怎么使用php在kaufland平台刊登商品?-icode9专业技术文章分享
- 2024-11-05PHP的抽象类和接口是什么,有什么区别-icode9专业技术文章分享
- 2024-11-01开源 PHP 商城项目 CRMEB 安装和使用教程
- 2024-11-01用php和mysql写无限分类,有哪几种方法-icode9专业技术文章分享
- 2024-10-31php数据分表导出时部分数据无法导出什么原因-icode9专业技术文章分享
- 2024-10-30有经验的 PHP 开发者学习一门新的编程语言,有哪些推荐的有前景的语言-icode9专业技术文章分享
- 2024-10-21php 检测图片是否篡改过-icode9专业技术文章分享