震惊,YAK-JWT靶场的通关方式竟然是...

心中无爱人,工作自然神

图片

图片

图片

图片

打开jwt靶场是一个登录页面

图片

尝试弱口令admin/admin成功登录。

图片

通过抓包可以看到,整个登录过程主要是3个请求:

第一个页面:https://127.0.0.1:8080/jwt/unsafe-login1 (GET请求)

这个页面是登录首页,通过localStorage从会话中读取VULINBOX_JWT变量,如果存在则通过这个jwt请求/jwt/unsafe-login1/profile,获取用户信息并展示。否则显示登录页面。

图片

第二个页面:https://127.0.0.1:8080/jwt/unsafe-login1 (POST请求)

同在/jwt/unsafe-login1页面,通过POST请求发送认证信息,如果成功则返回jwt,否则返回认证失败的错误

图片

图片

第三个页面:https://127.0.0.1:8080/jwt/unsafe-login1/profile

通过Authorization将jwt传递给后端,如果验证成功则返回用户信息,否则返回认证失败的提示

图片

图片

图片

用户首先通过用户名密码向后端请求得到jwt,再通过jwt向后端请求得到完整用户信息,并将信息展示在前端。

图片

图片

首先打开JWT的登录(未验证算法)案例,在这个案例中,后端未校验加密算法,将根据用户传递的加密算法解密验证jwt。

如图是正常的jwt结构。可以看到在header中存储了用户名,根据页面提示,游戏目标是为用户信息添加flag字段。所以我们的目标就是修改jwt内的header,并绕过后端的校验。

图片

首先了解一下jwt结构:jwt由3部分组成,使用.连接,第一部分是header信息,第二部分是Claims信息,第三部分是签名。

如果使用node方式生成jwt那header部分和Claims部分都是直接通过base64编码,签名为空,那可以编写脚本:

header = codec.EncodeBase64(json.dumps({        "age": 25,        "alg": "none",        "kid": 1,        "typ": "JWT",        "username": "admin",        "flag":1,    }))claims = codec.EncodeBase64(json.dumps({ }))println("%s.%s."%[header,claims])

通过webfuzzer将刚生成的jwt发送到/jwt/unsafe-login1/profile接口,发现这次返回值只有一个flag

图片

通过mitm抓包改包修改jwt可以看到通关页面

图片

图片

打开案例:登录(错误中泄漏key)

和案例1相同的页面,发现获取用户信息的接口改为了/jwt/unsafe-login2/profile。尝试使用案例1的手段发现报错:

图片

可以看到原因是禁用了none的认证方式:'none' signature type is not allowed,但从错误中可以看到泄漏的key。

key是一个byte数组,所以可以编写yak代码,通过泄漏的key生成修改后的jwt:

key = []byte{100,89,84,117,75,83,66,116,72,120,88,98,73,109,110,70,99,74,97,75}jwtStr = jwt.JWTGenerateEx("HS256", {        "flag":1,    },{}, key)~println(jwtStr)

将生成的jwt应用到/jwt/unsafe-login2/profile接口,得到返回数据

图片

从前端页面可以看到修改成功

图片

END
YAK官方资源

Yak 语言官方教程:
Yak:致力于安全能力融合的语言 | Yak Program Language
Yakit 视频教程:
YakProject的个人空间-YakProject个人主页-哔哩哔哩视频
Github下载地址:
GitHub - yaklang/yakit: Cyber Security ALL-IN-ONE Platform
GitHub - yaklang/yaklang: A programming language exclusively designed for cybersecurity
Yakit官网下载地址:
https://yaklang.com/
Yakit安装文档:
下载安装与更新配置 | Yak Program Language
Yakit使用文档:
Yakit: 集成化单兵安全能力平台 | Yak Program Language
常见问题速查:
FAQ | Yak Program Language

