命令执行&&代码执行
原理也是之前说过n次的,观察下面的输入
这是一个ping IP的接口,我们结束一个命令,添加一个命令,&&作为分隔符
就会返回相应的结果
下一个是个eval函数,php的执行命令的函数,输入phpinfo()
没什么多说的,就是提供的接口就是执行命令&代码的,但是没有限制能执行哪些命令
文件包含
文件包含主要是代码复用用的到的,像是网站的导航栏,每个页面都有,但是代码又不能每页都写一遍,所以会把导航栏拆分出来成为一个单独的文件,然后用require引用一下就ok了
漏洞的原理就是对引用的文件没有限制,随便引用
$html='';
if(isset($_GET['submit']) && $_GET['filename']!=null){
$filename=$_GET['filename'];
include "include/$filename";//变量传进来直接包含,没做任何的安全限制
}
应该做过滤,比如只能引用这几个文件
if($filename=='file1.php' || $filename=='file2.php' || $filename=='file3.php' || $filename=='file4.php' || $filename=='file5.php'){
include "include/$filename";
}
暂时想象不出来什么情景会需要这个函数
关于需要使用几个…/的问题,多几个保证穿到根目录,读取一些配置文件,要看看是什么系统,有没有那些文件
./是当前目录
../是上一级目录
包含远程文件更简单了,只看网站让不让引用了,两个配置allow_url_fopen,allow_url_include都为on就可以
修改完配置,直接通过url引用外部文件
本地包含文件只能读取一些配置文件,那么更进一步就是自己上传程序文件再进行包含
文件上传
先介绍一个函数
$_FILES()
这是一个预定义的数组,通过POST方法接收上传的文件的信息,和session数组类似,session是保存会话的一些信息
$_FILES()["file"]["name"] //上传文件的名称
$_FILES()["file"]["type"] //上传文件的类型
$_FILES()["file"]["tmp_name"] //存储在服务器的文件的临时副本的名称
$_FILES()["file"]["size"] //上传文件的大小
$_FILES()["file"]["error"] //报错
普通用户上传都是传一些图片啊,文档什么的,那么没有对文件做验证,攻击者上传个一句话木马,就会产生危害
文件验证也是分为前端和后端验证
我们说过,前端验证都是纸老虎,没有不能绕过的,这个只是最初级的文件头检验就更别提了
使用js函数
检验content-type,此参数是通过http头获取的
可以看到此处有两个content-type,我们需要修改的是下面的,第一个content-type是传输例如视频、图片、音频等的特殊编码格式的说明,传输的是二进制数据,分段传输,第二个才是服务器获取的文件类型
这些都是小case,还有检查文件头的,文件头就是系统识别如何解释(?)文件的特殊编码,比如
jpg图片的文件头
用010editor打开jpg格式的图片
都是以FF D8开头的,将其删除,图片就无法打开,或者将JFIF对应的编码4A 46 49 46这一段删除,文件也是无法识别的,其它的大家自己测试学习,在系统中,数据都是以二进制的形式存储的,并不存在什么所谓的类型,所以设置了一些文件头来选择以什么形式来运行,文件后缀这种就不说了
在传输时,只能看到JFIF的文本
直接在图片编码缝隙中插入代码,失败,原来,检查文件头这个函数不仅仅检查文件头,还有文件大小是否匹配
正常上传图片,修改content-length大小,原值是10306,上传失败
那么解决方法就是先将代码插入图片再上传
copy /b images.jpg+p0.php 1.jpg # 生成1.jpg
我们可以看到代码被拼接到最后,content-length变为10319,上传成功
值得注意的是,文件上传后被保存为jpg后缀的文件,那么能否按php文件执行?
不行,所以说只有把图片按php文件执行能利用(因为我们插入的是php代码)
刚才讲到的文件包含漏洞,include和require两个函数,include函数在包含时遇到错误会继续执行,也就是说我们可以直接引用图片,图片中的代码会正常执行,而require在遇到错误时不再执行
顺便说一下任意文件下载,原理就是下载的时候传文件名,这个文件名可以被控制且没做权限控制,导致我们可以随便下载服务器的文件,要求知道文件名和路径,听起来很简单,实验起来也很简单,但是遇到有价值的利用场景并不容易
越权
我们在执行一些敏感操作时,比如查询xx用户的个人隐私信息,应该判断请求的用户是否是请求查看自己的信息,当身份和请求不匹配时,就会产生各种权限控制问题
案例1:
通过提交用户名查看个人信息
代码中未对当前会话的用户和请求查看哪个用户进行比对,是否是一个人或者权限是否允许,我们可以通过注册一些session变量保存当前用户信息
案例2:
两个用户,管理员admin具有添加用户的操作权限,同理,普通用户pikachu是否能执行该操作?
首先尝试访问添加用户的页面,并未对身份进行校验
在我未登录任何账号的情况下,访问该页面,跳转登录,说明只对登录态做了校验,没有校验是否是管理员
修改用户信息,提交,发现其又跳转到登录页面,但是用户已经成功添加了
反序列化
所谓序列化就是一个函数,通过serialize这个函数把对象转换为字符串,方便传输
o代表对象类型,1代表1个变量,多个变量就在后面继续排,新增一个testt2变量
O:4:"PIKA":2:{s:5:"test1";s:7:"pikachu";s:5:"test2";s:4:"tien";}
对象类型:长度:"类名":类中变量的个数:{类型:长度:"值";类型:长度:"值";......}
class类对象包括函数和变量,序列化后的这一串字符包括变量类型,长度,值,但是对象中的方法并不会被序列化
object(PIKA)#2 (1) { ["test1"]=> string(7) "pikachu" }
我觉得倒是更像一个数组,还是类似session那种,保存某个对象的一些值
翻了一些讲解,什么魔术方法,不知所云,看的云里雾里
我们在反序列化后的数据就是一串变量,如果程序不进行处理就没什么危害了
看下面这个例子
class User
{
public $age = 0;
public $name = '';
public function PrintData()
{
echo 'User '.$this->name.'is'.$this->age.'years old. <br />';
}
}
同样是一个对象,包含两个变量和一个函数,赋值
$user = new User();
$user->age = 20;
$user->name = 'day';
序列化
$ser=serialize($user);
O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:3:"day";}
反序列化
var_dump(unserialize($ser));
object(User)#2 (2) { ["age"]=> int(20) ["name"]=> string(3) "day" }
关键步骤来了,用反序列化的数据重建对象,然后调用(函数可重用,属性值不同)
程序的后台代码反序列化后调用了PrintData方法
$user2 = unserialize($ser);
$user2->PrintData();
这个函数是直接echo了变量到页面,漏洞就出现在这里,很容易联想到我们刚学的xss漏洞,只是传输的流程不一样,并不是因为反序列化,也不是因为魔术方法所以存在漏洞,而是通过这种数据传输格式,将恶意payload交给某个函数执行,而这个函数将值输出到前端页面导致了xss
直接把day这个变量值替换为xss payload,注意字符长度匹配,27个字符
$user2 = unserialize('O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:27:"<script>alert(233)</script>";}');
预期弹框
魔术方法就是在创建销毁序列化反序列化时会自动调用的,比如销毁某些变量会调用__destruct()函数,那么会存在漏洞吗?也是要看具体执行了什么代码,和普通方法其实没什么差别,但是这可能是反序列化漏洞特有的地方
__construct 创建对象时调用
__sleep 序列化对象时调用
__wakeup 反序列化对象时调用
__destruct 脚本结束时调用
XXE
定义:输入的恶意xml文档被解析,造成这个什么xxe漏洞,要求libxml<2.9.0,因为高版本默认是禁止解析外部实体的
xml文档是传输和存储数据的,libxml是解析xml文档的库
一个基础的xml文档,看起来和html差不多,还是有本质区别的
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
一个基础的xxe payload
<!--声明xml-->
<?xml version = "1.0"?>
<!DOCTYPE ANY [
<!--SYSTEM标识符说明后面的文档是外部实体 f命名该文件-->
<!ENTITY f SYSTEM "file:///etc/passwd">
]>
<!--引用该文件-->
<x>&f;</x>
产生漏洞的代码
$html='';
//考虑到目前很多版本里面libxml的版本都>=2.9.0了,所以这里添加了LIBXML_NOENT参数开启了外部实体解析
if(isset($_POST['submit']) and $_POST['xml'] != null){
$xml =$_POST['xml'];
//simplexml_load_string将xml字符串转换为对象,就是方便操作文档内容
$data = @simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOENT);
if($data){
$html.="<pre>{$data}</pre>";
}else{}
}
后端接收了我们的xml字符串,解析了我们的输入,然后发现要引用/etc/passwd这个文件,就引用并将数据输出到前端页面,我们在html文档中引用,比如php文件,字体文件,css文件的接口,只要可控,是不是也可能存在漏洞呢?
SSRF
定义:后端在向不同服务器请求资源时,如果这个url参数可控,我们就可以请求其内网的资源
这为什么是一个漏洞呢?因为内网的很多资源都是比较敏感的,对于外网用户不可见的,一些人经常用它来探测内网信息收集
获取文件
if(isset($_GET['file']) && $_GET['file'] !=null){
$filename = $_GET['file'];
$str = file_get_contents($filename);
echo $str;
}
这个漏洞更像是偏?代理的那么一个东西??
不安全的url跳转
我觉得这个漏洞看到名字就知道是什么意思了,也不用说,只是提醒一下,这个东西也是个漏洞,钓鱼用都可以
其它
本次学习的漏洞基本都是由于不安全的输入导致的,具体的利用方式是后端决定的,如何处理我们的输入,我们根据其逻辑构造不同的恶意代码
讲的都很浅,主要是理解原理 ,后面会继续进阶学习
在自学的过程中,动辄几十甚至上百小时的教程,确实很劝退,短教程又无法让我们在最开始建立相对完整的体系,对此,只能说,一定要记录自己的学习进度甚至做学习笔记,在你放弃后再次学习的时候,不需要重头再来,总是处于反复入门的状态