問題:SQL注入修改,歷史代碼全是${};無法修改的比如表名,列名,動態排序之類的不改,其他的都要修改完成
背景:新公司第一個任務就是SQL注入的修改,歷史sql全部都是${},一個個調整不太合適只能批量修改。查了一下,基本分為 like '%${}%';= ${}?; in (${});to_char(${})之類的.需要注意的是每個都有可能有多種情況,比如 = ${} 有 =${} 和 = '${}'兩種可能,in 有 in ${} ;in (${});in('${}')可能,主要是代碼傳遞的時候,有些人只是在中間拼接了單引號,有些人兩端都拼接了單引號,還有的人把括號也拼起來了。掃描出來是有1900多個問題,一個個解決也不太現實,只能批量修改
實現:利用idea的替換功能對數據批量替換,已in 為例,搜索in\s*\(\s*\$\{(.*?)}\s*\),替換成in
? ? ? ? <foreach item="item" collection="$1.split(',')" open="(" separator="," close=")">
? ? ? ? ? ? replace(#{item},'''')
? ? ? ? </foreach>
注意需要勾選上正則匹配,in\s*\(\s*\$\{(.*?)}\s*\)表示in+任意空格+(+任意空格+${+匹配組+}+任意空格+),匹配組用()包起來,替換的時候可以用$1來獲取這個值,需要多個匹配組的話,替換時依次$1,$2既可,傳的參數再使用replace切掉單引號。這個確認過前后端交互不會有單引號,所有特殊字符都會被去掉。replace替換MySQL并不支持默認為空(截圖當時是用的oracle測試,oracle不寫的話默認轉成空),所以要寫成replace(#{},'''','')單引號轉義要寫兩次,表示把字符串中的單引號改成空
這種基本就可以批量替換,還有要注意一點,sql標簽有一個屬性叫statementType配置成"STATEMENT"的時候代表不接收入參,這樣的話把${}改成#{}會報錯。去掉這個屬性既可