溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

sql注入報錯怎么解決

發(fā)布時間:2022-06-10 11:54:05 來源:億速云 閱讀:140 作者:iii 欄目:開發(fā)技術(shù)

今天小編給大家分享一下sql注入報錯怎么解決的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

0x01

我們先來看一看現(xiàn)象,我這里有一個users表,里面有五條數(shù)據(jù):

sql注入報錯怎么解決

然后用我們的報錯語句查詢一下:

select count(*),(concat(floor(rand()*2),(select version())))x from users group by x

sql注入報錯怎么解決

成功爆出了數(shù)據(jù)庫的版本號。

要理解這個錯誤產(chǎn)生的原因,我們首先要知道group by語句都做了什么。我們用一個studetn表來看一下:

sql注入報錯怎么解決

現(xiàn)在我們通過年齡對這個表中的數(shù)據(jù)進(jìn)行下分組:

sql注入報錯怎么解決

形成了一個新的表是吧?你其實(shí)應(yīng)該能夠想到group by 語句的執(zhí)行流程了吧?最開始我們看到的這張sage-count()表應(yīng)該時空的,但是在group by語句執(zhí)行過程中,一行一行的去掃描原始表的sage字段,如果sage在sage-count()不存在,那么就將他插入,并置count()置1,如果sage在sage-count()表中已經(jīng)存在,那么就在原來的count(*)基礎(chǔ)上加1,就這樣直到掃描完整個表,就得到我們看到的這個表了。

注:這里有特別重要的一點(diǎn),group by后面的字段時虛擬表的主鍵,也就是說它是不能重復(fù)的,這是后面報錯成功的關(guān)鍵點(diǎn),其實(shí)前面的報錯語句我們已經(jīng)可以窺見點(diǎn)端倪了

sql注入報錯怎么解決

0x02

正如我前面所說的,報錯的主要原因時虛擬表的主鍵重復(fù)了,那么我們就來看一下它到底是在哪里,什么時候重復(fù)的。這里rand()函數(shù)就登場了。
首先我們先來了解rand()函數(shù)的用法:

1.用來生成一個0~1的數(shù)

2.還可以給rand函數(shù)傳一個參數(shù)作為rand()的種子,然后rand函數(shù)會依據(jù)這個種子進(jìn)行隨機(jī)生成。

那他們的區(qū)別是什么呢?我們來看一下,這兩個語句的執(zhí)行效果:

sql注入報錯怎么解決

可以看到rand()生成的數(shù)據(jù)毫無規(guī)律,而rand(0)生成的數(shù)據(jù)則有規(guī)律可循,是:
0110 0110

注:如果你覺得數(shù)據(jù)不夠,證明不了rand()的隨機(jī)性,你可以自己多插入幾條數(shù)據(jù)再查詢試一下。

0x03

現(xiàn)在我們弄清楚了group by語句的工作流程,以及rand()與rand(0)的區(qū)別,那么接下來就是重點(diǎn)了,mysql官方說,在執(zhí)行g(shù)roup by語句的時候,group by語句后面的字段會被運(yùn)算兩次。

**第一次:**我們之前不是說了會把group by后面的字段值拿到虛擬表中去對比嗎,在對比之前肯定要知道group by后面字段的值,所以第一次的運(yùn)算就發(fā)生在這里。

**第二次:**現(xiàn)在假設(shè)我們下一次掃描的字段的值沒有在虛擬表中出現(xiàn),也就是group by后面的字段的值在虛擬表中還不存在,那么我們就需要把它插入到虛擬表中,這里在插入時會進(jìn)行第二次運(yùn)算,由于rand函數(shù)存在一定的隨機(jī)性,所以第二次運(yùn)算的結(jié)果可能與第一次運(yùn)算的結(jié)果不一致,但是這個運(yùn)算的結(jié)果可能在虛擬表中已經(jīng)存在了,那么這時的插入必然導(dǎo)致錯誤!

所以我們現(xiàn)在通過一個例子來驗(yàn)證我們的理論,拿出我們最開始的例子:

select count(*),(concat(floor(rand(0)*2),'@',(select version())))x from users group by x

聲明:users表就是本文第一個表,表中有五條數(shù)據(jù)

注意我這里用的是rand(0),不是rand(),rand(0)生成的有規(guī)律的序列:

sql注入報錯怎么解決

我們跟著剛剛的思路走,最開始的虛擬表是空的,就像下面一樣:

當(dāng)我掃描原始表的第一項(xiàng)時,第一次計算,floor(rand(0)*2)是0,然后和數(shù)據(jù)庫的版本號(假設(shè)就是5.7.19)拼接,到虛擬表里去尋找x有沒有x的值是x@5.7.19的數(shù)據(jù)項(xiàng),結(jié)果顯然是沒有,那么接下來就將它插入到上表中,但是還記得嗎,在插入之前會進(jìn)行第二次計算,這時x的值就變成了1@5.7.19,所以虛擬表變成了下面這樣:

count(*)x
11@5.7.19

現(xiàn)在掃描原始表的第二項(xiàng),第一次計算x==’1@5.7.19‘,已經(jīng)存在,不需要進(jìn)行第二次計算,直接插入,得到下表:

count(*)x
21@5.7.19

掃描原始表的第三項(xiàng),第一次計算x==‘0@5.7.19’,虛擬表中找不到,那么進(jìn)行第二次計算,這時x==‘1@5.7.19’,然后插入,但是插入的時候問題就發(fā)生了,虛擬表中已經(jīng)存在以1@5.7.19為主鍵的數(shù)據(jù)項(xiàng)了,插入失敗,然后就報錯了!

上面是使用rand(0)的情況,rand(0)是比較穩(wěn)定的,所以每次執(zhí)行都可以報錯,但是如果使用rand()的話,因?yàn)樗傻男蛄惺请S機(jī)的嘛,所以并不是每次執(zhí)行都會報錯,下面是我的測試結(jié)果:

sql注入報錯怎么解決

執(zhí)行了五次,報錯兩次,所以是看運(yùn)氣。

以上就是“sql注入報錯怎么解決”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

sql
AI