php安全之我见

php安全之我见

1.把握整站的结构,避免泄露站点敏感目录

问题:老网站一般在跟目录下放上index.php、register.php、login.php,访问注册页面跳转到http://localhost/register.php,不易扩展和维护

解决: 如果url为http://localhost/act=register这种,通过变量来跳转到相应页面便于管理,dvwa靶机环境用的就是种搭建的思想

优点:1.不会暴露网站后台绝对路径http://localhost/act=admin.php推测不出网站的后台目录

     2.易维护,不需修改太多代码,http://localhost/act=admin.php想修改后台地址,只需修改swtich的代码和后台文件名

     3.结构严谨,有层次感

     4.统一管理身份认证。可在在入口处进行身份认证,如游客不可访问网站,只有登录会员才有权限浏览,可在入口页面管理

     5.通过绝对路径访问页面报错, http://localhost/register.php报错

在页面添加<?php if(!defined('WWW_ROOT')) {header("HTTP/1.1 404 Not Found"); exit;} ?>实现

 

2.使用预编译语句,避免sql注入

2.1.数据与代码未区分

一条sql语句select * from admin where username='admin' password='xxxxx',admin和xxxx是数据,如未做处理,用户可以输入admin=' or 1=1 #,这条语句变成select * from admin where username='' or 1=1 #' password='xxxxx' ,#将后面的代码注释掉,username=''为假,1=1为真,所以最终结果为真,将所有数据都查询出来

2.2 预编译

后端SQL语句:select * from admin where username='?' password='?',将这条sql语句编译成stmt对象中,方法stmt->bind_param将用户输入的数据绑定到?的位置,这样通过类来操作,所以sql语句的执行都要进行预编译。

Mysqli的预处理

1.创建连接

$conn = new mysqli($servername, $username, $password, $dbname);

2.预处理,也就是封装成stmt类

$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");

3.绑定参数

$stmt->bind_param("sss", $firstname, $lastname, $email);

4.设置参数值

$firstname=’firstname’

5.执行

$stmt->execute();

不过现在php常用pdo来进行sql操作

1.pdo实例化

$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);

2.预处理

$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (:firstname, :lastname, :email)");

3.绑定参数

$stmt->bindParam(':firstname', $firstname);

$stmt->bindParam(':lastname', $lastname);

 $stmt->bindParam(':email', $email);

4.赋值及执行

$firstname = "John";

$lastname = "Doe";

$email = "john@example.com";

$stmt->execute();

 

3预防XSS代码,如果不需要使用cookie就不使用

不幸被xss注入,页面不使用cookie,可降低危害

 

4. 限制用户权限,预防CSRF

4.1举一个例子,给某篇文章点赞,一开始设计的是get请求的方式,如A用户点赞某篇文章的url请求是

http://localhost/?act=support&articleid=12,A用户可以将这个请求发送给B用户,B用户点击此链接也发起了一个点赞的请求

4.2post请求。Get请求太容易利用,如是设计成post来发起这个点赞的请求,如以下代码:

<form action="http://localhost/?act=support" method="POST">

  <input type="hidden" value="12" name="articleid">

  <input type="submit" value="赞">

</form>

第一个input中出现了文章的id,可以构造form表格,或ajax,或利用burpsuite构造攻击页面,发送给B,B点击发起了点赞的post请求

4.3验证码来限制。这样会降低用户体验感,现实中也未见点个赞还需要输入验证码的情形。

4.4增加token验证。客户端每次访问http://localhost/?act=support&articleid=12页面时,服务器都会随机生成一个token,并发送给客户端,客户端点赞时发送这个参数和服务端比较,如果一样点赞成功,这里如果页面存在xss的漏洞,可以通过js获取到token值,成功发起攻击,这种方式是目前常用且有效的手段

4.5 referer验证。访问http://localhost/?act=support&articleid=12点赞时,验证请求包中的rerferer值,来验证其页面来源,理想情况下,当A用户将攻击页面发给B,B点击,referer来源肯定不一致导致点赞失效,但是攻击者可以修改攻击页面的网站名,文件名,目录名为点赞域名以混过rerferer检测

 

5严格控制上传文件类型

5.1前端验证不可靠的

5.2mime验证不可靠的

5.3白名单验证,就是取文件名, 如array('jpg','gif','png','bmp'),文件名为数组中的元素才可上传,但是要注意解析漏洞

5.4 重命名,现在一般命名规则为日期时间+随机数+白名单后缀对上传的文件进行重命名,这样就算被上传webshell,也因为攻击者无法猜测出文件名而导致无法访问webshell

5.5禁止php代码的执行,可以参考文章webshell禁止你执行

 

6.加密混淆javascript代码,提高攻击门槛

很多xss漏洞都是在本地阅读网页源码发现的,加密javascript代码提高阅读门槛

 

7. 使用更高级的hash算法保存数据库中重要信息

目前一般破解hash的手段

7.1彩虹表。可以去官网下载,几百g,经常那这个去破解系统的sam文件

7.2 md5网站,百度一下就有,解密简单的

 

8.验证码安全

验证验证码是否安全可以通过一下几个方式:

8.1 验证码是否前端生成,可抓包绕过

8.2 单个验证码是否有有效期,单个验证码可重复使用

8.3 验证码内容输出到客户端,攻击者可通过js代码获取到

8.4 验证码太弱

验证码太简单,导致开源的tessertact OCR就可以识别。这里有一个最新机器识别绕过12306

火车票验证码的实例

参考链接:https://www.leavesongs.com/PENETRATION/php-secure.html

上一篇:MySQL编程


下一篇:在Java中向MySQL添加数据,statement