Archive for March, 2008

The Anatomy of a SQL Injection

Wednesday, March 26th, 2008
We had a client recently come to us to add something onto a project that another developer had done. In the process, we noticed the site was probably susceptible to SQL Injections. We did some testing, and sure enough, SQL Injections were possible.
 
As any responsible developer would do, we notified the client and provided them some links to some information regarding SQL Injections. The client was interested in knowing how to fix it, however, their server admin also told them that the server was secure and that it probably wasn’t that likely to happen and maybe not that big of an issue.
 
With that said, let’s get something out of the way: A SQL Injection has absolutely nothing to do with the security of the server. You can have the best security practices in the world for your server, but if it’s hosting an insecure application, there’s a risk. And the risk is not only to the app, but can be to your entire server.
 
We prepared a quick demo to show the client what is possible via SQL Injection. The code that we discovered was on the login page for this particular application. The code looked something like this:
 
SELECT * FROM tablename WHERE user = ‘$variable’ AND passwrd = ‘$variable’;
 
Note: throughout this blog entry, I’m replacing the real table name with ‘tablename’ for ease, as well as to not publicly reveal the actual table name.
 
The variables are coming straight from the browser and are not ’sanitized’, or filtered, in any way. So, our first demo to the client was to leave the password field empty and enter the following into the username box:
 
‘ OR ‘1′ = ‘1
 
When we first showed this to the client, they were a bit confused. Let’s see what that looks like when we insert it into the query above:
 
SELECT * FROM tablename WHERE user = ” OR ‘1′ = ‘1′ AND passwrd = ‘$variable’;
 
Wow, so now we’re asking the database for any users where the username is empty OR 1 = 1 AND password = ”. Guess what? The database will return a record because of the fact there’s an OR in there that evaluates true.
 
At this point, we were successfully logged into the application. That concerned the client enough, however, there’s more. Much more. Part of the scary thing about SQL Injections is that they often allow you to execute more than one query. So, our next step was to try to execute some additional queries. The next thing we entered into the username box looked like this:
 
‘ OR ‘1′ = ‘1′; DROP TABLE test_table_name;
 
That threw an error. Here’s what the database saw when we ran that:
SELECT * FROM tablename WHERE user = ” OR ‘1′ = ‘1′; DROP TABLE test_table_name; ‘ AND passwd = ”;
 
We have an unmatched quote in there. However, the error wasn’t handled in the application and it printed a message to the screen that said something along the lines of:
 
