تزریق xml

از Secure Coding

در نرم افزار هایی که از فرمت xml برای انتقال اطلاعات استفاده می کنند، اگر به درستی نوع ارتباط و موجودیت ها بررسی و کنترل نشود امکان تزریق xml وجود خواهد داشت.

برای مثال در کد زیر اطلاعات دو user را مشاهده می کنید.

<?xml version="1.0" encoding="ISO-8859-1"?> 
<users> 
	<user> 
		<username>gandalf</username> 
		<password>!c3</password> 
		<userid>0</userid>
		<mail>[email protected]</mail>
	</user> 
	<user> 
		<username>Stefan0</username> 
		<password>w1s3c</password> 
		<userid>500</userid>
		<mail>[email protected]</mail>
	</user> 
</users>


حال اگر مهاجم اطلاعات username، password و mail را توسط uri زیر در xml بالا درج کند xml injection رخ داده است.

http://www.example.com/addUser.php?username=tony&password=Un6R34kb!e&[email protected]


محتوای xml بعد از تزریق

<?xml version="1.0" encoding="ISO-8859-1"?> 
<users> 
	<user> 
		<username>gandalf</username> 
		<password>!c3</password> 
		<userid>0</userid>
		<mail>[email protected]</mail>
	</user> 
	<user> 
		<username>Stefan0</username> 
		<password>w1s3c</password> 
		<userid>500</userid>
		<mail>[email protected]</mail>
	</user> 
	<user> 
		<username>tony</username> 
		<password>Un6R34kb!e</password> 
		<userid>500</userid>
		<mail>[email protected]</mail>
	</user> 
</users>

روش های جلوگیری

روش های جلوگیری در PHP

مثال 1)

<!DOCTYPE html>
<html lang="en">


	<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

		<title>XML Bomb Denial-of-Service</title>

		<?php require(dirname(__FILE__)."../../../bootstrap.php") ?>

	</head>
	 <body>


		 <!-- Sidebar -->
	 <div id="wrapper">

		 <div class="col-md-3">
		 <?php require(dirname(__FILE__)."../../../sidebar.php") ?>
	</div>

			<div id="page-content-wrapper">
						<div class="container-fluid">
								<div class="row">
										<div class="col-lg-12">


    </html>
<?php
	$simple = $_POST['name'];
	$p = xml_parser_create();
	xml_parse_into_struct($p, $simple, $vals, $index);
	xml_parser_free($p);
	echo "<br><br>The following array was created from your XML data\n <br><br>";
	print_r($index);
	echo "\nVals array\n";
	print_r($vals);
	 get_server_memory_usage();
	 get_server_cpu_usage();
function get_server_memory_usage(){
    //shows server memory usage
    if (stristr(PHP_OS, 'Linux'))
    {
		$free = shell_exec('free');
		$free = (string)trim($free);
		$free_arr = explode("\n", $free);
		$mem = explode(" ", $free_arr[1]);
		$mem = array_filter($mem);
		$mem = array_merge($mem);
		$memory_usage = $mem[2]/$mem[1]*100;
		print "<br><br><br> The server memory usage is ".$memory_usage;
	}
	else
	{
	$cmd = 'typeperf  -sc 1  "\Processor(_Total)\% Processor Time"';
	exec($cmd, $lines, $retval);
	if($retval == 0) {
		$values = str_getcsv($lines[2]);
		print "<br><br><br> The server memory usage is ".floatval($values[1]);
	} else {
		return false;
	}
	}
}
function get_server_cpu_usage(){
    //shows server CPU Usage
{
    $load=array();
    if (stristr(PHP_OS, 'win'))
    {
    $output = array();
    exec( 'tasklist ', $output );
    foreach ($output as $value)
    {
        $ex=explode(" ",$value);
        $count_ex=count($ex);
        if (eregi(" ".getmypid()." Console",$value))
        {
            $memory_size=$ex[$count_ex-2]." Kb";
            print "<br><br>The server CPU usage is ".$memory_size;
        }
    }
    }
    else
    {
        $load = sys_getloadavg();
        print "<br><br>The server CPU usage is ".$load[0];
    }
    return $load;
}
}
?>

راه حل 1)

<!DOCTYPE html>
<html lang="en">


	<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

		<title>XML Bomb Denial-of-Service</title>

		<?php require(dirname(__FILE__)."../../../bootstrap.php") ?>

	</head>
	 <body>


		 <!-- Sidebar -->
	 <div id="wrapper">

		 <div class="col-md-3">
		 <?php require(dirname(__FILE__)."../../../sidebar.php") ?>
	</div>

			<div id="page-content-wrapper">
						<div class="container-fluid">
								<div class="row">
										<div class="col-lg-12">


    </html>
<?php
	$simple = addslashes($_POST['name']);
	$p = xml_parser_create();
	xml_parse_into_struct($p, $simple, $vals, $index);
	xml_parser_free($p);
	echo "<br><br>The following array was created from your XML data\n <br><br>";
	print_r($index);
	echo "\nVals array\n";
	print_r($vals);
	 get_server_memory_usage();
	 get_server_cpu_usage();
