| DetailsAffected Software:WPhone Plug-in Fixed in Version:1.5.2 Issue Type:Cross Site Scripting (XSS) Original Code:Found Here DetailsThis bug is a straightforward XSS bug. Once again,we see the familiar $_SERVER['PHP_SELF'] variable being echoed back to the user without any encoding. The fix is simple,remove the value for the ACTION form attribute completely. This removes the need for any type of sanitization and ensures the form is POSTed to the URL that is hosting the form. On a side note,many developers reduce the testing/defenses implemented in web pages designed for mobile clients. For some reason,it’s tempting to assume web pages designed for mobile applications have less exposure. Less exposure is obviously not the case;web pages designed for mobile clients have just as much exposure as web pages designed for normal web browsers. Please ensure your security diligence and security test cases cover your mobile attack surface. Just because the devices are smaller,that doesn’t make your attack surface is smaller too! Developers Solution<?php# Visit this file in your browser to simulate a mobile device's screensize via an <iframe>$devices = array('iphone_p' =>array('type' =>'iPhone:portrait (320x480)','width' =>320,'height' =>480),'iphone_l' =>array('type' =>'iPhone:landscape (480x320)','width' =>480,'height' =>320),'moto' =>array('type' =>'Motorola phone/browser (RAZR,v551,etc)','width' =>176,'height' =>220),'n80' =>array('type' =>'Nokia N80 (N60WebKit)','width' =>352,'height' =>416));if ( (int) $_REQUEST['w'] &&(int) $_REQUEST['h'] ){$choice = array('type' =>"Custom size ({$_REQUEST['w']}x{$_REQUEST['h']})",'width' =>$_REQUEST['w'],'height' =>$_REQUEST['h'])}elseif ( $devices[$_REQUEST['d']] )$choice = $devices[$_REQUEST['d']];else $choice = $devices['iphone_p'];?><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type"content="text/html;charset=UTF-8"><title>WPhone iFramer test tool:<?php echo $choice['type'];?></title></head><body>-<form action="<?php echo $_SERVER['PHP_SELF'];?>"method="get">+ <form action=""method="get"><label for="h">CHOOSE</label><select name="d"id="d"><option></option><?phpforeach ( $devices as $this_d_key =>$this_d ){$selected = ( $_REQUEST['d'] == $this_d_key ) ? 'selected':'';echo '<option value="' . $this_d_key . '"' . $selected . '>' . $this_d['type'] . '</option>' . "\n\t\t\t"}echo "\n";?></select><br />OR INPUT<label for="w">Width</label><input type="text"name="w"id="w"value=""size="5"/>x<label for="h">Height</label><input type="text"name="h"id="h"value=""size="5"/><br /><input type="submit"name="submit"value="view"/></form><h2><?php echo $choice['type'];?></h2><iframe src="../../../wp-login.php"width="<?php echo $choice['width'];?>"height="<?php echo $choice['height'];?>">your browser does not support iframes.</iframe></body></html>DetailsAffected Software:Comment-Rating Plugin Fixed in Version:2.9.24 Issue Type:SQL Injection (SQLi) Original Code:Found Here DetailsThis week’s vulnerability was a tricky one. The bug patched in this change list affected the Comment-Rating plugin for WordPress (fixed in 2.9.24). Let’s take the bug step by step. First,the application takes a user/attacker supplied value and runs it through an escaping function here (line 9): $k_id = strip_tags($wpdb->escape($_GET['id'])); So,$k_id is now tainted and contains an escaped value provided by the attacker. A few lines later,we see the following code: if($k_id &&$k_action &&$k_path){ //Check to see if the comment id exists and grab the rating $query = “SELECT * FROM `$table_name` WHERE ck_comment_id = $k_id”; $result = mysql_query($query); The code above checks for a specific condition (which is a condition controllable by the attacker) then proceeds to build and execute a SQL query. On line 22 we see $k_id is used to build a dynamic SQL statement. Variables usage within stings are valid in PHP (http://php.net/manual/en/language.types.string.php –see Variable parsing). $k_id is escaped so we should be ok here…right? Actually,in this case escaping isn’t sufficient to prevent SQL injection. Escaping functions typically work by preventing a variable value from breaking out of quotes,unfortunately in this case there are no quotes to break out of. $k_id is designed to be a numeric value not a string,so there is no need to encapsulate the $k_id value in quotes. Although $k_id is designed to be numeric,there was nothing that would prevent an attacker from providing an arbitrary value for $k_id. For example,an attacker could provide a value like this for $k_id: 99999 union select uname,passwd from users As you can see,there are no special characters (double quotes,single quotes,or database escape characters) in the string above that would have been escaped by a database escaping function. When used to build the $query variable,we end up with: $query = “SELECT * FROM `$table_name` WHERE ck_comment_id = 99999 union select uname,passwd from users“; The developers addressed this vulnerability by validating that $k_id is indeed numeric before using the value to build a dynamic SQL statement. Developers Solution<?phprequire_once('../../../wp-config.php');require_once('../../../wp-includes/functions.php');// CSRF attack protection. Check the Referal field to be the same// domain of the script$k_id = strip_tags($wpdb->escape($_GET['id']));$k_action = strip_tags($wpdb->escape($_GET['action']));$k_path = strip_tags($wpdb->escape($_GET['path']));$k_imgIndex = strip_tags($wpdb->escape($_GET['imgIndex']));+// prevent SQL injection+if (!is_numeric($k_id)) die('error|Query error');$table_name = $wpdb->prefix . 'comment_rating';$comment_table_name = $wpdb->prefix . 'comments';if($k_id &&$k_action &&$k_path){ //Check to see if the comment id exists and grab the rating $query = "SELECT * FROM `$table_name` WHERE ck_comment_id = $k_id"; $result = mysql_query($query);if(!$result){die('error|mysql:'.mysql_error());} if(mysql_num_rows($result)){$duplicated = 0;// used as a counter to off set duplicated votes if($row = @mysql_fetch_assoc($result)){if(strstr($row['ck_ips'],getenv("REMOTE_ADDR"))){ // die('error|You have already voted on this item!'); // Just don't count duplicated votes $duplicated = 1; $ck_ips = $row['ck_ips']; } else{ $ck_ips = $row['ck_ips'] . ',' . getenv("REMOTE_ADDR");// IPs are separated by ',' } } $total = $row['ck_rating_up'] - $row['ck_rating_down'];if($k_action == 'add'){ $rating = $row['ck_rating_up'] + 1 - $duplicated; $direction = 'up'; $total = $total + 1 - $duplicated;} elseif($k_action == 'subtract'){ $rating = $row['ck_rating_down'] + 1 - $duplicated; $direction = 'down'; $total = $total - 1 + $duplicated;} else{ die('error|Try again later');//No action given. } if (!$duplicated){ $query = "UPDATE `$table_name` SET ck_rating_$direction = '$rating',ck_ips = '". $ck_ips . "' WHERE ck_comment_id = $k_id"; $result = mysql_query($query); if(!$result) { // die('error|query '.$query); die('error|Query error'); } // Now duplicated votes will not if(!mysql_affected_rows()) { die('error|affected '. $rating); } $karma_modified = 0; if (get_option('ckrating_karma_type') == 'likes' &&$k_action == 'add'){ $karma_modified = 1;$karma = $rating; } if (get_option('ckrating_karma_type') == 'dislikes' &&$k_action == 'subtract'){ $karma_modified = 1;$karma = $rating; } if (get_option('ckrating_karma_type') == 'both'){ $karma_modified = 1;$karma = $total; } if ($karma_modified){ $query = "UPDATE `$comment_table_name` SET comment_karma = '$karma' WHERE comment_ID = $k_id"; $result = mysql_query($query); if(!$result) die('error|Comment Query error'); } } } else{ die('error|Comment doesnt exist');//Comment id not found in db,something wrong ? }} else{ die('error|Fatal:html format error')}// Add the + sign,if ($total >0){$total = "+$total";}//This sends the data back to the js to process and show on the page// The dummy field will separate out any potential garbage that// WP-superCache may attached to the end of the return.echo("done|$k_id|$rating|$k_path|$direction|$total|$k_imgIndex|dummy");?>DetailsAffected Software:PhotoSmash Fixed in Version:1.0.5 Issue Type:Cross Site Scripting (XSS) Original Code:Found Here DescriptionOnce again,we see the familiar pattern of the developer taking user/attacker controlled values and using those values to build HTML markup. Line 76 is the start of a large echo statement which writes a couple input fields to markup. The developer uses the $_REQUEST[‘bwbps_galname’] variable to populate the value attribute for one of the input form fields. Although not completely clear from the code snippet,the developers addressed this issue by placing an encoded version of $_REQUEST[‘bwbps_galname’] into a variable named $gallery_name and using the newly encoded value to build the HTML markup. Although not addressed by this patch,there are a couple of areas that deserve deeper inspection. For example,on line 113 the application is calling a javascript eval on an unknown function. If this function contains user/attacker supplied content,this could result in XSS. Additionally,on line 136 it seems the user/attacker has some influence on variables passed to a SWF object. If the SWF doesn’t have the appropriate logic to handle the tainted data,this could result in a security vulnerability. Developers Solution<?php...snip...//Get a link for the Start Slideshow for PicLensfunction getPicLensLink($g,$atts){if($atts['link_text']){$link_text = $atts['link_text']} else{$link_text = 'Start Slideshow <img src="http://lite.piclens.com/images/PicLensButton.png"alt="PicLens"width="16"height="12"border="0"align="absmiddle">'}$picatts['id'] = $g['gallery_id'];$picatts['thumb_width'] = $g['thumb_width'];$picatts['thumb_height'] = $g['thumb_height'];$picatts['gallery_type'] = $g['gallery_type'];$picatts['images'] = $g['images'];$picatts['page'] = $g['page'];if($g['tags'] == 'post_tags'){$picatts['tags'] = $this->getPostTags(0)} else{$picatts['tags'] = $g['tags']}$param_array = $this->filterMRSSAttsFromArray($picatts,"");if( is_array($param_array)){$params = implode("&",$param_array);//$params = urlencode($params)}$ret = '<a class="piclenselink"href="javascript:PicLensLite.start({feedUrl:\''. plugins_url() . '/photosmash-galleries/bwbps-media-rss.php?'. $params . '\'});">' . $link_text . ' </a>';return $ret}function getPostTags($post_id){if(!$post_id ){global $wp_query;$post_id = $wp_query->post->ID}$terms = wp_get_object_terms( $post_id,'post_tag',$args ) ;if(is_array($terms)){foreach( $terms as $term ){$_terms[] = $term->name}unset($terms);if( is_array($_terms)){$ret = implode(",",$_terms)} else{$ret = ""}}return $ret}function mediaUAddGalleryFieldToMediaUploader(){if(isset($_REQUEST['bwbps_galid']) &&(int)$_REQUEST['bwbps_galid']){echo "<input type='hidden' id='bwbps_mediau_galid' name='bwbps_mediau_galid' value='". (int)$_REQUEST['bwbps_galid'] . "' /><input type='hidden' id='bwbps_galid' name='bwbps_galid' value='". (int)$_REQUEST['bwbps_galid'] . "' />-<input type='hidden' name='bwbps_galname' value='". $_REQUEST['bwbps_galname'] . "' />-<div style='background-color:#eaffdf;padding:5px;border:1px solid #a0a0a0;margin:3px;font-size:14px;color:#333;'>Adding to PhotoSmash:". $_REQUEST['bwbps_galname'] . "</div>+<input type='hidden' name='bwbps_galname' value='". $gallery_name . "' />+<div style='background-color:#eaffdf;padding:5px;border:1px solid #a0a0a0;margin:3px;font-size:14px;color:#333;'>Adding to PhotoSmash:". $gallery_name . "</div>"} else{$gid = isset($_REQUEST['bwbps_mediau_galid']) ? (int)$_REQUEST['bwbps_mediau_galid']:0;$galleryDDL = $this->getGalleryDDL($gid,"select gallery","","bwbps_mediau_galid",30,true,true);echo "<div style='padding:5px;margin:3px;font-size:14px;color:#333;'>Add to PhotoSmash:$galleryDDL</div>"}}function mediaUAddGalleryFieldToFlashUploader(){?><script type="text/javascript">if (typeof flashStartUploadFunctions == 'undefined'){var flashStartUploadFunctions = [];function addFlashStartUploadFunction( funct_name ){flashStartUploadFunctions.push( funct_name )}function runFlashStartUploadFunctions(){if( flashStartUploadFunctions.length >0 ){var bwbfunc;for( bwbfunc in flashStartUploadFunctions){eval(flashStartUploadFunctions[ bwbfunc ])}}}}addFlashStartUploadFunction( 'bwbpsAddGalleryToFlashUploader();' );jQuery(window).load( function(){swfu.settings.upload_start_handler = function(){runFlashStartUploadFunctions()}});function bwbpsAddGalleryToFlashUploader(){jQuery('#bwbps_uploaded_images',top.document).show().append('<h4>Flash upload...preview not available.</h4>');var gid = jQuery("#bwbps_mediau_galid_flash").val() + "";if( gid ){swfu.addPostParam('bwbps_mediau_galid',gid);<?phpif(isset($_REQUEST['bwbps_galid']) ){?>swfu.addPostParam('bwbps_galid',gid);<?php}?>}}</script><?phpif(isset($_REQUEST['bwbps_galid']) &&(int)$_REQUEST['bwbps_galid']){$this->count++;echo "<script type='text/javascript'>jQuery(window).load( function(){//Hide the other Media TabsjQuery('#tab-type_url').hide();jQuery('#tab-library').hide();";...snip...?>DetailsAffected Software:FreePBX Fixed in Version:2.9 Issue Type:Cross Site Scripting (XSS) Original Code:Found Here DescriptionTo be honest,I was a little confused by this week’s patch. There are several XSS bugs in this code. Originally,the vulnerable code would take a tainted $_REQUEST value (a value from a GET,POST,or cookie) and assign the tainted value to a couple of different PHP variables ($description and $notes in particular). The application then uses of these tainted values on lines 136 and 140,resulting in XSS. The developer addressed these XSS issues by html encoding the $_REQUEST values before assigning them to PHP variables. In the code mentioned above,the developer decided to encode/sanitize at the point of assignment (as opposed to the point of consumption). There are differing perspectives as to whether one should encode/sanitize upon assignment or consumption,but the truth is both methods work. What’s confusing is the code sample contains many symptoms that are exactly like the vulnerable code patched by this security patch. $type,$action,$old_custom_dest,and $custom_dest are all set in exactly the same way the patched assignments were. For some reason,the developer chose to ignore these assignments even though they are only a few lines away. Also,instead of encoding at the point of assignment (like they did for $description and $notes),the developer chose to change styles and encode at the point of consumption for one of the tainted variables (see line 96 and 97). What’s even more confusing is only 4 lines later,we see the developer missed the same tainted variable used in an echo and failed to encode the tainted $custom_dest variable resulting in XSS. Lines 77 – 79 also contain XSS vulnerabilities that were missed in this patch. Developers Solution<?php$tabindex = 0;$display = 'customdests';$type = isset($_REQUEST['type']) ? $_REQUEST['type']:'tool';$action = isset($_REQUEST['action']) ? $_REQUEST['action']:'';if (isset($_REQUEST['delete'])) $action = 'delete';$old_custom_dest = isset($_REQUEST['old_custom_dest']) ? $_REQUEST['old_custom_dest']:'';$custom_dest = isset($_REQUEST['extdisplay']) ? $_REQUEST['extdisplay']:'';-$description = isset($_REQUEST['description']) ? $_REQUEST['description']:'';-$notes = isset($_REQUEST['notes']) ? $_REQUEST['notes']:'';+$description = isset($_REQUEST['description']) ? htmlentities($_REQUEST['description']):'';+$notes = isset($_REQUEST['notes']) ? htmlentities($_REQUEST['notes']):'';switch ($action){case 'add':if (customappsreg_customdests_add($custom_dest,$description,$notes)){needreload();redirect_standard()} else{$custom_dest=''}break;case 'edit':if (customappsreg_customdests_edit($old_custom_dest,$custom_dest,$description,$notes)){needreload();redirect_standard('extdisplay')}break;case 'delete':customappsreg_customdests_delete($custom_dest);needreload();redirect_standard();break}?></div><div class="rnav"><ul><?php echo '<li><a href="config.php?display='.$display.'&type='.$type.'">'._('Add Custom Destination').'</a></li>';foreach (customappsreg_customdests_list() as $row){$descr = $row['description'] != '' ? $row['description']:'('.$row['custom_dest'].')';echo '<li><a href="config.php?display='.$display.'&type='.$type.'&extdisplay='.$row['custom_dest'].'"class="">'.$descr.'</a></li>'}?></ul></div><div class="content"><?phpif ($custom_dest != ''){// load$usage_list = framework_display_destination_usage(customappsreg_customdests_getdest($custom_dest));$row = customappsreg_customdests_get($custom_dest);$description = $row['description'];$notes = $row['notes'];$disp_description = $row['description'] != '' ? $row['description']:'('.$row['custom_dest'].')';echo "<h2>"._("Edit:")."$disp_description"."</h2>"} else{echo "<h2>"._("Add Custom Destination")."</h2>"}$helptext = _("Custom Destinations allows you to register your custom destinations that point to custom dialplans and will also 'publish' these destinations as available destinations to other modules. This is an advanced feature and should only be used by knowledgeable users. If you are getting warnings or errors in the notification panel about CUSTOM destinations that are correct,you should include them here. The 'Unknown Destinations' chooser will allow you to choose and insert any such destinations that the registry is not aware of into the Custom Destination field.");echo $helptext;?><form name="editCustomDest"action="<?php $_SERVER['PHP_SELF'] ?>"method="post"onsubmit="return checkCustomDest(editCustomDest);"><input type="hidden"name="extdisplay"value="<?php echo $custom_dest;?>"><input type="hidden"name="old_custom_dest"value="<?php echo $custom_dest;?>"><input type="hidden"name="action"value="<?php echo ($custom_dest != '' ? 'edit':'add');?>"><table><tr><td colspan="2"><h5><?php echo ($custom_dest ? _("Edit Custom Destination"):_("Add Custom Destination")) ?><hr></h5></td></tr><tr><td><a href="#"class="info"><?php echo _("Custom Destination")?>:<span><?phpecho _("This is the Custom Destination to be published. It should be formatted exactly as you would put it in a goto statement,with context,exten,priority all included. An example might look like:<br />mycustom-app,s,1");if (!empty($usage_list)){echo "<br />"._("READONLY WARNING:Because this destination is being used by other module objects it can not be edited. You must remove those dependencies in order to edit this destination,or create a new destination to use")}?></span></a></td><?phpif (!empty($usage_list)){?>-<td><b><?php echo $custom_dest;?></b></td>+ <td><b><?php echo htmlentities($custom_dest);?></b></td><?php} else{?><td><input size="30"type="text"name="extdisplay"id="extdisplay"value="<?php echo $custom_dest;?>"tabindex="<?php echo ++$tabindex;?>"></td><?php}?></tr><?phpif (empty($usage_list)){?><tr><td><a href=# class="info"><?php echo _("Destination Quick Pick")?><span><?php echo _("Choose un-identified destinations on your system to add to the Custom Destination Registry. This will insert the chosen entry into the Custom Destination box above.")?></span></a></td><td><select onChange="insertDest();"id="insdest"tabindex="<?php echo ++$tabindex;?>"><option value=""><?php echo _("(pick destination)")?></option><?php$results = customappsreg_customdests_getunknown();foreach ($results as $thisdest){echo "<option value='$thisdest'>$thisdest</option>\n"}?></select></td></tr><?php}?><tr><td><a href="#"class="info"><?php echo _("Description")?>:<span><?php echo _("Brief Description that will be published to modules when showing destinations. Example:My Weather App")?></span></a></td><td><input size="30"type="text"name="description"value="<?php echo $description;?>"tabindex="<?php echo ++$tabindex;?>"></td></tr><tr><td valign="top"><a href="#"class="info"><?php echo _("Notes")?>:<span><?php echo _("More detailed notes about this destination to help document it. This field is not used elsewhere.")?></span></a></td><td><textarea name="notes"cols="23"rows="6"tabindex="<?php echo ++$tabindex;?>"><?php echo $notes;?></textarea></td></tr><tr><td colspan="2"><br><input name="Submit"type="submit"value="<?php echo _("Submit Changes")?>"tabindex="<?php echo ++$tabindex;?>"><?php if ($custom_dest != ''){echo ' <input name="delete"type="submit"value="'._("Delete").'">';} ?></td><?phpif ($custom_dest != ''){if (!empty($usage_list)){?><tr><td colspan="2"><a href="#"class="info"><?php echo $usage_list['text']?>:<span><?php echo $usage_list['tooltip']?></span></a></td></tr><?php}}?></tr></table></form>...snip...</script>DetailsAffected Software:BezahlCode-Generator Fixed in Version:1.1 Issue Type:Cross Site Scripting (XSS) Original Code:Found Here DescriptionA couple straightforward XSS bugs. $_REQUEST will create an associative array which contains the contents of $_GET,$_POST,and $_COOKIE which are all user/attacker controllable. These variables are then used to create HTML markup. Security bugs are caused by many different reasons. When auditing code for security issues,if you come across issues like the ones shown below its highly likely that the developer simply doesn’t understand the security risk they created. It might be a good idea to review other change lists associated with this developer as they will likely contain similar code symptoms. This type of issue is also indicative of lack of security awareness. The developer here could use some security education about various security issues along with some tips on preventing these types of security issues in the future. Developers Solution<?php if ($data!='') {?><img src="/generator/?generate=<?php echo urlencode($data)?>"/><?php }?></div><br/><form action="/generator/"name="wizard"method="post"class="BezahlCodeForm"><label for="singlepayment"><input type="radio"id="singlepayment"name="gen_type"value="singlepayment"<?php if($_REQUEST['gen_type']=="singlepayment"|| empty($_REQUEST['gen_type'])) echo 'checked="checked"'?>/>Überweisung</label><br /><label for="singlepaymentspende"><input type="radio"id="singlepaymentspende"name="gen_type"value="singlepaymentspende"<?php if($_REQUEST['gen_type']=="singlepaymentspende") echo 'checked="checked"'?>/>Spendenzahlung</label><br /><label for="singledirectdebit"><input type="radio"id="singledirectdebit"name="gen_type"value="singledirectdebit"<?php if($_REQUEST['gen_type']=="singledirectdebit") echo 'checked="checked"'?>/>Lastschrift</label><br />-Name:<br /><input type="text"tooltipText="Format:DTAUS Text"id="gen_name"onblur="checkInput(this,'dtaus')"name="gen_name"maxlength="27"value="<?= isset($_REQUEST['gen_name'])?$_REQUEST['gen_name']:""?>">+Name:<br /><input type="text"tooltipText="Format:DTAUS Text"id="gen_name"onblur="checkInput(this,'dtaus')"name="gen_name"maxlength="27"value="<?= isset($_REQUEST['gen_name'])?htmlspecialchars($_REQUEST['gen_name']):""?>"><br />-Kontonummer:<br /><input type="text"tooltipText="Format:Ganzzahl z.B. 1234"id="gen_account"onblur="checkInput(this,'ganzzahl')"name="gen_account"value="<?= isset($_REQUEST['gen_account'])?$_REQUEST['gen_account']:""?>">+Kontonummer:<br /><input type="text"tooltipText="Format:Ganzzahl z.B. 1234"id="gen_account"onblur="checkInput(this,'ganzzahl')"name="gen_account"value="<?= isset($_REQUEST['gen_account'])?htmlspecialchars($_REQUEST['gen_account']):""?>"><br />-BLZ:<br /><input type="text"tooltipText="Format:Ganzzahl z.B. 1234"id="gen_BNC"onblur="checkInput(this,'ganzzahl')"name="gen_BNC"value="<?= isset($_REQUEST['gen_BNC'])?$_REQUEST['gen_BNC']:""?>">+BLZ:<br /><input type="text"tooltipText="Format:Ganzzahl z.B. 1234"id="gen_BNC"onblur="checkInput(this,'ganzzahl')"name="gen_BNC"value="<?= isset($_REQUEST['gen_BNC'])?htmlspecialchars($_REQUEST['gen_BNC']):""?>"><br />-Betrag in Euro (z.B. 1234,50) <br /><input type="text"tooltipText="Format:Dezimalzahl z.B. 1234,50"onblur="checkInput(this,'dezimalzahl')"id="gen_amount"name="gen_amount"value="<?= isset($_REQUEST['gen_amount'])?$_REQUEST['gen_amount']:""?>">+Betrag in Euro (z.B. 1234,50) <br /><input type="text"tooltipText="Format:Dezimalzahl z.B. 1234,50"onblur="checkInput(this,'dezimalzahl')"id="gen_amount"name="gen_amount"value="<?= isset($_REQUEST['gen_amount'])?htmlspecialchars($_REQUEST['gen_amount']):""?>"><br />-Verwendungszweck:<br /><input type="text"id="gen_reason"tooltipText="Format:DTAUS Text"onblur="checkInput(this,'dtaus')"name="gen_reason"maxlength="54"value="<?= isset($_REQUEST['gen_reason'])?$_REQUEST['gen_reason']:""?>">+Verwendungszweck:<br /><input type="text"id="gen_reason"tooltipText="Format:DTAUS Text"onblur="checkInput(this,'dtaus')"name="gen_reason"maxlength="54"value="<?= isset($_REQUEST['gen_reason'])?htmlspecialchars($_REQUEST['gen_reason']):""?>"><br/><input type="button"value="Erstellen"onclick='javascript:generateImage();'></form><?php if(!(get_option("bezahlcode_showlink") == "hidden")){?><br /><span class="bezahlCodeLink">Weitere Informationen:<a href="http://www.bezahlcode.de"title="BezahlCode - Schnell,einfach und sicher bezahlen"target="_blank">www.bezahlcode.de</a></span><?php } ?></div><script type="text/javascript">var tooltipObj = new DHTMLgoodies_formTooltip();tooltipObj.initFormFieldTooltip();</script>DetailsAffected Software:FreeNAS Fixed in Version:0.69.3 Issue Type:Cross Site Scripting (XSS) Original Code:Found Here DescriptionThe code sample for this week contained a couple XSS vulnerabilities. Although not essential for exploitation,its also interesting to note that this response is within an SVG image. You can see this by examining the header() api specifying the content-type:header(“Content-type:image/svg+xml”); The first issue is pretty easy to follow,so we’ll begin there. On line 11,$ifname is assigned a tainted value from $_GET["ifname"]. After the variable assignment,the authors use the tainted variable to build HTML markup on line 66. The second issue requires a little bit of tracing. First,the $ifnum variable is assigned a tainted value from $_GET["ifnum"] on line 10. $ifnum is then used to build the $fetch_link variable on line 18. If $fetch_link is ever used to build HTML markup,it will result in XSS. The third issue also requires a bit of tracing as well. Once again,we start with the assignment of a tainted variable to $ifnum on line 10. $ifnum is then used to build an error message on line 37 ($error_text). $error_text is then used to build HTML markup on line 72 resulting in XSS. The developers addressed this issue by using htmlspecialchars() during the inital variable assignments. This takes care of all three of the XSS issues described above. Developers Solution<?php... snip ...require("guiconfig.inc");header("Content-type:image/svg+xml");+$ifnum=@htmlspecialchars($_GET["ifnum"]);// BSD / SNMP interface name / number+$ifname=@htmlspecialchars($_GET["ifname"]) ? htmlspecialchars($_GET["ifname"]):"Interface $ifnum";//Interface name that will be showed on top right of graph-$ifnum=@$_GET["ifnum"];// BSD / SNMP interface name / number-$ifname=@$_GET["ifname"]?$_GET["ifname"]:"Interface $ifnum";//Interface name that will be showed on top right of graph$scale_type="follow";//Autoscale default setup:"up"= only increase scale;"follow"= increase and decrease scale according to current graphed datas$nb_plot=120; //NB plot in graph$time_interval=1;//Refresh time Interval$unit="bits"; //Initial unit type:"bits"or "bytes"$fetch_link = "stats.php?if=$ifnum";//SVG attributes$attribs['bg']='fill="#EEEEEE"stroke="none"stroke-width="0"opacity="1"';$attribs['axis']='fill="black"stroke="black"';$attribs['in']='fill="#00CC00"font-family="Tahoma,Verdana,Arial,Helvetica,sans-serif"font-size="7"';$attribs['out']='fill="#FF0000"font-family="Tahoma,Verdana,Arial,Helvetica,sans-serif"font-size="7"';$attribs['graph_in']='fill="none"stroke="#00CC00"stroke-opacity="0.8"';$attribs['graph_out']='fill="none"stroke="#FF0000"stroke-opacity="0.8"';$attribs['legend']='fill="black"font-family="Tahoma,Verdana,Arial,Helvetica,sans-serif"font-size="4"';$attribs['graphname']='fill="#435370"font-family="Tahoma,Verdana,Arial,Helvetica,sans-serif"font-size="8"';$attribs['grid_txt']='fill="gray"font-family="Tahoma,Verdana,Arial,Helvetica,sans-serif"font-size="6"';$attribs['grid']='stroke="gray"stroke-opacity="0.5"';$attribs['switch_unit']='fill="#435370"font-family="Tahoma,Verdana,Arial,Helvetica,sans-serif"font-size="4"text-decoration="underline"';$attribs['switch_scale']='fill="#435370"font-family="Tahoma,Verdana,Arial,Helvetica,sans-serif"font-size="4"text-decoration="underline"';$attribs['error']='fill="red"font-family="Arial"font-size="4"';$attribs['collect_initial']='fill="gray"font-family="Tahoma,Verdana,Arial,Helvetica,sans-serif"font-size="4"';//Error text if we cannot fetch data:depends on which method is used$error_text = gettext("Cannot get data about interface") . "$ifnum";$height=100; //SVG internal height:do not modify$width=200; //SVG internal width:do not modify$encoding = system_get_language_codeset();header("Last-Modified:". gmdate( "D,j M Y H:i:s") . "GMT");header("Expires:". gmdate( "D,j M Y H:i:s",time() ) . "GMT");header("Cache-Control:no-store,no-cache,must-revalidate");// HTTP/1.1header("Cache-Control:post-check=0,pre-check=0",FALSE);header("Pragma:no-cache");// HTTP/1.0header("Content-type:image/svg+xml");echo "<?xml version=\"1.0\"encoding=\"{$encoding}\"?>\n";?><svg width="100%"height="100%"viewBox="0 0 <?=$width?><?=$height?>"preserveAspectRatio="none"xml:space="preserve"xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"onload="init(evt)"><g id="graph"> <rect id="bg"x1="0"y1="0"width="100%"height="100%"<?=$attribs['bg']?>/> <line id="axis_x"x1="0"y1="0"x2="0"y2="100%"<?=$attribs['axis']?>/> <line id="axis_y"x1="0"y1="100%"x2="100%"y2="100%"<?=$attribs['axis']?>/> <path id="graph_out"d="M0 <?=$height?>L 0 <?=$height?>"<?=$attribs['graph_out']?>/> <path id="graph_in"d="M0 <?=$height?>L 0 <?=$height?>"<?=$attribs['graph_in']?>/> <path id="grid"d="M0 <?=$height/4*1?>L <?=$width?><?=$height/4*1?>M0 <?=$height/4*2?>L <?=$width?><?=$height/4*2?>M0 <?=$height/4*3?>L <?=$width?><?=$height/4*3?>"<?=$attribs['grid']?>/> <text id="grid_txt1"x="<?=$width?>"y="<?=$height/4*1?>"<?=$attribs['grid_txt']?>text-anchor="end">75%</text> <text id="grid_txt2"x="<?=$width?>"y="<?=$height/4*2?>"<?=$attribs['grid_txt']?>text-anchor="end">50%</text> <text id="grid_txt3"x="<?=$width?>"y="<?=$height/4*3?>"<?=$attribs['grid_txt']?>text-anchor="end">25%</text> <text id="graph_in_lbl"x="5"y="8"<?=$attribs['in']?>><?=gettext("In");?><tspan id="graph_in_txt"<?=$attribs['in']?>></tspan></text> <text id="graph_out_lbl"x="5"y="16"<?=$attribs['out']?>><?=gettext("Out");?><tspan id="graph_out_txt"<?=$attribs['out']?>></tspan></text> <text id="ifname"x="<?=$width?>"y="8"<?=$attribs['graphname']?>text-anchor="end"><?=$ifname?></text> <text id="switch_unit"x="<?=$width*0.55?>"y="5"<?=$attribs['switch_unit']?>><?=sprintf(gettext("Switch to %s/s"),("bits"=== $unit) ? "bytes":"bits");?></text> <text id="switch_scale"x="<?=$width*0.55?>"y="11"<?=$attribs['switch_scale']?>><?=gettext("AutoScale");?>(<?=("up"=== $scale_type) ? gettext("Up"):gettext("Follow");?>)</text> <text id="datetime"x="<?=$width*0.55?>"y="17"<?=$attribs['legend']?>></text> <text id="graphlast"x="<?=$width*0.55?>"y="23"<?=$attribs['legend']?>><?=gettext("Graph shows last");?><?=$time_interval*$nb_plot?><?=gettext("seconds");?></text> <polygon id="axis_arrow_x"<?=$attribs['axis']?>points="<?=($width) . ",". ($height)?><?=($width-2) . ",". ($height-2)?><?=($width-2) . ",". $height?>"/> <text id="error"x="<?=$width*0.5?>"y="<?=$height*0.4?>"visibility="hidden"<?=$attribs['error']?>text-anchor="middle"><?=$error_text?></text> <text id="collect_initial"x="<?=$width*0.5?>"y="<?=$height*0.4?>"visibility="hidden"<?=$attribs['collect_initial']?>text-anchor="middle"><?=gettext("Collecting initial data,please wait...");?></text></g><script type="text/ecmascript"> <![CDATA[if (typeof getURL == 'undefined'){getURL = function(url,callback){ if (!url) throw 'No URL for getURL'; try{if (typeof callback.operationComplete == 'function') callback = callback.operationComplete; } catch (e){} if (typeof callback != 'function') throw 'No callback function for getURL'; var http_request = null; if (typeof XMLHttpRequest != 'undefined'){http_request = new XMLHttpRequest(); } else if (typeof ActiveXObject != 'undefined'){try{ http_request = new ActiveXObject('Msxml2.XMLHTTP');} catch (e){ try{ http_request = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e){} } } if (!http_request) throw 'Both getURL and XMLHttpRequest are undefined'; http_request.onreadystatechange = function(){if (http_request.readyState == 4){ callback({success:true,content:http_request.responseText,contentType:http_request.getResponseHeader("Content-Type") } );} } http_request.open('GET',url,true); http_request.send(null);}}DetailsAffected Software:Surfnet IDS Fixed in Version:1.03.07 Issue Type:SQL Injection Original Code:Found Here DescriptionThere were a couple of SQL injection bugs here. Beginning at line 35,we see that the Surfnet IDS developers have accepted three POST parameters and have assigned tainted values to three different variables:$keyname,$vlanid,$action. $keyname is eventually passed to three different dynamic SQL queries,all of which result in SQL injection. Those queries can be seen on lines 52,59,and 69. $vlanid is passed to a dynamic SQL query,resulting in SQL injection. This dynamic query can be seen on line 59. Finally,$action is passed to a dynamic SQL statement,resulting in yet another SQL injection bug. This dynamic query can be found on line 69. All of the bugs were straightforward SQL injection bugs and should have been caught early in the dev cycle. The developers addressed the issue by and/or validating all of the POST parameters before using those values in SQL statements. Developers Solution<?php...snip...include '../include/config.inc.php';include '../include/connect.inc.php';include '../include/functions.inc.php';session_start();header("Cache-control:private");if (!isset($_SESSION['s_admin'])){pg_close($pgconn);$address = getaddress($web_port);header("location:${address}login.php");exit}$s_org = intval($_SESSION['s_org']);$s_admin = intval($_SESSION['s_admin']);$s_access = $_SESSION['s_access'];$s_access_sensor = intval($s_access{0});if ($s_access_sensor == 0){$m = 90;pg_close($pgconn);header("location:sensorstatus.php?selview=$selview&m=$m");exit}if (isset($_GET['selview'])){$selview = intval($_GET['selview'])}$error = 0;-$keyname = $_POST['keyname'];-$vlanid = $_POST['vlanid'];-$action = $_POST['action'];-if (isset($_POST[tapip])){+$keyname = pg_escape_string($_POST['keyname']);+$vlanid = intval($_POST['vlanid']);+$action = pg_escape_string($_POST['action']);+$action_pattern = '/^(NONE|REBOOT|SSHOFF|SSHON|CLIENT|RESTART|BLOCK)$/';+if (preg_match($action_pattern,$action) != 1){+ $m = 44;+ $error = 1;+}++if (isset($_POST[tapip]) &&$error != 1){$tapip = pg_escape_string(stripinput($_POST[tapip]));if (preg_match($ipregexp,$tapip)){ $sql_checkip = "SELECT tapip FROM sensors WHERE tapip = '$tapip' AND NOT keyname = '$keyname'"; $result_checkip = pg_query($pgconn,$sql_checkip); $checkip = pg_num_rows($result_checkip); if ($checkip >0){$m = 101;$error = 1; } else{$sql_updatestatus = "UPDATE sensors SET tapip = '$tapip' WHERE keyname = '$keyname' AND vlanid ='$vlanid'";$result_updatestatus = pg_query($pgconn,$sql_updatestatus);$m = 7; } } else{ $m = 102; $error = 1;}}if ($error == 0){$sql_updatestatus = "UPDATE sensors SET action = '".$action. "' WHERE keyname = '$keyname'";$result_updatestatus = pg_query($pgconn,$sql_updatestatus);$m = 7}pg_close($pgconn);if ($m != 1){header("location:sensorstatus.php?selview=$selview&m=$m&key=$keyname")} else{header("location:sensorstatus.php?selview=$selview&m=$m")}?>DetailsAffected Software:WordPress Core Fixed in Version:2.2 Issue Type:SQL Injection Original Code:Found Here DescriptionThis is a fairly straight forward SQL Injection bug here. First,although we can’t see exactly where $args[] is set,we have some strong clues that it contains user/attacker controlled data. For example,the first function on the code snippet wp_newCategory() takes an $args parameter and the first thing it does is escape the values within the array. The names of variables holding various values in the array also provide clues that $args cannot be trusted. On line 66 we see that $max_results is assigned the value from $args[4]. $max_results is then used to build a portion of a SQL string which is assigned to the $limit variable. $limit is then passed to the end of a SQL statement on line 84,resulting in SQL injection. Some readers may point out that $args is escaped in on line 60,before it is used to build any SQL statement. Unfortunately,escaping values in this case doesn’t prevent SQL injection. The attacker controlled value is eventually used to build a LIMIT clause. The LIMIT clause doesn’t enclose the attacker supplied values within quotes,so there are no quotes to break out of. The developers addressed this issue by casting args[4] to int during assignment to $max_results. If args[4] contains any characters that do not qualify as an integer,the value will not be passed to the LIMIT statement. Developers Solution<?php...snip...function wp_newCategory($args){$this->escape($args);$blog_id= (int) $args[0];$username= $args[1];$password= $args[2];$category= $args[3];if(!$this->login_pass_ok($username,$password)){return($this->error)}// Set the user context and make sure they are// allowed to add a category.set_current_user(0,$username);if(!current_user_can("manage_categories",$page_id)){return(new IXR_Error(401,__("Sorry,you do not have the right to add a category.")))}// We need this to make use of the wp_insert_category()// funciton.require_once(ABSPATH . "wp-admin/admin-db.php");// If no slug was provided make it empty so that// WordPress will generate one.if(empty($category["slug"])){$category["slug"] = ""}// If no parent_id was provided make it empty// so that it will be a top level page (no parent).if ( !isset($category["parent_id"]) )$category["parent_id"] = "";// If no description was provided make it empty.if(empty($category["description"])){$category["description"] = ""}$new_category = array("cat_name"=>$category["name"],"category_nicename"=>$category["slug"],"category_parent"=>$category["parent_id"],"category_description"=>$category["description"]);$cat_id = wp_insert_category($new_category);if(!$cat_id){return(new IXR_Error(500,__("Sorry,the new category failed.")))}return($cat_id)}function wp_suggestCategories($args){global $wpdb;$this->escape($args);$blog_id= (int) $args[0];$username= $args[1];$password= $args[2];$category= $args[3];-$max_results= $args[4];+$max_results = (int) $args[4];if(!$this->login_pass_ok($username,$password)){return($this->error)}// Only set a limit if one was provided.$limit = "";if(!empty($max_results)){$limit = "LIMIT{$max_results}"}$category_suggestions = $wpdb->get_results("SELECT cat_ID category_id,cat_name category_nameFROM{$wpdb->categories}WHERE cat_name LIKE '{$category}%'{$limit}");return($category_suggestions)}function blogger_getUsersBlogs($args){$this->escape($args);$user_login = $args[1];$user_pass = $args[2];if (!$this->login_pass_ok($user_login,$user_pass)){return $this->error}set_current_user(0,$user_login);$is_admin = current_user_can('level_8');$struct = array('isAdmin' =>$is_admin,'url' =>get_option('home') . '/','blogid' =>'1','blogName' =>get_option('blogname'));return array($struct)}...snip...?>DetailsAffected Software:Short URL Plugin Fixed in Version:Changeset 55280 Issue Type:SQL Injection Original Code:Found Here DescriptionThis weeks’ vulnerabilities were a couple of SQL injection bugs in the Short URL Plugin for WordPress. The symptoms for the issues indicate classic SQL injection,let’s have a quick look at the code. First,looking over the code sample,we see a couple of dynamically built SQL statements. It would probably make sense to spend a bit of time and convert these dynamic SQL statements into prepared statements,that way you won’t have to worry about a code change inadvertently re-introducing a SQL injection flaw or an escaping filter bypass. With dynamically built SQL statements we’ll also have to trace each variable until we can determine whether the value can be controlled by an attacker. Lucky for us,the variable assignments are very close to the SQL statements. In the vulnerable sample,we see that the author is taking values directly from a POST request and using those tainted values to build SQL statements. Looking at the check-in,we see that the developer chose to use WordPress’ built-in escaping function for escaping user/attacker controlled data before passing it to a SQL statement. Although the checked-in fixes were straightforward,I was surprised to see that the developers missed an obvious SQL injection on line 56. Same classic SQL injection symptoms,the only difference is the dynamic SQL being built is a DELETE SQL statement as opposed to an INSERT or UPDATE. For those that are wondering… YES,this SQL injection is still present in the latest version of the plug-in! If you happen to be using this plug-in on your website,I would recommend you escape $delete_id before passing it to a SQL statement! I notified the plug-in author,hopefully they’ll be a patch soon. Is this the first Spot-The-Vuln.com 0day? Developers Solution<?php...snip...function kd_admin_options_su(){ global $table_prefix,$wpdb,$user_ID; $table_name = $table_prefix . "short_url"; if($wpdb->get_var("show tables like '$table_name'") != $table_name){ $sql = "CREATE TABLE ".$table_name."( link_id int(11) NOT NULL auto_increment, link_url text NOT NULL, link_desc text NOT NULL, link_count int(11) NOT NULL default '0', PRIMARY KEY (`link_id`) );"; require_once(ABSPATH . 'wp-admin/upgrade-functions.php'); dbDelta($sql); } if(isset($_POST['action'])){$action = $_POST['action'];if($action == "create"){- $add_url = $_POST['form_url'];- $add_desc = $_POST['form_desc'];+ $add_url = $wpdb->escape($_POST['form_url']);+ $add_desc = $wpdb->escape($_POST['form_desc']);if($add_url == "http://"|| (!$add_url)){$ERR = $ERR . "<br>You must enter a URL to redirect to!";} if(!$ERR){$wpdb->query("INSERT INTO $table_name (link_url,link_desc) VALUES ('$add_url','$add_desc')"); $new_url = get_option("siteurl") . "/u/". mysql_insert_id(); $MES = $MES . "<br>The redirect URL has been added. Your new Short URL is:". $new_url; } }if($action == "edit"){- $edit_id = $_POST['id'];- $edit_url = $_POST['form_url'];- $edit_desc = $_POST['form_desc'];+ $edit_id = $wpdb->escape($_POST['id']);+ $edit_url = $wpdb->escape($_POST['form_url']);+ $edit_desc = $wpdb->escape($_POST['form_desc']); if($edit_url == "http://"|| (!$edit_url)){$ERR = $ERR . "<br>You must enter a URL to redirect to!";} if(!$ERR){$wpdb->query("UPDATE $table_name SET link_url='$edit_url',link_desc='$edit_desc' WHERE link_id = $edit_id"); $MES = $MES . "<br>The redirect URL has been modified."; } }if($action == "delete"){ $delete_id = $_POST['id']; $wpdb->query("DELETE FROM $table_name WHERE link_id = '$delete_id'"); $MES = $MES . "<br>Redirect deleted!"; } if($action == "clearall"){ $wpdb->query("UPDATE $table_name SET link_count='0' WHERE link_count >0"); $MES = $MES . "<br>Counts have been reset!"; }} ?> <div class=wrap> <form method="post"><h2>Short URL Admin</h2><?php if($ERR){echo "<p>". $ERR . "</p>";}if($MES){echo "<p>". $MES . "</p>";} ?><p>Short URL allows you to create shorter URL's and keeps track of how manytimes a link has been clicked. It's useful for managing downloads,keeping trackof outbound links and for masking URL's. Clicking the Clear All Clicks buttonwill reset the count for each entry. Visit the <a href="http://www.harleyquine.com/php-scripts/short-url-plugin/">plugin page</a>for more information about this plugin.</p><h2>Current Redirects</h2><table class="widefat"> <thead> <tr> <th scope="col">Short URL (The URL to use)</th> <th scope="col">Real URL (Where it redirects to)</th> <th scope="col">Notes</th> <th scope="col">Amount of Clicks</th> <th scope="col">Manage</th> </tr></thead> <tbody id="the-list"><?php $rowdata = $wpdb->get_results("SELECT * FROM $table_name"); foreach ($rowdata as $row){ $is_editing = $_POST['edit_id']; if($is_editing){if($is_editing == $row->link_id){$EDIT = 1;$EDIT_ID = $row->link_id;$EDIT_URL = $row->link_url;$EDIT_DESC = $row->link_desc;} }?> <tr class='<?php echo $class;?>'> <th scope="row"><a href="<? echo get_option("siteurl") . "/u/". $row->link_id;?>"target="_blank"><? echo get_option("siteurl") . "/u/". $row->link_id;?></a></th> <td><? echo $row->link_url;?></td> <td><? echo $row->link_desc;?></td> <td><? echo $row->link_count;?></td> <td><form method="post"name="delete"><input type="hidden"name="action"value="delete"><input type="hidden"name="id"value="<? echo $row->link_id;?>"><input type="submit"value="Delete"></form><form method="post"name="edit"><input type="hidden"name="edit_id"value="<? echo $row->link_id;?>"><input type="submit"value="Edit"></form></td>...snip...DetailsAffected Software:PunBB Fixed in Version:1.3.2 Issue Type:SMTP Command Injection Original Code:Found Here DescriptionInteresting bug here. In 2008,Stefan Esser reported a bug to the PunBB team which described a SMTP command injection vulnerability. If we look at the code below,we see that PunBB opens a socket connection to a SMTP host and passes various user/attacker controlled values to the SMTP server. Because of this setup,it is possible to craft a SMTP message that tricks the SMTP server into thinking the data provided for the message is completed,and executes any data that follows as SMTP commands. The attacker accomplished this by injecting Carriage Return and Line Feed characters following by a period character on a line by itself (as defined in RFC 821 – SMTP). The PunBB developers addressed this vulnerability by sanitizing CRLFs and period characters. The Web Application Hackers Handbook (by Dafydd Stuttard) describes various forms of SMTP injection in a pretty comprehensive manner. If the PunBB developers used the test cases described by Dafydd in his book would have likely identified this vulnerability before shipping. Here’s a sample from the Web Application Hackers Handbook that talks about SMTP injection (see section 8.2) Developers Solution<?php...snip...function smtp_mail($to,$subject,$message,$headers = ''){global $pun_config;$recipients = explode(',',$to);+// Sanitize the message+$message = str_replace("\r\n.","\r\n..",$message);+$message = (substr($message,0,1) == '.' ? '.'.$message:$message);// Are we using port 25 or a custom port?if (strpos($pun_config['o_smtp_host'],':') !== false)list($smtp_host,$smtp_port) = explode(':',$pun_config['o_smtp_host']);else{$smtp_host = $pun_config['o_smtp_host'];$smtp_port = 25}if (!($socket = fsockopen($smtp_host,$smtp_port,$errno,$errstr,15)))error('Could not connect to smtp host "'.$pun_config['o_smtp_host'].'"('.$errno.') ('.$errstr.')',__FILE__,__LINE__);server_parse($socket,'220');if ($pun_config['o_smtp_user'] != '' &&$pun_config['o_smtp_pass'] != ''){fwrite($socket,'EHLO '.$smtp_host."\r\n");server_parse($socket,'250');fwrite($socket,'AUTH LOGIN'."\r\n");server_parse($socket,'334');fwrite($socket,base64_encode($pun_config['o_smtp_user'])."\r\n");server_parse($socket,'334');fwrite($socket,base64_encode($pun_config['o_smtp_pass'])."\r\n");server_parse($socket,'235')}else{fwrite($socket,'HELO '.$smtp_host."\r\n");server_parse($socket,'250')}fwrite($socket,'MAIL FROM:<'.$pun_config['o_webmaster_email'].'>'."\r\n");server_parse($socket,'250');$to_header = 'To:';@reset($recipients);while (list(,$email) = @each($recipients)){fwrite($socket,'RCPT TO:<'.$email.'>'."\r\n");server_parse($socket,'250');$to_header .= '<'.$email.'>,'}fwrite($socket,'DATA'."\r\n");server_parse($socket,'354');fwrite($socket,'Subject:'.$subject."\r\n".$to_header."\r\n".$headers."\r\n\r\n".$message."\r\n");fwrite($socket,'.'."\r\n");server_parse($socket,'250');fwrite($socket,'QUIT'."\r\n");fclose($socket);return true} | |