Clearing unread messages from the Google Voice Inbox

I use Google Voice as a generic proxy for my public cell phone number to the actual land lines and cell phones that I use at customers, work, and in my private life.  It’s great an has very few rough edges.

Unfortunately, it is pretty easy to get lingering Unread Messages so deep in your call Inbox that removing them becomes impossible.  For several months, the Chrome Google Voice plugin looked like the following for me:

In the Google Voice inbox you can filter for these unread messages by using the following search syntax on the Google Voice web page

is:unread

At this point you can clear them 10 at a time.

XQuery Injection Mea Culpa

There was a paper at the 2011 Balisage about XQuery Injection attacks.  The paper focuses on attacks against eXist but got me thinking.
http://www.balisage.net/Proceedings/vol7/html/Vlist02/BalisageVol7-Vlist02.html

Usually when we talk about Injection attacks at ML, we focus on xdmp:eval() and xdmp:value() and making sure that the input string is not derived from user supplied data.

With injection attacks in mind, I turned my attention to source code I wrote for a project going live this month and found the following:

let $uri := xdmp:get-request-field($cfg:URI_PARAM, ())
let $doc := fn:doc($uri)/element()
return
   v:render( $doc )

So the web client clicks on a link  something like

<a href="/page/render?uri=%2Fdoc%2F1.xml">link</a>

and gets an XHTML rendering of the document at URI “/doc/1.xml”.   The only things in the content database of this HTTP server are  <doc:doc> XML documents which 100% of the user base are allowed to see and <audit:audit> XML audit logs, which are really meant only for admins.  It may not the biggest attack vulnerability but a user could URL-BASH to see other user’s audit logs.    Making the following change solves the problem:

let $doc := fn:doc($uri)/doc:doc

I then got paranoid and put in 2 or 3 other safeguards, but you get my point.  Here are some tips I have compiled:

  • Watch out for passing user contributed strings into fn:doc(), fn:collection() as well as xdmp:eval() and xdmp:value() if you aren’t using document permissions for security.
  • Prefer XPath to fn:doc() when selecting documents for update.
  • Never store a user’s password as plaintext in XML.  If you aren’t using the security database users, 1-way hash+salt those passwords or database hipsters will call you names.
  • Throw in an extra xdmp:request-timestamp() value assert to force read-only transactions where appropriate.  This is most likely to help protect you down the road in O&M when others are quickly modifying the code base to solve problems or add features.

Citation:

van der Vlist, Eric. “XQuery Injection: Easy to exploit, easy to prevent….” Presented at Balisage: The Markup Conference 2011, Montréal, Canada, August 2 – 5, 2011. In Proceedings of Balisage: The Markup Conference 2011. Balisage Series on Markup Technologies, vol. 7 (2011). doi:10.4242/BalisageVol7.Vlist02.

Hosting multiple MarkLogic app servers on port 80

Hosting more than one MarkLogic site on a server can be tricky to the uninitiated in Apache configuration.  This is not my area of expertise by any means; so given that I had to figure it out yesterday after once again forgetting how it works I think I’ll write it down here for the next time I need it.  Each MarkLogic application server listens on a different high numbered port.  Given the potential of draconian firewalls rules for both your hosting provider and users, typically the only reliable HTTP port will be 80.  Here’s what I do on Linux and Mac OSX (sorry Windows):

  • Set up my MarkLogic machine in cloud hosting (I’ve used both Amazon EC2 and Rackspace) or on on a spare machine with a dependable internet connection / power supply.
  • Register <domain>.com with a hosting provider or a domain registry
  • The hosting provider usually will have a website where I can edit my DNS rules
    • Create an A rule for <subdomain1> and direct it to my ML machine’s IP
    • Create a second A rule for <subdomain2> and direct it to the ML machine’s IP
  • On the ML machine, install Apache2 and edit the /etc/apache2/httpd.conf file to load the following modules (add to the end of the LoadModule section if it isn’t loaded already):
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
  • Add the following virtual host records to the very bottom of the file
NameVirtualHost *
<VirtualHost *>
ServerName subdomain1.domain.com
ProxyRequests Off
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    ProxyPass / http://localhost:9001/
    ProxyPassReverse / http://localhost:9001/
    <Location />
        Order allow,deny
        Allow from all
    </Location>
</VirtualHost>

<VirtualHost *>
ServerName subdomain2.domain.com
ProxyRequests Off
    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    ProxyPass / http://localhost:9002/
    ProxyPassReverse / http://localhost:9002/
    <Location />
        Order allow,deny
        Allow from all
    </Location>
</VirtualHost>
  • When done editing the file restart Apache2 with the following command:
sudo /usr/sbin/apachectl restart
Now requests for subdomain1.domain.com will go to port 80 of my ML machine and then internally within the server be proxied (reverse proxied actually) to port 9001.
–Dave