渗透测试--安全开发

PHP应用、数据库操作

数据导入-mysql架构&库表列

数据库名,数据库表名,数据库列名
数据库数据,格式类型,长度,键等

数据库操作 – mysql增删改查

PHP函数 作用
mysqli_connect() 打开一个到MySQL的新连接
mysqli_select_db() 更改连接的默认数据库
mysqli_query() 执行某个针对数据库的查询(sql语句执行)
mysqli_fetch_row() 从结果集中取得一行,并作为枚举数组返回
mysqli_close() 关闭先前打开的数据库连接
mysqli_num_rows() 返回结果集中行的数量
MySQL 语句
select*from 表名 where 列名 = ’ 条件 ’ ;
insert into 表名(’ 列名1 ‘,’ 列名 ‘)value(’ 列1值1 ‘,’ 列2值2 ');
delete from 表名 where 列名 = ’ 条件 ’ ;
update 表名 set 列名 = 数据 where 列名 = ’ 条件 ’ ;

超全局变量:
参考:
php全局变量、超全局变量

名称 作用
$GLOBALS 这种全局变量用于在 PHP 脚本中的任意位置访问全局变量
$_SERVER 这种超全局变量保存关于报头、路径和脚本位置的信息。
$_REQUEST $_REQUEST 用于收集 HTML 表单提交的数据。
$_POST 广泛用于收集提交method=“post” 的HTML表单后的表单数据。
$_GET 收集URL中的发送的数据。也可用于收集提交HTML表单数据(method=“get”) $_FILES:文件上传且处理包含通过HTTP POST方法上传给当前脚本的文件内容。
$_ENV 是一个包含服务器端环境变量的数组。
$_COOKIE 是一个关联数组,包含通过cookie传递给当前脚本的内容。
$_SESSION 是一个关联数组,包含当前脚本中的所有session内容。

php后台、身份验证

php设置cookie
https://www.runoob.com/php/php-cookies.html

设置Session
https://www.runoob.com/php/php-sessions.html

#身份验证-Cookie使用
生成cookie的原理图过程:
1、客户端向服务器发送HTTP请求。
2、服务器检查请求头中是否包含cookie信息。
3、如果请求头中包含cookie信息,则服务器使用该cookie来识别客户端否则服务器将生成一个新的cookie。
4、服务器在响应头中设置cookie信息并将其发送回客户端。
5、客户端接收响应并将cookie保存在本地。
6、当客户端发送下一次HTTP请求时,它会将cookie信息附加到请求头中。
7、服务器收到请求并检查cookie的有效性。
8、如果cookie有效,则服务器响应请求。否则,服务器可能会要求客户端重新登录。

setcookie(): 设置一个cookie并发送到客户端浏览器。
unset(): 用于删除指定的cookie。


#身份验证-Session使用
1、客户端向服务器发送HTTP请求。
2、服务器为客户端生成一个唯一的session ID,并将其存储在服务器端的存储器中(如文件、数据库等)。
3、服务器将生成的session ID作为一个cookie发送给客户端。
4、客户端将session ID保存为一个cookie,通常是在本地浏览器中存储。
5、当客户端在发送下一次HTTP请求时,它会将该cookie信息附加到请求头中,以便服务器可以通过该session ID来识别客户端。
6、服务器使用session ID来检索存储在服务器端存储器中的与该客户端相关的session数据,从而在客户端和服务器之间共享数据。

session_start(): 启动会话,用于开始或恢复一个已经存在的会话。
$_SESSION: 用于存储和访问当前会话中的所有变量。
session_destroy(): 销毁当前会话中的所有数据。
session_unset(): 释放当前会话中的所有变量。
Session存储路径:PHP.INI中session.save_path设置路径

#唯一性判断-Token使用
1、生成Token并将其存储在Session
2、生成Token并将其绑定在Cookie触发
3、尝试登录表单中带入Token验证逻辑
4、思考Token安全特性

#具体安全知识点:
-Cookie和Session都是用来在Web应用程序中跟踪用户状态的机制
1、存储位置不同:
Cookie是存储在客户端(浏览器)上的,而Session是存储在服务器端的。
2、安全性不同:
Cookie存储在客户端上,可能会被黑客利用窃取信息,而Session存储在服务器上,更加安全。
3、存储容量不同:
Cookie的存储容量有限,一般为4KB,而Session的存储容量理论上没有限制,取决于服务器的硬件和配置。
4、生命周期不同:
Cookie可以设置过期时间,即便关闭浏览器或者重新打开电脑,Cookie仍然存在,直到过期或者被删除。
而Session一般默认在浏览器关闭后就会过期。
5、访问方式不同:
Cookie可以通过JavaScript访问,而Session只能在服务器端进行访问。
6、使用场景不同:
Cookie一般用于存储小型的数据,如用户的用户名和密码等信息。而Session一般用于存储大型的数据,如购物车、登录状态等信息。
总之,Cookie和Session都有各自的优缺点,选择使用哪一种方式,取决于具体的应用场景和需求。
一般来说,如果需要存储敏感信息或者数据较大,建议使用Session;
如果只需要存储少量的数据,并且需要在客户端进行访问,可以选择使用Cookie。

-在Web应用程序中,使用token和不使用token的主要差异在于身份验证和安全性。
1.身份验证:采用token机制的Web应用程序,用户在登录成功后会收到一个token
这个token可以在每次请求时发送给服务器进行身份验证。而不采用token机制的Web应用程序
一般会使用session机制来保存用户登录状态,服务器会在用户登录成功后创建一个session
之后的每个请求都需要在HTTP头中附带这个session ID,以便服务器能够验证用户身份

2、安全性:采用token机制的Web应用程序,在服务器上不会存储用户的登录状态
只需要存储token即可。因此,即使token被盗取,黑客也无法获得用户的密码或者其他敏感信息
而不采用token机制的Web应用程序,一般会在服务器上存储用户的登录状态
因此如果服务器被黑客攻击,黑客可能会获得用户的敏感信息。
(如抓包抓到的token值是死的,不会变化,但每登录一次就会换一个token,无法暴力破解)
数据包有token值可保证唯一性

3、跨域访问:采用token机制的Web应用程序,在跨域访问时
可以使用HTTP头中的Authorization字段来传递token信息,方便实现跨域访问
而不采用token机制的Web应用程序,在跨域访问时,需使用cookie或session来传递用户身份信息,比较麻烦。
总之,采用token机制可以提高Web应用程序的安全性,并且方便实现跨域访问。
不过,使用token机制也需要开发者自己来实现身份验证和token的生成和验证,相对来说比较复杂。
而不采用token机制,使用session机制则相对简单,但是安全性相对较低。
因此,具体采用哪种机制,需要根据实际情况进行权衡和选择。

php文件管理模块

#文件管理模块-上传-过滤机制
1、无过滤机制
2、黑名单过滤机制
-----------------------------
上传文件后缀过滤 黑名单机制
$black_ext=array('php','asp','jsp','aspx');
//xxx.jpg xxx.png(以上常见的脚本后门格式)
// 拆分出点号后面的内容比较数组
$fenge = explode('.',$name);
$exts = end($fenge);
if(in_array($exts,$black_ext)){
    echo '非法后缀文件'.$exts;
}else{
    move_uploaded_file($tmp_name,'upload/'.$name);
    echo '';
}
-------------------------------
3、白名单过滤机制
$allow_ext=array('png','jpg','gif','jpeg');

4、文件类型过滤机制
$allow_type=array('image/png','image/jpg','image/jpeg','image/gif');
如果$name变量的值为'xxx.jpg',则运行后:

$fenge = explode('.',$name);会将$name按照点号(.)进行拆分
得到一个数组$fenge,其中第一个元素是'xxx',第二个元素是'jpg'

end($fenge);会返回数组$fenge中的最后一个元素,也就是'jpg'

$_FILES:PHP中一个预定义的超全局变量,用于在上传文件时从客户端接收文件,并将其保存到服务器上。它是一个包含上传文件信息的数组,包括文件名、类型、大小、临时文件名等信息。

参数 作用
$_FILES[“表单值”][“name”] 获取上传文件原始名称
$_FILES[“表单值”][“type”] 获取上传文件MIME类型
$_FILES[“表单值”][“size”] 获取上传文件字节单位大小
$_FILES[“表单值”][“tmp_name”] 获取上传的临时副本文件名
$_FILES[“表单值”][“error”] 获取上传时发生的错误代码
函数 作用
move_uploaded_file() 将上传的文件移动到指定位置的函数

文件管理模块-显示-过滤机制

功能:显示 上传 下载 删除 编辑 包含等
1.打开目录读取文件列表
2.递归循环读取文件列表
3.判断是文件还是文件夹
 if(is_dir($file)) 
4.PHP.INI目录访问控制
函数 作用
is_dir() 用于检查指定的路径是否是一个目录
opendir() 用于打开指定的目录,返回句柄,用来读取目录中的文件和子目录
readdir() 用于从打开的目录句柄中读取目录中的文件和子目录

open_basedir:PHP.INI中的设置用来控制脚本程序访问目录
ini_set(‘open_basedir’,DIR); 设置配置文件中,只能访问本目录

opendir()函数用于打开一个目录,其语法如下:

$dir = opendir($path);
其中,$path是要打开的目录的路径,opendir()函数返回一个目录句柄
可以用于后续的操作。

readdir()函数用于读取目录中的文件,其语法如下:
$file = readdir($dir);
其中,$dir是opendir()函数返回的目录句柄
readdir()函数返回目录中的下一个文件名
如果到达目录结尾,则返回false。

通常,可以使用一个while循环来遍历目录中的所有文件,如下所示:
$dir = opendir($path);
while (($file = readdir($dir)) !== false) {
    // 处理$file
}

closedir($dir);
在上面的代码中,while循环会不断调用readdir()函数
直到返回false为止
处理每个文件名。最后,使用closedir()函数关闭目录句柄
$dir = $_GET['path'] ?? './';

从 URL 参数 path 中获取路径信息,如果 path 参数不存在或者为 null,则将 $dir 变量设置为 ‘./’,否则将 $dir 变量设置为 path 参数的值

PHP文件管理-删除、编辑、包含

文件包含
函数 作用
include() 在错误发生后脚本继续执行
require() 在错误发生后脚本停止执行
include_once() 如果已经包含,则不再执行
require_once() 如果已经包含,则不再执行
#文件删除:
unlink() 文件删除函数
调用命令删除:system shell_exec exec等

#文件下载:
修改HTTP头实现文件读取解析下载:
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename="");
header("Content-Length: " . filesize($file));
readfile($file);