You have an error in your SQL statement near (SELECT * FROM tablename  user = ” OR ‘1′ = ‘1′; DROP TABLE test_table_name; ‘ AND passwd = ”;
 
Guess what. Now the error message printed to the screen gave us the actual table name. And field names. That’s dangerous.
 
So, with that attempt failing, but the important note about the error message revealing the table name, we moved on to the next part of the demo. Our next entry into the username box looked like this:
 
‘ OR ‘1′ = ‘1′; DROP TABLE test_table_name; SELECT * FROM tablename WHERE ‘1′ = ‘1
 
Now, when the database sees that query, it looks like this:
 
SELECT * FROM tablename WHERE user = ” OR ‘1′ = ‘1′; DROP TABLE test_table_name; SELECT * FROM tablename WHERE ‘1′ = ‘1′ AND passwrd = ”;
 
We now have 3 valid SQL Statements here:
 
SELECT * FROM tablename WHERE user = ” OR ‘1′ = ‘1′;
DROP TABLE test_table_name;
SELECT * FROM tablename WHERE ‘1′ = ‘1′ AND passwrd = ”;
 
The first one will log us into this application. Nice, but not really the worst part of this situation. The second statement will delete the database table named ‘test_table_name’. Now, keep in mind that earlier, an error message told us an actual table name. We could easily substitute that, or, we could start guessing table names. Or, we could insert our own record, since we now know table names and field names from the error message earlier.
 
To give the full effect, we literally created a table named test_table_name, showed the client the table in the database, typed that into the username box, and clicked ‘log in’. We were greeted with an error message. However, when we refreshed the table list, our test_table_name was gone. It had been deleted. Ouch. Just imagine if that was our users table, or some other table full of sensitive information…
 
Joe Koenig
Creative Anvil
St. Louis Web Design Firm

Share/Save/Bookmark

Convert a Word Document to PDF Using Java

Thursday, March 20th, 2008
I had a need today to convert a Word Document to a PDF using Java. This needed to be an automated process. A quick Google search was turning up a little empty handed. I kept finding people talking about ‘just open it in OpenOffice and export as a PDF’. Obviously, that doesn’t fit the automated requirement.
 
Apache has a Java API, called POI, that allows you to access Microsoft formats from within Java. It looks handy, but I found some people complaining about the complexity of it. Some further searching turned up mention of something called JODConverter. This is a fantastic project.
 
JODConverter is essentially a Java library that utilizes OpenOffice’s conversion engine to convert to and from any format that OpenOffice supports. This includes Word, Excel, PowerPoint, RTF, Plain Text, etc.
 
I decided to see how easy it was going to be to use this library. Let’s face it, a lot of these open source projects claim to do all kinds of great things, but do not provide the greatest results. So, I created a small test project and wrote a simple class. Here’s what it looks like:
 
public class convertFile {
   public static void main(String[] args) {
      File inputFile = new File("resume-2.doc");
      File outputFile = new File("resume-2.pdf");
     OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
     try {
        connection.connect();
     } catch(Exception e) {
     }

     DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
     converter.convert(inputFile, outputFile);

     connection.disconnect();

   }
}

 

Obviously, there’s error-checking that is lacking. For example, the convert() method should be wrapped to ensure that a failed conversion doesn’t blow up your application, and something should be done if an exception is caught on the connection. However, this is the basic skeleton. Pretty cool.
 
Basically, all this does is open a connection to OpenOffice, create a converter, and pass in the files to convert. JODConverter and OpenOffice handle everything else.
 
The only caveat to this is that OpenOffice must be installed on the server and must be running as a headless app (the JODConverter README file explains how to do this). While that may not be ideal, it’s probably worth it for the amazing results this library provides.
 
Great tool, highly recommended.
 
Joe Koenig
Creative Anvil
Search Engine Optimization & Web Application Development

Share/Save/Bookmark

How To Create an iSCSI SAN using Heartbeat, DRBD, and OCFS2

Monday, March 17th, 2008
Overview
A client had a need recently for a Storage Area Network (SAN). We were expanding the system to a small cluster in order to prepare for future growth. For those of you unfamiliar with a cluster environment, when you have multiple servers accessing the same data, you need a SAN in order to protect the data. Well, let me clarify that, when you have multiple servers writing data you need a SAN. If they are only reading data, you can use something like NFS to export a drive.
 
Let me provide a quick cluster / file system intro here… In a cluster, each server is a ‘node’ of the cluster. In this case, the SAN is a server, and each server, or node, in the cluster, is actually a ‘client’. This is because there is 1 SAN server, and multiple ‘nodes’ accessing the same services/data, therefore, clients. And when you have multiple clients that have access to write to the data, you need a ‘Cluster File System’. A cluster file system ensures that files do not get corrupted by two nodes trying to write data to the same file at the same time. So, it manages file locks and write-ordering, which are critical to protecting data.
 
Problem?
A big part of the reason that I was looking for an open-source SAN solution was cost. We needed a reliable, low-cost solution. We really wanted to keep the budget around $10,000 or less.
 
The solution?
Through some research and creative thinking, I realized we could build a SAN with commodity hardware, in this case, Dell 2950 Servers (2), and a Dell gigabit switch. For the software, we’d use CentOS 5 as the Operating System, DRBD to mirror the data, Heartbeat to manage the cluster and failover, OCFS2 as the filesystem, and iSCSI to export the drive. Let me give a quick overview of these items:

 

CentOS: A downstream version of a very prominent North American Linux distributor. Virtually the same exact code, without the requirement to buy support in order to get updates.
 
DRBD: An amazing piece of software that acts at the block level to replicate data between servers. Basically, this piece of software mirrors all data writes from one server to the other, creating a network RAID 1 (mirror).
 
Heartbeat: A package that allows two servers to communicate and check if the other is still ‘alive’. If the software detects that one server has died, any services running on the ‘dead’ server will automatically migrate over to the ‘live’ server.
 
OCFS2: A cluster filesystem developed by Oracle. 
 
iSCSI: A network transport that wraps SCSI commands, enabling a ‘node’ to mount a drive, as if the drive were a local drive. iSCSI provides a reliable method for reading/writing data to a drive that is on a completely separate server, and could be on a separate network.

 

The Setup
I installed the software the exact same on both Dell servers. The two dell servers were then connected to the gigabit switch (192.168.1.x), which also connected the other nodes to the SAN. I would NOT recommend using a 100Mbps switch, as you’ll likely saturate the line. 1Gbps provided me with enough bandwidth. The two SAN servers were also connected with a crossover cable on a separate network (10.0.0.x). This allowed DRBD to have a dedicated 1Gbps line to replicate data between the two servers. The ‘nodes’ in the cluster mount the iSCSI drive over the local network.

 

Configuration
Essentially, I followed all of the typical configuration steps for the above software. You’ll need a working installation of CentOS. Nothing too special, though. I prefer to keep my servers slim and install only the minimum, leaving off the graphical interface. The only exception to this is the cluster nodes, because OCFS requires the GUI in order to set-up and maintain the cluster configuration.
I installed DRBD via yum:
yum install drbd

 

My DRBD configuration file looks like this:
global {
    usage-count yes;
}

common {
  syncer { rate 100M; }
}

resource drbd0 {

  protocol C;

  handlers {
    pri-on-incon-degr “echo o > /proc/sysrq-trigger ; halt -f”;

    pri-lost-after-sb “echo o > /proc/sysrq-trigger ; halt -f”;

    local-io-error “echo o > /proc/sysrq-trigger ; halt -f”;

    outdate-peer “/usr/lib64/heartbeat/drbd-peer-outdater”;
  }

  startup {
    wfc-timeout  600;

    degr-wfc-timeout 120;    # 2 minutes.
  }

  disk {
    on-io-error   detach;

    fencing resource-only;
  }

  net {
    cram-hmac-alg “sha1″;
    shared-secret “ImNotPostingThatOnTheInternet”;
    
    after-sb-0pri disconnect;

    after-sb-1pri disconnect;

    after-sb-2pri disconnect;

    rr-conflict disconnect;
  }

  on san1.xxxxxx.com {   
    device     /dev/drbd0;
    disk       /dev/sdb1;
    address    10.0.0.1:7788;
    flexible-meta-disk  internal;
  }

  on san2.xxxxxx.com {
    device    /dev/drbd0;
    disk      /dev/sdb1;
    address   10.0.0.2:7788;
    flexible-meta-disk internal;
  }
}

While the full configuration of DRBD is outside the scope of this post (and LinBit has a great User Guide), there are a few things to point out. First off, I have DRBD communicating on its own private network, on port 7788. Also, note that /dev/sb1 is where my 1TB RAID array is located (as far as CentOS is concerned). This is my shared storage.

 

So, at this point we have DRBD working. Next, let’s get Heartbeat up and running to manage the drive and failover. Again, full configuration of Heartbeat is outside the scope of this posting, but again, great information is available on their web site.
For this set-up, my heartbeat config (cib.xml) looks like this (I apologize in advance for the wrapping):

<cib admin_epoch=”0″ have_quorum=”true” num_peers=”1″ cib_feature_revision=”1.3″ generated=”true” epoch=”242″ ignore_dtd=”false” nu
m_updates=”13″ cib-last-written=”Sat Feb 23 13:51:32 2008″ ccm_transition=”1″ dc_uuid=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″>
<configuration>
<crm_config>
<cluster_property_set id=”default”>
<attributes>
<nvpair id=”symmetric-cluster” name=”symmetric-cluster” value=”true”/>
<nvpair id=”no-quorum-policy” name=”no-quorum-policy” value=”stop”/>
<nvpair id=”stonith-enabled” name=”stonith-enabled” value=”false”/>
<nvpair id=”short-resource-names” name=”short-resource-names” value=”true”/>
<nvpair id=”is-managed-default” name=”is-managed-default” value=”true”/>
<nvpair id=”transition-idle-timeout” name=”transition-idle-timeout” value=”60000″/>
<nvpair id=”default-resource-stickiness” name=”default-resource-stickiness” value=”INFINITY”/>
<nvpair id=”stop-orphan-resources” name=”stop-orphan-resources” value=”false”/>
<nvpair id=”stop-orphan-actions” name=”stop-orphan-actions” value=”false”/>
<nvpair id=”remove-after-stop” name=”remove-after-stop” value=”false”/>
</attributes>
</cluster_property_set>
<cluster_property_set id=”cib-bootstrap-options”>
<attributes>
<nvpair id=”cib-bootstrap-options-dc-version” name=”dc-version” value=”2.1.3-node: 552305612591183b1628baa5bc6e903e0f1e26
a3″/>
</attributes>
</cluster_property_set>
</crm_config>
<nodes>
<node id=”c343bdeb-26d4-405b-b852-04ed6a2a27c4″ uname=”san1.xxxxxx.com” type=”normal”/>
<node id=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″ uname=”san2.xxxxxx.com” type=”normal”/>
</nodes>
<resources>
<group id=”san_group”>
<primitive class=”heartbeat” id=”drbd” provider=”heartbeat” type=”drbddisk”>
<operations>
<op id=”drbd_monitor” interval=”120s” name=”monitor” timeout=”60s”/>
</operations>
<instance_attributes id=”drbd_attributes”>
<attributes>
<nvpair id=”drbd_resource_name” name=”1″ value=”drbd0″/>
</attributes>
</instance_attributes>
</primitive>
<primitive id=”ip_resource_1″ class=”ocf” type=”IPaddr” provider=”heartbeat”>
<instance_attributes id=”ip_attributes”>
<attributes>
<nvpair id=”ipaddr_ip” name=”ip” value=”192.168.1.200″/>
</attributes>
</instance_attributes>
</primitive>
<primitive id=”ietdid” class=”lsb” type=”iscsi-target”/>
</group>
</resources>
<constraints>
<rsc_location id=”run_ip_resource_1″ rsc=”ip_resource_1″>
<rule id=”pref_run_ip_resource_1″ score=”100″>
<expression attribute=”#uname” operation=”eq” value=”san1″ id=”san1″/>
</rule>
</rsc_location>
<rsc_order id=”order1″ from=”drbd” action=”start” type=”before” to=”ip_resource_1″/>
<rsc_order id=”order2″ from=”ip_resource_1″ action=”start” type=”before” to=”ietdid”/>
</constraints>
</configuration>
<status>
<node_state id=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″ uname=”san2.xxxxx.com” crmd=”online” crm-debug-origin=”do_update_r
esource” shutdown=”0″ in_ccm=”true” ha=”active” join=”member” expected=”member”>
<lrm id=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″>
<lrm_resources>
<lrm_resource id=”drbd” type=”drbddisk” class=”heartbeat” provider=”heartbeat”>
<lrm_rsc_op id=”drbd_monitor_0″ operation=”monitor” crm-debug-origin=”do_update_resource” transition_key=”3:0:379e97e4-
cfbd-47c4-8da9-2fa60ac47451″ transition_magic=”0:7;3:0:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”2″ crm_feature_set=”2.0″ rc_co
de=”7″ op_status=”0″ interval=”0″ op_digest=”ea09f933342d2b2407fb06548c8249df”/>
<lrm_rsc_op id=”drbd_start_0″ operation=”start” crm-debug-origin=”do_update_resource” transition_key=”7:0:379e97e4-cfbd
-47c4-8da9-2fa60ac47451″ transition_magic=”4:1;7:0:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”5″ crm_feature_set=”2.0″ rc_code=”
1″ op_status=”4″ interval=”0″ op_digest=”ea09f933342d2b2407fb06548c8249df”/>
<lrm_rsc_op id=”drbd_stop_0″ operation=”stop” crm-debug-origin=”do_update_resource” transition_key=”1:1:379e97e4-cfbd-4
7c4-8da9-2fa60ac47451″ transition_magic=”0:0;1:1:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”6″ crm_feature_set=”2.0″ rc_code=”0″
op_status=”0″ interval=”0″ op_digest=”ea09f933342d2b2407fb06548c8249df”/>
</lrm_resource>
<lrm_resource id=”ip_resource_1″ type=”IPaddr” class=”ocf” provider=”heartbeat”>
<lrm_rsc_op id=”ip_resource_1_monitor_0″ operation=”monitor” crm-debug-origin=”do_update_resource” transition_key=”4:0:
379e97e4-cfbd-47c4-8da9-2fa60ac47451″ transition_magic=”0:7;4:0:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”3″ crm_feature_set=”2
.0″ rc_code=”7″ op_status=”0″ interval=”0″ op_digest=”fbfabc6bc90887bc11bf8ed485ec821d”/>
</lrm_resource>
<lrm_resource id=”ietdid” type=”iscsi-target” class=”lsb”>
<lrm_rsc_op id=”ietdid_monitor_0″ operation=”monitor” crm-debug-origin=”do_update_resource” transition_key=”5:0:379e97e
4-cfbd-47c4-8da9-2fa60ac47451″ transition_magic=”0:7;5:0:379e97e4-cfbd-47c4-8da9-2fa60ac47451″ call_id=”4″ crm_feature_set=”2.0″ rc_
code=”7″ op_status=”0″ interval=”0″ op_digest=”f2317cad3d54cec5d7d7aa7d0bf35cf8″/>
</lrm_resource>
</lrm_resources>
</lrm>
<transient_attributes id=”0a38edda-e639-4f27-87c2-142ef3ff1fa9″>
<instance_attributes id=”status-0a38edda-e639-4f27-87c2-142ef3ff1fa9″>
<attributes>
<nvpair id=”status-0a38edda-e639-4f27-87c2-142ef3ff1fa9-probe_complete” name=”probe_complete” value=”true”/>
<nvpair id=”status-0a38edda-e639-4f27-87c2-142ef3ff1fa9-fail-count-drbd” name=”fail-count-drbd” value=”1″/>
</attributes>
</instance_attributes>
</transient_attributes>
</node_state>
</status>
</cib>

 

The only real things to point out here are that I have a ‘drbddisk’ defined and I’ve told heartbeat to manage it, as well as that I have defined a virtual IP address - 192.168.1.200. This IP will ‘float’ between the two servers, depending on which server is active. THIS IS THE IP THAT ISCSI WILL RUN ON!!! That’s critical. That allows me to configure the nodes to look for iSCSI drives on that IP and still have the cluster failover properly. That means, if the primary server fails, the secondary server should come up and essentially tell DRBD ‘you are now primary, take over’. The other piece to heartbeat is the ha.cf, which is pretty straightforward:

 

keepalive 3
deadtime 15
warntime 9
initdead 30
auto_failback off
node san1.xxxxxx.com san2.xxxxxx.com
udpport 694
baud 19200
serial /dev/ttyS0
crm yes
bcast eth0
use_logd yes
ping 192.168.1.1
respawn hacluster /usr/lib64/heartbeat/dopd
apiauth dopd gid=haclient uid=hacluster

 

Basically, this file defines the cluster members and how the cluster will communicate. In my case, I’m communicating over a serial port AND over ethernet. This is critical - you need more than one communication path. If you only communicate over ethernet and your network has a small hiccup, both nodes will think the other went away and will BOTH try to be primary, which can be a very bad thing.

 

OK, so here we are, we have DRBD set up to mirror the data between the two servers and heartbeat set up to manage the failover. Almost there. Now, we need a way to export the device. For this, I’m using iSCSI. 

 

I choose to use IETD - iSCSI Enterprise Target. Installation was really quite simple. I downloaded the file, untarred it, and just followed the instructions in the README - basically, just make && make install. Configuration is pretty straight-forward, too. There is a default config file that pretty much has everything you need, just a few things to update, such as your target name. Honestly, the file is commented so good that I’m not going to post it. All I had to do was specify the Target name, the authentication username/password (which is so basic that it hardly provides an protection) and the location of the drive to export.

 

This is the one thing that threw me off for a bit - you MUST EXPORT THE DRBD DRIVE. If you export your physical drive, the data will not be mirrored. So, in my case, this looked like:
Lun 0 Path=/dev/drbd0,Type=fileio

Now, I’ve got everything I need set up on the SAN servers. Remember, I have 2 servers for the failover, so all of this must be done on both servers. Time for the nodes…

 

Each node will need OCFS2 and OCFS2 Tools installed. Again, this is beyond the scope of this document. However, Oracle provides RPMS for RHEL, which will install just fine on CentOS. Again, for the initial setup, you need the GUI (X-Windows, Gnome, KDE, etc). The GUI generates a config file for OCFS2. Just follow the instructions provided by Oracle for this step. It’s really pretty simple. You’re basically just naming the nodes and assigning them to a cluster.

 

The only trick with the nodes is to discover the iSCSI drive and add it to /etc/fstab so that it finds it on boot. You’ll need iscsi-initiator-utils for RHEL5 or CentOS 5. Basically, once you have that installed, you’ll just need to:
iscsiadm -m discovery -t sendtargets -p

You can then login to the device you find with:

 

iscsiadm -m node -T iqn.2001-04.il.org.tournament:diskserv.disk1 -p :3260,1 -l

 

To have the discovery happen automatically, you’ll need to create a file in /etc/iscsi/ called ‘initiatorname.iscsi’. You can read more at this site.

After you can see the drive, make sure you format it with OCFS. Again, this is very simple through the GUI that Oracle provides.

At this point, we’re ready to edit the /etc/fstab file. I added:
/dev/sdb                /data                   ocfs2   _netdev         0 0

The _netdev command tells the OS that this drive is mounted over the network, so we need to wait for the network to be available before attempting to mount this drive. By this point, OCFS will have started up, so it will be ready to handle the drive. You can see that I’m mounting mine to a /data directory.

Next? Test it out!! Make sure that OCFS is set to start on boot on all of the nodes, which it should be. 

What would I do differently?
I’d buy a better switch. One that had more robust support for VLAN’s. Basically, the dell switch I bought is a web-managed switch. I’d really recommend a fully-managed switch for this type of set-up. Yes, it’s more expensive, but it will give you much better VLAN control and growth ability.

 

I didn’t even look into GFS when I set this up. I’d now explore it as an alternative to OCFS2, mainly due to the fact that RedHat developed and maintains it, which makes me think that RHEL and CentOS will probably integrate better with it, than with OCFS2.

 

Additional Notes:
Please, please, please do NOT put this kind of setup on the internet. It’s not really that safe. Yes, your web servers will need to be public. That’s what a DMZ is for. Please make sure you have some sort of firewall between the nodes that are public and the SAN servers. If not, your data is at risk…

 

Lastly, I’ll gladly take comments / questions on this setup. It can be tricky to get right, but it’s usually a small configuration problem. Make sure you test each individual step along the way. Make sure you get DRBD working right, then add in Heartbeat, then add in iSCSI, then add in OCFS. If you try to do it all at once and hope it works, you’ll have a heck of a time trying to figure out where your problem is…

 

Joe Koenig
Creative Anvil

Share/Save/Bookmark

Google Account Security Issue?

Friday, March 14th, 2008

I had an odd thing happen to me the other day. I was using my Google account in Firefox. I have multiple Google accounts - one for personal, one for business. I had first been logged into my business account, then logged out and logged in to my personal account. All was well, except when I clicked on a report in my Analytics list, I was taken to the ‘Analytics’ tab in my business account. So, I was able to see site reports for the account that I was no longer logged into.  I took some screenshots, because it was odd, and e-mailed Google to let them know they may have a security issue. This happened back on January 29th, and after giving Google ample time to reply / fix the issue, I’m now posting it.

Take a look at these screen shots - you can click on them to view the full-size screen shot.

On the screen shot below, note the two site names listed in the report listing.

Now, on this next screenshot, take a look at the name of the site that I am viewing report data for. It’s not one of the two reports listed.

I’m a huge fan of Google - I think they do a great job and provide great tools. However, their customer support completely failed to understand what was going on here, even with screen shots.
Below is the e-mail correspondence with Google. The original message from me was submitted through their support form.

From: xxx@creativeanvil.com

Subject: Security Issue with Adwords / Analytics

Date: Tue, 29 Jan 2008 15:24:01 -0800

I have two different google accounts - one for work and one for 

personal. When logged into my personal account, clicking on Analytics 

took me to the right spot, but clicking on a report took me to my work 

account — actually, into my work AdWords account, with the Analytics 

tab selected. I have used the same browser for both, but I specifically 

logged out of the work account, then logged into the personal account. 

I know it was logged in properly because I saw the right content in my 

google home page, my webmaster tools, but not my analytics. I have 

screen shots that I can e-mail of the different screens and what I got 

when I clicked different links. I’d be glad to send them so that you 

can verify this.

AdsUserLocale: en_US

Language: en

Name: Joe Koenig

Source: cuf

topic: Other

———- NEXT MESSAGE ———

Hello Joe,

Thank you for your email. I understand you are concerned as while you

try

to view the reports in one account, you are able to access the reports

of

some other account. To help us troubleshoot further it would be

advisable

if you could send a direct response to this email with the relevant

screenshots and the login email addresses you are trying to access your

account with. It would be better if you could include your work login

email address and your personal login email address. 

If you have additional questions, please visit our Help Center at

https://adwords.google.com/support to find answers to many frequently

asked questions. Or, try our Learning Center at

http://www.google.com/adwords/learningcenter/ for self-paced lessons

that

cover the scope of AdWords.

We look forward to providing you with the most effective advertising

available. 

Sincerely,

Suchi Kumar

The Google AdWords Team

—————-

To access your AdWords account, please log in at:

https://adwords.google.com

——- NEXT MESSAGE ——–

From: Joseph Koenig

Subject: Re: [#237202376] Security Issue with Adwords / Analytics

Date: Wed, 30 Jan 2008 08:49:11 -0600

Thanks for the response. Attached are screen shots. Picture 7.png shows 

the link in the status bar of the browser that I got when hovering over 

the report link. I wasn’t sure if anything in the parameters being 

passed in would be helpful. Other than that, the pictures just show the 

progression of screens from my account home page, to the analytics 

report. I was logged in as “xxxx@koenigland.com”, but I was seeing 

analytics reports for “xxxx@creativeanvil.com”. This was on Firefox 

2.0.11 on Mac OS 10.5.

*Joe Koenig*

*Creative Anvil, Inc.*

*Phone: *314.692.0338

1346 Baur Blvd.

Olivette, MO 63132

xxxx@creativeanvil.com

http://www.creativeanvil.com

—— NEXT MESSAGE ——

Hello Joseph,

Thank you for sending us this information. I’ll be happy to assist you in

this situation. I see that you’re having trouble while toggling between

two login email address for two different Analytics accounts. I have

escalated this issue to our Analytics team. They’re currently

investigating the situation, and we’ll contact you as soon as we’ve found

a resolution. 

In the meantime, I encourage you to log in to your accounts from two

different browsers. 

Thank you for your patience and apologize for any inconvenience.

Sincerely,

Seva

The Google AdWords Team

—————-

To access your AdWords account, please log in at:

https://adwords.google.com

OK, at this point, I’m thinking ‘What?!??! Trouble toggling between accounts!?!?! Clearly, they don’t get it….’ So, I wait a bit and this is the response I then get from the Adwords team…

Hello Joseph,

Thank you for your patience while we researched this issue. I understand

you’re concerned about your Analytics reports for the website

‘http://www.koenigland.com’ showing in your Analytics account with the

login email address ‘xxxx@koenigland.com’ which you expected would show in

the account with the login ‘xxxx@creativeanvil.com.’ I would like to

explain that in the site ‘http://www.koenigland.com,’ you’ve installed the

tracking code for the Analytics account ID ‘UA-2618736-2′ which is

associated with the email address ‘xxxx@koenigland.com.’ This is the reason

why your Analytics reports for this site is showing in an account

different from the one you intended. 

If you would like to receive data for this site in your account with the

login email address 

‘xxxx@creativeanvil.com,’ you’ll need to place the appropriate code on the

site. 

To view your personalized Google Analytics tracking code, please follow

the steps in the following Help Center article:

http://www.google.com/support/googleanalytics/bin/answer.py?answer=55603&utm_id=cr

I hope this helps clarify your concern. 

As always, we look forward to providing you with the most effective

advertising available. 

Sincerely,

Seva

The Google AdWords Team

At what point did I say I expected them to both show up the same account!?!?! I said I was seeing them from the wrong account! There’s a security problem somewhere here, and their low-level techs don’t even have the ability to recognize that and pass it on to the appropriate team. I gave up at this point. As I said, this was back in January. In fact, the last email was 2/4/08. If they haven’t had a chance to fix it yet, not my fault. If anyone can explain how this happens, or how to reliably duplicate the security breach, I’d love to hear it. I’ve tried it again, but only once or twice and couldn’t duplicate. I figured someone with some more time may want to give this a try and see what they come up with. All I know is that I did NOT quit firefox in between switching from accounts and had been logged into my adwords account before logging out and going back into analytics. Any ideas anyone?


Joe Koenig

Creative Anvil

Web Design and Development, St. Louis

Share/Save/Bookmark