I am new to wss4j and ws-security in general. So I maybe missing something obvious.

I have axis 1.2 RC3 along with latest wss4j code from cvs. I have a simple service setup with my own password call back handler and everything works as expected from java environment. However, while testing interoperability with some simple python scripts I ran into a behavior that I can at best call a security hole.

Here is the scenario. If the password Type is specified as "wsse:PasswordDigest" (compliant to older specification) the WSDoAllReceiver class never detects the password as legitimate digest password. The type is compared against fixed constant value specified in WSConstants.PASSWORD_DIGEST (http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest). Since the password type supplied is non compliant (or unknown) to the Type specification should not wss4j throw some sort of exception? The user is allowed to invoke the web service method as if he was fully authenticated. This can be easily reproduced with the attached python scripts. Just create a simple echo/ping service with axis and wss4j

ping1.py : Does not authenticate using password call back class and lets user invoke method
ping2.py : Does the right thing and invokes appropriate password call back class
server.config.xml : My service deployer file
ping1.output.txt: Packet captured via ethereal. Never authenticated the user but invoked the ws method successfully
ping2.output.txt: Packet captured via ethereal. Failed to authenticate the user so displayed proper error message



Thanks! Mir



POST /ping/services/PingService HTTP/1.0
Content-length: 875
Host: localhost:8080
User-agent: Python-urllib/2.0a1
Soapaction: "ping"
Content-type: text/xml


<soap:Envelope 
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/";
  xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility";
  
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>

  <soap:Header>
    <wsse:Security mustUnderstand="1">
      <wsse:UsernameToken>
        <wsse:Username>[EMAIL PROTECTED]</wsse:Username>
        <wsse:Password 
Type="wsse:PasswordDigest">ZPMVFLniUXXaxMTBl4OpeKSh5kQ=</wsse:Password>
        <wsse:Nonce>7E+wxgFHcSbmolLtdIHwyAcwNtI=
</wsse:Nonce>
        <wsu:Created>2005-04-19T19:26:07Z</wsu:Created>
        <wsu:Expires>2005-04-19T19:29:07Z</wsu:Expires>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>

  <soap:Body>
    <echo><input xsi:type="xsd:string">Hello World</input></echo>
  </soap:Body>
</soap:Envelope>HTTP/1.1 200 OK
Content-Type: text/xml;charset=utf-8
Date: Tue, 19 Apr 2005 19:26:07 GMT
Server: Apache-Coyote/1.1
Connection: close

<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";><soapenv:Body><echoResponse
 soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";><echoReturn 
xsi:type="soapenc:string" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/";>Hello 
World</echoReturn></echoResponse></soapenv:Body></soapenv:Envelope>
<!-- define the service, use the WSDoAllSender security handler in request flow -->
    <service name="PingService" provider="java:RPC">
        <requestFlow>
            <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
                <parameter name="passwordCallbackClass" value="test.services.PWCallBack"/>
                <parameter name="action" value="UsernameToken"/>
                <parameter name="passwordType" value="PasswordDigest" />
            </handler>
        </requestFlow>
        <parameter name="className" value="test.services.PingServiceManager"/>
        <parameter name="allowedMethods" value="echo"/>
        <parameter name="scope" value="application"/>
    </service>

"""
    Simple python script to talk to WSS4j enabled axis service

    Based on Sam Ruby's minimal example to talk to MicorSoft WS for getting
    Top 10 downloads. http://intertwingly.net/stories/2003/09/03/mstop10.py

    Mir S Islam <[EMAIL PROTECTED]>
        -Added mustUnderstand=1 attribute
        -Updated the schema for Password
        -replacing trailing EOL from password

    create a file mstoken.py in the same directory as this file is in and
    put the following:

        token = 'authid'
        pin = 'password'

"""

import random, binascii
from urllib2 import *
from time import *
import mstoken

# Your SOAP service url
endpoint='http://localhost:8080/ping/services/PingService'

nonce = sha.new(str(random.random())).digest()
created = strftime('%Y-%m-%dT%H:%M:%SZ',gmtime(time()))
digest = sha.new(nonce + created + mstoken.pin).digest()

mypass =  binascii.b2a_base64(digest)
mypass = mypass.replace('\n','')
security = {
  'PasswordDigest': mypass,
  'Username': mstoken.token,
  'Nonce': binascii.b2a_base64(nonce),
  'Created': created,
  'Expires': strftime('%Y-%m-%dT%H:%M:%SZ',gmtime(time()+180))
}