#文件编辑:
1、file_get_contents() 读取文件内容
2、fopen() fread() 文件打开读入

php框架、模版、组件

框架:thinkphp  yii  laravel
核心开发  代码逻辑核心

模板:smarty
负责主要显示页面美观

组件:
第三方功能(图片处理、数据转换、数据库操作)

JS应用、原生开发、JQuery库

#参考
1、原生JS教程
https://www.w3school.com.cn/js/index.asp
2、jQuery库教程
https://www.w3school.com.cn/jquery/index.asp

#JS原生开发-文件上传-变量&对象&函数&事件
1、布置前端页面
2、JS获取提交数据
3、JS对上传格式判断
4、后端对上传数据处理
前端JS进行后缀过滤,后端PHP进行上传处理
架构:html js php - upload.php
安全问题:
1、过滤代码能被看 到,通过分析绕过 
2、禁用JS或删除过滤代码绕过

#JS导入库开发-登录验证-JQuery库&Ajax技术
0、布置前端页面
1、获取登录事件
2、配置Ajax请求
3、后端代码验证
4、成功回调判断
后端PHP进行帐号判断,前端JS进行登录处理
架构:html js login.html - logincheck.php

#JS导入库开发-逻辑购买-JQuery库&Ajax技术
1、布置前端页面
2、获取登录事件
3、配置Ajax请求
4、后端代码验证
5、成功回调判断
架构:html js shop.html - shopcheck.php

