sql sql复习
虽然之前学习过sql,但由于重在赶学习进度,没有学扎实,导致自己刷题的时候有的地方还是模模糊糊,现在主要是复习,补一补知识点。
今日靶场:
NSSCTF
云曦历年考核题
在做题之前先回顾一下sql注入的原理,以便在做题的过程中更快的找到解题方法。
其实最简单粗暴的讲sql注入就是利用题目会把用户输入的语句加入SQL语句进行拼接,导致攻击者构造的恶意语句被迫执行,然后达到攻击者想要的目的。
SQL语句的结构
例如一个简单的SQL语句如下:
SELECT * FROM users WHERE username = 'admin' AND password = 'password';
这里就有两个用户注入点:两个单引号内的部分 'admin' 和 'password'
然后用户在admin处输入这个:
' OR '1'='1
上面的SQL语句就被改动了:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = 'password';
可以看到,OR '1'='1' 是一个永远为真的条件,这将导致查询返回所有用户的信息。
当然,在做CTF Web题的时候返回我们攻击者需要的信息是最好的事儿,因为这是目的。
但是题目当然不可能这么简单,一定会对我们的语句进行过滤、转义或者验证,此时页面就会出现报错,那也没关系,因为我们还是可以根据题目报错或者页面的响应然后对我们输入的语句进行校正,以达到在绕过限制的同时让它在SQL语句中被执行的目的。
会出现报错
比如在上面的例子中,SQL语句是这样的:
SELECT * FROM users WHERE username = 'admin' AND password = 'password';
当然了,刚刚是假设SQL语句就是那一句固定样式的情况,然而现实中很多题目肯定也不可能就那么一个固定的SQL语句,不然就一个固定样式多没意思。那还有些什么样式呢?比如双引号的:
SELECT * FROM users WHERE username = "admin" AND password = "password123";
那我们输入 ' OR '1'='1 肯定要报错的了,因为拼接进去这样:
SELECT * FROM users WHERE username = "' OR '1'='1" AND password = "password123";
" ' OR '1'='1" 这一堆妖魔鬼怪 OR '1'='1" 当然不符合SQL语法,此时页面一报错也可以知道原SQL语句的注入点闭合方式为 " " 这也是所说的判断闭合方式。
而刚刚假设的SQL语句也是固定为字符型注入的情况(这样说是因为数字值1加了引号如 '1'='1'后被字符串化了,此刻数字1变成了字符'1'),事实还有数字型注入,但数字型注入方式不用引号闭合,因此不用判断闭合方式。
不会出现报错
这种情况就只能看执行sql注入语句后的结果有没有达到目的了,没有达到目的是不会出现报错的
当然了,刚刚是假设SQL语句就是那一句固定样式的情况,然而现实中很多题目肯定也不可能就那么一个固定的SQL语句,不然就一个固定样式多没意思。那还有些什么样式呢?比如双引号的:
SELECT * FROM users WHERE username = "admin" AND password = "password123";
那我们输入 ' OR '1'='1 肯定要报错的了,因为拼接进去这样:
SELECT * FROM users WHERE username = "' OR '1'='1" AND password = "password123";
" ' OR '1'='1" 这一堆妖魔鬼怪 当然不符合SQL语法, 但也可以知道原SQL语句的注入点闭合方式为 " " 这也是所说的判断闭合方式。
做sql题步骤:
判断列数(order by) >>> 联合查询数据库名(用database()查table_schema) >>> 查表名(从table_schema中查table_name) >>> 查列名(从table_name中查column_name) >>> 查具体数据
NSSCTF:
【SWPUCTF 2021 新生赛】ez_sql
提示安全的传参即POST传参
得到一个假的flag
传参 1' 报错,看引号部分是字符型注入
把引号注释掉又恢复正常了
注意这里我发现注释符 --+ 和 -- 都被过滤掉了
诶嘿,在判断列数时发现我 order by 被它截断了
说明or被过滤了 ,而且,它给我空格也删了(过滤了)
那就要找绕过方法了
去网上找了一下
替换 order by 的,用 group by:
替换空格的,用 /**/ :
替换后继续查询,发现绕过
加第2列
3列
第4列就没有了
所以总的只有三列
接下来联合查询
结果 union 也被过滤了
双写union绕过
但是发现没有返回我想要的信息,这样的话就会想到之前的报错信息提到的LIMIT子句:
也就是说LIMIT是表示所在页数,这样的话我换一页试试:limit 1,1
哦豁,可以看到返回位数是第2列和第3列,但要注意的是第三列前提示的才是True flag,所以应该查询第3列
给 database() 换个位:
得到数据库名 NSS_db
接下来爆表名
说明又有字符被过滤了
仔细一看就是 information少了or嘛
进行双写绕过,但是发现语句最后被截断了,
欧欧欧原来是忘了加括号(加了括号才代表查询的是第3列的表名,和不加括号是完全不一样的)
加括号:
欧喉,返回长度超过一行
这个我熟啊,我记得是有这么个东西:
使用聚合函数 group_concat 来将多行数据合并为一行(用它包裹住table_name即可)
包裹执行
得到两个表名 NSS_tb users
接下来查列名
查具体数据
得到flag
ok,恭喜自己又掉进出题佬的圈套(提交了好几次发现还是不正确)
后来才意识到被骗了 ,true flag反而是false,而真正的flag应该在Flag:这一栏
emmm我真的是,怎么这么多坑
但是发现仅仅只替换为第2列回显时任然是一样的flag,可能是两列目录不一样,所以光换位还不行,需要换位重新做一遍。。
做就做谁怕谁
可以看到数据库名是一样的:
表名也是一样的 :
耶?怎么列名也一样??? :
这样的话就说明是目录查错了(flag根本不在flll444g目录下)
试试Secr3t
这次该对了吧 昂?
[LitCTF 2023]这是什么? SQL! 注一下!
搜什么
先注入万能密码试试
发现只是切换了页面,并没有报错或其他提示,说明是盲注
试了一些字符发现照样只是换了页面,没有进入,应该是有字符被过滤了
那就先注个简单点的1,再进行fuzz模糊测试判断一下哪些字符是被过滤了
进行爆破
好像看似也没过滤什么
结果搞了半天不是盲注,下滑鼠标发现SQL语句和回显
那这样就没什么难度了
注1看看
可以看到一个嵌套数组 ,正确排版应该是这样:
Array ([0] => Array ([username] => tanji[password] => OHHHHHHH)
)
这个可以不用管它,注意到包裹1的是六个括号(((((()))))),这样就需要把括号给闭合掉
没有结果了,加个注释符注释掉后面6个反括号又有结果了
(由于题目有稍不雅的图,被屏蔽了,所以改了截一半)
判断列数
第3列无结果,说明只有两列
联合查询
发现返回结果有点长,应该是id=1的值和联合查询均返回了,那把id=1的值个影藏掉,看着有点费眼睛(id=1改为-1)
这次就只返回联合查询的值了
继续查数据库名
注意到username是第1列返回,psassword是第2列返回
猜测flag应该在password下,所以数据库名查第2列
得到数据库名ctf
继续查表名
-1))))))union select 1,(select table_name from information_schema.tables where table_schema='ctf')#
得到表名users
接续查列名
但是查了好几次都是没有返回值
我还以为是过滤了column,但是测试过后发现并没有
再后来想到有可能列名比较多,不是没有返回值而是返回值太多导致无法显示,所以用group_concat来输出所有,然后的确出了很多列名
查询第一个数据,但发现是无用的flag
接下来这个奥:
查询所有数据库:
id=-1)))))) union select 1,schema_name from information_schema.schemata #
执行
我嘞个,有点多,还好吧,注意到ctftraining这个数据库
直接从头查询
又忘了group_concat
得到flag了吧终于
取数据!!!
特喵的,到这一步又忘了一个东西,虽然列名叫flag,但表中的字段可能包含数据库名而不仅仅是表名,所以应该差ctftraining.flag
最后终于是出flag了
云曦历年考核:
24年秋期末考
admin
开启题目是个登录界面:
提示查看普通用户
那就试试admin登录
出现 js 弹窗提示错误,说明这个这个账户已经存在
注意到有一个 sign up 的注册界面,那就先注册一个看能不能登录进去
设置账户名 adminin 密码为666
注册成功后登录
发现进来了 有一个按钮,但点了以后是一个假的flag
诶但是点完以后关闭了 js 弹窗时发现 URL 地址多了一个参数值 id=1
这个应该就是提示,因此直接利用参数 id 进行sql注入
传id=1跳转到假的flag html界面
加单引号报错,字符型注入,且闭合方式为单引号
加注释符--+,页面正常
说明上面用的这些符号都没被过滤,防止1的值覆盖查询结果,改为-1开始查询列数
才到第2列就不认识了,说明只有1列
联合查询
得到数据库名 TGlu
查表名
得到User和flag
但根据做题的经验来看,500分的题flag应该不会在flag目录下,直接用User查询列名
(或者说登录的sql注入题查询用户名和密码应该首选User或users目录)
看叭,得到用户名和密码的列名
接下来分别给它们爆出来就好了
先查用户名
可以看到有两个用户,而后面那个adminin明显是我们注册的,所以前面的admin就是管理员的
接下来查密码
不用说,666是我注册用的密码,所以前面那部分就是管理员的
现在就用管理员的账户和密码直接返回原页面登录即可到后台拿到flag
登录,get flag