data="""
<soap:Envelope 
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/";
  xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility";
  
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>

  <soap:Header>
    <wsse:Security mustUnderstand="1">
      <wsse:UsernameToken>
        <wsse:Username>%(Username)s</wsse:Username>
        <wsse:Password 
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest";>%(PasswordDigest)s</wsse:Password>
        <wsse:Nonce>%(Nonce)s</wsse:Nonce>
        <wsu:Created>%(Created)s</wsu:Created>
        <wsu:Expires>%(Expires)s</wsu:Expires>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>

  <soap:Body>
    <echo><input xsi:type="xsd:string">Hello World</input></echo>
  </soap:Body>
</soap:Envelope>""" % security

request = Request(endpoint, data)
request.add_header("Content-type", "text/xml")
request.add_header("SOAPAction", '"ping"')

try:
  print urlopen(request).read()
except HTTPError,e:
  print e.read()
  

POST /ping/services/PingService HTTP/1.0
Content-length: 953
Host: localhost:8080
User-agent: Python-urllib/2.0a1
Soapaction: "ping"
Content-type: text/xml


<soap:Envelope 
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/";
  xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility";
  
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>

  <soap:Header>
    <wsse:Security mustUnderstand="1">
      <wsse:UsernameToken>
        <wsse:Username>[EMAIL PROTECTED]</wsse:Username>
        <wsse:Password 
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest";>c4uXbBdnI+lzM3/kEgpn+WITOns=</wsse:Password>
        <wsse:Nonce>1WzKKosiP3XEW1jLTpeXBLbQtxk=
</wsse:Nonce>
        <wsu:Created>2005-04-19T19:24:53Z</wsu:Created>
        <wsu:Expires>2005-04-19T19:27:53Z</wsu:Expires>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>

  <soap:Body>
    <echo><input xsi:type="xsd:string">Hello World</input></echo>
  </soap:Body>
</soap:Envelope>HTTP/1.1 500 Internal Server Error
Content-Type: text/xml;charset=utf-8
Date: Tue, 19 Apr 2005 19:24:54 GMT
Server: Apache-Coyote/1.1
Connection: close

<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";><soapenv:Body><soapenv:Fault><faultcode>soapenv:Server.generalException</faultcode><faultstring>WSDoAllReceiver:
 security processing failed; nested exception is: 
        org.apache.ws.security.WSSecurityException: The security token could 
not be authenticated or authorized</faultstring><detail><ns1:hostname 
xmlns:ns1="http://xml.apache.org/axis/";>jupiter.local</ns1:hostname></detail></soapenv:Fault></soapenv:Body></soapenv:Envelope>
"""
    Simple python script to talk to WSS4j enabled axis service

    Based on Sam Ruby's minimal example to talk to MicorSoft WS for getting
    Top 10 downloads. http://intertwingly.net/stories/2003/09/03/mstop10.py

    Mir S Islam <[EMAIL PROTECTED]>
        -Added mustUnderstand=1 attribute
        -Updated the schema for Password
        -replacing trailing EOL from password

    create a file mstoken.py in the same directory as this file is in and
    put the following:

        token = 'authid'
        pin = 'password'

"""

import random, binascii
from urllib2 import *
from time import *
import mstoken

# Your SOAP service url
endpoint='http://localhost:8080/ping/services/PingService'

nonce = sha.new(str(random.random())).digest()
created = strftime('%Y-%m-%dT%H:%M:%SZ',gmtime(time()))
digest = sha.new(nonce + created + mstoken.pin).digest()

mypass =  binascii.b2a_base64(digest)
mypass = mypass.replace('\n','')
security = {
  'PasswordDigest': mypass,
  'Username': mstoken.token,
  'Nonce': binascii.b2a_base64(nonce),
  'Created': created,
  'Expires': strftime('%Y-%m-%dT%H:%M:%SZ',gmtime(time()+180))
}

data="""
<soap:Envelope 
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/";
  xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility";
  
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>

  <soap:Header>
    <wsse:Security mustUnderstand="1">
      <wsse:UsernameToken>
        <wsse:Username>%(Username)s</wsse:Username>
        <wsse:Password 
Type="wsse:PasswordDigest">%(PasswordDigest)s</wsse:Password>
        <wsse:Nonce>%(Nonce)s</wsse:Nonce>
        <wsu:Created>%(Created)s</wsu:Created>
        <wsu:Expires>%(Expires)s</wsu:Expires>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>

  <soap:Body>
    <echo><input xsi:type="xsd:string">Hello World</input></echo>
  </soap:Body>
</soap:Envelope>""" % security

request = Request(endpoint, data)
request.add_header("Content-type", "text/xml")
request.add_header("SOAPAction", '"ping"')

try:
  print urlopen(request).read()
except HTTPError,e:
  print e.read()
  

Reply via email to