#实例测试-某违规APP-密码找回&JS验证逻辑安全

JS应用&DOM树、加密编码库


#JS原生开发-DOM树-用户交互
DOM:文档操作对象
浏览器提供的一套专门用来操作网页代码内容的功能
实现自主或用户交互动作反馈

安全问题:本身的前端代码通过DOM技术实现代码的更新修改,但是更新修改如果修改的数据可以由用户来指定,就会造成DOM-XSS攻击!
1、获取对象
标签:直接写
Class:加上符号.
id:加上符号#
<h1 id="myHeader" onclick="getValue()">这是标题</h1>
document.querySelector('h1')
document.querySelector('.id')
document.querySelector('#myHeader')

2、获取对象属性
<h1 id="myHeader" onclick="getValue()">这是标题</h1>
const h1=document.querySelector('h1')
const id=h1.id
console.log(id)

2、操作元素数据
innerHTML 解析后续代码
innerText 不解析后续代码

3、操作元素属性
className src id等
<img src="iphone.jpg" width="300" height="300"></img>
const src=document.querySelector('img')
src.src='huawei.png'

#JS导入库开发-编码加密-逆向调试
//Base64

//MD5
<script src="js/md5.js"></script>
<script>
    var str1 = 'xiaodisec'
    var str_encode = md5(str1);
    console.log(str_encode) 
