安全开发 PHP PHP应用 Att@ckxu 2025-05-27 2025-05-29 留言板功能
mysqli函数&增删改查 PHP操作数据库函数
常用: mysqli_connect() 打开一个到MySQL的新的连接。 mysqli_select_db() 更改连接的默认数据库。 mysqli_query() 执行某个针对数据库的查询。 mysqli_fetch_row() 从结果集中取得一行,并作为枚举数组返回。 mysqli_close() 关闭先前打开的数据库连接。
查:select * from 表名 where 列名=‘条件’; 增:insert into 表名(列名1 , 列名2 ) value(‘列1 值1 ’, ‘列2 值2 ’); 删:delete from 表名 where 列名 = ‘条件’; 改:update 表名 set 列名 = 数据 where 列名 = ‘条件’;
mysqli.connect函数连接数据库 构建数据库连接,以及执行数据库插入操作
发现可以插入数据,但是由于用户名和内容 可以不进行添加 就加入数据库
多加一层判空 ,如果<font style="background-color:rgba(255, 255, 255, 0);">!empty($u)</font>
用户名为空 则不写入数据即可
<!-- HTML 表单 --> <form id="form1" name="form1" method="post" action="" > <p> <!-- 用户名输入框 --> 用户名:<input type="text" name="username" > </p> <p> 内容: </p> <p> <!-- 文本框 --> <textarea name="content" ></textarea> </p> <!-- 提交按钮 --> <input type="submit" name="submit" id="submit" value="提交" > </form> <?php $dbip = 'localhost' ; $dbuser = 'root' ;$dbpass = 'root' ;$dbname = 'dome01' ;$con = mysqli_connect ($dbip , $dbuser , $dbpass , $dbname );if (!$con ) { die ("连接错误:" . mysqli_connect_errno ()); } else { $u = @$_POST ['username' ]; if (!empty ($u )) { $c = @$_POST ['content' ]; $i = @$_SERVER ['REMOTE_ADDR' ]; $ua = @$_SERVER ['HTTP_USER_AGENT' ]; $sql = "INSERT INTO gbook(`username`, `content`, `ipaddr`, `uagent`) VALUES ('$u ', '$c ', '$i ', '$ua ');" ; if (mysqli_query ($con , $sql )) { echo "<script>alert('留言成功!')</script>" ; $sql1 = "SELECT * FROM gbook" ; $data = mysqli_query ($con , $sql1 ); while ($row = mysqli_fetch_row ($data )) { echo '<hr>' ; echo '用户名:' . $row [0 ] . '<br>' ; echo '内容:' . $row [1 ] . '<br>' ; echo 'IP地址:' . $row [2 ] . '<br>' ; echo 'UA浏览器:' . $row [3 ] . '<br>' ; } } else { echo "<script>alert('留言失败!')</script>" ; } } else { echo "<script>alert('用户名不能为空!')</script>" ; } } ?>
html混编&超全局变量 html混编:使HTML(JS)在PHP语言中运行
超全局变量
https://www.w3school.com.cn/php/php_superglobals.asp
https://www.php.net/manual/zh/language.variables.superglobals.php
<?php include '../config.php' ;$sql1 ="select * from gbook" ;$data =mysqli_query ($con ,$sql1 );while ($row =mysqli_fetch_row ($data )){ echo '<hr>' ; echo '用户名:' .$row [0 ].'<br>' ; echo '内容:' .$row [1 ].'<br>' ; echo 'IP地址:' .$row [2 ].'<br>' ; echo 'UA浏览器:' .$row [3 ].'<br>' ; ** echo "<a href='gbook-admin.php?del=$row [0]'>删除</a>" ;** } $delstr =@$_GET ['del' ];** $sql2 ="delete from gbook where username ='$delstr ';" ;if (mysqli_query ($con ,$sql2 )){ echo "<script>alert('删除成功 !')</script>" ;** }
创建gbook-admin.php文件和admin目录,方便执行删除等后台功能
发现重复的代码太多,所以将经常用到的数据库链接操作生成config.php文件,方便管理。修改后正常访问增加,查询。
删除功能创建成功
<?php include '../config.php' ;$sql1 ="select * from gbook" ;$data =mysqli_query ($con ,$sql1 );while ($row =mysqli_fetch_row ($data )){ echo '<hr>' ; echo '用户名:' .$row [0 ].'<br>' ; echo '内容:' .$row [1 ].'<br>' ; echo 'IP地址:' .$row [2 ].'<br>' ; echo 'UA浏览器:' .$row [3 ].'<br>' ; ** echo "<a href='gbook-admin.php?del=$row [0]'>删除</a>" ;** } $delstr =@$_GET ['del' ];** $sql2 ="delete from gbook where username ='$delstr ';" ;if (mysqli_query ($con ,$sql2 )){ echo "<script>alert('删除成功 !')</script>" ;** }
发现问题,可以将代码加一层判断当触发的时候,再进行删除操作
$delstr = @$_GET ['del' ];** if (isset ($delstr )) {** $sql2 = "DELETE FROM gbook WHERE username ='$delstr ';" ; if (mysqli_query ($con , $sql2 )) { echo "<script>alert('删除成功!')</script>" ; } }
第三方插件引用-js传参&函数对象调用 htmlCopy code <script src='../xxx.js' ></script>
这是一个在 HTML 中引用外部 JavaScript 文件的标签。src 属性指定了 JavaScript 文件的路径,相对于当前 HTML 文件的位置。在这里,../xxx.js 表示 JavaScript 文件位于上一级目录(../)并且文件名为 xxx.js。
**<script src="/ueditor/ueditor.config.js" ></script> <script src="/ueditor/ueditor.all.js" ></script>** <form id="form1" name="form1" method="post" action="" <p> 用户名:<input type="text" name="username" > </p> <p> 内容: </p> <p> **<textarea id="content" rows="10" cols="70" name="content" style="border:1px solid #E5E5E5;" > </textarea> <script type="text/javascript" > UE.getEditor ("content" ); </script> </p>** <input type="submit" name="submit" id="submit" value="提交" > </form>
这里的ueditor需要单独下载文件,放入目录中
完整代码 <script src="/ueditor/ueditor.config.js" ></script> <script src="/ueditor/ueditor.all.js" ></script> <form id="form1" name="form1" method="post" action="" <p> 用户名:<input type="text" name="username" > </p> <p> 内容: </p> <p> <textarea id="content" rows="10" cols="70" name="content" style="border:1px solid #E5E5E5;" > </textarea> <script type="text/javascript" > UE.getEditor ("content" ); </script> </p> <input type="submit" name="submit" id="submit" value="提交" > </form> <?php include 'config.php' ;function add_gbook ($con ) { $u =@$_POST ['username' ]; if (!empty ($u )) { $c = @$_POST ['content' ]; $i = @$_SERVER ['REMOTE_ADDR' ]; $ua = @$_SERVER ['HTTP_USER_AGENT' ]; $sql = "insert into gbook(`username`, `content`,`ipaddr`,`uagent`) value('$u ', '$c ','$i ','$ua ');" ; if (mysqli_query ($con , $sql )) { echo "<script>alert('留言成功!')</script>" ; } } } function show_gbook ($con ,$del ) { $sql1 ="select * from gbook" ; $data =mysqli_query ($con ,$sql1 ); while ($row =mysqli_fetch_row ($data )) { echo '<hr>' ; echo '用户名:' . $row [0 ] . '<br>' ; echo '内容:' . $row [1 ] . '<br>' ; echo 'IP地址:' . $row [2 ] . '<br>' ; echo 'UA浏览器:' . $row [3 ] . '<br>' ; if ($del =='del' ){ echo "<a href='gbook-admin.php?del=$row [0]'>删除</a>" ; } } } add_gbook ($con );show_gbook ($con ,'x' );
<?php include '../config.php' ;include '../gbook.php' ;show_gbook ($con ,'del' );$delstr =@$_GET ['del' ];if (isset ($delstr )){ $sql2 ="delete from gbook where username ='$delstr ';" ; if (mysqli_query ($con ,$sql2 )){ echo "<script>alert('删除成功 !')</script>" ; } }
<?php $dbip ='localhost' ;$dbuser ='root' ;$dbpass ='root' ;$dbname ='dome01' ;$con =mysqli_connect ($dbip ,$dbuser ,$dbpass ,$dbname );
后台验证功能 身份验证-Cookie
生成cookie的原理图过程:见图
1、客户端向服务器发送HTTP请求。
2、服务器检查请求头中是否包含cookie信息。
3、如果请求头中包含cookie信息,则服务器使用该cookie来识别客户端,否则服务器将生成一个新的cookie。
4、服务器在响应头中设置cookie信息并将其发送回客户端。
5、客户端接收响应并将cookie保存在本地。
6、当客户端发送下一次HTTP请求时,它会将cookie信息附加到请求头中。
7、服务器收到请求并检查cookie的有效性。
8、如果cookie有效,则服务器响应请求。否则,服务器可能会要求客户端重新登录。
php函数
setcookie(): 设置一个cookie并发送到客户端浏览器。
unset(): 用于删除指定的cookie。
Cookie安全性
信息泄露:如果Cookie中包含敏感信息(如用户ID、密码等),攻击者可以通过窃取Cookie来获取这些敏感数据。为了防止信息泄露,应确保敏感信息在传输和存储过程中进行加密,并使用安全的传输协议(如HTTPS)来保护Cookie的传输过程。
跨站点脚本攻击(XSS):攻击者可以通过在Web应用程序中注入恶意脚本来获取用户的Cookie。为了防止XSS攻击,开发人员应对用户输入进行正确的验证和过滤,并对输出进行适当的转义,以防止恶意脚本的注入。
跨站点请求伪造(CSRF):攻击者可以通过欺骗用户访问恶意网站来利用用户的身份进行非法操作。为了防止CSRF攻击,可以使用随机生成的令牌(CSRF令牌)来验证每个请求的合法性,并确保令牌在每个请求中都是唯一且难以预测的。
会话劫持:攻击者可以通过窃取用户的会话Cookie来冒充用户身份。为了防止会话劫持,可以通过使用安全标志(如”Secure”和”HttpOnly”)来限制Cookie的使用范围,并在会话身份验证上使用额外的保护措施,如双因素身份验证。
不安全的存储:如果Cookie存储在用户计算机上的不安全位置,如明文存储或不加密的存储,攻击者可以轻易地访问和修改Cookie。为了保护Cookie的存储,应将Cookie存储在安全的位置,如服务器端的数据库或加密的本地存储。
身份验证-Session
session生成过程
1、客户端向服务器发送HTTP请求。
2、服务器为客户端生成一个唯一的session ID,并将其存储在服务器端的存储器中(如文件、数据库等)。
3、服务器将生成的session ID作为一个cookie发送给客户端。
4、客户端将session ID保存为一个cookie,通常是在本地浏览器中存储。
5、当客户端在发送下一次HTTP请求时,它会将该cookie信息附加到请求头中,以便服务器可以通过该session ID来识别客户端。
6、服务器使用session ID来检索存储在服务器端存储器中的与该客户端相关的session数据,从而在客户端和服务器之间共享数据。
session函数
session_start(): 启动会话,用于开始或恢复一个已经存在的会话。
$_SESSION: 用于存储和访问当前会话中的所有变量。
session_destroy(): 销毁当前会话中的所有数据。
session_unset(): 释放当前会话中的所有变量。
Session存储路径:PHP.INI中session.save_path设置路径:
Cookie和Session的区别 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。
唯一性判断-Token 在Web应用程序中,使用token和不使用token的主要差异在于身份验证和安全性。
1.身份验证:采用token机制的Web应用程序,用户在登录成功后会收到一个token,这个token可以在每次请求时发送给服务器进行身份验证。而不采用token机制的Web应用程序,一般会使用session机制来保存用户登录状态,服务器会在用户登录成功后创建一个session,之后的每个请求都需要在HTTP头中附带这个session ID,以便服务器能够验证用户身份。
2、安全性:采用token机制的Web应用程序,在服务器上不会存储用户的登录状态,只需要存储token即可。因此,即使token被盗取,黑客也无法获得用户的密码或者其他敏感信息。而不采用token机制的Web应用程序,一般会在服务器上存储用户的登录状态,因此如果服务器被黑客攻击,黑客可能会获得用户的敏感信息。
3、跨域访问:采用token机制的Web应用程序,在跨域访问时,可以使用HTTP头中的Authorization字段来传递token信息,方便实现跨域访问。而不采用token机制的Web应用程序,在跨域访问时,需使用cookie或session来传递用户身份信息,比较麻烦。
总之,采用token机制可以提高Web应用程序的安全性,并且方便实现跨域访问。不过,使用token机制也需要开发者自己来实现身份验证和token的生成和验证,相对来说比较复杂。而不采用token机制,**使用session机制则相对简单,但是安全性相对较低。**因此,具体采用哪种机制,需要根据实际情况进行权衡和选择。
使用token之后,无法进行抓包爆破,即使抓包爆破有正确账户密码,但是抓包的token是写死的,而token每次是随机生成的,经token检验也会登录失败;可以正常使用网站功能登录,在网站登录时每次登录的token会与服务器端同步
完整代码 cookie <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <meta name="viewport" content="width=device-width, initial-scale=1.0" > <title>后台登录</title> <style> body { font-family: Arial, sans-serif; background-color: margin: 0 ; padding: 0 ; display: flex; align-items: center; justify-content: center; height: 100 vh; } form { background-color: border-radius: 8 px; box-shadow: 0 0 10 px rgba (0 , 0 , 0 , 0.1 ); padding: 20 px; width: 300 px; } label { display: block; margin-bottom: 8 px; } input { width: 100 %; padding: 8 px; margin-bottom: 16 px; box-sizing: border-box; } button { background-color: color: padding: 10 px; border: none; border-radius: 4 px; cursor: pointer; width: 100 %; } button:hover { background-color: } </style> </head> <body> <!-- <form action="" method="post" > <label for ="username" >用户名:</label> <input type="text" id="username" name="username" required> <label for ="password" >密码:</label> <input type="password" id="password" name="password" required> <button type="submit" >登录</button> </form> </body> </html> <?php include "../config.php" ;$user =$_POST ['username' ];$pass =$_POST ['password' ];$sql = "SELECT * FROM admin WHERE username='$user ' AND password='$pass ';" ;$data = mysqli_query ($con , $sql );if ($_SERVER ["REQUEST_METHOD" ] == "POST" ) { if (mysqli_num_rows ($data ) > 0 ) { $expire = time () + 60 * 60 * 24 * 30 ; setcookie ('username' , $user , $expire , '/' ); setcookie ('password' , $pass , $expire , '/' ); header ('Location: index-c.php' ); exit (); } else { echo "<script>alert('登录失败!')</script>" ; } }
<?php if ($_COOKIE ['username' ]!='admin' and $_COOKIE ['password' ]!='123456' ) header ('Location: index-c.php' ); ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title>后台首页</title> </head> <body> <h1>后台首页</h1> <p>欢迎您,<?php echo $_COOKIE ['username' ]; ?> !</p> <p><a href="logout-c.php" >退出登录</a></p> </body> </html>
<?php setcookie ('username' , '' , time () - 3600 , '/' );setcookie ('password' , '' , time () - 3600 , '/' );header ('Location: admin-c.php' );exit ;?>
session <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <meta name="viewport" content="width=device-width, initial-scale=1.0" > <title>后台登录</title> <style> body { font-family: Arial, sans-serif; background-color: margin: 0 ; padding: 0 ; display: flex; align-items: center; justify-content: center; height: 100 vh; } form { background-color: border-radius: 8 px; box-shadow: 0 0 10 px rgba (0 , 0 , 0 , 0.1 ); padding: 20 px; width: 300 px; } label { display: block; margin-bottom: 8 px; } input { width: 100 %; padding: 8 px; margin-bottom: 16 px; box-sizing: border-box; } button { background-color: color: padding: 10 px; border: none; border-radius: 4 px; cursor: pointer; width: 100 %; } button:hover { background-color: } </style> </head> <body> <!-- <form action="" method="post" > <label for ="username" >用户名:</label> <input type="text" id="username" name="username" required> <label for ="password" >密码:</label> <input type="password" id="password" name="password" required> <button type="submit" >登录</button> </form> </body> </html> <?php include "../config.php" ;$user =$_POST ['username' ];$pass =$_POST ['password' ];$sql = "SELECT * FROM admin WHERE username='$user ' AND password='$pass ';" ;$data = mysqli_query ($con , $sql );if ($_SERVER ["REQUEST_METHOD" ] == "POST" ) { if (mysqli_num_rows ($data ) > 0 ) { session_start (); $_SESSION ['username' ]=$user ; $_SESSION ['password' ]=$pass ; header ('Location: index-s.php' ); exit (); } else { echo "<script>alert('登录失败!')</script>" ; } }
<?php session_start ();if ($_SESSION ['username' ]!='admin' && $_SESSION ['password' ]!='123456' ){ header ('Location: admin-s.php' ); } ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8" > <title>后台首页</title> </head> <body> <h1>后台首页</h1> <p>欢迎您,<?php echo $_SESSION ['username' ]; ?> !</p> <p><a href="logout-s.php" >退出登录</a></p> </body> </html>
<?php session_start ();session_unset ();session_destroy ();header ('Location: admin-s.php' );exit ;?>
token <?php session_start ();$_SESSION ['token' ] = bin2hex (random_bytes (16 ));?> <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8" > <title>后台登录</title> <style> body { background-color: } .login { width: 400 px; margin: 100 px auto; background-color: border-radius: 5 px; box-shadow: 0 0 10 px rgba (0 ,0 ,0 ,0.3 ); padding: 30 px; } .login h2 { text-align: center; font-size: 2 em; margin-bottom: 30 px; } .login label { display: block; margin-bottom: 20 px; font-size: 1.2 em; } .login input[type="text" ], .login input[type="password" ] { width: 100 %; padding: 10 px; border: 1 px solid border-radius: 5 px; font-size: 1.2 em; margin-bottom: 20 px; } .login input[type="submit" ] { background-color: color: border: none; padding: 10 px 20 px; border-radius: 5 px; font-size: 1.2 em; cursor: pointer; } .login input[type="submit" ]:hover { background-color: } </style> </head> <body> <div class ="login "> <h2 >后台登录</h2 > <!-- 提交表单到 "token_check .php ",使用 POST 方法 --> <form action ="token_check .php " method ="post "> <!-- 隐藏域用于存储 CSRF token --> <input type ="hidden " name ="token " value ="<?php echo $_SESSION ['token '] ; ?>"> <label for ="username ">用户名:</label > <input type ="text " name ="username " id ="username " required > <label for ="password ">密码:</label > <input type ="password " name ="password " id ="password " required > <input type ="submit " value ="登录"> </form > </div > </body > </html >
<?php session_start ();$token = $_POST ['token' ] ?? '' ;if ($token !== $_SESSION ['token' ]) { header ('HTTP/1.1 403 Forbidden' ); $_SESSION ['token' ] = bin2hex (random_bytes (16 )); echo 'Access denied' ; exit ; }else { $_SESSION ['token' ] = bin2hex (random_bytes (16 )); if ($_POST ['username' ]=='admin' && $_POST ['password' ]=='123456' ){ echo '登录成功!' ; echo '你是管理员可以访问文件管理页面!' ; }else { echo '登录失败!' ; } } ?>
文件管理 上传 $_FILES:PHP中一个预定义的超全局变量,用于在上传文件时从客户端接收文件,并将其保存到服务器上。它是一个包含上传文件信息的数组,包括文件名、类型、大小、临时文件名等信息。
$_FILES[“表单值”][“name”] 获取上传文件原始名称
$_FILES[“表单值”][“type”] 获取上传文件MIME类型
$_FILES[“表单值”][“size”] 获取上传文件字节单位大小
$_FILES[“表单值”][“tmp_name”] 获取上传的临时副本文件名
$_FILES[“表单值”][“error”] 获取上传时发生的错误代码
move_uploaded_file() 将上传的文件移动到指定位置的函数
上传的两种架构:
1.上传到服务器本身存储磁盘
2.上传到云存储OSS(OSS中的文件无法被解析)
文件后缀无过滤 创建upload.php和upload.html(upload.html用chatgpt实现实现)
enctype=”multipart/form-data” 告诉服务器,表单中包含了文件上传的数据,并且服务器需要以二进制格式解析这些数据。这样可以确保文件等二进制数据能够正确地传输到服务器。
<!-- 提交表单到 "upload.php" ,使用 POST 方法,并启用文件上传功能 --> <form **action="upload.php" ** method="POST" enctype="multipart/form-data" > **<!-- 用于标识上传文件的标签 --> <label for ="file" >选择文件:</label> <br> <!-- 文件输入框,允许用户选择要上传的文件 --> <input type="file" id="file" name="f" > <br> <!-- 提交按钮,触发文件上传操作 --> <button type="submit" >上传文件</button>** </form>
upload.php的实现并在项目创建新的目录,upload目录来存放上传的内容
<?php $name = $_FILES ['f' ]['name' ];$type = $_FILES ['f' ]['type' ];$size = $_FILES ['f' ]['size' ];$tmp_name = $_FILES ['f' ]['tmp_name' ];$error = $_FILES ['f' ]['error' ];echo $name . "<br>" ;echo $type . "<br>" ;echo $size . "<br>" ;echo $tmp_name . "<br>" ;echo $error . "<br>" ;** if (move_uploaded_file ($tmp_name , 'upload/' . $name )) { echo "文件上传成功!" ; }** ?>
文件后缀黑名单过滤 使用 explode 函数通过点号分割文件名,获取文件后缀
使用 end 函数获取数组中的最后一个元素,即文件后缀
检查文件后缀是否在黑名单中
如果文件后缀在黑名单中,输出非法后缀文件信息
如果文件后缀不在黑名单中,移动上传的文件到指定目录
输出上传成功的提示信息
$black_ext = array ('php' , 'asp' , 'jsp' , 'aspx' );$fenge = explode ('.' , $name );$exts = end ($fenge );if (in_array ($exts , $black_ext )) { echo '非法后缀文件' . $exts ; } else { move_uploaded_file ($tmp_name , 'upload/' . $name ); echo "<script>alert('上传成功!')</script>" ; } ?>
文件后缀白名单过滤 ** $allow_ext = array ('png' , 'jpg' , 'gif' , 'jpeg' );**$fenge = explode ('.' , $name );$exts = end ($fenge );**if (!in_array ($exts , $allow_ext )) { echo '非法后缀文件' . $exts ;** } else { move_uploaded_file ($tmp_name , 'upload/' . $name ); echo "<script>alert('上传成功!')</script>" ; }
文件MIME类型过滤 ** $allow_type = array ('image/png' , 'image/jpg' , 'image/jpeg' , 'image/gif' );**if (!in_array ($type , $allow_type )) { echo '非法文件类型' ; } else { move_uploaded_file ($tmp_name , 'upload/' . $name ); echo '<script>alert("上传成功")</script>' ; }
显示 1.打开目录读取文件列表
2.递归循环读取文件列表
3.判断是文件还是文件夹
4.PHP.INI目录访问控制
is_dir () 函数用于检查指定的路径是否是一个目录(文件夹)opendir () 函数用于打开指定的目录,返回句柄,用来读取目录中的文件和子目录readdir () 函数用于从打开的目录句柄中读取目录中的文件和子目录open_basedir:PHP.INI中的设置用来控制脚本程序访问目录
opendir() readdir() 区别
opendir() 函数:
opendir() 用于打开一个目录句柄(directory handle)。
接受一个参数,即要打开的目录的路径。
返回一个目录句柄,该句柄可以用于后续对目录的操作。
通常与 closedir() 配合使用,用于关闭目录句柄。
phpCopy code $dir_handle = opendir ('/path/to/directory' );
readdir() 函数:
readdir() 用于读取目录句柄中的条目。
接受一个参数,即之前使用 opendir() 打开的目录句柄。
在每次调用时,返回目录中的下一个文件或目录的名称。
当没有更多的文件或目录时,返回 false。
phpCopy code $file = readdir ($dir_handle );
使用 opendir() 打开目录,然后使用 readdir() 循环读取目录中的文件和目录,最后使用 closedir() 关闭目录句柄。
phpCopy code $dir_handle = opendir ('/path/to/directory' );while (($file = readdir ($dir_handle )) !== false ) { echo $file . '<br>' ; } closedir ($dir_handle );
总体代码实现 <?php $dir = $_GET ['path' ] ?? './' ;function filelist ($dir ) { if ($dh = opendir ($dir )) { **while (($file = readdir ($dh )) !== false ) { if (is_dir ($dir . '/' . $file )) { echo "<li><i class='fa fa-folder'></i> <a href='?path=$dir /$file '>" . $file . '</a></li>' ; } else { echo '<li><i class="fa fa-file"></i> <a href="#">' . $file . '</a></li>' ; } } closedir ($dh ); }** } filelist ($dir );?>
while 循环迭代目录中的每个条目。
**readdir($dh)**读取目录中的下一个条目。
循环继续,直到没有更多的条目(readdir返回false)。
在循环内部,is_dir($dir . ‘/‘ . $file)检查当前目录项是否是一个目录,通过构建完整路径并使用is_dir 函数来判断。
条件通过使用斜杠(/)将目录路径($dir)与当前目录项($file)连接起来,形成完整的路径。
PHP.INI目录访问控制 目的是避免目录穿越,限制目录访问范围
php的配置文件
open_basedir
规定了目录访问的根目录,我们不能跳出该目录查看其它文件内容
php配置文件前面有;则为被注释(不生效)
包含 include () 在错误发生后脚本继续执行require () 在错误发生后脚本停止执行include_once () 如果已经包含,则不再执行require_once () 如果已经包含,则不再执行
如果使用文件包含函数,并且函数的参数为用户可控
比如
用户可以通过手动修改page的参数来进行任意文件包含
编辑 file_get_contents () 读取文件内容fopen () fread () 文件打开读入
删除 unlink () 文件删除函数调用命令删除:system shell_exec exec等
下载 修改HTTP头实现文件读取解析下载: header ("Content-Type: application/octet-stream" );header ("Content-Disposition: attachment; filename=" "); header(" Content-Length : " . filesize($file )); readfile($file );
新闻列表&模版引用 自写模板 模板:由于牵涉到美观问题,将php代码中插入html代码以达到更美观,而当我们使用模板时,对于模板相应的位置进行替换即可
模板要被调用运行,有eval函数,可能存在RCE
第三方模板安全性较高,查看网上是否爆出相关版本漏洞
插件能做到哪些功能,需要用到哪些函数,这些函数会引发什么安全漏洞
** $template = file_get_contents ('new.html' );**while ($row = mysqli_fetch_row ($data )) { $page_title = $row [1 ]; $heading = $row [2 ]; $subheading = $row [3 ]; $content = $row [4 ]; $item = $row [5 ]; } $template = str_replace ('{page_title}' , $page_title , $template );$template = str_replace ('{heading}' , $subheading , $template );$template = str_replace ('{subheading}' , $subheading , $template );$template = str_replace ('{content}' , $content , $template );$template = str_replace ('{$item}' , $item , $template );** eval ('?>' . $template );**mysqli_close ($con );
如果在数据库中任何地方添加 <font style="background-color:rgba(255, 255, 255, 0);"><?php phpinfo();?></font>
,在调用数据库内容的时候会自动显示
如果在html模板源码中加入 <font style="background-color:rgba(255, 255, 255, 0);"><?php phpinfo();?></font>
,在执行HTML并不会显示,但通过php解析调用,则依然会展示有关内容
php代码解析调用,存在RCE
Smarty模板 smarty模板使用
使用:
1、创建一个文件夹,命名为smarty
2、下载Smarty对应版本并解压缩到该文件夹中。
3、创建一个PHP文件,命名为index.php,并在文件中添加以下代码:
<?php require ('smarty/libs/Smarty.class.php' );$smarty = new Smarty ;**$smarty ->template_dir = 'smarty/templates/' ; $smarty ->compile_dir = 'smarty/templates_c/' ; $smarty ->cache_dir = 'smarty/cache/' ; $smarty ->config_dir = 'smarty/configs/' ; $smarty ->assign ('title' , '欢迎使用 Smarty' ); $smarty ->display ('index.tpl' ); ?>
路径要进行更改,index.tpl要自行创建
4、在smarty相关目录下创建smarty/templates/ 并在目录下创建一个名为index.tpl的模板文件,并将以下代码复制到上述点定义文件夹中
<!DOCTYPE html> <html> <head> <title>{$title }</title> </head> <body> <h1>{$title }</h1> <p>这是一个使用 Smarty 的例子。</p> </body> </html>
在网上查找相关版本漏洞
框架ThinkPHP(TP) MVC:model view controller(模板、视图、控制器)
ThinkPHP官方手册
路由访问 路由访问,要规定路由关系
两种访问方式
数据库操作 使用TP框架操作数据库,默认是受到框架内置过滤保护,语句写法会改变
1.连接数据库找到数据库配置文件(database.php),并打开调试模式
2.引用数据的的类use think\Db;,使用数据库的查询语句
use think \Db ;public function testsql ( ) { $data = Db ::table ('news' )->where ('id' , 1 )->findOrFail (); return json ($data ); }
文件上传 网站根目录创建upload.html
写入表单代码,并修改action的值
创建php文件并写入控制器代码
前端页面渲染view 在例如index(需要渲染的文件当前并行目录下)→view→index→index.html等
http://192.168.137.1:84/index.php/Index/index/index 输入对应的路由访问即可看到以及渲染的页面
也可以指定内容可以指定模板
public function index ( ) { ** $this ->assign ('name' ,'ThinkPHP' ); $this ->assign ('email' ,'thinkphp@qq.com' ); $this ->assign ([ 'name' == 'ThinkPHP' , 'email' == 'thinkphp@qq.com' ]); return $this ->fetch ('index/edit' );** }
安全 think还提供了原生写法
如果使用原生写法,仍然存在安全漏洞
$id =request ()->param ('x' );$data =Db ::table ('news' )->where ('id' ,$id )->find ();
$id =request ()->param ('x' ); $data =Db ::query ("select * from news where id=$id " );