大神Karpathy:我給大模型「SQL注入」攻擊,簡直不要太輕松
AI 大牛 Andrej Karpathy 又來科普知識了,這次的主題是「利用特殊 token 對 LLM 進行類 SQL 注入的攻擊」。
所謂 SQL 注入攻擊,它是一種網絡攻擊技術。攻擊者通過將惡意的 SQL 語句插入到應用程序的輸入字段中,誘使后臺數據庫執(zhí)行這些惡意的 SQL 語句。此類攻擊通常利用應用程序對用戶輸入的處理不當,比如沒有正確地對輸入進行過濾或轉義,導致攻擊者能夠訪問、修改甚至刪除數據庫中的數據。
由于人們的安全意識逐漸升高,目前對于大多數軟件產品來說,SQL 注入都不應該出現。
但在大模型領域,一切都還處于初步階段。LLM 分詞器負責對輸入字符串中的特殊 token(如 <s>、<|endoftext|> 等)進行解析。雖然這看起來很方便,但最多會導致誤判;最壞的情況下會導致 LLM 安全漏洞,相當于 SQL 注入攻擊。
這里就要注意了:用戶輸入字符串是不受信任的數據。
在 SQL 注入中,你可以使用「DROP TABLE」攻擊來破解不良代碼。在 LLM 中同樣會遇到相同的問題,不良代碼會將字符串的特殊 token 描述符解析為實際的特殊 token,弄混輸入表示,導致 LLM 無法分發(fā)聊天模版。
下面是一個使用當前 huggingface Llama 3 分詞器默認的示例。
可以看到,同時出現了兩種不直觀的情況:
- <|begin_of_text|> token 被(128000)被添加到了序列前面
- <|end_of_text|> token(128001)從字符串中被解析出來,并插入了特殊 token?,F在文本(可能來自用戶)可能與 token 協(xié)議混淆,并導致 LLM 無法分發(fā),進而產生未定義的輸出結果。
因此,Karpathy 建議始終使用兩個額外的 flag 進行 tokenizing 操作,禁用 add_special_tokens=False 和 split_special_tokens=True,并在代碼中自行添加特殊 token。他認為這兩個選項的命名會有點令人困惑。對于聊天模型,你也可以使用聊天模板 apply_chat_template。
通過以上操作,你可以得到一些看到來更正確的東西。比如 <|end_of_text|> 現在被視為任何其他字符串序列,并被底層 BPE 分詞器分解,就像任何其他字符串一樣。
Karpathy 認為對編碼和解碼的調用永遠不應該通過解析字符串的方式來處理特殊 token,我們需要完全棄用這一功能。相反,這些應該只通過單獨的代碼路徑來顯式且以編程方式來添加。在 tiktoken 中,始終使用 encode_ordinary;在 huggingface 中,使用上文提到的 flag 更安全。至少要注意到這個問題,并始終保持自己 token 的可視化并測試自己的代碼。
Karpathy 認為這些東西非常微妙且記錄不全,他預計現在大約 50% 的代碼都出現了上述問題導致的 bug。
即使是出廠前經歷了嚴格測試的 ChatGPT 也出現了一些奇怪的問題。最好的情況是它只刪除了 token,最壞的情況則是以一種未定義的方式混淆了 LLM。Karpathy 也不清楚背后發(fā)生了什么,但 ChatGPT 無法將字符串 <|endoftext|> 重復發(fā)給他。所以這里要格外注意。
Andrej Karpathy 的文章一出,立刻引起了討論。有人問:那么 LLM 開發(fā)人員需要采取什么措施來提升安全性嗎?
Karpathy 認為說來也簡單,始終以「普通」方式標記字符串,即 utf8 字節(jié)序列就可以了。這讓人想起了安全領域中的「最小特權」原則 —— 本質上,通過將功能限制在絕對必要的范圍內,就可以最大限度地減少發(fā)生意外后果的可能性。
也有人表示「我們已經在這個方向上前進了」。VLM 模型 PaliGemma 作者,Google DeepMind 科學家 Lucas Beyer 表示,我們在新工作得代碼里已經提升了安全機制,這會有些麻煩,尤其是在支持多個 tokenizer 時,但總體而言是值得的。它也會讓代碼更加直接。
也有網友問道,如果代碼是正確的,但是訓練數據時候輸入 <|endoftext|> 會發(fā)生什么?
Karpathy 表示,如果代碼沒錯,什么都不會發(fā)生。但問題是很多代碼可能并不正確,這會悄悄破壞大模型的世界觀。
Karpathy 發(fā)現的新問題,你怎么看呢?