</script>

//SHA1
<!DOCTYPE html>
    <script src="js/crypto-js.js"></script>
    <script>
        var str1 = 'xiaodisec';
        var str_encode = CryptoJS.SHA1(str1).toString(); // 注意:1是数字1
        console.log(str_encode)  
    </script>
</html>      

//HMAC
<script src="js/crypto-js.js"></script>
<script>
    var key = 'key';
    var str1 = 'xiaodisec';
    var hash = CryptoJS.HmacSHA256(key, str1);
    var str_encode = CryptoJS.enc.Hex.stringify(hash);
    console.log(str_encode)  // '11a7960cd583ee2c3f1ed910dbc3b6c3991207cbc527d122f69e84d13cc5ce5c'
</script>


//AES
<script src="js/crypto-js.js"></script>
    <script type="text/javascript">
          var aseKey = "12345678"     // 定制秘钥,长度必须为:8/16/32位, 长度不一致也没问题
          var message = "xiaodisec";  // 需要加密的内容
          // 加密 DES/AES切换只需要修改 CryptoJS.AES <=> CryptoJS.DES
          var encrypt = CryptoJS.AES.encrypt(message, CryptoJS.enc.Utf8.parse(aseKey),  // 参数1=密钥, 参数2=加密内容
              {
                mode: CryptoJS.mode.ECB, // 为DES的工作方式
                padding: CryptoJS.pad.Pkcs7  // 当加密后密文长度达不到指定整数倍(8个字节、16个字节)则填充对应字符
             }
          ).toString(); // toString=转字符串类型

          console.log(encrypt); // 在弹窗中打印字符串 2vcsEDJv9vAZZLgFLjkZ9A==

          //解密
          var decrypt = CryptoJS.AES.decrypt(encrypt, CryptoJS.enc.Utf8.parse(aseKey), // 参数1=密钥, 参数2=解密内容
              {
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
              }
          ).toString(CryptoJS.enc.Utf8); // toString=转字符串类型,并指定编码
          console.log(decrypt); // "xiaodisec"
    </script>

//DES
<script src="js/crypto-js.js"></script>
<script type="text/javascript">
      var aseKey = "12345678"     // 定制秘钥,长度必须为:8/16/32位, 长度不一致也没问题
      var message = "xiaodisec";  // 需要加密的内容
      // 加密 DES/AES切换只需要修改 CryptoJS.AES <=> CryptoJS.DES
      var encrypt = CryptoJS.DES.encrypt(message, CryptoJS.enc.Utf8.parse(aseKey),  // 参数1=密钥, 参数2=加密内容
          {
            mode: CryptoJS.mode.ECB, // 为DES的工作方式
            padding: CryptoJS.pad.Pkcs7  // 当加密后密文长度达不到指定整数倍(8个字节、16个字节)则填充对应字符
         }
      ).toString(); // toString=转字符串类型

      console.log(encrypt); // 控制台打印 CDVNwmEwDRM

      //解密
      var decrypt = CryptoJS.DES.decrypt(encrypt, CryptoJS.enc.Utf8.parse(aseKey), // 参数1=密钥, 参数2=解密内容
          {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
          }
      ).toString(CryptoJS.enc.Utf8); // toString=转字符串类型,并指定编码
      console.log(decrypt); // 控制台打印 "i am xiaozhou ?"
</script>


