这是我的计算机安全类(class)作业的一部分,所以我不是在寻找具体的答案,只是一些帮助。
我们得到了一个控制 sql 数据库(银行帐户)的错误程序(在 php 中),我们必须找到一种方法来创建 SQL 注入(inject)攻击,让我们在不知道帐户 ID 的情况下登录帐户时间。
我很确定我知道漏洞在哪里,但我似乎无法让我的攻击发挥作用。
有问题的代码(有点长,但唯一重要的部分是第一部分):
<html><head><title>FrobozzCo Community Credit Union</title></head>
<body>
<h1>FrobozzCo Community Credit Union</h1>
<h4><i>We're working for GUE</i></h4>
<hr>
<?php
$debugmode = 1;
function debug($msg) {
global $debugmode;
if ($debugmode) {
echo "<h4>$msg</h4>\n";
}
}
$thispage = 'FCCU.php';
echo "<form action='$thispage' method='post' name='theform'>\n";
$dbuser = 'fccu';
$dbpass = 'fccubucks';
$dbhost = 'localhost';
$dbname = $dbuser;
$PARAM = array_merge($_GET, $_POST);
// get username and password from form
if (!$PARAM['id'] || !$PARAM['password']) {
login();
} else { // otherwise, attempt to authenticate
$id = $PARAM['id'];
$password = $PARAM['password'];
$link_id = mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db($dbname);
$query = "SELECT * FROM accounts WHERE id = $id AND password = '$password'";
debug($query);
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result); // there should be only one row
if (!$row) { // auth failure
echo "<p><b>Your ID number and password you entered do not match.</b></p>";
echo "<p>Please try again.</p>";
login();
} else { // this user is authenticated!
// store authentication information in this form
echo "<input type=\"hidden\" name=\"id\" value=\"$id\" />\n";
echo "<input type=\"hidden\" name=\"password\" value=\"$password\" />\n";
banner($row);
// perform any requested actions (wire, transfer, withdraw)
if ($PARAM['action'] == 'Transfer Money') {
transfer_funds($id,
$password,
$PARAM['transfer_to'],
$PARAM['transfer_amount']);
} elseif ($PARAM['action'] == 'Wire Money') {
wire_funds($id,
$password,
$PARAM['routing'],
$PARAM['wire_acct'],
$PARAM['wire_amount']);
} elseif ($PARAM['action'] == 'Withdraw Money') {
withdraw_cash($id,
$password,
$PARAM['withdraw_amount']);
}
// normal output
// account info
$query = "SELECT * FROM accounts WHERE id = $id AND password = '$password'";
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result); // there should be only one row
account_info($row);
// get current account list by name
$query = "SELECT first, last FROM accounts ORDER BY last";
$names = mysql_query($query) or die(mysql_error());
account_actions($row, $names);
}
}
echo "<hr>\n";
echo "Generated by FCCU.php at " . date("l M dS, Y, H:i:s",5678)."<br>";
function name_to_id($name) {
global $dbhost, $dbuser, $dbpass, $dbname;
$splitname = explode(", ", $name);
$link_id = mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db($dbname);
$query = "SELECT id FROM accounts WHERE first = '$splitname[1]' AND last = '$splitname[0]'";
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result);
$id = $row[0];
return $id;
}
function action_error($msg, $error) {
echo "<table bgcolor='#ff0000' color='#ffffff' align=center border=1>
<tr><td><center><b>ERROR!</b></center></td></tr>
<tr><td>
<p align='center'>$msg</p>
<p align='center'>Please go back and try again or contact tech support.</p>
<p align='center'><i>args: $error</i></p>
<p align='center'><input type='submit' name='clear' value='Clear Message'></p>
</td></tr>
</table>";
}
function withdraw_cash($id, $password, $amount) {
global $dbhost, $dbuser, $dbpass, $dbname;
$amount = floor($amount);
$link_id = mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db($dbname);
$query = "SELECT bal FROM accounts WHERE password = '$password' AND id = $id";
debug("126: ($password) " . $query);
$result = mysql_query($query);
$row = mysql_fetch_array($result);
$giver_has = $row[0];
if ($amount > 0 && $giver_has >= $amount) {
$giver_has = $giver_has - $amount; // there's a problem here but it's not SQL Injection...
pretend("withdraw cash", $amount);
$query = "UPDATE accounts SET bal = $giver_has WHERE password = '$password' AND id = $id LIMIT 1";
mysql_query($query) or die(mysql_error());
echo "<h2 align='center'>Cash withdrawal of $$amount complete.</h2>
<h3 align='center'>Your cash should be ready in accounting within 45 minutes.</h3>\n";
} else {
action_error("Problem with cash withdrawal!",
"'$id', '$giver_has', '$amount'");
}
}
function wire_funds($id, $password, $bank, $account, $amount) {
global $dbhost, $dbuser, $dbpass, $dbname;
$amount = floor($amount);
$link_id = mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db($dbname);
$query = "SELECT bal FROM accounts WHERE password = '$password' AND id = $id";
debug($query);
$result = mysql_query($query);
$row = mysql_fetch_array($result);
$giver_has = $row[0];
if ($amount > 0 && $giver_has >= $amount && $bank && $account) {
$giver_has = $giver_has - $amount; // there's a problem here but it's not SQL Injection...
pretend("wire money", $amount, $bank, $acct);
$query = "UPDATE accounts SET bal = $giver_has WHERE password = '$password' AND id = $id LIMIT 1";
debug($query);
mysql_query($query) or die(mysql_error());
echo "<h2 align='center'>Wire of $$amount to bank ($bank) account ($account) complete.</h2>\n";
} else {
action_error("Problem with wire fund transfer!",
"'$id', '$amount', '$giver_has', '$bank', '$account'");
}
}
function pretend() {
return 1;
}
function transfer_funds($giver_id, $password, $recipient, $amount) {
global $dbhost, $dbuser, $dbpass, $dbname;
$amount = floor($amount);
$recipient_id = name_to_id($recipient);
$link_id = mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db($dbname);
$query = "SELECT bal FROM accounts WHERE id = $giver_id OR id = $recipient_id";
debug($query);
$result = mysql_query($query);
$row = mysql_fetch_array($result);
$recipient_has = $row[0];
$row = mysql_fetch_array($result);
$giver_has = $row[0];
debug("$giver_has, $recipient_has");
if ($amount > 0 && $giver_has >= $amount && $recipient_has) {
$giver_has = $giver_has - $amount; // there's a problem here but it's not SQL Injection...
$recipient_has = $recipient_has + $amount; // does anyone know what it is?
$query = "UPDATE accounts SET bal = $recipient_has WHERE id = $recipient_id LIMIT 1";
debug($query);
mysql_query($query) or die(mysql_error());
$query = "UPDATE accounts SET bal = $giver_has WHERE password = '$password' AND id = $giver_id LIMIT 1";
debug($query);
mysql_query($query) or die(mysql_error());
echo "<h2 align='center'>Transfer of $$amount to $recipient complete.</h2>\n";
} else {
action_error("Problem with employee fund transfer!",
"'$giver_id', '$recipient', '$amount', '$giver_has'");
}
}
function account_info($row) {
echo "<table border='1' align='center'>
<tr><td colspan='2'><p><center><b>Account Information</b></center></p></td></tr>
<tr><td><b>Account:</b></td><td>$row[0]</td></tr>
<tr><td><b>Balance:</b></td><td>$$row[1]</td></tr>
<tr><td><b>Birthdate:</b></td><td>$row[6]</td></tr>
<tr><td><b>SSN:</b></td><td>$row[5]</td></tr>
<tr><td><b>Phone:</b></td><td>$row[4]</td></tr>
<tr><td><b>Email:</b></td><td>$row[7]@frobozzco.com</td></tr>
</table>\n";
}
function account_actions($row, $names) {
global $thispage;
echo "<table border=1 width='600' align='center'>
<tr><td><center><b>Account Actions</b></center></td></tr>
<tr><td><center><b>Wire Funds</b></center></td></tr>
<tr><td>
<p>To wire funds: enter the amount (in whole dollars), the
receiving bank's <b>routing number</b> and <b>receiving account number</b>,
and press 'Wire Funds!'</p>
Wire amount: $<input name=wire_amount /><br />
Routing Number: <input name=routing /> (e.g. 091000022)<br />
Account Number: <input name=wire_acct /> (e.g. 923884509)<br />
<p align='center'><input type='submit' name='action' value='Wire Money'></p>
<p />
</td></tr>
<tr><td><center><b>Transfer Money</b></center></td><tr>
<tr><td><p>To transfer money to another FCCU account holder, select the
employee from the drop-down menu below, enter an ammount (in whole dollars)
to transfer, and press 'Transfer Money!'</p>
Transfer Amount: $<input name=transfer_amount /><br />
Transfer To: ";
// create dropdown menu with accounts
echo "<select name='transfer_to' selected='select employee'>\n";
echo "<option value='nobody'>select employee</option>\n";
while ($name = mysql_fetch_array($names)) {
echo "<option value=\"$name[1], $name[0]\">$name[1], $name[0]</option>\n";
}
echo "</select>\n";
echo "<br />
<p align='center'><input type='submit' name='action' value='Transfer Money'></p>
<p />
</td></tr>
<tr><td><center><b>Withdraw Cash</b></center></td><tr>
<tr><td><p>To withdraw cash, enter an amount (in whole dollars) and press
the 'Withdraw Cash!' button. The cash will be available in the accounting
office within 45 minutes.</p>
Withdraw Amount: $<input name=withdraw_amount /><br />
<p align='center'><input type='submit' name='action' value='Withdraw Money'></p>
<p />
</td></tr>
</table>
\n";
}
function banner($row) {
global $thispage;
$fullname = "$row[2] $row[3]";
echo "<table width='100%'><tr><td>
<p align='left'>Welcome, $fullname. (<a href='$thispage'>Log Out</a>)</p>
</td><td>
<p align='right'><i>(If you aren't $fullname, <a href='$thispage'>click here</a>.)</i></p>
</td></tr></table>\n";
echo "<hr>\n";
}
function login() {
global $thispage;
echo "<p>Enter your <b>account ID</b> and password and click \"submit.\"</p>\n";
echo "<table>\n";
echo "<tr><td>Account ID Number: </td><td><input name='id' cols='10' /></td></tr>\n";
echo "<tr><td>Password (alphanumeric only): </td><td><input name='password' cols='30' /></td></tr>\n";
echo "<tr><td><input type='submit' value='Submit' name='submit'></td><td></td></tr>\n";
echo "</table>\n";
}
?>
</form>
<p>Done.</p>
</body>
</html>
行:
$query = "SELECT * FROM accounts WHERE id = $id AND password = '$password'";
我在 ID 输入中尝试了几个字符串(我在浏览器中工作),例如
100 OR id=id;
0 OR 1=1;
尝试注释掉命令的密码部分。我对 SQL 很陌生,所以我认为我只是格式错误。
那个或者我完全忽略了一个更明显的漏洞。
最佳答案
您需要确保注释掉查询的其余部分,这样引号就不会让您感到困惑,因此任何额外的子句都会被忽略。
尝试将 ID 设置为:
0 OR id=id --
--(即连字符、连字符、空格:空格很重要)是 MySQL 中的注释。
关于php - 使用 php 进行 SQL 注入(inject)攻击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23685314/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h