function get_server_memory_usage(){
    //shows server memory usage
    if (stristr(PHP_OS, 'Linux'))
    {
		$free = shell_exec('free');
		$free = (string)trim($free);
		$free_arr = explode("\n", $free);
		$mem = explode(" ", $free_arr[1]);
		$mem = array_filter($mem);
		$mem = array_merge($mem);
		$memory_usage = $mem[2]/$mem[1]*100;
		print "<br><br><br> The server memory usage is ".$memory_usage;
	}
	else
	{
	$cmd = 'typeperf  -sc 1  "\Processor(_Total)\% Processor Time"';
	exec($cmd, $lines, $retval);
	if($retval == 0) {
		$values = str_getcsv($lines[2]);
		print "<br><br><br> The server memory usage is ".floatval($values[1]);
	} else {
		return false;
	}
	}
}
function get_server_cpu_usage(){
    //shows server CPU Usage
{
    $load=array();
    if (stristr(PHP_OS, 'win'))
    {
    $output = array();
    exec( 'tasklist ', $output );
    foreach ($output as $value)
    {
        $ex=explode(" ",$value);
        $count_ex=count($ex);
        if (eregi(" ".getmypid()." Console",$value))
        {
            $memory_size=$ex[$count_ex-2]." Kb";
            print "<br><br>The server CPU usage is ".$memory_size;
        }
    }
    }
    else
    {
        $load = sys_getloadavg();
        print "<br><br>The server CPU usage is ".$load[0];
    }
    return $load;
}
}
?>


روش های جلوگیری در ASP.NET

مثال 1)

XmlDocument doc = new XmlDocument();
doc.LoadXml(template);
XmlElement list = doc.CreateElement(conn.XmlListTagName);
foreach (EaiItem updateItem in itemList)
{
    XmlElement item = doc.CreateElement( conn.XmlItemTagName );
    foreach(String itemAttrib in updateItem.ItemAttributes.Keys)
    {
        item.SetAttribute(itemAttrib, updateItem.ItemAttributes[itemAttrib]);
    }
    item.InnerXml = updateItem.ItemFieldXml;
    list.AppendChild(item);
}
doc.LastChild.AppendChild(list);

راه حل 1)

XmlDocument doc = new XmlDocument();
doc.LoadXml(template);
XmlElement list = doc.CreateElement(conn.XmlListTagName);
foreach (EaiItem updateItem in itemList)
{
    XmlElement item = doc.CreateElement( conn.XmlItemTagName );
    foreach(String itemAttrib in updateItem.ItemAttributes.Keys)
    {
        item.SetAttribute(itemAttrib, updateItem.ItemAttributes[itemAttrib]);
    }
    item.InnerText = updateItem.ItemFieldXml;
    list.AppendChild(item);
}
doc.LastChild.AppendChild(list);

روش های جلوگیری در JAVA

مثال 1)

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
 
public class OnlineStore {
  private static void createXMLStreamBad(final BufferedOutputStream outStream,
      final String quantity) throws IOException {
    String xmlString = "<item>\n<description>Widget</description>\n"
        + "<price>500</price>\n" + "<quantity>" + quantity
        + "</quantity></item>";
    outStream.write(xmlString.getBytes());
    outStream.flush();
  }
}

راه حل 1)

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
 
public class OnlineStore {
  private static void createXMLStream(final BufferedOutputStream outStream,
      final String quantity) throws IOException, NumberFormatException {
    // Write XML string only if quantity is an unsigned integer (count).
    int count = Integer.parseUnsignedInt(quantity);
    String xmlString = "<item>\n<description>Widget</description>\n"
        + "<price>500</price>\n" + "<quantity>" + count + "</quantity></item>";
    outStream.write(xmlString.getBytes());
    outStream.flush();
  }
}

راه حل 2)

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
 
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
 
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
 
public class OnlineStore {
 
  private static void createXMLStream(final BufferedOutputStream outStream,
      final String quantity) throws IOException {
    String xmlString;
    xmlString = "<item>\n<description>Widget</description>\n"
        + "<price>500.0</price>\n" + "<quantity>" + quantity
        + "</quantity></item>";
    InputSource xmlStream = new InputSource(new StringReader(xmlString));
    // Build a validating SAX parser using our schema
    SchemaFactory sf = SchemaFactory
        .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    DefaultHandler defHandler = new DefaultHandler() {
      public void warning(SAXParseException s) throws SAXParseException {
        throw s;
      }
      public void error(SAXParseException s) throws SAXParseException {
        throw s;
      }
      public void fatalError(SAXParseException s) throws SAXParseException {
        throw s;
      }
    };
    StreamSource ss = new StreamSource(new File("schema.xsd"));
    try {
      Schema schema = sf.newSchema(ss);
      SAXParserFactory spf = SAXParserFactory.newInstance();
      spf.setSchema(schema);
      SAXParser saxParser = spf.newSAXParser();
      // To set the custom entity resolver,
      // an XML reader needs to be created
      XMLReader reader = saxParser.getXMLReader();
      reader.setEntityResolver(new CustomResolver());
      saxParser.parse(xmlStream, defHandler);
    } catch (ParserConfigurationException x) {
      throw new IOException("Unable to validate XML", x);
    } catch (SAXException x) {
      throw new IOException("Invalid quantity", x);
    }
    // Our XML is valid, proceed
    outStream.write(xmlString.getBytes());
    outStream.flush();
  }
}