//RSA
<script src="js/jsencrypt.js"></script>
    <script type="text/javascript">
        // 公钥 私匙是通过公匙计算生成的,不能盲目设置
        var PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALyBJ6kZ/VFJYTV3vOC07jqWIqgyvHulv6us/8wzlSBqQ2+eOTX7s5zKfXY40yZWDoCaIGk+tP/sc0D6dQzjaxECAwEAAQ==-----END PUBLIC KEY-----';
        //私钥
        var PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvIEnqRn9UUlhNXe84LTuOpYiqDK8e6W/q6z/zDOVIGpDb545NfuznMp9djjTJlYOgJogaT60/+xzQPp1DONrEQIDAQABAkEAu7DFsqQEDDnKJpiwYfUE9ySiIWNTNLJWZDN/Bu2dYIV4DO2A5aHZfMe48rga5BkoWq2LALlY3tqsOFTe3M6yoQIhAOSfSAU3H6jIOnlEiZabUrVGqiFLCb5Ut3Jz9NN+5p59AiEA0xQDMrxWBBJ9BYq6RRY4pXwa/MthX/8Hy+3GnvNw/yUCIG/3Ee578KVYakq5pih8KSVeVjO37C2qj60d3Ok3XPqBAiEAqGPvxTsAuBDz0kcBIPqASGzArumljkrLsoHHkakOfU0CIDuhxKQwHlXFDO79ppYAPcVO3bph672qGD84YUaHF+pQ-----END PRIVATE KEY-----';
        //使用公钥加密
        var encrypt = new JSEncrypt();//实例化加密对象
        encrypt.setPublicKey(PUBLIC_KEY);//设置公钥
        var message = 'xiaodisec' // 需要加密的数据 
        var encrypted = encrypt.encrypt(message);//对指定数据进行加密
        console.log(encrypted)  // 'JQ83h8tmJpsSZcb4BJ3eQvuqIAs3ejepcUUnoFhQEvum8fA8bf1Y/fG+DO1bSIVNJF6EOZKe4wa0njv6aOar9w=='
        //使用私钥解密
        var decrypt = new JSEncrypt(); // 创建解密对象
        decrypt.setPrivateKey(PRIVATE_KEY); //设置私钥
        var uncrypted = decrypt.decrypt(encrypted); //解密 'xiaodisec'
        console.log(uncrypted);
    </script>

java开发

#JavaEE-HTTP-Servlet&路由&周期
参考:https://blog.csdn.net/qq_52173163/article/details/121110753
1、解释
Servlet是运行在Web服务器或应用服务器上的程序
它是作为来自Web浏览器或其他HTTP客户端的请求
和HTTP服务器上的数据库或应用程序之间的中间层
使用Servlet可以收集来自网页表单的用户输入
呈现来自数据库或者其他源的记录,还可以动态创建网页

2、创建和使用Servlet
-创建一个类继承HttpServlet
-web.xml配置Servlet路由
-WebServlet配置Servlet路由
-写入内置方法(init service destroy doget dopost)

3Servlet生命周期
见图

4、处理接受和回显
● HttpServletRequestServletRequest的子接口
getParameter(name)String 通过name获得值
getParameterValues — String[ ] 通过name获得多值

● HttpServletResponseServletResponse的子接口 
setCharacterEncoding() 设置编码格式
setContentType() 设置解析语言
getWriter() 获得一个PrintWriter字符输出流输出数据
PrintWriter 接受符合类型数据

#JavaEE-数据库-JDBC&Mybatis&-原生态数据库开发:JDBC
参考:https://www.jianshu.com/p/ed1a59750127
JDBC(Java Database connectivity): 由java提供,用于访问数据库的统一API接口规范.数据库驱动: 由各个数据库厂商提供,用于访问数据库的jar包(JDBC的具体实现),遵循JDBC接口,以便java程序员使用!
1、下载jar
https://mvnrepository.com/
2、引用封装jar
创建lib目录,复制导入后,添加为库
3、注册数据库驱动
Class.forName("com.mysql.jdbc.Driver");
4、建立数据库连接
String url ="jdbc:mysql://localhost:3306/demo01";
Connection connection=DriverManager.getConnection(url,"x","x");
5、创建Statement执行SQL
Statement statement= connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
6、结果ResultSet进行提取
while (resultSet.next()){
    int id = resultSet.getInt("id");
    String page_title = resultSet.getString("page_title");
    .......
}

安全修复SQL注入:预编译
原理:提前编译好执行逻辑,你注入的语句不会改变原有逻辑!

-框架数据库开发:Mybatis
Mybatis是一款优秀的持久层框架,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程,减少了代码的冗余,减少程序员的操作。

你可能感兴趣的:(php,安全)