不一样的sql注入

一、update注入

$query=“update member set sex=’$sex’,phonenum=’$phonenum’,address=’$add,email=‘email where username=’$uesernam’”;

这是update语句的简化版,update语法语句:

UPDATE table_name
SET column1=value1,column2=value2,...
WHERE column (1)=value(1), column (2)=value(2)...``and` `column``(n)=value(n);

一般where后面的条件语句只有一条

update有两种玩法:1、报错和盲注(一般不用union注入,好像不能用)

​ 2、更改管理员密码(当第一种不能使用时,有些会拦截,这时可以更改管理员密码)

1、报错注入(盲注和它差不多)

  1. 首先找到注入点
  2. 这里的关键是在于插入报错语句并且不会破坏正常语句的执行所以我们利用 ‘or updatexml(1,2,3) or’ 将语句插入,or也可以是and,前后的闭合符看具体情况,有时没有闭合符就写成:or updatexml(1,2,3) or。如:update users set password=‘123’ where id=1这里我们可写成 update users set password=‘123 ‘or updatexml(1,2,3) or’’ where id=1

2、更改管理员密码

  1. 开始的步骤一样,不过它有点鸡肋!!! 原因:我们需要猜它存放数据的密码那一列的名字,可能是password,passw,pw,没猜中就JJ

  2. 它的思路是我修改了很多的值并且在后面加了where限制条件,如果我们再多加一个修改密码的参数,并且在后面将where语句给注释掉,这样修改的值就从改这一个变成了改全部,从而将管理员密码修改。

    如:update user set age=‘ a g e ′ , s e x = ′ age',sex=' age,sex=sex’ where id=1 这里假如age注入点,并且密码的列名是password,则可以改为:update user set age=‘KaTeX parse error: Expected 'EOF', got '#' at position 21: …,password='123'#̲',sex='sex’ where id=1 插入的语句为:’ ,password=‘123’#

  3. 但是在我们创建账号时基本上password会先加密在放入数据库,而我们上面的写法肯定没有经过加密,所以我们还要知道它的加密形式,一般最简单的是md5,所以要将123加密为202cb962ac59075b964b07152d234b70再使用

  4. 除了要将password加密后再上传,还要注意#需要改写成%23,要不然有时#会失效

  5. 还有一点直接插入:’ ,password=‘202cb962ac59075b964b07152d234b70’%23,可能会被拦截我们还需要将’202cb962ac59075b964b07152d234b70’用hex转化从而绕过,最终变为:0x3230326362393632616335393037356239363462303731353264323334623730

    最后语句为:update user set age=‘ a g e ′ , p a s s w o r d = 0 x 3230326362393632616335393037356239363462303731353264323334623730 age' ,password=0x3230326362393632616335393037356239363462303731353264323334623730%23',sex=' age,password=0x3230326362393632616335393037356239363462303731353264323334623730sex’ where id=1

三、二次注入

  1. 原理:进行一次注入时因为addslashes等保护函数将’,"等转义而无法达到注入的效果,但是有些保护函数如addslashes,它的 \ 转义不会写入数据库内,导致存入数据库内的是有用的注入语句。这是我们只需重新让数据库使用这注入语句就达到了注入的目的!

  2. 使用场景:一般在注册页面进行第一次注入,在登录页面时期再次使用。注:能再次使用完全取决于代码不严谨,语句where username=‘ u s e r n a m e ′ a n d p a s s w o r d = ′ username' and password=' usernameandpassword=password’。

    过程为:

    ​ a. 首先将我们输入的 p a s s w o r d , password, password,username进行数据比较( 注:进行数据比较时转义的 \ 是不在二次语句内或不起效果的,这时找到了一次语句,之后才算登录成功)。

    ​ b.然后代码不严谨,将一次注入的语句拿来当where语句的条件,如果拿二次语句(有转义)的话注入不会成功!

  3. 过程分析:

    ​ a. 我们可以使用:1’ and 1=0#来判断是否有二次注入,我们先正常注册账号并登录,观察页面。之后使用1’ and 1=0#( 注:如果有漏洞,它会使where条件为假,而正常时where条件为真,所以页面会有所不同!)进行注册和登录,若页面于正常的不同则有漏洞

    ​ b.group by使用:先正常注册,假如username=1,password=1,之后在页面留下标记。然后注入:1’group by 1#( 注:它的username其实就是1,所以成功就能看到之前留下的标记),当失败时减去1就得到列数

    ​ c.一般使用union,报错,盲注(没办法时用)

  4. 过程详解:

    ​ a.union:

    ​ 条件:登录成功后会返回数据

    ​ 注意:和普通的union注入一样,第一条语句为假才能返回第二条的注入结果,所以xxx’ union select database()#中的 xxx必须是没有被注册的。

    ​ 语句:admin’ union select group_concat(column_name)from information_schema.columns where table_schema=database()and table_name=‘flag’#

    b.报错:

    ​ 条件:写报错语句登录后有回显(注:它如果没有设计报错提示是没有报错回显!)

    ​ 语句:1’ and updatexml(1,concat(0x7e,database()),1)#

