<?php // // Trigger Moved to index.php //if (false !== ($who = Common::getGet(‘vote_for‘))) { // noesc_voteup($who);//} // /** * Get the database link * @return GDO_Database */ function noesc_db() { static $noescdb = true; if ($noescdb === true) { $noescdb = gdo_db_instance(‘localhost‘, NO_ESCAPE_USER, NO_ESCAPE_PW, NO_ESCAPE_DB); $noescdb->setLogging(false); $noescdb->setEMailOnError(false); } return $noescdb; } /** * Create table (called by install-script) * The table layout is crappy, there is only 1 row in the table Oo. * @return boolean */ function noesc_createTable() { $db = noesc_db(); $query = "CREATE TABLE IF NOT EXISTS noescvotes ( ". "id INT(11) UNSIGNED PRIMARY KEY, ". # I could have one row per candidate, but currently there is only one global row(id:1). I know it`s a bit unrealistic, but at least it is safe, isn`t it? "bill INT(11) UNSIGNED NOT NULL DEFAULT 0, ". # bill column "barack INT(11) UNSIGNED NOT NULL DEFAULT 0, ". # barack column "george INT(11) UNSIGNED NOT NULL DEFAULT 0 )"; # george columb if (false === $db->queryWrite($query)) { return false; } return noesc_resetVotes(); } /** * Reset the votes. * @return void */ function noesc_resetVotes() { noesc_db()->queryWrite("REPLACE INTO noescvotes VALUES (1, 0, 0, 0)"); echo GWF_HTML::message(‘No Escape‘, ‘All votes have been reset‘, false); } /** * Count a vote. * Reset votes when we hit 100 or 111. * TODO: Implement multi language * @param string $who * @return void */ function noesc_voteup($who) { if ( (stripos($who, ‘id‘) !== false) || (strpos($who, ‘/‘) !== false) ) { echo GWF_HTML::error(‘No Escape‘, ‘Please do not mess with the id. It would break the challenge for others‘, false); return; } $db = noesc_db(); $who = mysql_real_escape_string($who); $query = "UPDATE noescvotes SET `$who`=`$who`+1 WHERE id=1"; if (false !== $db->queryWrite($query)) { echo GWF_HTML::message(‘No Escape‘, ‘Vote counted for ‘.GWF_HTML::display($who), false); } noesc_stop100(); } /** * Get all votes. * @return array */ function noesc_getVotes() { return noesc_db()->queryFirst("SELECT * FROM noescvotes WHERE id=1"); } /** * Reset when we hit 100. Or call challenge solved on 111. * @return void */ function noesc_stop100() { $votes = noesc_getVotes(); foreach ($votes as $who => $count) { if ($count == 111) { noesc_solved(); noesc_resetVotes(); break; } if ($count >= 100) { noesc_resetVotes(); break; } } } /** * Display fancy votes table. * New: it is multi language now. * @return unknown_type */function noesc_displayVotes(WC_Challenge $chall) { $votes = noesc_getVotes(); echo ‘<table>‘; echo sprintf(‘<tr><th>%s</th><th>%s</th><th>%s!</th></tr>‘, $chall->lang(‘th_name‘), $chall->lang(‘th_count‘), $chall->lang(‘th_vote‘)); $maxwho = ‘‘; $max = 0; $maxcount = 0; // Print Candidate rows foreach ($votes as $who => $count) { if ($who !== ‘id‘) // Skip ID { $count = (int) $count; if ($count > $max) { $max = $count; $maxwho = $who; $maxcount = 1; } elseif ($count === $max) { $maxcount++; } $button = GWF_Button::generic($chall->lang(‘btn_vote‘, array($who)), "index.php?vote_for=$who"); echo sprintf(‘<tr><td>%s</td><td class="gwf_num">%s</td><td>%s</td></tr>‘, $who, $count, $button); } } echo ‘</table>‘; // Print best candidate. if ($maxcount === 1) { echo GWF_Box::box($chall->lang(‘info_best‘, array(htmlspecialchars($maxwho)))); } } /** * Try to get here :) */ function noesc_solved() { if (false === ($chall = WC_Challenge::getByTitle(‘No Escape‘))) { $chall = WC_Challenge::dummyChallenge(‘No Escape‘, 2, ‘/challenge/no_escape/index.php‘, false); } $chall->onChallengeSolved(GWF_Session::getUserID()); } ?> |
这是no escape 的源代码,可以看到题目最下面是投票的框并且显示,大概猜测与票数有关,大概浏览一下代码,会发现它对于票数有两个限制,一个是在111以上,另一个是超过100,页面就会被重置,也就是说,通过点击投票是不能达到111票的,所以直接提交就可以,但是观察query那一句用的`而不是‘ , 所以在提交时使用`,构造出来就是`bill=111--+,后面那句就是把后面的代码注释掉。
MYSQL I
<?php /* TABLE STRUCTURE CREATE TABLE IF NOT EXISTS users ( userid INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,password CHAR(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL ) ENGINE=myISAM; */ # Username and Password sent?if ( (‘‘ !== ($username = Common::getPostString(‘username‘))) && (false !== ($password = Common::getPostString(‘password‘, false))) ) { auth1_onLogin($chall, $username, $password); } /** * Get the database for this challenge. * @return GDO_Database */ function auth1_db() { if (false === ($db = gdo_db_instance(‘localhost‘, WCC_AUTH_BYPASS1_USER, WCC_AUTH_BYPASS1_PASS, WCC_AUTH_BYPASS1_DB))) { die(‘Database error 0815_1!‘); } $db->setLogging(false); $db->setEMailOnError(false); return $db; } /** * Exploit this! * @param WC_Challenge $chall * @param unknown_type $username * @param unknown_type $password * @return boolean */function auth1_onLogin(WC_Challenge $chall, $username, $password) { $db = auth1_db(); $password = md5($password); $query = "SELECT * FROM users WHERE username=‘$username‘ AND password=‘$password‘"; if (false === ($result = $db->queryFirst($query))) { echo GWF_HTML::error(‘Auth1‘, $chall->lang(‘err_unknown‘), false); # Unknown user return false; } # Welcome back! echo GWF_HTML::message(‘Auth1‘, $chall->lang(‘msg_welcome_back‘, htmlspecialchars($result[‘username‘])), false); # Challenge solved? if (strtolower($result[‘username‘]) === ‘admin‘) { $chall->onChallengeSolved(GWF_Session::getUserID()); } return true; } ?> <form action="index.php" method="post"><table> <tr> <td><?php echo $chall->lang(‘username‘); ?>:</td> <td><input type="text" name="username" value="" /></td> </tr><tr> <td><?php echo $chall->lang(‘password‘); ?>:</td> <td><input type="password" name="password" value="" /></td> </tr> <tr> <td></td> <td><input type="submit" name="login" value="<?php echo $chall->lang(‘btn_login‘); ?>" /></td> </tr> </table> </form> |
看到登录框和MYSQL第一个反应就是注入绕过,然后我就union select 了。。。然而不用这样,代码里面知道username=admin ,这时候就要想办法绕过去,因为密码也不知道,就构造一个最简单的or试试,username: admin ‘ or ‘1‘=‘1,第一个单引号闭合admin ,第二和第三个圈1,第三个闭合最后的单引号,1=1必定成立,就直接过去了,密码随便输。
MYSQL II
<?php /* TABLE STRUCTURE CREATE TABLE IF NOT EXISTS users ( userid INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, username VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,password CHAR(32) CHARACTER SET ascii COLLATE ascii_bin NOT NULL ) ENGINE=myISAM; */ # Username and Password sent?if ( (‘‘ !== ($username = Common::getPostString(‘username‘))) && (false !== ($password = Common::getPostString(‘password‘, false))) ) { auth2_onLogin($chall, $username, $password); } /** * Get the database for this challenge. * @return GDO_Database */ function auth2_db() { if (false === ($db = gdo_db_instance(‘localhost‘, WCC_AUTH_BYPASS2_USER, WCC_AUTH_BYPASS2_PASS, WCC_AUTH_BYPASS2_DB))) { die(‘Database error 0815_2!‘); } $db->setLogging(false); $db->setEMailOnError(false); return $db; } /** * Exploit this! It is the same as MySQL-I, but with an additional check, marked with ### * @param WC_Challenge $chall * @param unknown_type $username * @param unknown_type $password * @return boolean */function auth2_onLogin(WC_Challenge $chall, $username, $password) { $db = auth2_db(); $password = md5($password); $query = "SELECT * FROM users WHERE username=‘$username‘"; if (false === ($result = $db->queryFirst($query))) { echo GWF_HTML::error(‘Auth2‘, $chall->lang(‘err_unknown‘), false); return false; } ############################# ### This is the new check ### if ($result[‘password‘] !== $password) { echo GWF_HTML::error(‘Auth2‘, $chall->lang(‘err_password‘), false); return false; } # End of the new code ### ############################# echo GWF_HTML::message(‘Auth2‘, $chall->lang(‘msg_welcome_back‘, array(htmlspecialchars($result[‘username‘]))), false); if (strtolower($result[‘username‘]) === ‘admin‘) { $chall->onChallengeSolved(GWF_Session::getUserID()); } return true;} ?> <form action="index.php" method="post"> <table> <tr> <td><?php echo $chall->lang(‘username‘); ?>:</td> <td><input type="text" name="username" value="" /></td> </tr> <tr> <td><?php echo $chall->lang(‘password‘); ?>:</td> <td><input type="password" name="password" value="" /></td> </tr> <tr> <td></td> <td><input type="submit" name="login" value="<?php echo $chall->lang(‘btn_login‘); ?>" /></td></tr> </table> </form> 终于是union select 语句了。。。username :‘ union select 1,‘admin‘ as username ,md5(‘1‘) as password from users where username =‘admin‘#password:1
时间: 2024-08-06 23:04:49