./bin/flink run -d -t yarn-per-job \ -Dyarn.application.name="flinkcdc_prod_old_smpcdb_3" \ -Dyarn.application.queue="hive" \ -Dstate.backend=rocksdb \ -Dstate.externalize-checkpoints=true \ -Dexecution.checkpointing.externalized-checkpoint-retention=RETAIN_ON_CANCELLATION \ -Dexecution.checkpointing.interval=180s \ -Dexecution.checkpointing.timeout=7200s \ -Dexecution.checkpointing.min-pause=60s \ -Dexecution.checkpointing.max-concurrent-checkpoints=1 \ -Dstate.checkpoints.dir=hdfs://hadoop102:8020/flink_ck/offline/prod_old_smpcdb \ --allowNonRestoredState \ -Dparallelism.default=4 \ -Djobmanager.memory.process.size=2048m \ -Dtaskmanager.memory.process.size=5120m \ -Dtaskmanager.numberOfTaskSlots=2 \ -c org.apache.doris.flink.tools.cdc.CdcTools \ /opt/module/flink-1.17.2-sql-cdc/lib/flink-doris-connector-1.17-1.6.2.jar \ oracle-sync-database \ --database prod_old_smpcdb \ --oracle-conf hostname=10.1.9.2 \ --oracle-conf port=1521 \ --oracle-conf database-name=PMS2 \ --oracle-conf username=pms \ --oracle-conf password="SRX3yak#8" \ --oracle-conf schema-name=PMS \ --oracle-conf debezium.database.history.store.only.captured.tables.ddl=true \ --oracle-conf debezium.log.miner.enabled=false \ --oracle-conf debezium.snapshot.mode=initial_only \ --oracle-conf debezium.snapshot.fetch.size=20000 \ --oracle-conf debezium.column.mapping="CLOB:STRING,BLOB:STRING" \ --oracle-conf debezium.snapshot.checkpoint.interval.ms=0 \ --oracle-conf debezium.transforms=encodeBlob \ --oracle-conf debezium.transforms.encodeBlob.format=base64 \ --oracle-conf debezium.database.url="jdbc:oracle:thin:@//10.1.9.2:1521/PMS" \ --including-tables "EXP_PHOTO" \ --sink-conf fenodes=10.210.31.92:18030 \ --sink-conf username=root \ --sink-conf password=zjj000000 \ --sink-conf jdbc-url=jdbc:mysql://10.210.31.92:9030 \ --sink.buffer-size=100M \ --sink.buffer-flush.interval=60000 \ --sink-conf sink.enable-2pc=false \ --sink-conf sink.label-prefix=label_cdc_prod_old_smpcdb_340 \ --sink-conf sink.stream-load.timeout=7200 \ --sink-conf sink.connect.timeout.ms=60000 \ --sink-conf sink.request.timeout.ms=3600000 \ --table-conf replication_num=1 目前是flink doris connetct 来采集表中大字段
07-26
<think>我们正在解决Flink Doris Connector通过Oracle CDC同步时大字段(CLOB/BLOB)为空的问题。根据用户提供的引用和之前的分析,我们需要重点关注Oracle CDC连接器对大字段的支持以及Flink Doris Connector的数据映射处理。 引用[1]指出:Flink的schema定义仅声明如何将物理列从外部系统映射到Flink,映射规则取决于连接器实现。引用[2]提到Oracle中expr不能使用BFILE、BLOB、CLOB等类型,这提示我们在CDC同步中需要特殊处理这些类型。 结合之前的分析,以下是解决方案: ### 解决方案步骤 #### 1. **配置Oracle CDC源以捕获大字段** - 使用Debezium Oracle Connector时,必须显式启用LOB支持并设置相关参数。 - 在Flink CDC作业中,配置`debezium`属性: ```java Properties debeziumProperties = new Properties(); debeziumProperties.setProperty("snapshot.mode", "initial"); debeziumProperties.setProperty("lob.enabled", "true"); // 关键:启用LOB支持 debeziumProperties.setProperty("column.include.list", "SCHEMA_NAME.TABLE_NAME.CLOB_COLUMN,BLOB_COLUMN"); // 包含大字段列 // 调整事件大小限制(根据实际字段大小调整) debeziumProperties.setProperty("max.request.size", "10485760"); // 10MB debeziumProperties.setProperty("message.key.columns", "SCHEMA_NAME.TABLE_NAME:PRIMARY_KEY_COLUMN"); OracleSource<String> oracleSource = OracleSource.<String>builder() .hostname("oracle_host") .port(1521) .database("ORCL") .username("user") .password("password") .debeziumProperties(debeziumProperties) .deserializer(new JsonDebeziumDeserializationSchema()) // 使用JSON格式 .build(); ``` - 注意:`column.include.list`需要指定包含大字段的列,格式为`SCHEMA.TABLE.COLUMN`(区分大小写)。 #### 2. **在Flink中处理大字段数据** - 由于Debezium会将CLOB/BLOB字段转换为字符串(Base64编码)或字节数组,在Flink中需要进行转换。 - 如果使用`JsonDebeziumDeserializationSchema`,CDC事件会以JSON字符串形式传递。我们需要解析JSON并提取大字段: ```java DataStream<RowData> stream = env.fromSource(oracleSource, WatermarkStrategy.noWatermarks(), "Oracle Source") .flatMap(new FlatMapFunction<String, RowData>() { @Override public void flatMap(String value, Collector<RowData> out) throws Exception { // 解析JSON字符串 JsonObject json = JsonParser.parseString(value).getAsJsonObject(); JsonObject after = json.getAsJsonObject("after"); // 提取CLOB字段(假设在CDC事件中CLOB字段被转换为Base64字符串) String clobData = after.get("CLOB_COLUMN").getAsString(); // 将Base64字符串解码为原始字符串(如果是文本) // 注意:如果CLOB存储的是文本,则可以直接使用;如果是二进制数据,则按BLOB处理 String decodedClob = new String(Base64.getDecoder().decode(clobData), StandardCharsets.UTF_8); // 构建RowData对象,这里省略其他字段 GenericRowData row = new GenericRowData(2); row.setField(0, ...); // 主键等其他字段 row.setField(1, StringData.fromString(decodedClob)); out.collect(row); } }); ``` - 对于BLOB字段,处理方式类似,但需要根据实际需求决定是否转换为Doris支持的格式(如十六进制字符串或Base64字符串)。 #### 3. **配置Doris表以接收大字段** - Doris中,CLOB可以映射为`VARCHAR(65533)`或`STRING`类型(Doris 1.2+支持),BLOB可以映射为`STRING`(存储Base64编码)或`BITMAP`(如果适用)等。 - 创建Doris表示例: ```sql CREATE TABLE doris_table ( id BIGINT, clob_column STRING, -- 使用STRING类型存储大文本 blob_column STRING -- 存储Base64编码的二进制数据 ) ENGINE=OLAP DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 10 PROPERTIES ( "replication_num" = "1" ); ``` #### 4. **配置Flink Doris Sink** - 在Flink Doris Sink中,确保字段映射正确,并设置合适的序列化格式: ```java DorisOptions dorisOptions = DorisOptions.builder() .setFenodes("FE_HOST:8030") .setTableIdentifier("db.doris_table") .setUsername("doris_user") .setPassword("doris_password") .build(); DorisExecutionOptions executionOptions = DorisExecutionOptions.builder() .setLabelPrefix("doris_label") // 确保label唯一性 .setStreamLoadProp("format", "json") // 使用JSON格式传输 .setStreamLoadProp("strip_outer_array", "true") // 去除JSON外层数组 .build(); // 使用RowDataSerializer RowType rowType = ...; // 根据Doris表结构构建RowType DorisSerializer serializer = new DorisRowDataSerializer(rowType, dorisOptions.getTableIdentifier()); DorisSink<RowData> dorisSink = DorisSink.<RowData>builder() .setDorisOptions(dorisOptions) .setDorisExecutionOptions(executionOptions) .setSerializer(serializer) .build(); stream.sinkTo(dorisSink); ``` #### 5. **性能调优与监控** - **内存调整**:在Flink任务管理器中增加内存,防止大字段导致OOM: ```yaml # flink-conf.yaml taskmanager.memory.process.size: 4096m ``` - **批处理大小**:在Doris Sink中调整批量写入大小: ```java executionOptions = DorisExecutionOptions.builder() .setBufferSize(1024 * 1024) // 1MB .setBufferCount(3) .setCheckInterval(3000) .setMaxRetries(3) .build(); ``` - **监控**:通过Flink Web UI观察背压情况,并在Doris中查看导入状态(`SHOW LOAD WHERE label='doris_label...'`)。 ### 备选方案:使用TapData工具 如果上述步骤仍无法解决问题,或需要更简便的同步方式,可考虑引用[3]提到的TapData工具。它提供图形化界面和内置的Oracle到Doris连接器,支持大字段同步,无需编码: 1. 在TapData中创建Oracle和Doris连接。 2. 选择要同步的表,并在映射规则中启用大字段处理。 3. 启动实时同步任务。 ### 注意事项 - **Oracle CDC连接器版本**:确保使用支持大字段的Debezium版本(如1.9+)。 - **数据类型转换**:CLOB/BLOB在CDC事件中的表示方式(Base64或十六进制)需与Flink处理逻辑一致。 - **Doris版本**:Doris 1.2+对STRING类型支持更好,可存储最大2GB的文本数据。 通过以上步骤,应能解决大字段同步为空的问题。如果问题仍然存在,请检查Debezium日志和Flink任务日志,确认大字段是否在CDC事件中被正确捕获。 §§相关问题§§ 1. 如何监控和优化Flink CDC作业的吞吐量? 2. Doris中如何处理超长字符串(超过1MB)的存储和查询? 3. 使用TapData同步数据时,如何保证端到端的数据一致性? [^1]: Flink SQL CREATE TABLE语句的映射规则说明。 [^2]: Oracle中expr的限制,提示大字段需要特殊处理。 [^3]: TapData作为替代方案,提供简便的Oracle到Doris同步。 [^4]: Flink CBO优化器可能影响执行计划,但与大字段问题关联较小。</think>### Flink Doris Connector Oracle CDC 同步 CLOB/BLOB 字段为空解决方案 针对 Oracle CDC 同步 CLOB/BLOB 字段到 Doris 为空的问题,结合引用信息和实际经验,提供以下完整解决方案: --- #### 一、核心问题诊断(基于引用分析) 1. **Oracle CDC 限制** Oracle 的 `expr` 不支持直接操作 `CLOB/BLOB` 类型字段(引用[2]),导致 CDC 捕获时可能忽略或截断这些字段。 2. **Flink 映射机制** Flink 的 schema 映射依赖于连接器实现(引用[1]),Oracle CDC 默认不处理大字段的完整映射。 3. **Doris 类型兼容** Doris 的 `VARCHAR` 最大支持 65533 字符(引用[1]),超长 CLOB 需特殊处理。 --- #### 二、完整解决方案 ##### 步骤 1:启用 Oracle CDC 大字段支持 在 Debezium 配置中显式启用 LOB 处理: ```properties # Debezium Oracle 连接器配置 debezium.source.connector.class=io.debezium.connector.oracle.OracleConnector debezium.source.database.hostname=oracle-host debezium.source.database.port=1521 debezium.source.database.user=user debezium.source.database.password=pass debezium.source.database.dbname=ORCL debezium.source.table.include.list=SCHEMA.TABLE debezium.source.lob.enabled=true # 关键:启用大字段支持 debezium.source.column.include.list=SCHEMA.TABLE.CLOB_COL,SCHEMA.TABLE.BLOB_COL debezium.source.max.request.size=10485760 # 扩大事件大小至10MB ``` ##### 步骤 2:Flink 数据处理层优化 ```java // 自定义反序列化器处理大字段 public class CustomDebeziumDeserializer implements DebeziumDeserializationSchema<RowData> { @Override public void deserialize(SourceRecord record, Collector<RowData> out) { Struct value = (Struct) record.value(); Struct after = value.getStruct("after"); // 显式处理 CLOB 字段 String clobData = after.getString("CLOB_COL"); if (clobData == null) { clobData = ""; // 防 null 处理 } else if (clobData.length() > 65533) { clobData = clobData.substring(0, 65533); // Doris VARCHAR 截断 } // BLOB 转 Base64 字符串 byte[] blobBytes = after.getBytes("BLOB_COL"); String blobData = (blobBytes != null) ? Base64.getEncoder().encodeToString(blobBytes) : ""; // 构建 RowData 输出 GenericRowData row = new GenericRowData(2); row.setField(0, StringData.fromString(clobData)); row.setField(1, StringData.fromString(blobData)); out.collect(row); } } ``` ##### 步骤 3:Doris 表结构优化 ```sql CREATE TABLE doris_table ( id BIGINT, clob_col VARCHAR(65533) COMMENT '存储截断后的CLOB', blob_col TEXT COMMENT '存储Base64编码的BLOB' ) ENGINE=OLAP DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 10 PROPERTIES ( "replication_num" = "3", "storage_format" = "V2" ); ``` ##### 步骤 4:Flink Doris Sink 配置 ```java DorisSink<RowData> sink = DorisSink.<RowData>builder() .setDorisOptions(DorisOptions.builder() .setFenodes("doris-fe:8030") .setTableIdentifier("db.doris_table") .setUsername("user") .setPassword("pass") .build()) .setDorisExecutionOptions(DorisExecutionOptions.builder() .setLabelPrefix("doris-cdc-") .setStreamLoadProp("format", "json") // JSON格式支持大字段 .setStreamLoadProp("strip_outer_array", "true") .build()) .setSerializer(new SimpleRowDataSerializer( // 自定义序列化器 TableSchema.builder() .field("clob_col", DataTypes.STRING()) .field("blob_col", DataTypes.STRING()) .build() )) .build(); ``` --- #### 三、备选方案:使用 TapData(引用[3]) 对于复杂场景,推荐使用专业数据同步工具: ```mermaid graph LR A[Oracle] -->|CDC| B(TapData Agent) B -->|实时同步| C[Doris] ``` 优势: 1. 自动处理 CLOB/BLOB 类型转换 2. 图形化监控同步状态 3. 支持断点续传和一致性校验 --- #### 四、性能优化建议(引用[4]) 1. **Flink CBO 调优** 在 `flink-conf.yaml` 中启用成本优化器: ```yaml table.optimizer.cbo.enabled: true table.optimizer.join-reorder-enabled: true ``` 2. **内存配置** 增加 TaskManager 内存防止 OOM: ```yaml taskmanager.memory.process.size: 8192m taskmanager.memory.managed.fraction: 0.4 ``` 3. **并行度调整** 根据大字段分布设置并行度: ```java env.fromSource(oracleSource, WatermarkStrategy.noWatermarks(), "Oracle Source") .setParallelism(4) // 根据字段大小调整 .sinkTo(sink); ``` --- #### 五、验证方法 1. **日志检查** 在 Debezium 日志中搜索 `LOB_ENABLED` 确认配置生效 2. **中间数据验证** 在 Flink 作业中添加 `print()` 观察字段内容: ```java stream.map(row -> "CLOB length: " + row.getString(0).length()).print(); ``` 3. **Doris 数据查验** ```sql SELECT LENGTH(clob_col) AS clob_len, LENGTH(blob_col) AS blob_len FROM doris_table LIMIT 10; ``` > **关键提示**:若 CLOB 超过 64KB,需在 Doris 侧使用 `TEXT` 类型,并在 Flink 中确保 JSON 序列化完整(`sink.properties.format=json`)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值