SQLite,ASCII字符0x20到0x7E检查约束

sshcrbum  于 2023-10-23  发布在  SQLite
关注(0)|答案(2)|浏览(114)

我有下面的表,我试图限制列“名称”的ASCII字符范围从0x20到0x7E(所有可打印的ASCII字符)。为什么我的检查约束不起作用?

CREATE TABLE test
( 
    id INTEGER NOT NULL,
    name TEXT NOT NULL CHECK(name NOT GLOB '*[^\x20-\x7E]*'),
    PRIMARY KEY(id)
)

例如:

INSERT INTO test (name) VALUES("Tom");

预期:应添加一个touple,名称为:“Tom”添加到表中(因为插入的名称仅由可打印的ASCII字符组成)。结果:重复约束失败:测试

aurhwmvo

aurhwmvo1#

反斜杠在SQL字符串中并不特殊。例如,“\x20”是4个单独的字符,而不是转义的单个字符。所以GLOB模式总是匹配(因为T不是集合中的字符),NOT使它失败,因此约束失败。

bis0qfac

bis0qfac2#

解决方案

name NOT GLOB cast(x'2a5b5e202d7f5d2a' as TEXT)

说明

为了确保字符串中的所有字符都是可打印的ASCII,我们尝试查找不是的字符。如果没有找到这样的字符,则字符串是可打印的ASCII。从概念上讲,查询可能看起来像这样:

name NOT GLOB '*[^\x20-\x7E]*'   -- (doesn't work in SQLite)

这里GLOB运算符匹配任何不在0x20-0x7E中的字符,并且由于我们用NOT否定表达式,如果没有找到范围外的字符,查询将解析为逻辑true。但是,SQLite不允许对字符串字面量中的十六进制字符进行转义,例如,'\x20'不是十六进制编码的空格字符。作为一种变通方法,我们提供与字节序列x'2a5b5e202d7f5d2a'相同的GLOB模式,并将其转换为TEXT,剩下的是:

name NOT GLOB cast(x'2a5b5e202d7f5d2a' as TEXT)

现在,这可能是太丑陋的合法开发人员,但对我们顽皮的流氓搞SQL注入这只是完美的。
PS:我在我的Blind SQL Injection框架中实现了类似的逻辑。感兴趣的读者可以在这里找到它。

相关问题