四、堆叠注入

  1. 条件:目标存在sql注入漏洞

    ​ 目标未对";"号进行过滤

    ​ 目标中间层查询数据库信息时可同时执行多条sql语句

  2. 使用场景:

    ​ a.如果其他注入能用自不必说

    ​ b.比如本来要用union注入,但是union 被绝对拦截(/*union*/都不行),这时用堆叠就可以更改注入方法。如我们这时不需要union也能直接用select查询了,或者用其他的注入都行。

    ​ c.前面两种比较乐观,还有比较麻烦情况

  3. 过程详解:

    ​ a. 用堆叠的话,没必要直接用select了。直接用show databases; show tables; show columns from 表名;( 注:表名是字 符串就直接写,若是纯数字,则需要用反引号"`"括起来!) 。但是这里只能显示列的名字,不会显示数据,所以最后用select查询数据就行了!

    麻烦情况1: select被绝对过滤

    ​ 方法一:尝试绕过,将select拆开,

    ​ 1. prepare不能被过滤

    ​ 2.语法:

    set @sql=concat('sele','ct * fr','om Fl','ag');
    prepare xxx from @sql;
    execute xxx;
    

    ​ 方法二:使用别的语句查数据,select的替换是handler(相当于一个数据指针,先创建要一个准备读取的对象然后操作这个 数据指针去读取表中的数据)

    1. handler 要读取的表名 open as 别名;(打开一个句柄实例,也可以不取别名,用一个as是为了下面更加方便操作)
    2. handler 别名 read next;(将句柄移动到表中的第一行数据并且读取,也可以用first或者last读取第一行和最后一行)
    3. handler 别名 close;(将这个句柄实例关闭)(我们查数据就没必要写第三句了)
    4. 语句:1’;handler 1919810931114514 open as toert ;(这里用了as写了别名,原来的名字太长了) handler toert read next%23

    ​ 方法三:

    ​ 1.分析:select不能写就用它语句自带的select(只有查询类题目能用),但是它查询的表(words)肯定不是flag所在的表 (1919810931114514 )。 所以我们要将words改为别的名字(word),同时将flag这数据所在表名改为words (语句顺序不能改,不允许同时出现同名表!) 。这里还要注意它的语句不是:select * from words 的话,我们还需要考虑列名是否一样,不一样还得改!

    1. 语句:改表名:rename table 原来的表名 to 更改的表名; 或者:alter table 旧名 rename (to) 新名((to)表示to可省略)

      实现:1’;rename table words to word;rename table1919810931114514to words;

      语句:改列名:alter table 表名 change ( column)原列名 新列名 列类型;((column)表示它可省略),列类型show column from 表名,返回的数据里写了的)

      实现 : alter table words change flag id varchar(100);

      语句:增加列名:alter table 表名 add column 列名 列属性 (这里假设用不上)

​ 3. 整体实现:1’;rename table words to word;rename table1919810931114514 to words;alter table words change flag id varchar(100); 然后再写个令where永为真的语句:1’ or ‘1’='1

#####     麻烦情况二:关键性的表名被绝对过滤(并且prepare也被过滤)

​ 1.因为我们查数据必须要用到表名,被过滤flag所在的表名的话这时我们只有使用它自带的表名这一种办法,而且该表名的方法也 不能用

​ 2.思路:题目的后端语句可能和次类似:select $post[‘query’]||flag from Flag ,可以看到flag的表给了我们。一般的||是or的 意思,但是我们可以将||改变其作用,变为concat的意思。注:改为concat意思时的||,select 1||flag from Flag 不是select 1flag from Flag 的 意思,相当于在表后面加一列 1,所以列名flag不受影响。

​ 3. 语句:set sql_mode=PIPES_AS_CONCAT; 可将||改为concat的意思

​ 4.实现:1;set sql_mode=PIPES_AS_CONCAT;select 1

​ 5.补充:||为or意思时,注意字母相当于0,0为假,非0为真。而这里 $post[‘query’]||flag ,flag是字母已经有一边为假,所以 我们传非0数字有查询结果1,因为:数字||flag=1 相当于:select 1 from Flag 。而传0或字母时,字母||flag为假,可能会 有人觉得它有查询结果0,但是自己在数据库里测试它没有执行成功的,所以没有回显。大佬可以根据这个猜出后端语句,之 后这里没有过滤 * 也可以上传:*,1 ,也能得flag。代入select *,1||flag(这个等于1) from Flag 就不难理解了。

个人笔记参考了很多作者,用了一些知识点在里面(如果感到不满请联系我删除),但是还是有自己的总结在里面的。欢迎在评论区发表自己的看法(分享知识,指出错误之类的,我会不定时更新内容)。只是分享笔记,出了事跟我没有关系,我只会吃西瓜!

你可能感兴趣的:(web安全,网络安全,sql)