先看题目, 依然还是POST, 但是却是更新update询问基于错误的字符串类型的问题.....= = 迷
进去测试...对了, 我找到了可以用的hackbar, 原本的hackbar只能在老版的Firefox浏览器使用, 具体低于哪个版本也不太清楚, 就在这里下了一个35.0.1Windows32位的, 不想折腾了, 32位就32位啦, 反正我是Chrome的粉(/ω\)就是用用这个插件而已. 如果想折腾具体只要低于哪个版本或者想找64位的就来这里自己找吧, 这个好像是官方自己的历史版本仓库, 所以可以放心
回正题, 进入题目以后, 发现界面是跟前面几题有点不一样(;´д`)ゞ
尝试之前的老办法'or 1=1# 发现办法不行叻, 作者调皮还骂人 ̄へ ̄
没办法, 省事大法, 看源码吧, (#.#)
具体关于那个check_input()有什么作用, 下面等会会分析, 其实不知道也是可以解出这道题的. 这里可以看出代码对传递过去的uname进行了某种过滤检查机制, 但是仔细发现对传递过去的passwd却没有进行这个检查, 因此可以猜测passwd能够作为一个注入点.
但是这里有一个问题点哦, 就是这里的uname这一栏是肯定要带入数据库进行检查对比的, 那就意味着我们要输入正确的用户名才行, 因此这里要猜测常用的用户名, 什么admin啊user啊还有administrator之类的常见的, 一般是这样的, 但是如果真的运气差猜不中怎么办...我也不知道ε=(´ο`*)))唉
分析以后就是尝试啦, 动手!
这里发现绕过成功
其实我们这里不是光想登录进去这么简单而已, 我们是想要拿到数据, 因此这里登录成功说明就是单引号这种形式的闭合, 接下来我们就可以使用前面正常的注入语句来注入获取我们想要的数据了
这些payload都是前面用过的, 是一样的
尝试获取具体的数据时, 发现提示什么more than 1 row, 说我超过了一列, 猜测这里应该是只能显示一列的数据, 没关系, 加上一条limit语句就行了
剩下的数据以此类推就能全部获取了
其实这里还可以使用DNSLOG的方法来获取, 怎么好像全都可以使用DNSLOG这种类似作弊的手段获取数据2333
尝试了是可以的. 太懒就不重复了= =\
其实现在注入已经完成了, 但是其实还有个问题没有解决, 前面的check_input那段代码是什么意思, 不想当脚本小子的话肯定是要弄明白的.....真是麻烦呢
要看懂源码有几个PHP的函数可以了解一下, 详细的可以参考php.net
1.get_magic_quotes_gpc()
获取当前magic_quotes_gpc的配置选项设置.
返回值: 如果magic_quotes_gpc为关闭时返回0, 否则返回1. 在PHP5.4.x起将始终返回false, 因为从这个版本以后这个魔术引号(magic_quotes_gpc)的功能已经从PHP中移除了.
2.magic_quotes_gpc()
如果设置了这个选项,那么php解析器就会自动为POST、GET、COOKIE过来的数据增加转义字符""
增加转义符最主要的目的就是为了防止包含sql注入之内的数据注入攻击。
在php5.4的更高版本中,这个选项被去掉了,也即是php解析器不会自动为POST、GET、COOKIE过来的数据增加转义字符"",而是把安全编码交给了用户自己,从而避免了magic_quotes_gpc未设置,用户依赖这个设置而带来了安全隐患。
这就需要我们在进行sql语句执行前,必须转义任何变量:
$value = mysql_real_escape_string($value);
3.ctype_digit()
(PHP 4 >= 4.0.4, PHP 5, PHP 7)
ctype_digit — 做纯数字检测
说明:
bool ctype_digit ( string $text )
检查提供的 string 和 text 里面的字符是不是都是数字。
参数:
text
需要被测试的字符串。
返回值:
如果 text 字符串是一个十进制数字,就返回 TRUE ;反之就返回 FALSE 。
版本说明:
在 PHP 5.1.0 之前,当 text 是一个空字符串的时候,该函数将返回 TRUE 。
4.mysql_real_escape_string
mysql_real_escape_string-------转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集
Warning:
本扩展自 PHP 5.5.0 起已废弃,并在自 PHP 7.0.0 开始被移除。应使用 MySQLi 或 PDO_MySQL 扩展来替换之。
mysql_real_escape_string() 调用mysql库的函数 mysql_real_escape_string, 在以下字符前添加反斜杠: \x00, \n, \r, , ', " 和 \x1a.
为了安全起见,在像MySQL传送查询前,必须调用这个函数(除了少数例外情况)。
5.stripslashes
stripslashes — 反引用一个引用字符串
说明
string stripslashes ( string $str )
返回值
返回一个去除转义反斜线后的字符串(\' 转换为 ' 等等)。双反斜线(\\)被转换为单个反斜线(\)。
6.intval
intval — 获取变量的整数值
7.mysql_query
mysql_query — 发送一条 MySQL 查询
Warning:
本扩展自 PHP 5.5.0 起已废弃,并在自 PHP 7.0.0 开始被移除。应使用 MySQLi 或 PDO_MySQL 扩展来替换之
返回的结果资源应该传递给 mysql_fetch_array() 和其他函数来处理结果表,取出返回的数据。
8.mysql_fetch_array
(PHP 4, PHP 5)
mysql_fetch_array — 从结果集中取得一行作为关联数组,或数字数组,或二者兼有
这就是在check_input中需要了解的函数, 看着比较多, 其实主要就是几个转义逆转义的函数, 有的函数甚至已经被废除了, 毕竟这个天梯练习环境已经很老了, 没办法, 掌握思想就行.
其中还看到一个老哥的关于这个魔术引号的理解分享, 就直接贴张下面了
php中关于反斜线转义:
php中数据的魔法引用函数 magic_quotes_gpc 或 magic_quotes_runtime
设置为on时,当数据遇到 单引号' 和 双引号" 以及 反斜线\ NULL时自动加上反斜线,进行自动转义。注释:默认情况下,PHP 指令 magic_quotes_gpc 为 on,对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。magic_quotes_gpc 和 magic_quotes_runtime二者的区别:
magic_quotes_gpc
作用范围是:WEB客户服务端;
作用时间:请求开始的时候,例如当脚本运行时。magic_quotes_runtime
此函数是该函数的别名: set_magic_quotes_runtime()
作用范围:从文件中读取的数据或执行exec()的结果或是从SQL查询中得到的;
作用时间:每次当脚本访问运行状态中产生的数据。由此我们可以看出:
magic_quotes_gpc的设定值将会影响通过GET、POST 和 COOKIE获得的数据
magic_quotes_runtime的设定值将会影响从文件中读取的数据或从数据库查询得到的数据下面是几个相关的函数:
set_magic_quotes_runtime():
设置magic_quotes_runtime值. 0或者false代表“关闭”.1或者true代表“打开”.默认状态是关闭的.可以通过 echo phpinfo()查看magic_quotes_runtime的当前状态。
get_magic_quotes_gpc():
查看magic_quotes_gpc值.0或者false代表“关闭”.1或者true代表“打开”。
get_magic_quotes_runtime():
查看magic_quotes_runtime值。0或者false代表“关闭”.1或者true代表“打开”。
需要特别注意的是不存在set_magic_quotes_gpc()这个函数,就是不能在程序里面设置magic_quotes_gpc的值。
由于两个值的设置问题,会给编程时造成部分混淆或者会多加一次转义,针对这种情况,需要在程序开始的时候进行设置和判断,或者默认配置
这两个值都关闭。转义部分通过程序来执行。
保证数据插入数据时正常 通常会使用 addslashes 这个来处理, 数据读出时多用 stripslashes 来去掉加的反斜杠php中类似的字符转换或者置取的函数
ini_get 获取一些配置选项的值
addslashes 指定的预定义字符前添加反斜杠
stripslashes 删除由 addslashes() 函数添加的反斜杠
htmlspecialchars 把一些预定义的字符转换为 HTML 实体
htmlspecialchars_decode 把一些预定义的 HTML 实体转换为字符
html_entity_decode() 把 HTML 实体转换为字符
htmlentities() 把字符转换为 HTML 实体
来到正题, 我就直接把代码贴出来, 然后在后面注释写上我自己的理解啦
function check_input($value) //定义一个名为check_input的函数, 并且需要有一个参数, 这个形参就是$value
{
if(!empty($value)) //检测这个形参是否为空, 不为空就执行if里面的语句, 为空就执行else里的语句
{
// truncation (see comments)
$value = substr($value,0,15); //substr()函数, 前面接触过, 就是分割一串字符串的效果, 第二个参数是从第0个字符开始切割, 后面是限制长度为15
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc()) //检测是否开启了魔术引号这个配置, 开启了就返回true, 执行这个if语句中的内容, 关闭的话就返回false
{
$value = stripslashes($value); //去除含有转义符\的字符串
}
// Quote if not a number
if (!ctype_digit($value)) //检测$value是不是纯数字, 如果是纯数字就不执行if语句中的内容
{
$value = "'" . mysql_real_escape_string($value) . "'"; //转义SQL语句中使用的字符串中的特殊字符
}
else //这个else是和最外面的if语句对应的, 就是那个检测是否为空empty()的条件语句
{
$value = intval($value); //intval这个函数就类似于强制转换成int整形的意思, 成功时返回变量的int值 ,比如'-21'转成21, 失败时就会返回0
}
return $value;
}
基本上这个check_input()函数就是这个意思, 就只是转义和不转义以及防止多重转义的用处, 在不知道这个含义的时候也是能做出来这道题, 知道最好, 也方便以后做PHP代码审计.
在做完这个以后以为就完成了, 但是往下瞟了一眼代码发现还有个update的SQL语句......这才恍然大悟!!!∑(゚Д゚ノ)ノ这一关就是让我们修改密码的, 所以肯定要检测用户名而不需要检测密码的正确与否, 所以才没有对密码进行check_input过滤, 刚开始还以为别人的业务逻辑有问题, 看来有问题的自己啊(╬ ̄皿 ̄)=○#( ̄#)3 ̄) 但是说句题外话, 现在修改密码好像大多部分都要验证旧密码, 除了找回密码那种....
尝试看是不是能修改密码
再到数据库中看看admin的密码有没有改变
这里说一下SQL语句的update修改数据的用法
作用:Update 语句用于修改表中的数据。
语法:UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
例句:修改users表中名为inputuser的数据
UPDATE users SET password = inputpass WHERE username = inputuser
注:其中“SET 列名称 = 新值”新值可以为逻辑运算的结果(True or False)
更新
闲逛发现了另外一种payload
获取数据库名
uname=admin&passwd=chybeta' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)#&submit=Submit
获取具体的数据
uname=admin&passwd=chybeta' and updatexml(1,concat(0x7e,(SELECT group_concat(0x23,username,0x3a,password,0x23) FROM (select * from users)tmp),0x7e),1)#&submit=Submit
还有另外一种通过extractvalue()函数构造的payload
两种都来自这里
最后在放一张关于concat()函数理解的SQL语句
反正这种一般加就加两个一样的吧...就当是前后对称.....目前理解费劲...